mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
224 lines
5.2 KiB
Swift
224 lines
5.2 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
|
|
_ = p12 as! S2
|
|
_ = p12 as! S12
|
|
_ = p12 as! S3
|
|
|
|
// 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
|
|
var _:Bool = p12 is S2
|
|
var _:Bool = p12 is S12
|
|
var _:Bool = p12 is S3
|
|
}
|
|
|
|
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 {{cannot invoke 'compare' with an argument list of type '(Bool)'}}
|
|
// expected-note@-2 {{overloads for 'compare' exist with these partially matching parameter lists: (T, T), (T?, T?)}}
|
|
}
|
|
|
|
func compare<T>(_: T, _: T) {}
|
|
func compare<T>(_: T?, _: T?) {}
|