mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
473 lines
18 KiB
Swift
473 lines
18 KiB
Swift
// RUN: %target-typecheck-verify-swift -enable-objc-interop
|
|
|
|
class B {
|
|
init() {}
|
|
}
|
|
class D : B {
|
|
override init() { super.init() }
|
|
}
|
|
|
|
var seven : Double = 7
|
|
|
|
var pair : (Int, Double) = (1, 2)
|
|
|
|
var closure : (Int, Int) -> Int = { $0 + $1 }
|
|
|
|
var d_as_b : B = D()
|
|
var b_as_d = B() as! D
|
|
var bad_b_as_d : D = B() // expected-error{{cannot convert value of type 'B' to specified type 'D'}}
|
|
|
|
var d = D()
|
|
var b = B()
|
|
|
|
var d_as_b_2 : B = d
|
|
var b_as_d_2 = b as! D
|
|
|
|
var b_is_d:Bool = B() is D
|
|
// FIXME: Poor diagnostic below.
|
|
var bad_d_is_b:Bool = D() is B // expected-warning{{always true}}
|
|
|
|
func base_class_archetype_casts<T : B>(_ t: T) {
|
|
var _ : B = t
|
|
_ = B() as! T
|
|
var _ : T = B() // expected-error{{cannot convert value of type 'B' to specified type 'T'}}
|
|
|
|
let b = B()
|
|
|
|
_ = b as! T
|
|
|
|
var _:Bool = B() is T
|
|
var _:Bool = b is T
|
|
var _:Bool = t is B // expected-warning{{always true}}
|
|
|
|
_ = t as! D
|
|
}
|
|
|
|
protocol P1 { func p1() }
|
|
protocol P2 { func p2() }
|
|
|
|
struct S1 : P1 {
|
|
func p1() {}
|
|
}
|
|
class C1 : P1 {
|
|
func p1() {}
|
|
}
|
|
class D1 : C1 {}
|
|
|
|
struct S2 : P2 {
|
|
func p2() {}
|
|
}
|
|
|
|
struct S3 {}
|
|
|
|
struct S12 : P1, P2 {
|
|
func p1() {}
|
|
func p2() {}
|
|
}
|
|
|
|
func protocol_archetype_casts<T : P1>(_ t: T, p1: P1, p2: P2, p12: P1 & P2) {
|
|
// Coercions.
|
|
var _ : P1 = t
|
|
var _ : P2 = t // expected-error{{value of type 'T' does not conform to specified type 'P2'}}
|
|
|
|
// Checked unconditional casts.
|
|
_ = p1 as! T
|
|
_ = p2 as! T
|
|
_ = p12 as! T
|
|
|
|
_ = t as! S1
|
|
_ = t as! S12
|
|
_ = t as! C1
|
|
_ = t as! D1
|
|
|
|
_ = t as! S2
|
|
|
|
_ = S1() as! T
|
|
_ = S12() as! T
|
|
_ = C1() as! T
|
|
_ = D1() as! T
|
|
|
|
_ = S2() as! T
|
|
|
|
// Type queries.
|
|
var _:Bool = p1 is T
|
|
var _:Bool = p2 is T
|
|
var _:Bool = p12 is T
|
|
|
|
var _:Bool = t is S1
|
|
var _:Bool = t is S12
|
|
var _:Bool = t is C1
|
|
var _:Bool = t is D1
|
|
|
|
var _:Bool = t is S2
|
|
}
|
|
|
|
func protocol_concrete_casts(_ p1: P1, p2: P2, p12: P1 & P2) {
|
|
// Checked unconditional casts.
|
|
_ = p1 as! S1
|
|
_ = p1 as! C1
|
|
_ = p1 as! D1
|
|
_ = p1 as! S12
|
|
|
|
_ = p1 as! P1 & P2
|
|
|
|
_ = p2 as! S1 // expected-warning {{cast from 'P2' to unrelated type 'S1' always fails}}
|
|
|
|
_ = p12 as! S1 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S1' always fails}}
|
|
_ = p12 as! S2 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S2' always fails}}
|
|
_ = p12 as! S12
|
|
_ = p12 as! S3 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S3' always fails}}
|
|
|
|
// Type queries.
|
|
var _:Bool = p1 is S1
|
|
var _:Bool = p1 is C1
|
|
var _:Bool = p1 is D1
|
|
var _:Bool = p1 is S12
|
|
|
|
var _:Bool = p1 is P1 & P2
|
|
|
|
var _:Bool = p2 is S1 // expected-warning {{cast from 'P2' to unrelated type 'S1' always fails}}
|
|
|
|
var _:Bool = p12 is S1 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S1' always fails}}
|
|
var _:Bool = p12 is S2 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S2' always fails}}
|
|
var _:Bool = p12 is S12
|
|
var _:Bool = p12 is S3 // expected-warning {{cast from 'P1 & P2' to unrelated type 'S3' always fails}}
|
|
}
|
|
|
|
func conditional_cast(_ b: B) -> D? {
|
|
return b as? D
|
|
}
|
|
|
|
@objc protocol ObjCProto1 {}
|
|
@objc protocol ObjCProto2 {}
|
|
protocol NonObjCProto : class {}
|
|
|
|
@objc class ObjCClass {}
|
|
class NonObjCClass {}
|
|
|
|
func objc_protocol_casts(_ op1: ObjCProto1, opn: NonObjCProto) {
|
|
_ = ObjCClass() as! ObjCProto1
|
|
_ = ObjCClass() as! ObjCProto2
|
|
_ = ObjCClass() as! ObjCProto1 & ObjCProto2
|
|
_ = ObjCClass() as! NonObjCProto
|
|
_ = ObjCClass() as! ObjCProto1 & NonObjCProto
|
|
|
|
_ = op1 as! ObjCProto1 & ObjCProto2
|
|
_ = op1 as! ObjCProto2
|
|
_ = op1 as! ObjCProto1 & NonObjCProto
|
|
_ = opn as! ObjCProto1
|
|
|
|
_ = NonObjCClass() as! ObjCProto1
|
|
}
|
|
|
|
func dynamic_lookup_cast(_ dl: AnyObject) {
|
|
_ = dl as! ObjCProto1
|
|
_ = dl as! ObjCProto2
|
|
_ = dl as! ObjCProto1 & ObjCProto2
|
|
}
|
|
|
|
// Cast to subclass with generic parameter inference
|
|
class C2<T> : B { }
|
|
class C3<T> : C2<[T]> {
|
|
func f(_ x: T) { }
|
|
}
|
|
var c2i : C2<[Int]> = C3()
|
|
var c3iOpt = c2i as? C3
|
|
c3iOpt?.f(5)
|
|
var b1 = c2i is C3
|
|
var c2f: C2<Float>? = b as? C2
|
|
var c2f2: C2<[Float]>? = b as! C3
|
|
|
|
|
|
// <rdar://problem/15633178>
|
|
var f: (Float) -> Float = { $0 as Float }
|
|
var f2: (B) -> Bool = { $0 is D }
|
|
|
|
func metatype_casts<T, U>(_ b: B.Type, t:T.Type, u: U.Type) {
|
|
_ = b is D.Type
|
|
_ = T.self is U.Type
|
|
_ = type(of: T.self) is U.Type.Type
|
|
_ = type(of: b) is D.Type // expected-warning{{always fails}}
|
|
_ = b is D.Type.Type // expected-warning{{always fails}}
|
|
|
|
}
|
|
|
|
// <rdar://problem/17017851>
|
|
func forcedDowncastToOptional(_ b: B) {
|
|
var dOpt: D? = b as! D // expected-warning{{treating a forced downcast to 'D' as optional will never produce 'nil'}}
|
|
// expected-note@-1{{use 'as?' to perform a conditional downcast to 'D'}}{{22-23=?}}
|
|
// expected-note@-2{{add parentheses around the cast to silence this warning}}{{18-18=(}}{{25-25=)}}
|
|
dOpt = b as! D // expected-warning{{treating a forced downcast to 'D' as optional will never produce 'nil'}}
|
|
// expected-note@-1{{use 'as?' to perform a conditional downcast to 'D'}}{{14-15=?}}
|
|
// expected-note@-2{{add parentheses around the cast to silence this warning}}{{10-10=(}}{{17-17=)}}
|
|
dOpt = (b as! D)
|
|
_ = dOpt
|
|
}
|
|
|
|
_ = b1 as Int // expected-error {{cannot convert value of type 'Bool' to type 'Int' in coercion}}
|
|
_ = seven as Int // expected-error {{cannot convert value of type 'Double' to type 'Int' in coercion}}
|
|
|
|
func rdar29894174(v: B?) {
|
|
let _ = [v].compactMap { $0 as? D }
|
|
}
|
|
|
|
// When re-typechecking a solution with an 'is' cast applied,
|
|
// we would fail to produce a diagnostic.
|
|
func process(p: Any?) {
|
|
compare(p is String)
|
|
// expected-error@-1 {{missing argument for parameter #2 in call}} {{22-22=, <#Bool#>}}
|
|
}
|
|
|
|
func compare<T>(_: T, _: T) {} // expected-note {{'compare' declared here}}
|
|
func compare<T>(_: T?, _: T?) {}
|
|
|
|
_ = nil? as? Int?? // expected-error {{'nil' requires a contextual type}}
|
|
|
|
func test_tuple_casts_no_warn() {
|
|
struct Foo {}
|
|
|
|
let arr: [(Any, Any)] = [(Foo(), Foo())]
|
|
let tup: (Any, Any) = (Foo(), Foo())
|
|
|
|
_ = arr as! [(Foo, Foo)] // Ok
|
|
_ = tup as! (Foo, Foo) // Ok
|
|
|
|
_ = arr as! [(Foo, Foo, Foo)] // Ok
|
|
_ = tup as! (Foo, Foo, Foo) // expected-warning {{cast from '(Any, Any)' to unrelated type '(Foo, Foo, Foo)' always fails}}
|
|
|
|
_ = arr as! [(a: Foo, Foo)] // Ok
|
|
_ = tup as! (a: Foo, Foo) // Ok
|
|
}
|
|
|
|
infix operator ^^^
|
|
func ^^^ <T> (lhs: T?, rhs: @autoclosure () -> T) -> T { lhs! }
|
|
func ^^^ <T> (lhs: T?, rhs: @autoclosure () -> T?) -> T? { lhs! }
|
|
|
|
func ohno<T>(_ x: T) -> T? { nil }
|
|
|
|
// SR-12369: Make sure we don't drop the coercion constraint.
|
|
func test_coercions_with_overloaded_operator(str: String, optStr: String?, veryOptString: String????) {
|
|
_ = (str ?? "") as String // expected-warning {{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}}
|
|
_ = (optStr ?? "") as String
|
|
|
|
_ = (str ?? "") as Int // expected-error {{cannot convert value of type 'String' to type 'Int' in coercion}}
|
|
_ = (optStr ?? "") as Int // expected-error {{cannot convert value of type 'String' to type 'Int' in coercion}}
|
|
_ = (optStr ?? "") as Int? // expected-error {{'String' is not convertible to 'Int?'}}
|
|
// expected-note@-1 {{did you mean to use 'as!' to force downcast?}} {{22-24=as!}}
|
|
|
|
_ = (str ^^^ "") as Int // expected-error {{cannot convert value of type 'String' to type 'Int' in coercion}}
|
|
_ = (optStr ^^^ "") as Int // expected-error {{cannot convert value of type 'String' to type 'Int' in coercion}}
|
|
_ = (optStr ^^^ "") as Int? // expected-error {{'String' is not convertible to 'Int?'}}
|
|
// expected-note@-1 {{did you mean to use 'as!' to force downcast?}} {{23-25=as!}}
|
|
|
|
_ = ([] ?? []) as String // expected-error {{cannot convert value of type '[Any]' to type 'String' in coercion}}
|
|
_ = ([""] ?? []) as [Int: Int] // expected-error {{cannot convert value of type '[String]' to type '[Int : Int]' in coercion}}
|
|
_ = (["": ""] ?? [:]) as [Int] // expected-error {{cannot convert value of type '[String : String]' to type '[Int]' in coercion}}
|
|
_ = (["": ""] ?? [:]) as Set<Int> // expected-error {{cannot convert value of type '[String : String]' to type 'Set<Int>' in coercion}}
|
|
_ = (["": ""] ?? [:]) as Int? // expected-error {{cannot convert value of type '[String : String]' to type 'Int?' in coercion}}
|
|
|
|
_ = ("" ?? "" ?? "") as String // expected-warning 2{{left side of nil coalescing operator '??' has non-optional type 'String', so the right side is never used}}
|
|
_ = ((veryOptString ?? "") ?? "") as String??
|
|
_ = ((((veryOptString ?? "") ?? "") ?? "") ?? "") as String
|
|
|
|
_ = ("" ?? "" ?? "") as Float // expected-error {{cannot convert value of type 'String' to type 'Float' in coercion}}
|
|
_ = ((veryOptString ?? "") ?? "") as [String] // expected-error {{cannot convert value of type 'String??' to type '[String]' in coercion}}
|
|
_ = ((((veryOptString ?? "") ?? "") ?? "") ?? "") as [String] // expected-error {{cannot convert value of type 'String' to type '[String]' in coercion}}
|
|
|
|
_ = ohno(ohno(ohno(str))) as String???
|
|
_ = ohno(ohno(ohno(str))) as Int // expected-error {{cannot convert value of type 'String???' to type 'Int' in coercion}}
|
|
}
|
|
|
|
func id<T>(_ x: T) -> T { x }
|
|
|
|
func test_compatibility_coercions(_ arr: [Int], _ optArr: [Int]?, _ dict: [String: Int], _ set: Set<Int>) {
|
|
// Successful coercions don't raise a warning.
|
|
_ = arr as [Any]?
|
|
_ = dict as [String: Int]?
|
|
_ = set as Set<Int>
|
|
|
|
// Don't fix the simple case where no type variable is introduced, that was
|
|
// always disallowed.
|
|
_ = arr as [String] // expected-error {{cannot convert value of type '[Int]' to type '[String]' in coercion}}
|
|
// expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}
|
|
_ = dict as [String: String] // expected-error {{cannot convert value of type '[String : Int]' to type '[String : String]' in coercion}}
|
|
// expected-note@-1 {{arguments to generic parameter 'Value' ('Int' and 'String') are expected to be equal}}
|
|
_ = dict as [String: String]? // expected-error {{'[String : Int]' is not convertible to '[String : String]?'}}
|
|
// expected-note@-1 {{did you mean to use 'as!' to force downcast?}} {{12-14=as!}}
|
|
_ = (dict as [String: Int]?) as [String: Int] // expected-error {{value of optional type '[String : Int]?' must be unwrapped to a value of type '[String : Int]'}}
|
|
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}}
|
|
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
|
|
_ = set as Set<String> // expected-error {{cannot convert value of type 'Set<Int>' to type 'Set<String>' in coercion}}
|
|
// expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}
|
|
|
|
// Apply the compatibility logic when a type variable is introduced. It's
|
|
// unfortunate that this means we'll temporarily accept code we didn't before,
|
|
// but it at least means we shouldn't break compatibility with anything.
|
|
_ = id(arr) as [String] // expected-warning {{coercion from '[Int]' to '[String]' may fail; use 'as?' or 'as!' instead}}
|
|
|
|
_ = (arr ?? []) as [String] // expected-warning {{coercion from '[Int]' to '[String]' may fail; use 'as?' or 'as!' instead}}
|
|
// expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
|
|
_ = (arr ?? [] ?? []) as [String] // expected-warning {{coercion from '[Int]' to '[String]' may fail; use 'as?' or 'as!' instead}}
|
|
// expected-warning@-1 2{{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
|
|
_ = (optArr ?? []) as [String] // expected-warning {{coercion from '[Int]' to '[String]' may fail; use 'as?' or 'as!' instead}}
|
|
|
|
// Allow the coercion to increase optionality.
|
|
_ = (arr ?? []) as [String]? // expected-warning {{coercion from '[Int]' to '[String]?' may fail; use 'as?' or 'as!' instead}}
|
|
// expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
|
|
_ = (arr ?? []) as [String?]? // expected-warning {{coercion from '[Int]' to '[String?]?' may fail; use 'as?' or 'as!' instead}}
|
|
// expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
|
|
_ = (arr ?? []) as [String??]?? // expected-warning {{coercion from '[Int]' to '[String??]??' may fail; use 'as?' or 'as!' instead}}
|
|
// expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
|
|
_ = (dict ?? [:]) as [String: String?]? // expected-warning {{coercion from '[String : Int]' to '[String : String?]?' may fail; use 'as?' or 'as!' instead}}
|
|
// expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[String : Int]', so the right side is never used}}
|
|
_ = (set ?? []) as Set<String>?? // expected-warning {{coercion from 'Set<Int>' to 'Set<String>??' may fail; use 'as?' or 'as!' instead}}
|
|
// expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type 'Set<Int>', so the right side is never used}}
|
|
|
|
// Allow the coercion to decrease optionality.
|
|
_ = ohno(ohno(ohno(arr))) as [String] // expected-warning {{coercion from '[Int]???' to '[String]' may fail; use 'as?' or 'as!' instead}}
|
|
_ = ohno(ohno(ohno(arr))) as [Int] // expected-warning {{coercion from '[Int]???' to '[Int]' may fail; use 'as?' or 'as!' instead}}
|
|
_ = ohno(ohno(ohno(Set<Int>()))) as Set<String> // expected-warning {{coercion from 'Set<Int>???' to 'Set<String>' may fail; use 'as?' or 'as!' instead}}
|
|
_ = ohno(ohno(ohno(["": ""]))) as [Int: String] // expected-warning {{coercion from '[String : String]???' to '[Int : String]' may fail; use 'as?' or 'as!' instead}}
|
|
_ = ohno(ohno(ohno(dict))) as [String: Int] // expected-warning {{coercion from '[String : Int]???' to '[String : Int]' may fail; use 'as?' or 'as!' instead}}
|
|
|
|
// In this case the array literal can be inferred to be [String], so totally
|
|
// valid.
|
|
_ = ([] ?? []) as [String] // expected-warning {{left side of nil coalescing operator '??' has non-optional type '[String]', so the right side is never used}}
|
|
_ = (([] as Optional) ?? []) as [String]
|
|
|
|
// The array can also be inferred to be [Any].
|
|
_ = ([] ?? []) as Array // expected-warning {{left side of nil coalescing operator '??' has non-optional type '[Any]', so the right side is never used}}
|
|
}
|
|
|
|
// SR-13088
|
|
protocol JSON { }
|
|
protocol JSONLeaf: JSON {}
|
|
extension Int: JSONLeaf { }
|
|
extension Array: JSON where Element: JSON { }
|
|
|
|
protocol SR13035Error: Error {}
|
|
class ChildError: SR13035Error {}
|
|
|
|
protocol AnyC {
|
|
func foo()
|
|
}
|
|
|
|
protocol AnyEvent {}
|
|
|
|
protocol A {
|
|
associatedtype C: AnyC
|
|
}
|
|
|
|
protocol EventA: A {
|
|
associatedtype Event
|
|
}
|
|
|
|
typealias Container<Namespace>
|
|
= (event: Namespace.Event, c: Namespace.C) where Namespace: EventA
|
|
|
|
enum ConcreteA: EventA {
|
|
struct C: AnyC {
|
|
func foo() {}
|
|
}
|
|
|
|
enum Event: AnyEvent {
|
|
case test
|
|
}
|
|
}
|
|
|
|
protocol ProtocolP1 {}
|
|
protocol ProtocolQ1 {}
|
|
typealias Composition = ProtocolP1 & ProtocolQ1
|
|
|
|
protocol ProtocolP {}
|
|
protocol ProtocolQ {}
|
|
|
|
class ConcreteP: ProtocolP {}
|
|
class ConcreteQ: ProtocolQ {}
|
|
class ConcretePQ: ProtocolP, ProtocolQ {}
|
|
class ConcreteCPQ: ConcreteP, ProtocolQ {}
|
|
|
|
class ConcreteP1: ProtocolP1 {}
|
|
class ConcretePQ1: ProtocolP1, ProtocolQ1 {}
|
|
|
|
class ConcretePPQ1: ProtocolP, ProtocolP1, ProtocolQ1 {}
|
|
class NotConforms {}
|
|
struct StructNotComforms {}
|
|
final class NotConformsFinal {}
|
|
|
|
func tests_SR13088_false_positive_always_fail_casts() {
|
|
// SR-13081
|
|
let x: JSON = [4] // [4]
|
|
_ = x as? [Any] // Ok
|
|
|
|
// SR-13035
|
|
func SR13035<SomeError: SR13035Error>(_ child: Result<String, ChildError>, _: Result<String, SomeError>) {
|
|
let _ = child as? Result<String, SomeError> // Ok
|
|
}
|
|
|
|
func SR13035_1<SomeError: SR13035Error, Child: ChildError>(_ child: Result<String, Child>, parent: Result<String, SomeError>) {
|
|
_ = child as? Result<String, SomeError> // Ok
|
|
_ = parent as? Result<String, Child> // OK
|
|
}
|
|
|
|
// SR-11434 and SR-12321
|
|
func encodable(_ value: Encodable) {
|
|
_ = value as! [String : Encodable] // Ok
|
|
_ = value as? [String: Encodable] // Ok
|
|
}
|
|
|
|
// SR-13025
|
|
func coordinate(_ event: AnyEvent, from c: AnyC) {
|
|
switch (event, c) {
|
|
case let container as Container<ConcreteA>: // OK
|
|
container.c.foo()
|
|
default:
|
|
break
|
|
}
|
|
}
|
|
|
|
// SR-7187
|
|
let a: [Any] = [String?.some("hello") as Any, String?.none as Any]
|
|
let b: [AnyObject] = [String?.some("hello") as AnyObject, String?.none as AnyObject]
|
|
|
|
_ = a is [String?] // Ok
|
|
_ = a as? [String?] as Any // OK
|
|
_ = b is [String?] // Ok
|
|
_ = b as? [String?] as AnyObject // OK
|
|
|
|
// SR-6192
|
|
let items = [String]()
|
|
let dict = [String: Any]()
|
|
let set = Set<String>()
|
|
|
|
_ = items is [Int] // Ok
|
|
_ = items as? [Int] as Any // Ok
|
|
_ = items as! [Int] // Ok
|
|
|
|
_ = dict is [Int: Any] // Ok
|
|
_ = dict as? [Int: Any] as Any // Ok
|
|
_ = dict as! [Int: Any] as Any // Ok
|
|
|
|
_ = set is Set<Int> // Ok
|
|
_ = set as? Set<Int> as Any // Ok
|
|
_ = set as! Set<Int> // Ok
|
|
|
|
}
|
|
|
|
// Protocol composition
|
|
func protocol_composition(_ c: ProtocolP & ProtocolQ, _ c1: ProtocolP & Composition) {
|
|
_ = c as? ConcretePQ // Ok
|
|
_ = c as? ConcreteCPQ // Ok
|
|
_ = c as? ConcreteP // Ok
|
|
_ = c as? NotConforms // Ok
|
|
_ = c as? StructNotComforms // expected-warning {{cast from 'ProtocolP & ProtocolQ' to unrelated type 'StructNotComforms' always fails}}
|
|
_ = c as? NotConformsFinal // expected-warning {{cast from 'ProtocolP & ProtocolQ' to unrelated type 'NotConformsFinal' always fails}}
|
|
_ = c1 as? ConcreteP // Ok
|
|
_ = c1 as? ConcreteP1 // OK
|
|
_ = c1 as? ConcretePQ1 // OK
|
|
_ = c1 as? ConcretePPQ1 // Ok
|
|
_ = c1 as? NotConforms // Ok
|
|
_ = c1 as? StructNotComforms // expected-warning {{cast from 'ProtocolP & Composition' (aka 'ProtocolP & ProtocolP1 & ProtocolQ1') to unrelated type 'StructNotComforms' always fails}}
|
|
_ = c1 as? NotConformsFinal // expected-warning {{cast from 'ProtocolP & Composition' (aka 'ProtocolP & ProtocolP1 & ProtocolQ1') to unrelated type 'NotConformsFinal' always fails}}
|
|
}
|