Skip to content

Commit 4f00d34

Browse files
committed
Merge pull request #2885 from gregomni/more-typealias
[Sema] Make typealiases in protocols available for nested type lookup.
2 parents 7a736cc + f2aaf41 commit 4f00d34

File tree

4 files changed

+47
-9
lines changed

4 files changed

+47
-9
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,6 +1347,9 @@ NOTE(optional_req_near_match_accessibility,none,
13471347
// Protocols and existentials
13481348
ERROR(assoc_type_outside_of_protocol,none,
13491349
"cannot use associated type %0 outside of its protocol", (Identifier))
1350+
ERROR(typealias_to_assoc_type_outside_of_protocol,none,
1351+
"cannot use typealias %0 of associated type %1 outside of its protocol",
1352+
(Identifier, TypeLoc))
13501353

13511354
ERROR(circular_protocol_def,none,
13521355
"circular protocol inheritance %0", (StringRef))

lib/Sema/TypeCheckNameLookup.cpp

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -362,17 +362,22 @@ LookupTypeResult TypeChecker::lookupMemberType(DeclContext *dc,
362362
}
363363
}
364364

365-
// Ignore typealiases found in protocol members.
366-
if (auto alias = dyn_cast<TypeAliasDecl>(typeDecl)) {
367-
auto aliasParent = alias->getParent();
368-
if (aliasParent != dc && isa<ProtocolDecl>(aliasParent))
369-
continue;
370-
}
371-
372365
// Substitute the base into the member's type.
373366
if (Type memberType = substMemberTypeWithBase(dc->getParentModule(),
374367
typeDecl, type,
375368
/*isTypeReference=*/true)) {
369+
370+
// Similar to the associated type case, ignore typealiases containing
371+
// associated types when looking into a non-protocol.
372+
if (auto alias = dyn_cast<TypeAliasDecl>(typeDecl)) {
373+
auto parentProtocol = alias->getDeclContext()->
374+
getAsProtocolOrProtocolExtensionContext();
375+
if (parentProtocol && memberType->hasTypeParameter() &&
376+
!type->is<ArchetypeType>() && !type->isExistentialType()) {
377+
continue;
378+
}
379+
}
380+
376381
// If we haven't seen this type result yet, add it to the result set.
377382
if (types.insert(memberType->getCanonicalType()).second)
378383
result.Results.push_back({typeDecl, memberType});

lib/Sema/TypeCheckType.cpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1154,13 +1154,22 @@ static Type resolveNestedIdentTypeComponent(
11541154
member = memberTypes.back().first;
11551155
}
11561156

1157-
if (parentTy->isExistentialType()) {
1157+
if (parentTy->isExistentialType() && isa<AssociatedTypeDecl>(member)) {
11581158
if (diagnoseErrors)
11591159
TC.diagnose(comp->getIdLoc(), diag::assoc_type_outside_of_protocol,
11601160
comp->getIdentifier());
11611161

11621162
return ErrorType::get(TC.Context);
11631163
}
1164+
if (auto alias = dyn_cast<TypeAliasDecl>(member)) {
1165+
if (parentTy->isExistentialType() && memberType->hasTypeParameter()) {
1166+
if (diagnoseErrors)
1167+
TC.diagnose(comp->getIdLoc(), diag::typealias_to_assoc_type_outside_of_protocol,
1168+
comp->getIdentifier(), alias->getUnderlyingTypeLoc());
1169+
1170+
return ErrorType::get(TC.Context);
1171+
}
1172+
}
11641173

11651174
// If there are generic arguments, apply them now.
11661175
if (auto genComp = dyn_cast<GenericIdentTypeRepr>(comp))
@@ -3243,10 +3252,18 @@ class UnsupportedProtocolVisitor
32433252
}
32443253

32453254
bool walkToTypeReprPre(TypeRepr *T) {
3255+
if (T->isInvalid())
3256+
return false;
3257+
if (auto compound = dyn_cast<CompoundIdentTypeRepr>(T)) {
3258+
// Only visit the last component to check, because nested typealiases in
3259+
// existentials are okay.
3260+
visit(compound->getComponentRange().back());
3261+
return false;
3262+
}
32463263
visit(T);
32473264
return true;
32483265
}
3249-
3266+
32503267
std::pair<bool, Stmt*> walkToStmtPre(Stmt *S) {
32513268
if (recurseIntoSubstatements) {
32523269
return { true, S };

test/decl/typealias/typealias.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,4 +248,17 @@ protocol P4 {
248248
func getSelf() -> X
249249
}
250250

251+
// Availability of typealiases in protocols for nested type lookup
252+
protocol P5 {
253+
associatedtype A
254+
typealias T1 = Int
255+
typealias T2 = A
256+
var a: T2 { get }
257+
}
258+
259+
struct T5 : P5 {
260+
var a: P5.T1 // OK
261+
var v2: P5.T2 // expected-error {{cannot use typealias 'T2' of associated type 'A' outside of its protocol}}
262+
}
263+
251264

0 commit comments

Comments
 (0)