Skip to content

Commit f2049df

Browse files
authored
Merge pull request #14665 from huonw/no-conditional-objc-generics-4.1
[4.1] [Sema] Disallow conditional conformances on objective-c generics.
2 parents 2bc8470 + f5329d9 commit f2049df

File tree

4 files changed

+66
-0
lines changed

4 files changed

+66
-0
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1420,6 +1420,10 @@ ERROR(objc_runtime_visible_cannot_conform_to_objc_protocol,none,
14201420
"class %0 cannot conform to @objc protocol %1 because "
14211421
"the class is only visible via the Objective-C runtime",
14221422
(Type, Type))
1423+
ERROR(objc_generics_cannot_conditionally_conform,none,
1424+
"type %0 cannot conditionally conform to protocol %1 because "
1425+
"the type uses the Objective-C generics model",
1426+
(Type, Type))
14231427
ERROR(protocol_has_missing_requirements,none,
14241428
"type %0 cannot conform to protocol %1 because it has requirements that "
14251429
"cannot be satisfied", (Type, Type))

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,27 @@ checkIndividualConformance(NormalProtocolConformance *conformance,
13131313
}
13141314
}
13151315

1316+
// Not every protocol/type is compatible with conditional conformances.
1317+
if (!conformance->getConditionalRequirements().empty()) {
1318+
auto nestedType = canT;
1319+
// Obj-C generics cannot be looked up at runtime, so we don't support
1320+
// conditional conformances involving them. Check the full stack of nested
1321+
// types for any obj-c ones.
1322+
while (nestedType) {
1323+
if (auto clas = nestedType->getClassOrBoundGenericClass()) {
1324+
if (clas->usesObjCGenericsModel()) {
1325+
TC.diagnose(ComplainLoc,
1326+
diag::objc_generics_cannot_conditionally_conform, T,
1327+
Proto->getDeclaredType());
1328+
conformance->setInvalid();
1329+
return conformance;
1330+
}
1331+
}
1332+
1333+
nestedType = nestedType.getNominalParent();
1334+
}
1335+
}
1336+
13161337
// If the protocol contains missing requirements, it can't be conformed to
13171338
// at all.
13181339
if (Proto->hasMissingRequirements()) {
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
@import Foundation;
2+
3+
@interface ObjC <ObjectType>: NSObject
4+
@end
5+
6+
@interface ObjC2: NSObject
7+
@end
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: %target-typecheck-verify-swift -import-objc-header %S/Inputs/conditional_conformances_objc.h
2+
3+
// REQUIRES: objc_interop
4+
5+
protocol Foo {}
6+
extension ObjC: Foo where ObjectType == ObjC2 {}
7+
// expected-error@-1{{type 'ObjC<ObjectType>' cannot conditionally conform to protocol 'Foo' because the type uses the Objective-C generics model}}
8+
9+
protocol Bar {}
10+
extension ObjC: Bar where ObjectType: Bar {}
11+
// expected-error@-1{{type 'ObjC<ObjectType>' cannot conditionally conform to protocol 'Bar' because the type uses the Objective-C generics model}}
12+
13+
extension ObjC {
14+
struct Struct {
15+
enum Enum {}
16+
}
17+
class Class<T> {}
18+
}
19+
20+
extension ObjC.Struct: Foo where ObjectType == ObjC2 {}
21+
// expected-error@-1{{type 'ObjC<ObjectType>.Struct' cannot conditionally conform to protocol 'Foo' because the type uses the Objective-C generics model}}
22+
extension ObjC.Struct: Bar where ObjectType: Bar {}
23+
// expected-error@-1{{type 'ObjC<ObjectType>.Struct' cannot conditionally conform to protocol 'Bar' because the type uses the Objective-C generics model}}
24+
25+
extension ObjC.Struct.Enum: Foo where ObjectType == ObjC2 {}
26+
// expected-error@-1{{type 'ObjC<ObjectType>.Struct.Enum' cannot conditionally conform to protocol 'Foo' because the type uses the Objective-C generics model}}
27+
extension ObjC.Struct.Enum: Bar where ObjectType: Bar {}
28+
// expected-error@-1{{type 'ObjC<ObjectType>.Struct.Enum' cannot conditionally conform to protocol 'Bar' because the type uses the Objective-C generics model}}
29+
30+
extension ObjC.Class: Foo where T == ObjC2 {}
31+
// expected-error@-1{{type 'ObjC<ObjectType>.Class<T>' cannot conditionally conform to protocol 'Foo' because the type uses the Objective-C generics model}}
32+
extension ObjC.Class: Bar where T: Bar {}
33+
// expected-error@-1{{type 'ObjC<ObjectType>.Class<T>' cannot conditionally conform to protocol 'Bar' because the type uses the Objective-C generics model}}
34+

0 commit comments

Comments
 (0)