Skip to content

Commit b756f76

Browse files
committed
Sema: Update 'can be represented in @objc' logic for subclass existentials
1 parent e4647bf commit b756f76

File tree

6 files changed

+72
-26
lines changed

6 files changed

+72
-26
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3093,7 +3093,11 @@ ERROR(function_type_no_parens,none,
30933093
NOTE(not_objc_empty_protocol_composition,none,
30943094
"'Any' is not considered '@objc'; use 'AnyObject' instead", ())
30953095
NOTE(not_objc_protocol,none,
3096-
"protocol %0 is not '@objc'", (Type))
3096+
"protocol-constrained type containing protocol %0 cannot be represented "
3097+
"in Objective-C", (Type))
3098+
NOTE(not_objc_class_constraint,none,
3099+
"protocol-constrained type containing class %0 cannot be represented "
3100+
"in Objective-C", (Type))
30973101
NOTE(not_objc_error_protocol_composition,none,
30983102
"protocol-constrained type containing 'Error' cannot be represented "
30993103
"in Objective-C", ())

lib/AST/Type.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2006,10 +2006,18 @@ getObjCObjectRepresentable(Type type, const DeclContext *dc) {
20062006
return ForeignRepresentableKind::Object;
20072007
}
20082008

2009-
// Objective-C existential types.
2010-
if (type->isObjCExistentialType())
2011-
return ForeignRepresentableKind::Object;
2012-
2009+
// Objective-C existential types are trivially representable if
2010+
// they don't have a superclass constraint, or if the superclass
2011+
// constraint is an @objc class.
2012+
if (type->isExistentialType()) {
2013+
auto layout = type->getExistentialLayout();
2014+
if (layout.isObjC() &&
2015+
(!layout.superclass ||
2016+
getObjCObjectRepresentable(layout.superclass, dc) ==
2017+
ForeignRepresentableKind::Object))
2018+
return ForeignRepresentableKind::Object;
2019+
}
2020+
20132021
// Any can be bridged to id.
20142022
if (type->isAny()) {
20152023
return ForeignRepresentableKind::Bridged;

lib/Sema/TypeCheckType.cpp

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3810,16 +3810,27 @@ void TypeChecker::diagnoseTypeNotRepresentableInObjC(const DeclContext *DC,
38103810

38113811
// Special diagnostic for protocols and protocol compositions.
38123812
if (T->isExistentialType()) {
3813-
SmallVector<ProtocolDecl *, 4> Protocols;
3814-
T->getExistentialTypeProtocols(Protocols);
3815-
if (Protocols.empty()) {
3813+
if (T->isAny()) {
38163814
// Any is not @objc.
38173815
diagnose(TypeRange.Start, diag::not_objc_empty_protocol_composition);
38183816
return;
38193817
}
3818+
3819+
auto layout = T->getExistentialLayout();
3820+
3821+
// See if the superclass is not @objc.
3822+
if (layout.superclass &&
3823+
!layout.superclass->getClassOrBoundGenericClass()->isObjC()) {
3824+
diagnose(TypeRange.Start, diag::not_objc_class_constraint,
3825+
layout.superclass);
3826+
return;
3827+
}
3828+
38203829
// Find a protocol that is not @objc.
38213830
bool sawErrorProtocol = false;
3822-
for (auto PD : Protocols) {
3831+
for (auto P : layout.getProtocols()) {
3832+
auto *PD = P->getDecl();
3833+
38233834
if (PD->isSpecificProtocol(KnownProtocolKind::Error)) {
38243835
sawErrorProtocol = true;
38253836
break;

test/attr/attr_ibaction.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,10 @@ protocol CP2 : class { }
7171
// Protocol types
7272
@IBAction func action7(_: P1) {} // expected-error{{argument to @IBAction method cannot have non-object type 'P1'}}
7373
// expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
74-
// expected-note@-2{{protocol 'P1' is not '@objc'}}
74+
// expected-note@-2{{protocol-constrained type containing protocol 'P1' cannot be represented in Objective-C}}
7575
@IBAction func action8(_: CP1) {} // expected-error{{argument to @IBAction method cannot have non-object type 'CP1'}}
7676
// expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}
77-
// expected-note@-2{{protocol 'CP1' is not '@objc'}}
77+
// expected-note@-2{{protocol-constrained type containing protocol 'CP1' cannot be represented in Objective-C}}
7878
@IBAction func action9(_: OP1) {}
7979
@IBAction func action10(_: P1?) {} // expected-error{{argument to @IBAction method cannot have non-object type}}
8080
// expected-error@-1{{method cannot be marked @IBAction because the type of the parameter cannot be represented in Objective-C}}

test/attr/attr_objc.swift

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -528,21 +528,21 @@ class subject_subscriptInvalid5 {
528528
class subject_subscriptInvalid6 {
529529
@objc
530530
subscript(a: PlainProtocol) -> Int { // expected-error {{subscript cannot be marked @objc because its type cannot be represented in Objective-C}}
531-
// expected-note@-1{{protocol 'PlainProtocol' is not '@objc'}}
531+
// expected-note@-1{{protocol-constrained type containing protocol 'PlainProtocol' cannot be represented in Objective-C}}
532532
get { return 0 }
533533
}
534534
}
535535
class subject_subscriptInvalid7 {
536536
@objc
537537
subscript(a: Protocol_Class1) -> Int { // expected-error {{subscript cannot be marked @objc because its type cannot be represented in Objective-C}}
538-
// expected-note@-1{{protocol 'Protocol_Class1' is not '@objc'}}
538+
// expected-note@-1{{protocol-constrained type containing protocol 'Protocol_Class1' cannot be represented in Objective-C}}
539539
get { return 0 }
540540
}
541541
}
542542
class subject_subscriptInvalid8 {
543543
@objc
544544
subscript(a: Protocol_Class1 & Protocol_Class2) -> Int { // expected-error {{subscript cannot be marked @objc because its type cannot be represented in Objective-C}}
545-
// expected-note@-1{{protocol 'Protocol_Class1' is not '@objc'}}
545+
// expected-note@-1{{protocol-constrained type containing protocol 'Protocol_Class1' cannot be represented in Objective-C}}
546546
get { return 0 }
547547
}
548548
}
@@ -641,7 +641,7 @@ class infer_instanceFunc1 {
641641

642642
@objc func func12_(a: PlainProtocol) {}
643643
// expected-error@-1 {{method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C}}
644-
// expected-note@-2 {{protocol 'PlainProtocol' is not '@objc'}}
644+
// expected-note@-2 {{protocol-constrained type containing protocol 'PlainProtocol' cannot be represented in Objective-C}}
645645

646646
func func13(a: Class_ObjC1) {}
647647
// CHECK-LABEL: @objc func func13(a: Class_ObjC1) {
@@ -653,7 +653,7 @@ class infer_instanceFunc1 {
653653

654654
@objc func func14_(a: Protocol_Class1) {}
655655
// expected-error@-1 {{method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C}}
656-
// expected-note@-2 {{protocol 'Protocol_Class1' is not '@objc'}}
656+
// expected-note@-2 {{protocol-constrained type containing protocol 'Protocol_Class1' cannot be represented in Objective-C}}
657657

658658
func func15(a: Protocol_ObjC1) {}
659659
// CHECK-LABEL: @objc func func15(a: Protocol_ObjC1) {
@@ -802,7 +802,7 @@ class infer_instanceVar1 {
802802

803803
@objc var (instanceVar1_, instanceVar2_): (Int, PlainProtocol)
804804
// expected-error@-1 {{property cannot be marked @objc because its type cannot be represented in Objective-C}}
805-
// expected-note@-2 {{protocol 'PlainProtocol' is not '@objc'}}
805+
// expected-note@-2 {{protocol-constrained type containing protocol 'PlainProtocol' cannot be represented in Objective-C}}
806806

807807
var intstanceVar4: Int {
808808
// CHECK: @objc var intstanceVar4: Int {
@@ -940,7 +940,7 @@ class infer_instanceVar1 {
940940

941941
@objc var var_PlainProtocol_: PlainProtocol
942942
// expected-error@-1 {{property cannot be marked @objc because its type cannot be represented in Objective-C}}
943-
// expected-note@-2 {{protocol 'PlainProtocol' is not '@objc'}}
943+
// expected-note@-2 {{protocol-constrained type containing protocol 'PlainProtocol' cannot be represented in Objective-C}}
944944

945945
var var_ClassObjC: Class_ObjC1
946946
// CHECK-LABEL: @objc var var_ClassObjC: Class_ObjC1
@@ -952,7 +952,7 @@ class infer_instanceVar1 {
952952

953953
@objc var var_ProtocolClass_: Protocol_Class1
954954
// expected-error@-1 {{property cannot be marked @objc because its type cannot be represented in Objective-C}}
955-
// expected-note@-2 {{protocol 'Protocol_Class1' is not '@objc'}}
955+
// expected-note@-2 {{protocol-constrained type containing protocol 'Protocol_Class1' cannot be represented in Objective-C}}
956956

957957
var var_ProtocolObjC: Protocol_ObjC1
958958
// CHECK-LABEL: @objc var var_ProtocolObjC: Protocol_ObjC1
@@ -1020,49 +1020,49 @@ class infer_instanceVar1 {
10201020

10211021
@objc var var_Existential1_: PlainProtocol
10221022
// expected-error@-1 {{property cannot be marked @objc because its type cannot be represented in Objective-C}}
1023-
// expected-note@-2 {{protocol 'PlainProtocol' is not '@objc'}}
1023+
// expected-note@-2 {{protocol-constrained type containing protocol 'PlainProtocol' cannot be represented in Objective-C}}
10241024

10251025
var var_Existential2: PlainProtocol & PlainProtocol
10261026
// CHECK-LABEL: {{^}} var var_Existential2: PlainProtocol
10271027

10281028
@objc var var_Existential2_: PlainProtocol & PlainProtocol
10291029
// expected-error@-1 {{property cannot be marked @objc because its type cannot be represented in Objective-C}}
1030-
// expected-note@-2 {{protocol 'PlainProtocol' is not '@objc'}}
1030+
// expected-note@-2 {{protocol-constrained type containing protocol 'PlainProtocol' cannot be represented in Objective-C}}
10311031

10321032
var var_Existential3: PlainProtocol & Protocol_Class1
10331033
// CHECK-LABEL: {{^}} var var_Existential3: PlainProtocol & Protocol_Class1
10341034

10351035
@objc var var_Existential3_: PlainProtocol & Protocol_Class1
10361036
// expected-error@-1 {{property cannot be marked @objc because its type cannot be represented in Objective-C}}
1037-
// expected-note@-2 {{protocol 'PlainProtocol' is not '@objc'}}
1037+
// expected-note@-2 {{protocol-constrained type containing protocol 'PlainProtocol' cannot be represented in Objective-C}}
10381038

10391039
var var_Existential4: PlainProtocol & Protocol_ObjC1
10401040
// CHECK-LABEL: {{^}} var var_Existential4: PlainProtocol & Protocol_ObjC1
10411041

10421042
@objc var var_Existential4_: PlainProtocol & Protocol_ObjC1
10431043
// expected-error@-1 {{property cannot be marked @objc because its type cannot be represented in Objective-C}}
1044-
// expected-note@-2 {{protocol 'PlainProtocol' is not '@objc'}}
1044+
// expected-note@-2 {{protocol-constrained type containing protocol 'PlainProtocol' cannot be represented in Objective-C}}
10451045

10461046
var var_Existential5: Protocol_Class1
10471047
// CHECK-LABEL: {{^}} var var_Existential5: Protocol_Class1
10481048

10491049
@objc var var_Existential5_: Protocol_Class1
10501050
// expected-error@-1 {{property cannot be marked @objc because its type cannot be represented in Objective-C}}
1051-
// expected-note@-2 {{protocol 'Protocol_Class1' is not '@objc'}}
1051+
// expected-note@-2 {{protocol-constrained type containing protocol 'Protocol_Class1' cannot be represented in Objective-C}}
10521052

10531053
var var_Existential6: Protocol_Class1 & Protocol_Class2
10541054
// CHECK-LABEL: {{^}} var var_Existential6: Protocol_Class1 & Protocol_Class2
10551055

10561056
@objc var var_Existential6_: Protocol_Class1 & Protocol_Class2
10571057
// expected-error@-1 {{property cannot be marked @objc because its type cannot be represented in Objective-C}}
1058-
// expected-note@-2 {{protocol 'Protocol_Class1' is not '@objc'}}
1058+
// expected-note@-2 {{protocol-constrained type containing protocol 'Protocol_Class1' cannot be represented in Objective-C}}
10591059

10601060
var var_Existential7: Protocol_Class1 & Protocol_ObjC1
10611061
// CHECK-LABEL: {{^}} var var_Existential7: Protocol_Class1 & Protocol_ObjC1
10621062

10631063
@objc var var_Existential7_: Protocol_Class1 & Protocol_ObjC1
10641064
// expected-error@-1 {{property cannot be marked @objc because its type cannot be represented in Objective-C}}
1065-
// expected-note@-2 {{protocol 'Protocol_Class1' is not '@objc'}}
1065+
// expected-note@-2 {{protocol-constrained type containing protocol 'Protocol_Class1' cannot be represented in Objective-C}}
10661066

10671067
var var_Existential8: Protocol_ObjC1
10681068
// CHECK-LABEL: @objc var var_Existential8: Protocol_ObjC1
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %target-typecheck-verify-swift -enable-experimental-subclass-existentials -disable-objc-attr-requires-foundation-module
2+
3+
@objc class ObjCClass {}
4+
@objc protocol ObjCProtocol {}
5+
6+
class SwiftClass {}
7+
protocol SwiftProtocol {}
8+
9+
class SomeMethods {
10+
11+
@objc
12+
func canRepresentInObjC(x: ObjCClass & ObjCProtocol) {}
13+
14+
@objc
15+
func cannotRepresentInObjC(x: SwiftClass & ObjCProtocol) {}
16+
// expected-error@-1 {{method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C}}
17+
// expected-note@-2 {{protocol-constrained type containing class 'SwiftClass' cannot be represented in Objective-C}}
18+
19+
@objc
20+
func alsoCannotRepresentInObjC(x: ObjCClass & SwiftProtocol) {}
21+
// expected-error@-1 {{method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C}}
22+
// expected-note@-2 {{protocol-constrained type containing protocol 'SwiftProtocol' cannot be represented in Objective-C}}
23+
}

0 commit comments

Comments
 (0)