Skip to content

Commit 6903e71

Browse files
committed
Sema: Diagnose unsupported existential types in more places
Fixes <rdar://problem/23427259>, <https://bugs.swift.org/browse/SR-4207>.
1 parent 14a3a5d commit 6903e71

File tree

6 files changed

+90
-10
lines changed

6 files changed

+90
-10
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3283,6 +3283,17 @@ class UnsupportedProtocolVisitor
32833283
});
32843284
}
32853285
}
3286+
3287+
void visitRequirements(ArrayRef<RequirementRepr> reqts) {
3288+
for (auto reqt : reqts) {
3289+
if (reqt.getKind() == RequirementReprKind::SameType) {
3290+
if (auto *repr = reqt.getFirstTypeLoc().getTypeRepr())
3291+
repr->walk(*this);
3292+
if (auto *repr = reqt.getSecondTypeLoc().getTypeRepr())
3293+
repr->walk(*this);
3294+
}
3295+
}
3296+
}
32863297
};
32873298

32883299
} // end anonymous namespace
@@ -3291,12 +3302,22 @@ void TypeChecker::checkUnsupportedProtocolType(Decl *decl) {
32913302
if (!decl || decl->isInvalid())
32923303
return;
32933304

3294-
// Type declarations are okay.
3295-
if (isa<TypeDecl>(decl))
3296-
return;
3297-
3298-
// Extensions are okay.
3299-
if (isa<ExtensionDecl>(decl))
3305+
if (auto *protocolDecl = dyn_cast<ProtocolDecl>(decl))
3306+
checkUnsupportedProtocolType(protocolDecl->getTrailingWhereClause());
3307+
else if (auto *genericDecl = dyn_cast<GenericTypeDecl>(decl))
3308+
checkUnsupportedProtocolType(genericDecl->getGenericParams());
3309+
else if (auto *assocType = dyn_cast<AssociatedTypeDecl>(decl))
3310+
checkUnsupportedProtocolType(assocType->getTrailingWhereClause());
3311+
else if (auto *extDecl = dyn_cast<ExtensionDecl>(decl))
3312+
checkUnsupportedProtocolType(extDecl->getTrailingWhereClause());
3313+
else if (auto *subscriptDecl = dyn_cast<SubscriptDecl>(decl))
3314+
checkUnsupportedProtocolType(subscriptDecl->getGenericParams());
3315+
else if (auto *funcDecl = dyn_cast<AbstractFunctionDecl>(decl)) {
3316+
if (!isa<AccessorDecl>(funcDecl))
3317+
checkUnsupportedProtocolType(funcDecl->getGenericParams());
3318+
}
3319+
3320+
if (isa<TypeDecl>(decl) || isa<ExtensionDecl>(decl))
33003321
return;
33013322

33023323
UnsupportedProtocolVisitor visitor(*this, /*checkStatements=*/false);
@@ -3310,3 +3331,19 @@ void TypeChecker::checkUnsupportedProtocolType(Stmt *stmt) {
33103331
UnsupportedProtocolVisitor visitor(*this, /*checkStatements=*/true);
33113332
stmt->walk(visitor);
33123333
}
3334+
3335+
void TypeChecker::checkUnsupportedProtocolType(TrailingWhereClause *whereClause) {
3336+
if (whereClause == nullptr)
3337+
return;
3338+
3339+
UnsupportedProtocolVisitor visitor(*this, /*checkStatements=*/false);
3340+
visitor.visitRequirements(whereClause->getRequirements());
3341+
}
3342+
3343+
void TypeChecker::checkUnsupportedProtocolType(GenericParamList *genericParams) {
3344+
if (genericParams == nullptr)
3345+
return;
3346+
3347+
UnsupportedProtocolVisitor visitor(*this, /*checkStatements=*/false);
3348+
visitor.visitRequirements(genericParams->getRequirements());
3349+
}

lib/Sema/TypeChecker.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -870,6 +870,14 @@ class TypeChecker final : public LazyResolver {
870870
/// Check for unsupported protocol types in the given statement.
871871
void checkUnsupportedProtocolType(Stmt *stmt);
872872

873+
/// Check for unsupported protocol types in the given generic requirement
874+
/// list.
875+
void checkUnsupportedProtocolType(TrailingWhereClause *whereClause);
876+
877+
/// Check for unsupported protocol types in the given generic requirement
878+
/// list.
879+
void checkUnsupportedProtocolType(GenericParamList *genericParams);
880+
873881
/// Expose TypeChecker's handling of GenericParamList to SIL parsing.
874882
GenericEnvironment *handleSILGenericParams(GenericParamList *genericParams,
875883
DeclContext *DC);

test/Constraints/same_types.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,9 +303,9 @@ func testSameTypeCommutativity4<U, T>(_ t: T, _ u: U)
303303
// expected-error@-1{{same-type requirement makes generic parameter 'T' non-generic}}
304304

305305
func testSameTypeCommutativity5<U, T: P1>(_ t: T, _ u: U)
306-
where P1 & P2 == T.Assoc { } // Ok, equivalent to T.Assoc == P1 & P2
306+
where PPP & P3 == T.Assoc { } // Ok, equivalent to T.Assoc == PPP & P3
307307

308308
// FIXME: Error emitted twice.
309309
func testSameTypeCommutativity6<U, T: P1>(_ t: T, _ u: U)
310-
where U & P2 == T.Assoc { } // Equivalent to T.Assoc == U & P2
310+
where U & P3 == T.Assoc { } // Equivalent to T.Assoc == U & P3
311311
// expected-error@-1 2 {{non-protocol, non-class type 'U' cannot be used within a protocol-constrained type}}

test/IDE/print_synthesized_extensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ public extension P1 where T1 : P2 {
4646
public func ef2(t : T2) {}
4747
}
4848

49-
public extension P1 where T1 == P2, T2 : P3 {
49+
public extension P1 where T1 == P3, T2 : P3 {
5050
public func ef3(t : T1) {}
5151
public func ef4(t : T1) {}
5252
}

test/SourceKit/InterfaceGen/Inputs/swift_mod_syn.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public extension P1 where T1 : P2 {
2121
public func ef2(t : T2) {}
2222
}
2323

24-
public extension P1 where T1 == P2, T2 : P3 {
24+
public extension P1 where T1 == P3, T2 : P3 {
2525
public func ef3(t : T1) {}
2626
public func ef4(t : T1) {}
2727
}

test/type/protocol_types.swift

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,38 @@ struct Outer {
103103
typealias X = Struct1<Pub & Bar>
104104
_ = Struct1<Pub & Bar>.self
105105

106+
typealias BadAlias<T> = T
107+
where T : HasAssoc, T.Assoc == HasAssoc
108+
// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}}
109+
110+
struct BadStruct<T>
111+
where T : HasAssoc,
112+
T.Assoc == HasAssoc {}
113+
// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}}
114+
115+
protocol BadProtocol where T == HasAssoc {
116+
// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}}
117+
associatedtype T
118+
119+
associatedtype U : HasAssoc
120+
where U.Assoc == HasAssoc
121+
// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}}
122+
}
123+
124+
extension HasAssoc where Assoc == HasAssoc {}
125+
// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}}
126+
127+
func badFunction<T>(_: T)
128+
where T : HasAssoc,
129+
T.Assoc == HasAssoc {}
130+
// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}}
131+
132+
struct BadSubscript {
133+
subscript<T>(_: T) -> Int
134+
where T : HasAssoc,
135+
T.Assoc == HasAssoc {
136+
// expected-error@-1 {{protocol 'HasAssoc' can only be used as a generic constraint because it has Self or associated type requirements}}
137+
get {}
138+
set {}
139+
}
140+
}

0 commit comments

Comments
 (0)