Skip to content

Commit 7690630

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 445a856 commit 7690630

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
@@ -1931,7 +1931,8 @@ NeverNullType TypeResolver::resolveType(TypeRepr *repr,
19311931

19321932
// Strip the "is function input" bits unless this is a type that knows about
19331933
// them.
1934-
if (!isa<SpecifierTypeRepr>(repr) && !isa<TupleTypeRepr>(repr) &&
1934+
if (options.is(TypeResolverContext::FunctionInput) &&
1935+
!isa<SpecifierTypeRepr>(repr) && !isa<TupleTypeRepr>(repr) &&
19351936
!isa<AttributedTypeRepr>(repr) && !isa<FunctionTypeRepr>(repr) &&
19361937
!isa<IdentTypeRepr>(repr) &&
19371938
!isa<ImplicitlyUnwrappedOptionalTypeRepr>(repr)) {
@@ -2049,7 +2050,7 @@ NeverNullType TypeResolver::resolveType(TypeRepr *repr,
20492050
}
20502051

20512052
auto *existential = cast<ExistentialTypeRepr>(repr);
2052-
return resolveType(existential->getConstraint(), options);
2053+
return resolveExistentialType(existential, options);
20532054
}
20542055

20552056
case TypeReprKind::NamedOpaqueReturn:
@@ -3363,6 +3364,14 @@ TypeResolver::resolveIdentifierType(IdentTypeRepr *IdType,
33633364
return ErrorType::get(getASTContext());
33643365
}
33653366

3367+
bool isConstraintType = (result->is<ProtocolType>() ||
3368+
result->is<ProtocolCompositionType>());
3369+
if (isConstraintType &&
3370+
getASTContext().LangOpts.EnableExplicitExistentialTypes &&
3371+
options.isConstraintImplicitExistential()) {
3372+
return ExistentialType::get(result);
3373+
}
3374+
33663375
// Hack to apply context-specific @escaping to a typealias with an underlying
33673376
// function type.
33683377
if (result->is<FunctionType>())
@@ -3542,6 +3551,9 @@ NeverNullType TypeResolver::resolveImplicitlyUnwrappedOptionalType(
35423551
case TypeResolverContext::TypeAliasDecl:
35433552
case TypeResolverContext::GenericTypeAliasDecl:
35443553
case TypeResolverContext::GenericRequirement:
3554+
case TypeResolverContext::SameTypeRequirement:
3555+
case TypeResolverContext::ProtocolMetatypeBase:
3556+
case TypeResolverContext::MetatypeBase:
35453557
case TypeResolverContext::ImmediateOptionalTypeArgument:
35463558
case TypeResolverContext::InExpression:
35473559
case TypeResolverContext::EditorPlaceholderExpr:
@@ -3684,7 +3696,8 @@ TypeResolver::resolveCompositionType(CompositionTypeRepr *repr,
36843696
};
36853697

36863698
for (auto tyR : repr->getTypes()) {
3687-
auto ty = resolveType(tyR, options.withoutContext());
3699+
auto ty = resolveType(tyR,
3700+
options.withContext(TypeResolverContext::GenericRequirement));
36883701
if (ty->hasError()) return ty;
36893702

36903703
auto nominalDecl = ty->getAnyNominal();
@@ -3721,19 +3734,27 @@ TypeResolver::resolveCompositionType(CompositionTypeRepr *repr,
37213734

37223735
// In user-written types, AnyObject constraints always refer to the
37233736
// AnyObject type in the standard library.
3724-
return ProtocolCompositionType::get(getASTContext(), Members,
3725-
/*HasExplicitAnyObject=*/false);
3737+
auto composition =
3738+
ProtocolCompositionType::get(getASTContext(), Members,
3739+
/*HasExplicitAnyObject=*/false);
3740+
if (getASTContext().LangOpts.EnableExplicitExistentialTypes &&
3741+
options.isConstraintImplicitExistential()) {
3742+
composition = ExistentialType::get(composition);
3743+
}
3744+
return composition;
37263745
}
37273746

37283747
NeverNullType
37293748
TypeResolver::resolveExistentialType(ExistentialTypeRepr *repr,
37303749
TypeResolutionOptions options) {
3731-
auto constraintType = resolveType(repr->getConstraint(), options);
3750+
auto constraintType = resolveType(repr->getConstraint(),
3751+
options.withContext(TypeResolverContext::GenericRequirement));
3752+
if (constraintType->is<ExistentialMetatypeType>())
3753+
return constraintType;
37323754

37333755
auto anyStart = repr->getAnyLoc();
37343756
auto anyEnd = Lexer::getLocForEndOfToken(getASTContext().SourceMgr, anyStart);
3735-
if (!constraintType->isExistentialType() &&
3736-
!constraintType->is<ExistentialMetatypeType>()) {
3757+
if (!constraintType->isExistentialType()) {
37373758
diagnose(repr->getLoc(), diag::any_not_existential,
37383759
constraintType->isTypeParameter(),
37393760
constraintType)
@@ -3754,7 +3775,8 @@ TypeResolver::resolveExistentialType(ExistentialTypeRepr *repr,
37543775
NeverNullType TypeResolver::resolveMetatypeType(MetatypeTypeRepr *repr,
37553776
TypeResolutionOptions options) {
37563777
// The instance type of a metatype is always abstract, not SIL-lowered.
3757-
auto ty = resolveType(repr->getBase(), options.withoutContext());
3778+
auto ty = resolveType(repr->getBase(),
3779+
options.withContext(TypeResolverContext::MetatypeBase));
37583780
if (ty->hasError()) {
37593781
return ErrorType::get(getASTContext());
37603782
}
@@ -3775,7 +3797,8 @@ NeverNullType TypeResolver::resolveMetatypeType(MetatypeTypeRepr *repr,
37753797
NeverNullType
37763798
TypeResolver::buildMetatypeType(MetatypeTypeRepr *repr, Type instanceType,
37773799
Optional<MetatypeRepresentation> storedRepr) {
3778-
if (instanceType->isAnyExistentialType()) {
3800+
if (instanceType->isAnyExistentialType() &&
3801+
!instanceType->is<ExistentialType>()) {
37793802
// TODO: diagnose invalid representations?
37803803
return ExistentialMetatypeType::get(instanceType, storedRepr);
37813804
} else {
@@ -3786,7 +3809,8 @@ TypeResolver::buildMetatypeType(MetatypeTypeRepr *repr, Type instanceType,
37863809
NeverNullType TypeResolver::resolveProtocolType(ProtocolTypeRepr *repr,
37873810
TypeResolutionOptions options) {
37883811
// The instance type of a metatype is always abstract, not SIL-lowered.
3789-
auto ty = resolveType(repr->getBase(), options.withoutContext());
3812+
auto ty = resolveType(repr->getBase(),
3813+
options.withContext(TypeResolverContext::ProtocolMetatypeBase));
37903814
if (ty->hasError()) {
37913815
return ErrorType::get(getASTContext());
37923816
}

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)