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-13812] Metatype subtype test behaves differently with swiftc
and Playground/iOS app
#56209
Comments
Comment by Fredrik Tõnisson-Bystam (JIRA) I just had an idea after posting this and tested it: Creating a new "macOS command line tool" in Xcode 12.1 and running the code in there ALSO made it work "as expected". As in this printing true instead of false: |
@swift-ci create |
There are a number of bugs in dynamic casting (which includes the `is`, `as!` and `as?` operators) in Swift 5.3. Many of these will be fixed in the next release as a result of PR #33561 (#33561 and related work. If you could, I'd appreciate if you could test two things:
A more subtle issue here is the confusing behavior of `.Type`: Your report mentions `B.Type` and `Fruit.Type`. These are entirely different things: Because `Fruit` is the name of a protocol, `Fruit.Type` is the "existential metatype" for `Fruit`. In contrast, `B` is a generic type variable, and `B.Type` is the metatype for whatever is bound to that variable. In your example where `B` is bound to the protocol type `Fruit`, `B.Type` is the same as `Fruit.Protocol` and is entirely unrelated to `Fruit.Type`. For a more detailed explanation of how casting in Swift is supposed to work (and should work in the next release), you can see the new Dynamic Casting Spec |
In the current `main` branch, which includes the updated casting logic, the following test passes in both debug and release builds: func check<A, B>(a: A.Type, b: B.Type) -> Bool {
return (a is B.Type)
}
protocol Fruit {}
struct Apple: Fruit {}
expectFalse(check(a: Apple.self, b: Fruit.self))
expectFalse(Apple.self is Fruit.Protocol)
expectTrue(Apple.self is Fruit.Type) Based on the casting specification, I believe this is the correct behavior. In particular, note that the first two `expectFalse` here are testing the same thing; the last `is Fruit.Type` is a completely different test. Based on your description above, it sounds like you were seeing this behavior in some circumstances but not all. Note that this behavior depends both on the compiler and on runtime libraries that are bundled with Apple operating systems. So you should see this behavior once both Xcode and the OS have these updates. |
Comment by Fredrik Tõnisson-Bystam (JIRA) Right! Thanks for the clarification.
I initially thought that this was the case too - but then when the things behaved differently when I tried it by using `swiftc` I decided to post it here anyway. Great to see it being resolved, and now I know what the expected behaviour is in the future. Thanks! � |
Attachment: Download
Environment
OS: macOS Catalina 10.15.7
Xcode 12.1
swift -version:
Apple Swift version 5.3 (swiftlang-1200.0.29.2 clang-1200.0.30.1)
Target: x86_64-apple-darwin19.6.0
Additional Detail from JIRA
md5: f0f62de5ffaf8f722d3f3bedff58b925
Issue Description:
I sought to build an API that had two generics part of a function signature, where one of them was a subtype of the other, but expressed only with metatypes, not instances. As this relationship cannot be expressed at compile time, I tried to instead describe it using runtime preconditions. Basically something like this:
This above actually didn't seem to work and printed "false". But spelling out the same thing without the generics works just fine:
What's funny is, this only seemed to behave differently in a Playground (or when running it straight in an app built with Xcode). When I tossed the exact same code into a .swift file and built it with swiftc, both of the things printed "true" as I expected.
After asking around about it on a big iOS Slack team, I was encouraged by @natecook1000 to file a bug report.
The text was updated successfully, but these errors were encountered: