Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SE-0072: Fully eliminate implicit bridging conversions from Swift #2419

Merged
merged 3 commits into from
May 7, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions lib/ClangImporter/ImportDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1587,8 +1587,10 @@ namespace {
// Construct right-hand side.
// FIXME: get the parameter from the init, and plug it in here.
auto rhs = new (cxt)
DeclRefExpr(init->getParameterList(1)->get(0), DeclNameLoc(),
/*Implicit=*/true);
CoerceExpr(new (cxt) DeclRefExpr(
init->getParameterList(1)->get(0),
DeclNameLoc(),
/*Implicit=*/true), {}, {nullptr, storedUnderlyingType});

// Add assignment.
auto assign = new (cxt) AssignExpr(lhs, SourceLoc(), rhs,
Expand Down
44 changes: 19 additions & 25 deletions lib/Sema/CSSimplify.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1709,33 +1709,27 @@ ConstraintSystem::matchTypes(Type type1, Type type2, TypeMatchKind kind,
// Bridging from a value type to an Objective-C class type.
// FIXME: Banned for operator parameters, like user conversions are.

// NOTE: The plan for <rdar://problem/18311362> was to make such bridging
// conversions illegal except when explicitly converting with the 'as'
// operator. But using a String to subscript an [NSObject : AnyObject] is
// sufficiently common due to bridging that disallowing such conversions is
// not yet feasible, and a more targeted fix in the type checker is hard to
// justify.

if (type1->isPotentiallyBridgedValueType() &&
type1->getAnyNominal()
!= TC.Context.getImplicitlyUnwrappedOptionalDecl() &&
!(flags & TMF_ApplyingOperatorParameter)) {

auto isBridgeableTargetType = type2->isBridgeableObjectType();

// Allow bridged conversions to CVarArg through NSObject.
if (!isBridgeableTargetType && type2->isExistentialType()) {
if (auto nominalType = type2->getAs<NominalType>())
isBridgeableTargetType = nominalType->getDecl()->getName() ==
TC.Context.Id_CVarArg;
}

if (isBridgeableTargetType && TC.getBridgedToObjC(DC, type1)) {
conversionsOrFixes.push_back(ConversionRestrictionKind::BridgeToObjC);
if (kind == TypeMatchKind::ExplicitConversion) {

if (type1->isPotentiallyBridgedValueType() &&
type1->getAnyNominal()
!= TC.Context.getImplicitlyUnwrappedOptionalDecl() &&
!(flags & TMF_ApplyingOperatorParameter)) {

auto isBridgeableTargetType = type2->isBridgeableObjectType();

// Allow bridged conversions to CVarArg through NSObject.
if (!isBridgeableTargetType && type2->isExistentialType()) {
if (auto nominalType = type2->getAs<NominalType>())
isBridgeableTargetType = nominalType->getDecl()->getName() ==
TC.Context.Id_CVarArg;
}

if (isBridgeableTargetType && TC.getBridgedToObjC(DC, type1)) {
conversionsOrFixes.push_back(ConversionRestrictionKind::BridgeToObjC);
}
}
}

if (kind == TypeMatchKind::ExplicitConversion) {
// Bridging from an Objective-C class type to a value type.
// Note that specifically require a class or class-constrained archetype
// here, because archetypes cannot be bridged.
Expand Down
2 changes: 1 addition & 1 deletion stdlib/private/StdlibUnittest/StdlibCoreExtras.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ public func createTemporaryFile(
_ fileNamePrefix: String, _ fileNameSuffix: String, _ contents: String
) -> String {
#if _runtime(_ObjC)
let tempDir: NSString = NSTemporaryDirectory()
let tempDir: NSString = NSTemporaryDirectory() as NSString
var fileName = tempDir.appendingPathComponent(
fileNamePrefix + "XXXXXX" + fileNameSuffix)
#else
Expand Down
16 changes: 8 additions & 8 deletions stdlib/public/SDK/SceneKit/SceneKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ extension SCNVector3 {
self.z = SCNFloat(z)
}
public init(_ x: CGFloat, _ y: CGFloat, _ z: CGFloat) {
self.x = SCNFloat(x)
self.y = SCNFloat(y)
self.z = SCNFloat(z)
self.x = SCNFloat(x as NSNumber)
self.y = SCNFloat(y as NSNumber)
self.z = SCNFloat(z as NSNumber)
Copy link
Contributor

@gribozavr gribozavr May 6, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I don't think that was intended.

#if os(OSX)
public typealias SCNFloat = CGFloat
#elseif os(iOS) || os(tvOS)
public typealias SCNFloat = Float
#endif

Given this definition, this was intended as a plain conversion, not a bridge.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed - debugging in, though, we've definitely been introducing this conversion implicitly. I've filed SR-1432 to track my investigation of what's been going on.

}
public init(_ x: Double, _ y: Double, _ z: Double) {
self.init(SCNFloat(x), SCNFloat(y), SCNFloat(z))
Expand Down Expand Up @@ -69,10 +69,10 @@ extension SCNVector4 {
self.w = SCNFloat(w)
}
public init(_ x: CGFloat, _ y: CGFloat, _ z: CGFloat, _ w: CGFloat) {
self.x = SCNFloat(x)
self.y = SCNFloat(y)
self.z = SCNFloat(z)
self.w = SCNFloat(w)
self.x = SCNFloat(x as NSNumber)
self.y = SCNFloat(y as NSNumber)
self.z = SCNFloat(z as NSNumber)
self.w = SCNFloat(w as NSNumber)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here.

}
public init(_ x: Double, _ y: Double, _ z: Double, _ w: Double) {
self.init(SCNFloat(x), SCNFloat(y), SCNFloat(z), SCNFloat(w))
Expand Down Expand Up @@ -182,7 +182,7 @@ extension SCNSceneSource {
@warn_unused_result
public func entryWithIdentifier<T>(_ uid: String, withClass entryClass: T.Type) -> T? {
return SCN_Swift_SCNSceneSource_entryWithIdentifier(
self, uid, entryClass as! AnyObject) as! T?
self, uid as NSString, entryClass as! AnyObject) as! T?
}
}

4 changes: 2 additions & 2 deletions test/1_stdlib/ArrayBridge.swift
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ func testRoundTrip() {

// Clear out the stats before returning array
BridgedSwift.resetStats()
return result
return result as NSArray
}
}

Expand All @@ -540,7 +540,7 @@ func testRoundTrip() {
BridgedSwift(40), BridgedSwift(50) ]

BridgedSwift.resetStats()
test.call(array)
test.call(array as NSArray)

// CHECK-NEXT: ---Returned Array---
print("---Returned Array---")
Expand Down
2 changes: 1 addition & 1 deletion test/1_stdlib/DictionaryLiteral.swift
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ expectType(DictionaryLiteral<String, NSString>.self, &stringNSStringLiteral)

let aString = "1"
let anNSString = "Foo" as NSString
var stringNSStringLet: DictionaryLiteral = ["a": aString, "b": anNSString]
var stringNSStringLet: DictionaryLiteral = [ "a": aString as NSString, "b": anNSString]
expectType(DictionaryLiteral<String, NSString>.self, &stringNSStringLet)

var hetero1: DictionaryLiteral = ["a": 1, "b": "Foo" as NSString]
Expand Down
6 changes: 3 additions & 3 deletions test/1_stdlib/Inputs/DictionaryKeyValueTypesObjC.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,18 @@ func isCocoaDictionary<KeyTy : Hashable, ValueTy>(
}

func isNativeNSDictionary(_ d: NSDictionary) -> Bool {
let className: NSString = NSStringFromClass(d.dynamicType)
let className: NSString = NSStringFromClass(d.dynamicType) as NSString
return className.range(of: "_NativeDictionaryStorageOwner").length > 0
}

func isCocoaNSDictionary(_ d: NSDictionary) -> Bool {
let className: NSString = NSStringFromClass(d.dynamicType)
let className: NSString = NSStringFromClass(d.dynamicType) as NSString
return className.range(of: "NSDictionary").length > 0 ||
className.range(of: "NSCFDictionary").length > 0
}

func isNativeNSArray(_ d: NSArray) -> Bool {
let className: NSString = NSStringFromClass(d.dynamicType)
let className: NSString = NSStringFromClass(d.dynamicType) as NSString
return className.range(of: "_SwiftDeferredNSArray").length > 0
}

Expand Down
14 changes: 7 additions & 7 deletions test/1_stdlib/NSStringAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1043,8 +1043,8 @@ NSStringAPIs.test("paragraphRangeFor(_:)") {
}

NSStringAPIs.test("pathComponents") {
expectEqual(["/", "foo", "bar"], "/foo/bar".pathComponents)
expectEqual(["/", "абв", "где"], "/абв/где".pathComponents)
expectEqual([ "/", "foo", "bar" ] as [NSString], ("/foo/bar" as NSString).pathComponents)
expectEqual([ "/", "абв", "где" ] as [NSString], ("/абв/где" as NSString).pathComponents)
}

NSStringAPIs.test("pathExtension") {
Expand Down Expand Up @@ -1646,10 +1646,10 @@ NSStringAPIs.test("trimmingCharacters(in:)") {
}

NSStringAPIs.test("NSString.stringsByAppendingPaths(_:)") {
expectEqual([], "".strings(byAppendingPaths: []))
expectEqual([] as [NSString], ("" as NSString).strings(byAppendingPaths: []))
expectEqual(
["/tmp/foo", "/tmp/bar"],
"/tmp".strings(byAppendingPaths: ["foo", "bar"]))
[ "/tmp/foo", "/tmp/bar" ] as [NSString],
("/tmp" as NSString).strings(byAppendingPaths: [ "foo", "bar" ]))
}

NSStringAPIs.test("substring(from:)") {
Expand Down Expand Up @@ -1867,8 +1867,8 @@ NSStringAPIs.test("MixedTypeComparisons") {
expectTrue(ys != "\u{1e69}")
expectFalse("\u{1e69}" == ys)
expectTrue("\u{1e69}" != ys)
expectFalse(xs == ys)
expectTrue(xs != ys)
expectFalse(xs as NSString == ys)
expectTrue(xs as NSString != ys)
expectTrue(ys == ys)
expectFalse(ys != ys)
}
Expand Down
2 changes: 1 addition & 1 deletion test/1_stdlib/SceneKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ if #available(iOS 8.0, OSX 10.10, *) {
expectEqual(scn_float_from_d, 2.0)

let cg = CGFloat(3.0)
let scn_float_from_cg = SCNFloat(cg)
let scn_float_from_cg = SCNFloat(cg as NSNumber)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it was intended to be a bridging conversion.

expectEqual(scn_float_from_cg, 3.0)

let node = SCNNode()
Expand Down
8 changes: 4 additions & 4 deletions test/1_stdlib/StringDiagnostics.swift
Original file line number Diff line number Diff line change
Expand Up @@ -45,15 +45,15 @@ func testNonAmbiguousStringComparisons() {

func testAmbiguousStringComparisons(s: String) {
let nsString = s as NSString
let a1 = s == nsString
let a2 = s != nsString
let a1 = s as NSString == nsString
let a2 = s as NSString != nsString
let a3 = s < nsString // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{24-24= as String}}
let a4 = s <= nsString // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{25-25= as String}}
let a5 = s >= nsString // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{25-25= as String}}
let a6 = s > nsString // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{24-24= as String}}
// now the other way
let a7 = nsString == s
let a8 = nsString != s
let a7 = nsString == s as NSString
let a8 = nsString != s as NSString
let a9 = nsString < s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{20-20= as String}}
let a10 = nsString <= s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
let a11 = nsString >= s // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{21-21= as String}}
Expand Down
4 changes: 2 additions & 2 deletions test/ClangModules/AppKit_test.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,15 @@ func test(_ URL: NSURL, controller: NSDocumentController) {

extension NSBox {
func foo() {
print("abc") // expected-warning {{use of 'print' treated as a reference to instance method in class 'NSView'}}
print("abc" as NSString) // expected-warning {{use of 'print' treated as a reference to instance method in class 'NSView'}}
// expected-note@-1 {{use 'self.' to silence this warning}} {{5-5=self.}}
// expected-note@-2 {{use 'Swift.' to reference the global function}} {{5-5=Swift.}}
}
}

class MyView : NSView {
func foo() {
print("abc") // expected-warning {{use of 'print' treated as a reference to instance method in class 'NSView'}}
print("abc" as NSString) // expected-warning {{use of 'print' treated as a reference to instance method in class 'NSView'}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens for a regular print("abc")? This was a special-case error message to improve QoI in this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll still infer type String for "abc", and then raise an invalid conversion error. (We do this because String is the favored type for all string literals.) I'll see if I can do something about this case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the intent of the test, maybe we should change it to print(NSObject()) or something like that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that would work - yeah.

// expected-note@-1 {{use 'self.' to silence this warning}} {{5-5=self.}}
// expected-note@-2 {{use 'Swift.' to reference the global function}} {{5-5=Swift.}}
}
Expand Down
36 changes: 18 additions & 18 deletions test/Constraints/bridging.swift
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,12 @@ func ==(x: OtherClass, y: OtherClass) -> Bool { return true }

// Basic bridging
func bridgeToObjC(_ s: BridgedStruct) -> BridgedClass {
return s
return s // expected-error{{cannot convert return expression of type 'BridgedStruct' to return type 'BridgedClass'}}
return s as BridgedClass
}

func bridgeToAnyObject(_ s: BridgedStruct) -> AnyObject {
return s
return s // expected-error{{return expression of type 'BridgedStruct' does not conform to 'AnyObject'}}
return s as AnyObject
}

Expand All @@ -115,10 +115,10 @@ func bridgeFromObjCDerived(_ s: BridgedClassSub) -> BridgedStruct {
func arrayToNSArray() {
var nsa: NSArray

nsa = [AnyObject]()
nsa = [BridgedClass]()
nsa = [OtherClass]()
nsa = [BridgedStruct]()
nsa = [AnyObject]() // expected-error {{cannot assign value of type '[AnyObject]' to type 'NSArray'}}
nsa = [BridgedClass]() // expected-error {{cannot assign value of type '[BridgedClass]' to type 'NSArray'}}
nsa = [OtherClass]() // expected-error {{cannot assign value of type '[OtherClass]' to type 'NSArray'}}
nsa = [BridgedStruct]() // expected-error {{cannot assign value of type '[BridgedStruct]' to type 'NSArray'}}
nsa = [NotBridgedStruct]() // expected-error{{cannot assign value of type '[NotBridgedStruct]' to type 'NSArray'}}

nsa = [AnyObject]() as NSArray
Expand Down Expand Up @@ -153,13 +153,13 @@ func dictionaryToNSDictionary() {

var nsd: NSDictionary

nsd = [NSObject : AnyObject]()
nsd = [NSObject : AnyObject]() // expected-error {{cannot assign value of type '[NSObject : AnyObject]' to type 'NSDictionary'}}
nsd = [NSObject : AnyObject]() as NSDictionary
nsd = [NSObject : BridgedClass]()
nsd = [NSObject : BridgedClass]() // expected-error {{cannot assign value of type '[NSObject : BridgedClass]' to type 'NSDictionary'}}
nsd = [NSObject : BridgedClass]() as NSDictionary
nsd = [NSObject : OtherClass]()
nsd = [NSObject : OtherClass]() // expected-error {{cannot assign value of type '[NSObject : OtherClass]' to type 'NSDictionary'}}
nsd = [NSObject : OtherClass]() as NSDictionary
nsd = [NSObject : BridgedStruct]()
nsd = [NSObject : BridgedStruct]() // expected-error {{cannot assign value of type '[NSObject : BridgedStruct]' to type 'NSDictionary'}}
nsd = [NSObject : BridgedStruct]() as NSDictionary
nsd = [NSObject : NotBridgedStruct]() // expected-error{{cannot assign value of type '[NSObject : NotBridgedStruct]' to type 'NSDictionary'}}
nsd = [NSObject : NotBridgedStruct]() as NSDictionary // expected-error{{cannot convert value of type '[NSObject : NotBridgedStruct]' to type 'NSDictionary' in coercion}}
Expand All @@ -169,18 +169,18 @@ func dictionaryToNSDictionary() {
nsd = [NSObject : BridgedStruct?]() // expected-error{{cannot assign value of type '[NSObject : BridgedStruct?]' to type 'NSDictionary'}}
nsd = [NSObject : BridgedStruct?]() as NSDictionary //expected-error{{cannot convert value of type '[NSObject : BridgedStruct?]' to type 'NSDictionary' in coercion}}

nsd = [BridgedClass : AnyObject]()
nsd = [BridgedClass : AnyObject]() // expected-error {{cannot assign value of type '[BridgedClass : AnyObject]' to type 'NSDictionary'}}
nsd = [BridgedClass : AnyObject]() as NSDictionary
nsd = [OtherClass : AnyObject]()
nsd = [OtherClass : AnyObject]() // expected-error {{cannot assign value of type '[OtherClass : AnyObject]' to type 'NSDictionary'}}
nsd = [OtherClass : AnyObject]() as NSDictionary
nsd = [BridgedStruct : AnyObject]()
nsd = [BridgedStruct : AnyObject]() // expected-error {{cannot assign value of type '[BridgedStruct : AnyObject]' to type 'NSDictionary'}}
nsd = [BridgedStruct : AnyObject]() as NSDictionary
nsd = [NotBridgedStruct : AnyObject]() // expected-error{{cannot assign value of type '[NotBridgedStruct : AnyObject]' to type 'NSDictionary'}}
nsd = [NotBridgedStruct : AnyObject]() as NSDictionary // expected-error{{cannot convert value of type '[NotBridgedStruct : AnyObject]' to type 'NSDictionary' in coercion}}

// <rdar://problem/17134986>
var bcOpt: BridgedClass?
nsd = [BridgedStruct() : bcOpt] // expected-error{{value of optional type 'BridgedClass?' not unwrapped; did you mean to use '!' or '?'?}}
nsd = [BridgedStruct() : bcOpt] // expected-error{{value of type 'BridgedStruct' does not conform to expected dictionary key type 'NSCopying'}}
bcOpt = nil
_ = nsd
}
Expand Down Expand Up @@ -236,7 +236,7 @@ func rdar19695671() {
// This failed at one point while fixing rdar://problem/19600325.
func getArrayOfAnyObject(_: AnyObject) -> [AnyObject] { return [] }
func testCallback(_ f: (AnyObject) -> AnyObject?) {}
testCallback { return getArrayOfAnyObject($0) }
testCallback { return getArrayOfAnyObject($0) } // expected-error {{cannot convert value of type '[AnyObject]' to closure result type 'AnyObject?'}}

// <rdar://problem/19724719> Type checker thinks "(optionalNSString ?? nonoptionalNSString) as String" is a forced cast
func rdar19724719(_ f: (String) -> (), s1: NSString?, s2: NSString) {
Expand Down Expand Up @@ -295,10 +295,10 @@ func rdar19836341(_ ns: NSString?, vns: NSString?) {

// <rdar://problem/20029786> Swift compiler sometimes suggests changing "as!" to "as?!"
func rdar20029786(_ ns: NSString?) {
var s: String = ns ?? "str" as String as String // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}} {{19-19=(}} {{50-50=) as String}}
var s2 = ns ?? "str" as String as String
var s: String = ns ?? "str" as String as String // expected-error{{cannot convert value of type 'NSString?' to expected argument type 'String?'}}
var s2 = ns ?? "str" as String as String // expected-error {{binary operator '??' cannot be applied to operands of type 'NSString?' and 'String'}} expected-note{{}}

let s3: NSString? = "str" as String?
let s3: NSString? = "str" as String? // expected-error {{cannot convert value of type 'String?' to specified type 'NSString?'}}

var s4: String = ns ?? "str" // expected-error{{'NSString' is not implicitly convertible to 'String'; did you mean to use 'as' to explicitly convert?}}{{20-20=(}}{{31-31=) as String}}
var s5: String = (ns ?? "str") as String // fixed version
Expand Down
2 changes: 1 addition & 1 deletion test/Constraints/casts_objc.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,6 @@ func test(_ a : CFString!, b : CFString) {


// <rdar://problem/22507759> QoI: poor error message for invalid unsafeDowncast()
let r22507759: NSObject! = "test"
let r22507759: NSObject! = "test" as NSString
let _: NSString! = unsafeDowncast(r22507759) // expected-error {{generic parameter 'T' could not be inferred}}

8 changes: 4 additions & 4 deletions test/Interpreter/SDK/objc_array_of_classes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ var ArrayOfClassObjectBridging = TestSuite("ArrayOfClassObjectBridging")
ArrayOfClassObjectBridging.test("bridging class object array to NSArray") {
let classes: [NSObject.Type] = [NSObject.self, NSString.self, NSArray.self]

let classesBridged: NSArray = classes
let classesBridged: NSArray = classes as NSArray

expectTrue(classesBridged.count == 3)
expectTrue(classesBridged[0] === NSObject.self)
Expand All @@ -39,7 +39,7 @@ ArrayOfClassObjectBridging.test("bridging class object array to NSArray") {

ArrayOfClassObjectBridging.test("bridging NSArray of class objects to [AnyObject]") {
let classes: [NSObject.Type] = [NSObject.self, NSString.self, NSArray.self]
let classesBridged: NSArray = classes
let classesBridged: NSArray = classes as NSArray
let classesUnbridgedAsAnyObject = classesBridged as [AnyObject]

expectTrue(classesUnbridgedAsAnyObject.count == 3)
Expand All @@ -50,7 +50,7 @@ ArrayOfClassObjectBridging.test("bridging NSArray of class objects to [AnyObject

ArrayOfClassObjectBridging.test("bridging NSArray of class objects to [AnyClass]") {
let classes: [NSObject.Type] = [NSObject.self, NSString.self, NSArray.self]
let classesBridged: NSArray = classes
let classesBridged: NSArray = classes as NSArray

if let classesUnbridgedAsAnyClass = classesBridged as? [AnyClass] {
expectTrue(classesUnbridgedAsAnyClass.count == 3)
Expand All @@ -64,7 +64,7 @@ ArrayOfClassObjectBridging.test("bridging NSArray of class objects to [AnyClass]

ArrayOfClassObjectBridging.test("bridging NSArray of class objects to [NSObject.Type]") {
let classes: [NSObject.Type] = [NSObject.self, NSString.self, NSArray.self]
let classesBridged: NSArray = classes
let classesBridged: NSArray = classes as NSArray

if let classesUnbridgedAsNSObjectType = classesBridged as? [NSObject.Type] {
expectTrue(classesUnbridgedAsNSObjectType.count == 3)
Expand Down
Loading