Skip to content

Commit 6d1b8d4

Browse files
committed
[TypeResolution] Diagnose invalid dependent member types of existential
types.
1 parent 268f6e2 commit 6d1b8d4

File tree

2 files changed

+30
-2
lines changed

2 files changed

+30
-2
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ Type TypeResolution::resolveDependentMemberType(
126126
// FIXME(ModQual): Reject qualified names immediately; they cannot be
127127
// dependent member types.
128128
Identifier refIdentifier = ref->getNameRef().getBaseIdentifier();
129+
ASTContext &ctx = DC->getASTContext();
129130

130131
switch (stage) {
131132
case TypeResolutionStage::Structural:
@@ -146,8 +147,6 @@ Type TypeResolution::resolveDependentMemberType(
146147
// Record the type we found.
147148
ref->setValue(nestedType, nullptr);
148149
} else {
149-
ASTContext &ctx = DC->getASTContext();
150-
151150
// Resolve the base to a potential archetype.
152151
// Perform typo correction.
153152
TypoCorrectionResults corrections(ref->getNameRef(), ref->getNameLoc());
@@ -188,6 +187,25 @@ Type TypeResolution::resolveDependentMemberType(
188187

189188
auto *concrete = ref->getBoundDecl();
190189

190+
if (auto concreteBase = genericSig->getConcreteType(baseTy)) {
191+
bool hasUnboundOpener = !!getUnboundTypeOpener();
192+
switch (TypeChecker::isUnsupportedMemberTypeAccess(concreteBase, concrete,
193+
hasUnboundOpener)) {
194+
case TypeChecker::UnsupportedMemberTypeAccessKind::TypeAliasOfExistential:
195+
ctx.Diags.diagnose(ref->getNameLoc(),
196+
diag::typealias_outside_of_protocol,
197+
ref->getNameRef(), concreteBase);
198+
break;
199+
case TypeChecker::UnsupportedMemberTypeAccessKind::AssociatedTypeOfExistential:
200+
ctx.Diags.diagnose(ref->getNameLoc(),
201+
diag::assoc_type_outside_of_protocol,
202+
ref->getNameRef(), concreteBase);
203+
break;
204+
default:
205+
break;
206+
};
207+
}
208+
191209
// If the nested type has been resolved to an associated type, use it.
192210
if (auto assocType = dyn_cast<AssociatedTypeDecl>(concrete)) {
193211
return DependentMemberType::get(baseTy, assocType);

test/decl/typealias/protocol.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,16 @@ struct T5 : P5 {
189189

190190
var v8 = P6.A.self
191191
var v9 = P6.B.self // expected-error {{cannot access type alias 'B' from 'P6'; use a concrete type or generic parameter base instead}}
192+
193+
struct Generic<T> {
194+
func okay(value: T.A) where T == any P6 {}
195+
196+
func invalid1(value: T.B) where T == any P6 {}
197+
// expected-error@-1 {{cannot access type alias 'B' from 'any P6'; use a concrete type or generic parameter base instead}}
198+
199+
func invalid2(value: T.A) where T == any P5 {}
200+
// expected-error@-1 {{cannot access associated type 'A' from 'any P5'; use a concrete type or generic parameter base instead}}
201+
}
192202
}
193203

194204
// Unqualified lookup finds typealiases in protocol extensions

0 commit comments

Comments
 (0)