@@ -113,10 +113,10 @@ func protocol_concrete_casts(_ p1: P1, p2: P2, p12: P1 & P2) {
113113
114114 _ = p2 as! S1 // expected-warning {{cast from 'P2' to unrelated type 'S1' always fails}}
115115
116- _ = p12 as! S1
117- _ = p12 as! S2
116+ _ = p12 as! S1 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S1' always fails}}
117+ _ = p12 as! S2 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S2' always fails}}
118118 _ = p12 as! S12
119- _ = p12 as! S3
119+ _ = p12 as! S3 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S3' always fails}}
120120
121121 // Type queries.
122122 var _: Bool = p1 is S1
@@ -128,10 +128,10 @@ func protocol_concrete_casts(_ p1: P1, p2: P2, p12: P1 & P2) {
128128
129129 var _: Bool = p2 is S1 // expected-warning {{cast from 'P2' to unrelated type 'S1' always fails}}
130130
131- var _: Bool = p12 is S1
132- var _: Bool = p12 is S2
131+ var _: Bool = p12 is S1 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S1' always fails}}
132+ var _: Bool = p12 is S2 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S2' always fails}}
133133 var _: Bool = p12 is S12
134- var _: Bool = p12 is S3
134+ var _: Bool = p12 is S3 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S3' always fails}}
135135}
136136
137137func conditional_cast( _ b: B ) -> D ? {
@@ -372,6 +372,26 @@ enum ConcreteA: EventA {
372372 }
373373}
374374
375+ protocol ProtocolP1 { }
376+ protocol ProtocolQ1 { }
377+ typealias Composition = ProtocolP1 & ProtocolQ1
378+
379+ protocol ProtocolP { }
380+ protocol ProtocolQ { }
381+
382+ class ConcreteP : ProtocolP { }
383+ class ConcreteQ : ProtocolQ { }
384+ class ConcretePQ : ProtocolP , ProtocolQ { }
385+ class ConcreteCPQ : ConcreteP , ProtocolQ { }
386+
387+ class ConcreteP1 : ProtocolP1 { }
388+ class ConcretePQ1 : ProtocolP1 , ProtocolQ1 { }
389+
390+ class ConcretePPQ1 : ProtocolP , ProtocolP1 , ProtocolQ1 { }
391+ class NotConforms { }
392+ struct StructNotComforms { }
393+ final class NotConformsFinal { }
394+
375395func tests_SR13088_false_positive_always_fail_casts( ) {
376396 // SR-13081
377397 let x : JSON = [ 4 ] // [4]
@@ -403,3 +423,20 @@ func tests_SR13088_false_positive_always_fail_casts() {
403423 }
404424 }
405425}
426+
427+ // Protocol composition
428+ func protocol_composition( _ c: ProtocolP & ProtocolQ , _ c1: ProtocolP & Composition ) {
429+ _ = c as? ConcretePQ // Ok
430+ _ = c as? ConcreteCPQ // Ok
431+ _ = c as? ConcreteP // Ok
432+ _ = c as? NotConforms // Ok
433+ _ = c as? StructNotComforms // expected-warning {{cast from 'ProtocolP & ProtocolQ' to unrelated type 'StructNotComforms' always fails}}
434+ _ = c as? NotConformsFinal // expected-warning {{cast from 'ProtocolP & ProtocolQ' to unrelated type 'NotConformsFinal' always fails}}
435+ _ = c1 as? ConcreteP // Ok
436+ _ = c1 as? ConcreteP1 // OK
437+ _ = c1 as? ConcretePQ1 // OK
438+ _ = c1 as? ConcretePPQ1 // Ok
439+ _ = c1 as? NotConforms // Ok
440+ _ = c1 as? StructNotComforms // expected-warning {{cast from 'ProtocolP & Composition' (aka 'ProtocolP & ProtocolP1 & ProtocolQ1') to unrelated type 'StructNotComforms' always fails}}
441+ _ = c1 as? NotConformsFinal // expected-warning {{cast from 'ProtocolP & Composition' (aka 'ProtocolP & ProtocolP1 & ProtocolQ1') to unrelated type 'NotConformsFinal' always fails}}
442+ }
0 commit comments