Skip to content

Commit 28460bc

Browse files
committed
[Sema] Always return the typealias from a member type lookup.
An expression like Type.Member will first do a normal lookup, and, if only associated types could be found, will then do associated type inference on them. Previously the types of these would be returned directly, but this loses the sugar associated with the implicit typealias that is created. The sugar is necessary to ensure that things like the checking of conditional requirements is satisfied, such as: protocol P { associatedtype T } struct X<T> {} extension X: P where T == Int {} let _ = X<String>.T.self If the underlying type 'String' (or even 'Int') of 'X<...>.T' is returned, then the above ends up being perfectly fine, because those are always available, but that expression itself isn't quite right because the T typealias is conditional. With this change, once associatedtype inference runs, the typealias that it creates is found, and the type is mapped to have all the right sugar, meaning the above is flagged. (This hints at an extra exciting bit of the original behaviour: if the `let ...` line was copied so that there were two, the second one gets the expected error, because it doesn't need to run inference and just finds the typealiases created by the first line.) Part of https://bugs.swift.org/browse/SR-5440 and https://bugs.swift.org/browse/SR-7976 and rdar://problem/41063870.
1 parent 7915d16 commit 28460bc

File tree

4 files changed

+40
-17
lines changed

4 files changed

+40
-17
lines changed

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -447,7 +447,7 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
447447
// Add the type to the result set, so that we can diagnose the
448448
// reference instead of just saying the member does not exist.
449449
if (types.insert(memberType->getCanonicalType()).second)
450-
result.Results.push_back({typeDecl, memberType});
450+
result.Results.push_back({typeDecl, memberType, nullptr});
451451

452452
continue;
453453
}
@@ -492,7 +492,7 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
492492

493493
// If we haven't seen this type result yet, add it to the result set.
494494
if (types.insert(memberType->getCanonicalType()).second)
495-
result.Results.push_back({typeDecl, memberType});
495+
result.Results.push_back({typeDecl, memberType, nullptr});
496496
}
497497

498498
if (result.Results.empty()) {
@@ -521,19 +521,21 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
521521

522522
// Use the type witness.
523523
auto concrete = conformance->getConcrete();
524-
Type memberType = concrete->getTypeWitness(assocType, this);
525524

526525
// This is the only case where NormalProtocolConformance::
527526
// getTypeWitnessAndDecl() returns a null type.
528527
if (concrete->getState() ==
529528
ProtocolConformanceState::CheckingTypeWitnesses)
530529
continue;
531530

532-
assert(memberType && "Missing type witness?");
531+
auto typeDecl = concrete->getTypeWitnessAndDecl(assocType, this).second;
533532

534-
// If we haven't seen this type result yet, add it to the result set.
533+
assert(typeDecl && "Missing type witness?");
534+
535+
auto memberType =
536+
substMemberTypeWithBase(dc->getParentModule(), typeDecl, type);
535537
if (types.insert(memberType->getCanonicalType()).second)
536-
result.Results.push_back({assocType, memberType});
538+
result.Results.push_back({typeDecl, memberType, assocType});
537539
}
538540
}
539541

lib/Sema/TypeCheckType.cpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,7 +1254,8 @@ static Type resolveNestedIdentTypeComponent(
12541254
bool diagnoseErrors,
12551255
GenericTypeResolver *resolver,
12561256
UnsatisfiedDependency *unsatisfiedDependency) {
1257-
auto maybeDiagnoseBadMemberType = [&](TypeDecl *member, Type memberType) {
1257+
auto maybeDiagnoseBadMemberType = [&](TypeDecl *member, Type memberType,
1258+
AssociatedTypeDecl *inferredAssocType) {
12581259
// Diagnose invalid cases.
12591260
if (TC.isUnsupportedMemberTypeAccess(parentTy, member)) {
12601261
if (diagnoseErrors) {
@@ -1285,20 +1286,21 @@ static Type resolveNestedIdentTypeComponent(
12851286
}
12861287
}
12871288

1289+
// Diagnose a bad conformance reference if we need to.
1290+
if (inferredAssocType && diagnoseErrors && memberType &&
1291+
memberType->hasError()) {
1292+
maybeDiagnoseBadConformanceRef(TC, DC, parentTy, comp->getLoc(),
1293+
inferredAssocType);
1294+
}
1295+
12881296
// If we found a reference to an associated type or other member type that
12891297
// was marked invalid, just return ErrorType to silence downstream errors.
12901298
if (member->isInvalid())
12911299
return ErrorType::get(TC.Context);
12921300

1293-
// Diagnose a bad conformance reference if we need to.
1294-
if (isa<AssociatedTypeDecl>(member) && diagnoseErrors &&
1295-
memberType && memberType->hasError()) {
1296-
maybeDiagnoseBadConformanceRef(TC, DC, parentTy, comp->getLoc(),
1297-
cast<AssociatedTypeDecl>(member));
1298-
}
1299-
13001301
// At this point, we need to have resolved the type of the member.
1301-
if (!memberType || memberType->hasError()) return memberType;
1302+
if (!memberType || memberType->hasError())
1303+
return memberType;
13021304

13031305
// If there are generic arguments, apply them now.
13041306
if (!options.contains(TypeResolutionFlags::ResolveStructure)) {
@@ -1335,7 +1337,7 @@ static Type resolveNestedIdentTypeComponent(
13351337
if (auto *typeDecl = comp->getBoundDecl()) {
13361338
auto memberType = TC.substMemberTypeWithBase(DC->getParentModule(),
13371339
typeDecl, parentTy);
1338-
return maybeDiagnoseBadMemberType(typeDecl, memberType);
1340+
return maybeDiagnoseBadMemberType(typeDecl, memberType, nullptr);
13391341
}
13401342

13411343
// Phase 1: Find and bind the component decl.
@@ -1390,6 +1392,7 @@ static Type resolveNestedIdentTypeComponent(
13901392
// If we didn't find anything, complain.
13911393
Type memberType;
13921394
TypeDecl *member = nullptr;
1395+
AssociatedTypeDecl *inferredAssocType = nullptr;
13931396
if (!memberTypes) {
13941397
// If we're not allowed to complain or we couldn't fix the
13951398
// source, bail out.
@@ -1405,10 +1408,11 @@ static Type resolveNestedIdentTypeComponent(
14051408
} else {
14061409
memberType = memberTypes.back().MemberType;
14071410
member = memberTypes.back().Member;
1411+
inferredAssocType = memberTypes.back().InferredAssociatedType;
14081412
comp->setValue(member, nullptr);
14091413
}
14101414

1411-
return maybeDiagnoseBadMemberType(member, memberType);
1415+
return maybeDiagnoseBadMemberType(member, memberType, inferredAssocType);
14121416
}
14131417

14141418
static Type resolveIdentTypeComponent(

lib/Sema/TypeChecker.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ class LookupResult {
155155
struct LookupTypeResultEntry {
156156
TypeDecl *Member;
157157
Type MemberType;
158+
/// The associated type that the Member/MemberType were inferred for, but only
159+
/// if inference happened when creating this entry.
160+
AssociatedTypeDecl *InferredAssociatedType;
158161
};
159162

160163
/// The result of name lookup for types.

test/Constraints/conditionally_defined_types.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ let _ = SameType<Y>.Decl3.self // expected-error {{'SameType<Y>.Decl3.Type' requ
4545
let _ = SameType<Y>.Decl4<X>.self // expected-error {{'SameType<Y>.Decl4' requires the types 'Y' and 'X' be equivalent}}
4646
let _ = SameType<Y>.Decl5<X>.self // expected-error {{'SameType<Y>.Decl5' requires the types 'Y' and 'X' be equivalent}}
4747

48+
extension SameType: AssociatedType where T == X {}
49+
50+
// (Y first here, because there were issues caused by running associated type
51+
// inference for the first time)
52+
let _ = SameType<Y>.T.self // expected-error {{'SameType<Y>.T.Type' (aka 'X.Type') requires the types 'Y' and 'X' be equivalent}}
53+
54+
let _ = SameType<X>.T.self
55+
4856
struct Conforms<T> {}
4957
extension Conforms where T: P {
5058
typealias TypeAlias1 = T
@@ -76,6 +84,12 @@ let _ = Conforms<Y>.Decl3.self // expected-error {{type 'Y' does not conform to
7684
let _ = Conforms<Y>.Decl4<X>.self // expected-error {{type 'Y' does not conform to protocol 'P'}}
7785
let _ = Conforms<Y>.Decl5<X>.self // expected-error {{type 'Y' does not conform to protocol 'P'}}
7886

87+
extension Conforms: AssociatedType where T: P {}
88+
89+
let _ = Conforms<Y>.T.self // expected-error {{type 'Y' does not conform to protocol 'P'}}
90+
91+
let _ = Conforms<X>.T.self
92+
7993
// Now, even more nesting!
8094

8195
extension SameType.Decl1 {

0 commit comments

Comments
 (0)