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-6872] Protocol as a generic argument is not suitable for conformance checking #49421

Open
werediver opened this issue Jan 30, 2018 · 7 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself

Comments

@werediver
Copy link

Previous ID SR-6872
Radar None
Original Reporter @werediver
Type Bug
Environment

Xcode 9.2 (9C40b), Swift 4.0.3

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

md5: 5285a477e2b79af708f9d2261a82a502

Issue Description:

It is possible to check if a generic parameter T is a subtype of generic parameter U if both are classes, but if U is a protocol, the check is impossible.

protocol P {}
struct S: P {}

func does<T, U>(_: T.Type, extend _: U.Type) -> Bool {

    print(U.Type.self) // P.Protocol

    return T.self is U.Type
}

print(P.Type.self) // P.Type

S.self is P.Type // true
does(S.self, extend: P.self) // false

Xcode 9.2 (9C40b)

$ swift --version
Apple Swift version 4.0.3 (swiftlang-900.0.74.1 clang-900.0.39.2)
Target: x86_64-apple-macosx10.9
@belkadan
Copy link
Contributor

@jckarter, do we have something tracking this already?

@jckarter
Copy link
Member

I can't find it, but this is a known design issue. The code is behaving correctly as currently designed—`U.Type` in the generic context represents a concrete metatype, so when you substitute `U = P` you get the concrete metatype for P, `P.Protocol`. This ends up asking "is S the type P", which is false, rather than "does S conform to P". A slightly different formulation works:

protocol P {}
struct S: P {}

func does<T, U>(_ x: T, extend _: U.Type) -> Bool {
  
  print(U.self) // P.Type
  
  return x is U
}

print(P.Type.self) // P.Type

S.self is P.Type // true
does(S.self, extend: P.Type.self) // false

@werediver
Copy link
Author

@jckarter

A slightly different formulation works ...

Whatever you meant does(S.self, extend: P.Type.self) still returns false in your sketch (in the original environment). Though it now prints "P.Type" in the console twice, it doesn't really help with the practical application.

But it's good to know you are aware of this limitation.

@jckarter
Copy link
Member

Sorry, I updated the comment. The new version should print `true`. You have to provide `Protocol.Type` as a generic argument in whole in order to get the behavior you want.

@werediver
Copy link
Author

@jckarter This time it really does what was expected. Thank a lot for this workaround!

@belkadan
Copy link
Contributor

Joe, what do you want to use this bug for? Diagnostics? Changing the interpretation?

@jckarter
Copy link
Member

It feels to me like a language design issue we should revisit at some point.

@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
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself
Projects
None yet
Development

No branches or pull requests

3 participants