mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
In Swift 4 mode, no longer consider e.g. 'nsNumber as Int' or 'nsValue as NSRange' to be valid coercions. This would break compatibility with Swift 3, so in Swift 3 mode, accept the coercion, but *also* accept a checked cast without a warning, and raise a migration warning about the unchecked coercion.
99 lines
3.6 KiB
Swift
99 lines
3.6 KiB
Swift
// RUN: %target-swift-frontend(mock-sdk: %clang-importer-sdk) -typecheck -verify %s
|
|
// REQUIRES: objc_interop
|
|
|
|
import Foundation
|
|
|
|
struct NotClass {}
|
|
|
|
class SomeClass {}
|
|
|
|
func nsobject_as_class_cast<T>(_ x: NSObject, _: T) {
|
|
let _ = x is AnyObject.Type
|
|
let _ = x as! AnyObject.Type
|
|
let _ = x as? AnyObject.Type
|
|
|
|
let _ = x is Any.Type
|
|
let _ = x as! Any.Type
|
|
let _ = x as? Any.Type
|
|
|
|
let _ = x is SomeClass.Type
|
|
let _ = x as! SomeClass.Type
|
|
let _ = x as? SomeClass.Type
|
|
|
|
let _ = x is T.Type
|
|
let _ = x as! T.Type
|
|
let _ = x as? T.Type
|
|
|
|
let _ = x is NotClass.Type // expected-warning{{cast from 'NSObject' to unrelated type 'NotClass.Type' always fails}}
|
|
let _ = x as! NotClass.Type // expected-warning{{cast from 'NSObject' to unrelated type 'NotClass.Type' always fails}}
|
|
let _ = x as? NotClass.Type // expected-warning{{cast from 'NSObject' to unrelated type 'NotClass.Type' always fails}}
|
|
}
|
|
|
|
|
|
// <rdar://problem/20294245> QoI: Error message mentions value rather than key for subscript
|
|
func test(_ a : CFString!, b : CFString) {
|
|
let dict = NSMutableDictionary()
|
|
let object = NSObject()
|
|
dict[a] = object
|
|
|
|
|
|
dict[b] = object
|
|
}
|
|
|
|
|
|
// <rdar://problem/22507759> QoI: poor error message for invalid unsafeDowncast()
|
|
let r22507759: NSObject! = "test" as NSString
|
|
let _: NSString! = unsafeDowncast(r22507759) // expected-error {{generic parameter 'T' could not be inferred}}
|
|
|
|
// rdar://problem/29496775 / SR-3319
|
|
func sr3319(f: CGFloat, n: NSNumber) {
|
|
let _ = [f].map { $0 as NSNumber }
|
|
let _ = [n].map { $0 as! CGFloat }
|
|
}
|
|
|
|
func alwaysSucceedingConditionalCasts(f: CGFloat, n: NSNumber) {
|
|
let _ = f as? NSNumber // expected-warning{{conditional cast from 'CGFloat' to 'NSNumber' always succeeds}}
|
|
let _ = n as? CGFloat
|
|
}
|
|
|
|
func optionalityReducingCasts(f: CGFloat?, n: NSNumber?) {
|
|
let _ = f as? NSNumber // expected-warning{{conditional downcast from 'CGFloat?' to 'NSNumber' is a bridging conversion; did you mean to use 'as'?}}
|
|
let _ = f as! NSNumber // expected-warning{{forced cast from 'CGFloat?' to 'NSNumber' only unwraps and bridges; did you mean to use '!' with 'as'?}}
|
|
let _ = n as? CGFloat
|
|
let _ = n as! CGFloat
|
|
}
|
|
|
|
func optionalityMatchingCasts(f: CGFloat?, n: NSNumber?) {
|
|
let _ = f as NSNumber?
|
|
let _ = f as? NSNumber? // expected-warning{{conditional cast from 'CGFloat?' to 'NSNumber?' always succeeds}}
|
|
let _ = f as! NSNumber? // expected-warning{{forced cast from 'CGFloat?' to 'NSNumber?' always succeeds; did you mean to use 'as'?}}{{13-16=as}}
|
|
let _ = n as? CGFloat?
|
|
let _ = n as! CGFloat?
|
|
}
|
|
|
|
func optionalityMatchingCastsIUO(f: CGFloat?!, n: NSNumber?!) {
|
|
let _ = f as NSNumber?
|
|
let _ = f as? NSNumber? // expected-warning{{conditional downcast from 'CGFloat?!' to 'NSNumber?' is a bridging conversion; did you mean to use 'as'?}}
|
|
let _ = f as! NSNumber? // expected-warning{{forced cast from 'CGFloat?!' to 'NSNumber?' only unwraps and bridges; did you mean to use '!' with 'as'?}}
|
|
let _ = n as? CGFloat?
|
|
let _ = n as! CGFloat?
|
|
}
|
|
|
|
func optionalityMismatchingCasts(f: CGFloat, n: NSNumber, fooo: CGFloat???,
|
|
nooo: NSNumber???) {
|
|
_ = f as NSNumber?
|
|
_ = f as NSNumber??
|
|
let _ = fooo as NSNumber?? // expected-error{{'CGFloat???' is not convertible to 'NSNumber??'; did you mean to use 'as!' to force downcast?}}
|
|
let _ = fooo as NSNumber???? // okay: injects extra optionals
|
|
}
|
|
|
|
func anyObjectCasts(xo: [Int]?, xooo: [Int]???, x: [Int]) {
|
|
_ = x as AnyObject
|
|
_ = x as AnyObject?
|
|
_ = xo as AnyObject
|
|
_ = xo as AnyObject?
|
|
_ = xooo as AnyObject??
|
|
_ = xooo as AnyObject???
|
|
_ = xooo as AnyObject???? // okay: injects extra optionals
|
|
}
|