Skip to content

Commit f4dabf9

Browse files
committed
[TypeResolver] Resolve existential types to ExistentialType when
explicit existential types are enabled. Note that existential metatypes still resolve to ExistentialMetatypeType, but later this type can be replaced with ExistentialType(MetatypeType).
1 parent 7bd3e83 commit f4dabf9

File tree

4 files changed

+101
-14
lines changed

4 files changed

+101
-14
lines changed

lib/AST/ASTPrinter.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4742,8 +4742,10 @@ class TypePrinter : public TypeVisitor<TypePrinter> {
47424742
printWithParensIfNotSimple(T->getInstanceType());
47434743

47444744
// We spell normal metatypes of existential types as .Protocol.
4745+
auto &ctx = T->getASTContext();
47454746
if (isa<MetatypeType>(T) &&
4746-
T->getInstanceType()->isAnyExistentialType()) {
4747+
T->getInstanceType()->isAnyExistentialType() &&
4748+
!ctx.LangOpts.EnableExplicitExistentialTypes) {
47474749
Printer << ".Protocol";
47484750
} else {
47494751
Printer << ".Type";

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -962,8 +962,16 @@ RequirementRequest::evaluate(Evaluator &evaluator,
962962
WhereClauseOwner owner,
963963
unsigned index,
964964
TypeResolutionStage stage) const {
965+
auto &reqRepr = getRequirement();
966+
965967
// Figure out the type resolution.
966-
auto options = TypeResolutionOptions(TypeResolverContext::GenericRequirement);
968+
TypeResolverContext context;
969+
if (reqRepr.getKind() == RequirementReprKind::SameType) {
970+
context = TypeResolverContext::SameTypeRequirement;
971+
} else {
972+
context = TypeResolverContext::GenericRequirement;
973+
}
974+
auto options = TypeResolutionOptions(context);
967975
if (owner.dc->isInSpecializeExtensionContext())
968976
options |= TypeResolutionFlags::AllowUsableFromInline;
969977
Optional<TypeResolution> resolution;
@@ -981,7 +989,6 @@ RequirementRequest::evaluate(Evaluator &evaluator,
981989
break;
982990
}
983991

984-
auto &reqRepr = getRequirement();
985992
switch (reqRepr.getKind()) {
986993
case RequirementReprKind::TypeConstraint: {
987994
Type subject = resolution->resolveType(reqRepr.getSubjectRepr());

lib/Sema/TypeCheckType.cpp

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1949,7 +1949,8 @@ NeverNullType TypeResolver::resolveType(TypeRepr *repr,
19491949

19501950
// Strip the "is function input" bits unless this is a type that knows about
19511951
// them.
1952-
if (!isa<SpecifierTypeRepr>(repr) && !isa<TupleTypeRepr>(repr) &&
1952+
if (options.is(TypeResolverContext::FunctionInput) &&
1953+
!isa<SpecifierTypeRepr>(repr) && !isa<TupleTypeRepr>(repr) &&
19531954
!isa<AttributedTypeRepr>(repr) && !isa<FunctionTypeRepr>(repr) &&
19541955
!isa<IdentTypeRepr>(repr) &&
19551956
!isa<ImplicitlyUnwrappedOptionalTypeRepr>(repr)) {
@@ -2067,7 +2068,7 @@ NeverNullType TypeResolver::resolveType(TypeRepr *repr,
20672068
}
20682069

20692070
auto *existential = cast<ExistentialTypeRepr>(repr);
2070-
return resolveType(existential->getConstraint(), options);
2071+
return resolveExistentialType(existential, options);
20712072
}
20722073

20732074
case TypeReprKind::NamedOpaqueReturn:
@@ -3381,6 +3382,14 @@ TypeResolver::resolveIdentifierType(IdentTypeRepr *IdType,
33813382
return ErrorType::get(getASTContext());
33823383
}
33833384

3385+
bool isConstraintType = (result->is<ProtocolType>() ||
3386+
result->is<ProtocolCompositionType>());
3387+
if (isConstraintType &&
3388+
getASTContext().LangOpts.EnableExplicitExistentialTypes &&
3389+
options.isConstraintImplicitExistential()) {
3390+
return ExistentialType::get(result);
3391+
}
3392+
33843393
// Hack to apply context-specific @escaping to a typealias with an underlying
33853394
// function type.
33863395
if (result->is<FunctionType>())
@@ -3560,6 +3569,9 @@ NeverNullType TypeResolver::resolveImplicitlyUnwrappedOptionalType(
35603569
case TypeResolverContext::TypeAliasDecl:
35613570
case TypeResolverContext::GenericTypeAliasDecl:
35623571
case TypeResolverContext::GenericRequirement:
3572+
case TypeResolverContext::SameTypeRequirement:
3573+
case TypeResolverContext::ProtocolMetatypeBase:
3574+
case TypeResolverContext::MetatypeBase:
35633575
case TypeResolverContext::ImmediateOptionalTypeArgument:
35643576
case TypeResolverContext::InExpression:
35653577
case TypeResolverContext::EditorPlaceholderExpr:
@@ -3702,7 +3714,8 @@ TypeResolver::resolveCompositionType(CompositionTypeRepr *repr,
37023714
};
37033715

37043716
for (auto tyR : repr->getTypes()) {
3705-
auto ty = resolveType(tyR, options.withoutContext());
3717+
auto ty = resolveType(tyR,
3718+
options.withContext(TypeResolverContext::GenericRequirement));
37063719
if (ty->hasError()) return ty;
37073720

37083721
auto nominalDecl = ty->getAnyNominal();
@@ -3739,19 +3752,27 @@ TypeResolver::resolveCompositionType(CompositionTypeRepr *repr,
37393752

37403753
// In user-written types, AnyObject constraints always refer to the
37413754
// AnyObject type in the standard library.
3742-
return ProtocolCompositionType::get(getASTContext(), Members,
3743-
/*HasExplicitAnyObject=*/false);
3755+
auto composition =
3756+
ProtocolCompositionType::get(getASTContext(), Members,
3757+
/*HasExplicitAnyObject=*/false);
3758+
if (getASTContext().LangOpts.EnableExplicitExistentialTypes &&
3759+
options.isConstraintImplicitExistential()) {
3760+
composition = ExistentialType::get(composition);
3761+
}
3762+
return composition;
37443763
}
37453764

37463765
NeverNullType
37473766
TypeResolver::resolveExistentialType(ExistentialTypeRepr *repr,
37483767
TypeResolutionOptions options) {
3749-
auto constraintType = resolveType(repr->getConstraint(), options);
3768+
auto constraintType = resolveType(repr->getConstraint(),
3769+
options.withContext(TypeResolverContext::GenericRequirement));
3770+
if (constraintType->is<ExistentialMetatypeType>())
3771+
return constraintType;
37503772

37513773
auto anyStart = repr->getAnyLoc();
37523774
auto anyEnd = Lexer::getLocForEndOfToken(getASTContext().SourceMgr, anyStart);
3753-
if (!constraintType->isExistentialType() &&
3754-
!constraintType->is<ExistentialMetatypeType>()) {
3775+
if (!constraintType->isExistentialType()) {
37553776
diagnose(repr->getLoc(), diag::any_not_existential,
37563777
constraintType->isTypeParameter(),
37573778
constraintType)
@@ -3772,7 +3793,8 @@ TypeResolver::resolveExistentialType(ExistentialTypeRepr *repr,
37723793
NeverNullType TypeResolver::resolveMetatypeType(MetatypeTypeRepr *repr,
37733794
TypeResolutionOptions options) {
37743795
// The instance type of a metatype is always abstract, not SIL-lowered.
3775-
auto ty = resolveType(repr->getBase(), options.withoutContext());
3796+
auto ty = resolveType(repr->getBase(),
3797+
options.withContext(TypeResolverContext::MetatypeBase));
37763798
if (ty->hasError()) {
37773799
return ErrorType::get(getASTContext());
37783800
}
@@ -3793,7 +3815,8 @@ NeverNullType TypeResolver::resolveMetatypeType(MetatypeTypeRepr *repr,
37933815
NeverNullType
37943816
TypeResolver::buildMetatypeType(MetatypeTypeRepr *repr, Type instanceType,
37953817
Optional<MetatypeRepresentation> storedRepr) {
3796-
if (instanceType->isAnyExistentialType()) {
3818+
if (instanceType->isAnyExistentialType() &&
3819+
!instanceType->is<ExistentialType>()) {
37973820
// TODO: diagnose invalid representations?
37983821
return ExistentialMetatypeType::get(instanceType, storedRepr);
37993822
} else {
@@ -3804,7 +3827,8 @@ TypeResolver::buildMetatypeType(MetatypeTypeRepr *repr, Type instanceType,
38043827
NeverNullType TypeResolver::resolveProtocolType(ProtocolTypeRepr *repr,
38053828
TypeResolutionOptions options) {
38063829
// The instance type of a metatype is always abstract, not SIL-lowered.
3807-
auto ty = resolveType(repr->getBase(), options.withoutContext());
3830+
auto ty = resolveType(repr->getBase(),
3831+
options.withContext(TypeResolverContext::ProtocolMetatypeBase));
38083832
if (ty->hasError()) {
38093833
return ErrorType::get(getASTContext());
38103834
}

lib/Sema/TypeCheckType.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,16 @@ enum class TypeResolverContext : uint8_t {
125125
/// Whether we are in a requirement of a generic declaration
126126
GenericRequirement,
127127

128+
/// Whether we are in a same-type requirement of a generic
129+
/// declaration.
130+
SameTypeRequirement,
131+
132+
/// Whether this is the base type of .Protocol
133+
ProtocolMetatypeBase,
134+
135+
/// Whether this is the base type of .Type
136+
MetatypeBase,
137+
128138
/// Whether we are in a type argument for an optional
129139
ImmediateOptionalTypeArgument,
130140

@@ -215,6 +225,9 @@ class TypeResolutionOptions {
215225
case Context::TypeAliasDecl:
216226
case Context::GenericTypeAliasDecl:
217227
case Context::GenericRequirement:
228+
case Context::SameTypeRequirement:
229+
case Context::ProtocolMetatypeBase:
230+
case Context::MetatypeBase:
218231
case Context::ImmediateOptionalTypeArgument:
219232
case Context::AbstractFunctionDecl:
220233
case Context::Inherited:
@@ -224,6 +237,40 @@ class TypeResolutionOptions {
224237
llvm_unreachable("unhandled kind");
225238
}
226239

240+
/// Whether a generic constraint type is implicitly an
241+
/// existential type in this context.
242+
bool isConstraintImplicitExistential() const {
243+
switch (context) {
244+
case Context::Inherited:
245+
case Context::ExtensionBinding:
246+
case Context::TypeAliasDecl:
247+
case Context::GenericTypeAliasDecl:
248+
case Context::GenericRequirement:
249+
case Context::MetatypeBase:
250+
return false;
251+
case Context::None:
252+
case Context::InExpression:
253+
case Context::ExplicitCastExpr:
254+
case Context::ForEachStmt:
255+
case Context::PatternBindingDecl:
256+
case Context::EditorPlaceholderExpr:
257+
case Context::ClosureExpr:
258+
case Context::FunctionInput:
259+
case Context::VariadicFunctionInput:
260+
case Context::InoutFunctionInput:
261+
case Context::FunctionResult:
262+
case Context::SubscriptDecl:
263+
case Context::EnumElementDecl:
264+
case Context::EnumPatternPayload:
265+
case Context::SameTypeRequirement:
266+
case Context::ProtocolMetatypeBase:
267+
case Context::ImmediateOptionalTypeArgument:
268+
case Context::AbstractFunctionDecl:
269+
case Context::CustomAttr:
270+
return true;
271+
}
272+
}
273+
227274
/// Determine whether all of the given options are set.
228275
bool contains(TypeResolutionFlags set) const {
229276
return !static_cast<bool>(unsigned(set) & ~unsigned(flags));
@@ -276,6 +323,13 @@ class TypeResolutionOptions {
276323
if (!preserveSIL) copy -= TypeResolutionFlags::SILType;
277324
return copy;
278325
}
326+
327+
inline
328+
TypeResolutionOptions withContext(TypeResolverContext context) const {
329+
auto copy = *this;
330+
copy.setContext(context);
331+
return copy;
332+
}
279333
};
280334

281335
/// A function reference used to "open" the given unbound generic type

0 commit comments

Comments
 (0)