Skip to content

Commit 2746a83

Browse files
authored
Merge pull request #81181 from slavapestov/fix-issue-79763
AST: Fix existential erasure of long member types
2 parents aad8513 + d2b0bf0 commit 2746a83

File tree

5 files changed

+54
-24
lines changed

5 files changed

+54
-24
lines changed

include/swift/AST/SubstitutionMap.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,6 @@ struct OuterSubstitutions {
337337
SubstitutionMap subs;
338338
unsigned depth;
339339

340-
bool isUnsubstitutedTypeParameter(Type type) const;
341340
Type operator()(SubstitutableType *type) const;
342341
ProtocolConformanceRef operator()(CanType dependentType,
343342
Type conformingReplacementType,

lib/AST/GenericEnvironment.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -317,9 +317,13 @@ GenericEnvironment::maybeApplyOuterContextSubstitutions(Type type) const {
317317
case Kind::OpenedExistential:
318318
case Kind::OpenedElement:
319319
case Kind::Opaque: {
320-
OuterSubstitutions replacer{
321-
getOuterSubstitutions(), getGenericSignature()->getMaxDepth()};
322-
return type.subst(replacer, replacer);
320+
if (auto subs = getOuterSubstitutions()) {
321+
OuterSubstitutions replacer{subs,
322+
getGenericSignature()->getMaxDepth()};
323+
return type.subst(replacer, replacer);
324+
}
325+
326+
return type;
323327
}
324328
}
325329
}

lib/AST/SubstitutionMap.cpp

Lines changed: 17 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -657,21 +657,8 @@ SubstitutionMap swift::substOpaqueTypesWithUnderlyingTypes(
657657
SubstFlags::PreservePackExpansionLevel);
658658
}
659659

660-
bool OuterSubstitutions::isUnsubstitutedTypeParameter(Type type) const {
661-
if (!type->isTypeParameter())
662-
return false;
663-
664-
if (auto depMemTy = type->getAs<DependentMemberType>())
665-
return isUnsubstitutedTypeParameter(depMemTy->getBase());
666-
667-
if (auto genericParam = type->getAs<GenericTypeParamType>())
668-
return genericParam->getDepth() >= depth;
669-
670-
return false;
671-
}
672-
673660
Type OuterSubstitutions::operator()(SubstitutableType *type) const {
674-
if (isUnsubstitutedTypeParameter(type))
661+
if (cast<GenericTypeParamType>(type)->getDepth() >= depth)
675662
return Type(type);
676663

677664
return QuerySubstitutionMap{subs}(type);
@@ -681,9 +668,23 @@ ProtocolConformanceRef OuterSubstitutions::operator()(
681668
CanType dependentType,
682669
Type conformingReplacementType,
683670
ProtocolDecl *conformedProtocol) const {
684-
if (isUnsubstitutedTypeParameter(dependentType))
685-
return ProtocolConformanceRef::forAbstract(
671+
auto sig = subs.getGenericSignature();
672+
if (!sig->isValidTypeParameter(dependentType) ||
673+
!sig->requiresProtocol(dependentType, conformedProtocol)) {
674+
// FIXME: We need the isValidTypeParameter() check instead of just looking
675+
// at the root generic parameter because in the case of an existential
676+
// environment, the reduced type of a member type of Self might be an outer
677+
// type parameter that is not formed from the outer generic signature's
678+
// conformance requirements. Ideally, we'd either add these supplementary
679+
// conformance requirements to the generalization signature, or we would
680+
// store the supplementary conformances directly in the generic environment
681+
// somehow.
682+
//
683+
// Once we check for that and handle it properly, the lookupConformance()
684+
// can become a forAbstract().
685+
return swift::lookupConformance(
686686
conformingReplacementType, conformedProtocol);
687+
}
687688

688689
return LookUpConformanceInSubstitutionMap(subs)(
689690
dependentType, conformingReplacementType, conformedProtocol);

lib/Sema/OpenedExistentials.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -823,10 +823,11 @@ Type swift::typeEraseOpenedExistentialReference(
823823

824824
auto applyOuterSubstitutions = [&](Type t) -> Type {
825825
if (t->hasTypeParameter()) {
826-
auto outerSubs = existentialSig.Generalization;
827-
unsigned depth = existentialSig.OpenedSig->getMaxDepth();
828-
OuterSubstitutions replacer{outerSubs, depth};
829-
return t.subst(replacer, replacer);
826+
if (auto outerSubs = existentialSig.Generalization) {
827+
unsigned depth = existentialSig.OpenedSig->getMaxDepth();
828+
OuterSubstitutions replacer{outerSubs, depth};
829+
return t.subst(replacer, replacer);
830+
}
830831
}
831832

832833
return t;
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %target-swift-emit-silgen %s
2+
3+
protocol N {
4+
associatedtype A: N
5+
}
6+
7+
protocol P<A> {
8+
associatedtype A: N
9+
associatedtype B
10+
11+
func f0(_: A) -> B
12+
func f1(_: A.A) -> B
13+
func f2(_: A.A.A) -> B
14+
}
15+
16+
struct G<T>: N {
17+
typealias A = G<G<T>>
18+
}
19+
20+
func call(x: any P<G<Int>>) -> (Any, Any, Any) {
21+
let y0 = x.f0(G<Int>())
22+
let y1 = x.f1(G<G<Int>>())
23+
let y2 = x.f2(G<G<G<Int>>>())
24+
return (y0, y1, y2)
25+
}

0 commit comments

Comments
 (0)