Skip to content

Commit d335b94

Browse files
committed
Sema: Substitute the root generic param when transforming OpaqueArchetypes.
For a nested associated type of an opaque archetype, the code would incorrectly substitute the immediate parent of the associated type with the root, causing crashes during substitution when the substitution failed unexpectedly. rdar://problem/52528543
1 parent ba73936 commit d335b94

File tree

3 files changed

+44
-2
lines changed

3 files changed

+44
-2
lines changed

include/swift/AST/Types.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5119,6 +5119,10 @@ class DependentMemberType : public TypeBase {
51195119
/// base.
51205120
Type substBaseType(Type base, LookupConformanceFn lookupConformance);
51215121

5122+
/// Substitute the root generic type, looking up the chain of associated types.
5123+
/// Returns null if the member could not be found in the new root.
5124+
Type substRootParam(Type newRoot, LookupConformanceFn lookupConformance);
5125+
51225126
// Implement isa/cast/dyncast/etc.
51235127
static bool classof(const TypeBase *T) {
51245128
return T->getKind() == TypeKind::DependentMember;

lib/AST/Type.cpp

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2977,7 +2977,8 @@ static Type getMemberForBaseType(LookupConformanceFn lookupConformances,
29772977

29782978
// Produce a failed result.
29792979
auto failed = [&]() -> Type {
2980-
if (!options.contains(SubstFlags::UseErrorType)) return Type();
2980+
if (!options.contains(SubstFlags::UseErrorType))
2981+
return Type();
29812982

29822983
Type baseType = ErrorType::get(substBase ? substBase : origBase);
29832984
if (assocType)
@@ -3111,6 +3112,19 @@ Type DependentMemberType::substBaseType(Type substBase,
31113112
getAssocType(), getName(), None);
31123113
}
31133114

3115+
Type DependentMemberType::substRootParam(Type newRoot,
3116+
LookupConformanceFn lookupConformance){
3117+
auto base = getBase();
3118+
if (auto param = base->getAs<GenericTypeParamType>()) {
3119+
return substBaseType(newRoot, lookupConformance);
3120+
}
3121+
if (auto depMem = base->getAs<DependentMemberType>()) {
3122+
return substBaseType(depMem->substRootParam(newRoot, lookupConformance),
3123+
lookupConformance);
3124+
}
3125+
return Type();
3126+
}
3127+
31143128
static Type substGenericFunctionType(GenericFunctionType *genericFnType,
31153129
TypeSubstitutionFn substitutions,
31163130
LookupConformanceFn lookupConformances,
@@ -3882,7 +3896,7 @@ case TypeKind::Id:
38823896
}
38833897

38843898
// Substitute the new root into the root of the interface type.
3885-
return nestedType->getInterfaceType()->substBaseType(substRoot,
3899+
return nestedType->getInterfaceType()->substRootParam(substRoot,
38863900
LookUpConformanceInModule(root->getDecl()->getModuleContext()));
38873901
}
38883902

test/type/opaque.swift

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,3 +413,27 @@ struct Foo {
413413
var instanceVar: some P = 17
414414
let instanceLet: some P = 38
415415
}
416+
417+
protocol P_52528543 {
418+
init()
419+
420+
associatedtype A: Q_52528543
421+
422+
var a: A { get }
423+
}
424+
425+
protocol Q_52528543 {
426+
associatedtype B // expected-note 2 {{associated type 'B'}}
427+
428+
var b: B { get }
429+
}
430+
431+
extension P_52528543 {
432+
func frob(a_b: A.B) -> some P_52528543 { return self }
433+
}
434+
435+
func foo<T: P_52528543>(x: T) -> some P_52528543 {
436+
return x
437+
.frob(a_b: x.a.b)
438+
.frob(a_b: x.a.b) // expected-error {{cannot convert}}
439+
}

0 commit comments

Comments
 (0)