blob: 8297d034723b0d781502505ed0725ad889aa0e32 [file] [log] [blame]
// 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?) {}