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

[SR-2420] AnyObject not working in Xcode8 beta6 #45025

Open
swift-ci opened this issue Aug 19, 2016 · 15 comments
Open

[SR-2420] AnyObject not working in Xcode8 beta6 #45025

swift-ci opened this issue Aug 19, 2016 · 15 comments

Comments

@swift-ci
Copy link
Collaborator

@swift-ci swift-ci commented Aug 19, 2016

Previous ID SR-2420
Radar rdar://problem/26268575
Original Reporter 100mango (JIRA User)
Type Bug
Status Reopened
Resolution
Environment

Xcode8 beta6 on OS X 10.11.5

Additional Detail from JIRA
Votes 2
Component/s Compiler
Labels Bug
Assignee None
Priority Medium

md5: f51cb8c5830727793b8f598a7fa1424e

is duplicated by:

  • SR-2453 Optional as? AnyObject breaks in Swift 3
  • SR-2498 Foo.self is AnyObject incorrectly claims it always returns true

Issue Description:

In Xcode8 beta6, the following code will cause a warning: 'is' test is always true. But it won't print pass.


    struct TestStruct {
    }

    //warning: 'is' test is always true
    if TestStruct() is AnyObject {
        print("pass")
    }

And the following code will cause a warning: Conditional cast from 'T' to 'AnyObject' always succeeds

public static func register<T>(_ protocolType: T.Type, observer: T) {

    //Warning: Conditional cast from 'T' to 'AnyObject' always succeeds
    guard let object = observer as? AnyObject else {
        fatalError("expecting reference type but found value type: \(observer)")
    }
    //...
}
@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Aug 19, 2016

Comment by Ling Guo (JIRA)

I came across the same issue:

protocol AProtocol {
    mutating func getPtr() -> UnsafeMutableRawPointer
}

extension AProtocol {
    mutating func getPtr() -> UnsafeMutableRawPointer {
        if self is AnyObject {
            return withUnsafePointer(to: &self, { unsafeBitCast($0.pointee, to: UnsafeMutableRawPointer.self) })
        } else {
            return withUnsafePointer(to: &self, { unsafeBitCast($0, to: UnsafeMutableRawPointer.self) })
        }
    }
}

@belkadan
Copy link
Contributor

@belkadan belkadan commented Aug 19, 2016

cc @jckarter

@jckarter
Copy link
Member

@jckarter jckarter commented Aug 19, 2016

This is correct, because everything bridges to AnyObject now. What you're trying to do using withUnsafePointer is undefined behavior. You can't preserve $0 beyond the duration of the closure. What are you trying to accomplish?

@belkadan
Copy link
Contributor

@belkadan belkadan commented Aug 19, 2016

Ling's example is invalid, but 100mango's isn't.

@jckarter
Copy link
Member

@jckarter jckarter commented Aug 19, 2016

is/as AnyObject always succeed for all types now. It's behaving as intended.

@belkadan
Copy link
Contributor

@belkadan belkadan commented Aug 19, 2016

Right, but the report says the runtime is behaving differently.

@belkadan
Copy link
Contributor

@belkadan belkadan commented Aug 19, 2016

@rjmccall has a fix for this in #4410

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Aug 20, 2016

Comment by 100mango (JIRA)

Thanks for your quick reply. It make me wonder how to detect value type and reference type in Swift now. One of my framework SwiftNotificationCenter need to detect value type and reference type. Because value type is copied when it is assigned to a variable or constant, or when it is passed to a function.So it can't be participated in one to many communication.Cocoa' NotificationCenter can't add value type as observer too.

@jckarter
Copy link
Member

@jckarter jckarter commented Aug 22, 2016

You can still statically constrain parameters to AnyObject so that they statically require classes, which would be appropriate for observers. Your observers probably need to also have methods of some sort, so you probably want a class-constrained protocol.

@lilyball
Copy link
Mannequin

@lilyball lilyball mannequin commented Aug 28, 2016

Does the PR fix the case reported in my dupe SR-2498, wherein the compiler claims that foo is AnyObject always returns true but if you actually execute the code at runtime, it evaluates to {{false]}?

@jckarter
Copy link
Member

@jckarter jckarter commented Aug 29, 2016

Eridius (JIRA User) Yeah, John's fix should address that.

@swift-ci
Copy link
Collaborator Author

@swift-ci swift-ci commented Apr 12, 2017

Comment by Rudolf Adamkovič (JIRA)

This bug is still present in Xcode 8.3.1 (8E1000a):

struct SwiftBug {

    struct TestStruct {}

    func test() {

        //warning: 'is' test is always true
        if TestStruct() is AnyObject {
            print("pass")
        }

    }

}

@amomchilov
Copy link

@amomchilov amomchilov commented Aug 9, 2019

@jckarter Can this behaviour be made explicit? Something like `ObjCRefBox(TestStruct())` (because IMO, `SwiftValue` is a poor class name to expose publicly)? It's really confusing to new people, and relatively hard to explain. It completely muddies the waters on `Any` vs `AnyObject`.

There were many other implicit bridging behaviours, like `NSString` to `String`, that were way more straight-forward than this one, but even they were changed to require an explicit coercion.

@jckarter
Copy link
Member

@jckarter jckarter commented Aug 9, 2019

"SwiftValue" is an implementation detail; the name of the class Swift happens to use to box values when bridging to ObjC could change at any time. It's exactly as explicit as the other bridging behaviors; Swift won't just convert something to AnyObject unless you ask it to with `as AnyObject`.

@amomchilov
Copy link

@amomchilov amomchilov commented Aug 9, 2019

@jckarter Thanks for your response. " It's exactly as explicit as the other bridging behaviors; Swift won't just convert something to AnyObject unless you ask it to with `as AnyObject`." Ah yes, I didn't realize that.

I guess my issue is that `is` doesn't operate on the value as it already exists, but it considers potential bridging that's available. If you have a `testStruct: TestStruct`, or a `str: Swift.String`, then `testStruct is AnyObject` and `str is NSString` both counterintuitively return true. Not because those values are those types, but because they could be bridged to be.

I think a lot of the confusion around this could be alleviated if `is` didn't consider bridging behaviour, and answers more directly about precisely what it was asked about.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants