Skip to content

Commit 52bb8b4

Browse files
committed
[CS] Record opened types early in getTypeOfMemberReference
Requirement opening relies on being able to query the opened type to allow requirement fix coalescing to work. Record the opened type before we open requirements to ensure we don't duplicate requirement fixes on the base type with requirement fixes for the member.
1 parent 51683c4 commit 52bb8b4

File tree

2 files changed

+34
-10
lines changed

2 files changed

+34
-10
lines changed

lib/Sema/TypeOfReference.cpp

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1646,17 +1646,30 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference(
16461646
DeclContext *innerDC = value->getInnermostDeclContext();
16471647
DeclContext *outerDC = value->getDeclContext();
16481648

1649+
auto genericSig = innerDC->getGenericSignatureOfContext();
1650+
16491651
// Open the type of the generic function or member of a generic type.
16501652
Type openedType;
1653+
ArrayRef<OpenedType> replacements;
16511654
SmallVector<OpenedType, 4> localReplacements;
1652-
auto &replacements = replacementsPtr ? *replacementsPtr : localReplacements;
1655+
{
1656+
auto &_replacements = replacementsPtr ? *replacementsPtr : localReplacements;
16531657

1654-
// If we have a generic signature, open the parameters. We delay opening
1655-
// requirements to allow contextual types to affect the situation.
1656-
auto genericSig = innerDC->getGenericSignatureOfContext();
1657-
if (genericSig) {
1658-
openGenericParameters(outerDC, genericSig, replacements, locator,
1659-
preparedOverload);
1658+
// If we have a generic signature, open the parameters. We delay opening
1659+
// requirements to allow contextual types to affect the situation.
1660+
if (genericSig) {
1661+
openGenericParameters(outerDC, genericSig, _replacements, locator,
1662+
preparedOverload);
1663+
}
1664+
1665+
// If we opened up any type variables, record the replacements. We do this
1666+
// up-front to allow requirement fix coalescing logic to work correctly with
1667+
// requirements imposed on base type (since that relies on being able to
1668+
// find the recorded opened type). We then make the array immutable for the
1669+
// following logic to ensure they don't attempt to add any additional opened
1670+
// types.
1671+
recordOpenedTypes(locator, _replacements, preparedOverload);
1672+
replacements = _replacements;
16601673
}
16611674

16621675
Type thrownErrorType;
@@ -1867,9 +1880,6 @@ DeclReferenceType ConstraintSystem::getTypeOfMemberReference(
18671880
isDynamicLookup, replacements);
18681881
}
18691882

1870-
// If we opened up any type variables, record the replacements.
1871-
recordOpenedTypes(locator, replacements, preparedOverload);
1872-
18731883
return { origOpenedType, openedType, origType, type, thrownErrorType };
18741884
}
18751885

test/decl/nested/type_in_type.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,3 +427,17 @@ extension OuterGeneric.MidNonGeneric {
427427

428428
}
429429
}
430+
431+
protocol P {}
432+
433+
struct A<T> {}
434+
extension A where T: P { // expected-note {{where 'T' = 'T'}}
435+
struct B<U> {
436+
init(_ u: U) {}
437+
}
438+
}
439+
extension A {
440+
func bar() {
441+
B(0) // expected-error {{referencing generic struct 'B' on 'A' requires that 'T' conform to 'P'}}
442+
}
443+
}

0 commit comments

Comments
 (0)