Skip to content

Commit 01d9d61

Browse files
committed
Add a Facility to Compute an Opened Archetype's Self Parameter
1 parent c5b8d1a commit 01d9d61

File tree

7 files changed

+66
-31
lines changed

7 files changed

+66
-31
lines changed

include/swift/AST/Types.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5746,6 +5746,15 @@ class OpenedArchetypeType final : public ArchetypeType,
57465746
ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
57475747
LayoutConstraint layout);
57485748

5749+
public:
5750+
/// Compute the parameter that serves as the \c Self type for an opened
5751+
/// archetype from the given declaration context.
5752+
///
5753+
/// For protocol extensions, this type is the context's \c Self type. For
5754+
/// all other contexts, this type is a generic parameter one level deeper
5755+
/// than the deepest generic context depth.
5756+
static Type getSelfInterfaceTypeFromContext(const DeclContext *useDC);
5757+
57495758
public:
57505759
/// Get or create an archetype that represents the opened type
57515760
/// of an existential value.

lib/AST/ASTContext.cpp

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4423,9 +4423,8 @@ CanTypeWrapper<OpenedArchetypeType> OpenedArchetypeType::getNew(
44234423
ArrayRef<ProtocolDecl *> conformsTo, Type superclass,
44244424
LayoutConstraint layout) {
44254425
// FIXME: It'd be great if all of our callers could submit interface types.
4426-
// But the constraint solver submits archetypes when trying to issue checks
4427-
// against members of existential types. For now, we'll work around them by
4428-
// forcing an interface type.
4426+
// But the constraint solver submits archetypes when e.g. trying to issue
4427+
// checks against members of existential types.
44294428
// assert((!superclass || !superclass->hasArchetype())
44304429
// && "superclass must be interface type");
44314430
auto arena = AllocationArena::Permanent;
@@ -4444,11 +4443,9 @@ CanTypeWrapper<OpenedArchetypeType> OpenedArchetypeType::getNew(
44444443
CanTypeWrapper<OpenedArchetypeType>
44454444
OpenedArchetypeType::get(CanType existential, const DeclContext *useDC,
44464445
Optional<UUID> knownID) {
4447-
Type interfaceType = GenericTypeParamType::get(
4448-
/*isTypeSequence=*/false,
4449-
/*depth*/ useDC->getGenericContextDepth() + 1, /*index*/ 0,
4450-
existential->getASTContext());
4451-
return get(existential, interfaceType, useDC, knownID);
4446+
return get(existential,
4447+
OpenedArchetypeType::getSelfInterfaceTypeFromContext(useDC),
4448+
useDC, knownID);
44524449
}
44534450

44544451
CanOpenedArchetypeType OpenedArchetypeType::get(CanType existential,
@@ -4511,10 +4508,9 @@ CanType OpenedArchetypeType::getAny(CanType existential, Type interfaceType,
45114508

45124509
CanType OpenedArchetypeType::getAny(CanType existential,
45134510
const DeclContext *useDC) {
4514-
Type interfaceType = GenericTypeParamType::get(
4515-
/*isTypeSequence=*/false, useDC->getGenericContextDepth() + 1, 0,
4516-
existential->getASTContext());
4517-
return getAny(existential, interfaceType, useDC);
4511+
return getAny(existential,
4512+
OpenedArchetypeType::getSelfInterfaceTypeFromContext(useDC),
4513+
useDC);
45184514
}
45194515

45204516
void SubstitutionMap::Storage::Profile(
@@ -5191,6 +5187,18 @@ CanGenericSignature ASTContext::getSingleGenericParameterSignature() const {
51915187
return canonicalSig;
51925188
}
51935189

5190+
Type OpenedArchetypeType::getSelfInterfaceTypeFromContext(const DeclContext *useDC) {
5191+
auto typeContext = useDC->getInnermostTypeContext();
5192+
if (typeContext && typeContext->getSelfProtocolDecl()) {
5193+
return typeContext->getProtocolSelfType();
5194+
} else {
5195+
return GenericTypeParamType::get(
5196+
/*isTypeSequence=*/false,
5197+
/*depth*/ useDC->getGenericContextDepth() + 1, /*index*/ 0,
5198+
useDC->getASTContext());
5199+
}
5200+
}
5201+
51945202
CanGenericSignature
51955203
ASTContext::getOpenedArchetypeSignature(Type type, const DeclContext *useDC) {
51965204
assert(type->isExistentialType());
@@ -5218,14 +5226,21 @@ ASTContext::getOpenedArchetypeSignature(Type type, const DeclContext *useDC) {
52185226
if (found != getImpl().ExistentialSignatures.end())
52195227
return found->second;
52205228

5221-
auto depth = useDC->getGenericContextDepth() + 1;
5222-
auto genericParam =
5223-
GenericTypeParamType::get(/*type sequence*/ false,
5224-
/*depth*/ depth, /*index*/ 0, *this);
5229+
GenericSignature outerSignature;
5230+
auto *typeContext = useDC->getInnermostTypeContext();
5231+
if (typeContext && typeContext->getSelfProtocolDecl()) {
5232+
outerSignature = GenericSignature();
5233+
} else {
5234+
outerSignature = useDC->getGenericSignatureOfContext();
5235+
}
5236+
5237+
auto genericParam = OpenedArchetypeType::getSelfInterfaceTypeFromContext(useDC)
5238+
->getCanonicalType()->getAs<GenericTypeParamType>();
5239+
52255240
Requirement requirement(RequirementKind::Conformance, genericParam,
52265241
constraint);
52275242
auto genericSig = buildGenericSignature(
5228-
*this, useDC->getGenericSignatureOfContext().getCanonicalSignature(),
5243+
*this, outerSignature.getCanonicalSignature(),
52295244
{genericParam}, {requirement});
52305245

52315246
CanGenericSignature canGenericSig(genericSig);

lib/AST/Decl.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2926,7 +2926,7 @@ CanType ValueDecl::getOverloadSignatureType() const {
29262926
/*topLevelFunction=*/true, isMethod,
29272927
/*isInitializer=*/isa<ConstructorDecl>(afd),
29282928
getNumCurryLevels())
2929-
->getMinimalCanonicalType(afd);
2929+
->getCanonicalType();
29302930
}
29312931

29322932
if (isa<AbstractStorageDecl>(this)) {
@@ -2942,22 +2942,22 @@ CanType ValueDecl::getOverloadSignatureType() const {
29422942
/*topLevelFunction=*/true,
29432943
/*isMethod=*/false,
29442944
/*isInitializer=*/false, getNumCurryLevels())
2945-
->getMinimalCanonicalType(getDeclContext());
2945+
->getCanonicalType();
29462946
}
29472947

29482948
// We want to curry the default signature type with the 'self' type of the
29492949
// given context (if any) in order to ensure the overload signature type
29502950
// is unique across different contexts, such as between a protocol extension
29512951
// and struct decl.
29522952
return defaultSignatureType->addCurriedSelfType(getDeclContext())
2953-
->getMinimalCanonicalType(getDeclContext());
2953+
->getCanonicalType();
29542954
}
29552955

29562956
if (isa<EnumElementDecl>(this)) {
29572957
auto mappedType = mapSignatureFunctionType(
29582958
getASTContext(), getInterfaceType(), /*topLevelFunction=*/false,
29592959
/*isMethod=*/false, /*isInitializer=*/false, getNumCurryLevels());
2960-
return mappedType->getMinimalCanonicalType(getDeclContext());
2960+
return mappedType->getCanonicalType();
29612961
}
29622962

29632963
// Note: If you add more cases to this function, you should update the

lib/AST/Type.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4017,7 +4017,12 @@ CanType ProtocolCompositionType::getMinimalCanonicalType(
40174017
Type superclass;
40184018
llvm::SmallVector<Type, 2> MinimalMembers;
40194019
bool MinimalHasExplicitAnyObject = false;
4020+
auto ifaceTy = OpenedArchetypeType::getSelfInterfaceTypeFromContext(useDC);
40204021
for (const auto &Req : Reqs) {
4022+
if (!Req.getFirstType()->isEqual(ifaceTy)) {
4023+
continue;
4024+
}
4025+
40214026
switch (Req.getKind()) {
40224027
case RequirementKind::Superclass:
40234028
assert((!superclass || superclass->isEqual(Req.getSecondType()))
@@ -4035,7 +4040,7 @@ CanType ProtocolCompositionType::getMinimalCanonicalType(
40354040
}
40364041
}
40374042

4038-
// Ensure any superclass bounds appears first regardless of its order among
4043+
// Ensure superclass bounds appear first regardless of their order among
40394044
// the signature's requirements.
40404045
if (superclass)
40414046
MinimalMembers.insert(MinimalMembers.begin(), superclass->getCanonicalType());

lib/SIL/Utils/MemoryLocations.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ void MemoryLocations::analyzeLocation(SILValue loc) {
200200
SubLocationMap subLocationMap;
201201
if (!analyzeLocationUsesRecursively(loc, currentLocIdx, collectedVals,
202202
subLocationMap)) {
203-
// locations.truncate(currentLocIdx);
203+
locations.truncate(currentLocIdx);
204204
for (SILValue V : collectedVals) {
205205
addr2LocIdx.erase(V);
206206
}

lib/Sema/ConstraintSystem.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6020,7 +6020,7 @@ void ConstraintSystem::maybeProduceFallbackDiagnostic(
60206020
/// Because opened archetypes are not part of the surface language, these
60216021
/// constraints render the member inaccessible.
60226022
static bool doesMemberHaveUnfulfillableConstraintsWithExistentialBase(
6023-
Type baseTy, const ValueDecl *member) {
6023+
Type baseTy, const ValueDecl *member, const DeclContext *useDC) {
60246024
const auto sig =
60256025
member->getInnermostDeclContext()->getGenericSignatureOfContext();
60266026

@@ -6057,7 +6057,7 @@ static bool doesMemberHaveUnfulfillableConstraintsWithExistentialBase(
60576057
return Action::Stop;
60586058
}
60596059
} isDependentOnSelfWalker(member->getASTContext().getOpenedArchetypeSignature(
6060-
baseTy, member->getDeclContext()));
6060+
baseTy, useDC));
60616061

60626062
for (const auto &req : sig.getRequirements()) {
60636063
switch (req.getKind()) {
@@ -6099,8 +6099,13 @@ bool ConstraintSystem::isMemberAvailableOnExistential(
60996099

61006100
// If the type of the member references 'Self' or a 'Self'-rooted associated
61016101
// type in non-covariant position, we cannot reference the member.
6102+
//
6103+
// N.B. We pass the module context because this check does not care about the
6104+
// the actual signature of the opened archetype in context, rather it cares
6105+
// about whether you can "hold" `baseTy.member` properly in the abstract.
61026106
const auto info = member->findExistentialSelfReferences(
6103-
baseTy, DC, /*treatNonResultCovariantSelfAsInvariant=*/false);
6107+
baseTy, DC->getModuleScopeContext(),
6108+
/*treatNonResultCovariantSelfAsInvariant=*/false);
61046109
if (info.selfRef > TypePosition::Covariant ||
61056110
info.assocTypeRef > TypePosition::Covariant) {
61066111
return false;
@@ -6113,7 +6118,8 @@ bool ConstraintSystem::isMemberAvailableOnExistential(
61136118
}
61146119

61156120
if (doesMemberHaveUnfulfillableConstraintsWithExistentialBase(baseTy,
6116-
member)) {
6121+
member,
6122+
DC)) {
61176123
return false;
61186124
}
61196125

test/SILGen/witnesses_class.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ class UsesDefaults<X : Barable> : HasDefaults {}
8484

8585
// Invariant Self, since type signature contains an associated type:
8686

87-
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s15witnesses_class12UsesDefaultsCyxGAA03HasD0A2aEP16hasDefaultTakesTyy1TQzFTW : $@convention(witness_method: HasDefaults) <τ_0_0 where τ_0_0 : Barable> (@in_guaranteed UsesDefaults<τ_0_0>, @in_guaranteed UsesDefaults<τ_0_0>) -> ()
87+
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s15witnesses_class12UsesDefaultsCyqd__GAA03HasD0A2aEP16hasDefaultTakesTyy1TQzFTW : $@convention(witness_method: HasDefaults) <τ_0_0><τ_1_0 where τ_0_0 : UsesDefaults<τ_1_0>, τ_1_0 : Barable> (@in_guaranteed UsesDefaults<τ_1_0>, @in_guaranteed τ_0_0) -> ()
8888
// CHECK: [[FN:%.*]] = function_ref @$s15witnesses_class11HasDefaultsPAAE16hasDefaultTakesTyy1TQzF : $@convention(method) <τ_0_0 where τ_0_0 : HasDefaults> (@in_guaranteed τ_0_0.T, @in_guaranteed τ_0_0) -> ()
89-
// CHECK: apply [[FN]]<UsesDefaults<τ_0_0>>(
89+
// CHECK: apply [[FN]]<τ_0_0>(
9090
// CHECK: return
9191

9292
// Covariant Self:
@@ -98,9 +98,9 @@ class UsesDefaults<X : Barable> : HasDefaults {}
9898

9999
// Invariant Self, since type signature contains an associated type:
100100

101-
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s15witnesses_class12UsesDefaultsCyxGAA03HasD0A2aEP23hasDefaultGenericTakesTyy1TQz_qd__tAA7FooableRd__lFTW : $@convention(witness_method: HasDefaults) <τ_0_0 where τ_0_0 : Barable><τ_1_0 where τ_1_0 : Fooable> (@in_guaranteed UsesDefaults<τ_0_0>, @guaranteed τ_1_0, @in_guaranteed UsesDefaults<τ_0_0>) -> ()
101+
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s15witnesses_class12UsesDefaultsCyqd__GAA03HasD0A2aEP23hasDefaultGenericTakesTyy1TQz_qd__tAA7FooableRd__lFTW : $@convention(witness_method: HasDefaults) <τ_0_0><τ_1_0 where τ_0_0 : UsesDefaults<τ_1_0>, τ_1_0 : Barable><τ_2_0 where τ_2_0 : Fooable> (@in_guaranteed UsesDefaults<τ_1_0>, @guaranteed τ_2_0, @in_guaranteed τ_0_0) -> ()
102102
// CHECK: [[FN:%.*]] = function_ref @$s15witnesses_class11HasDefaultsPAAE23hasDefaultGenericTakesTyy1TQz_qd__tAA7FooableRd__lF : $@convention(method) <τ_0_0 where τ_0_0 : HasDefaults><τ_1_0 where τ_1_0 : Fooable> (@in_guaranteed τ_0_0.T, @guaranteed τ_1_0, @in_guaranteed τ_0_0) -> ()
103-
// CHECK: apply [[FN]]<UsesDefaults<τ_0_0>, τ_1_0>(
103+
// CHECK: apply [[FN]]<τ_0_0, τ_2_0>(
104104
// CHECK: return
105105

106106
protocol ReturnsCovariantSelf {

0 commit comments

Comments
 (0)