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-11463] Type checker failure when bundling generics in a protocol #53863

Closed
mbrandonw opened this issue Sep 12, 2019 · 5 comments
Closed

[SR-11463] Type checker failure when bundling generics in a protocol #53863

mbrandonw opened this issue Sep 12, 2019 · 5 comments
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. compiler The Swift compiler in itself generics Feature: generic declarations and types type checker Area → compiler: Semantic analysis

Comments

@mbrandonw
Copy link
Contributor

Previous ID SR-11463
Radar None
Original Reporter @mbrandonw
Type Bug
Status Closed
Resolution Invalid
Environment

Xcode 11, beta 6

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

md5: dba09fb15865679b69759637aed6b1f2

Issue Description:

The following gives a type checker error:

protocol TypeBundle {
    associatedtype A
    associatedtype B
}

typealias Update<T: TypeBundle> = (T.A, T.B) -> T.A
typealias InoutUpdate<T: TypeBundle> = (inout T.A, T.B) -> Void

func toInout<T: TypeBundle>(_ update: @escaping Update<T>) -> InoutUpdate<T> {
    fatalError()
}

enum MyTypes: TypeBundle {
    typealias A = Int
    typealias B = ()
}

var update: Update<MyTypes>!

toInout(update)
// Cannot convert value of type 'Update<MyTypes>?' (aka 'Optional<(Int, ()) -> Int>') to expected argument type '(_.A, _.B) -> _.A'

If I manually unroll the typealiases I can get it to type check:

protocol TypeBundle {
    associatedtype A
    associatedtype B
}

typealias Update<T: TypeBundle> = (T.A, T.B) -> T.A
typealias InoutUpdate<T: TypeBundle> = (inout T.A, T.B) -> Void

func toInout<A, B>(_ update: @escaping (A, B) -> A) -> (inout A, B) -> Void {
    fatalError()
}

enum MyTypes: TypeBundle {
    typealias A = Int
    typealias B = ()
}

var update: Update<MyTypes>!

toInout(update)
@theblixguy
Copy link
Collaborator

cc @xedin

@belkadan
Copy link
Contributor

The error message is bad, but it's not really surprising the type-checker fails: there's no way to rederive MyTypes from Update<MyTypes>, because a typealias is just an alias. And that means the <T: TypeBundle> part of toInout can't be derived from the call site.

@mbrandonw
Copy link
Contributor Author

@belkadan yep thanks! we came to that conclusion after grappling with it for a bit. was mysterious at first.

@belkadan
Copy link
Contributor

We could still keep the bug around to improve the error message. We have a "cannot deduce generic parameter 'Blah'" that we use elsewhere, and I'm not sure why it's not kicking in here.

@xedin
Copy link
Member

xedin commented Sep 20, 2019

Just FYI after argument-to-parameter mismatch has landed this diagnostic has been improved:

```
error: generic parameter 'T' could not be inferred
toInout(update)
^
note: in call to function 'toInout'
func toInout<T: TypeBundle>(_ update: @escaping Update<T>) -> InoutUpdate<T> {
^
```

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
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 generics Feature: generic declarations and types type checker Area → compiler: Semantic analysis
Projects
None yet
Development

No branches or pull requests

4 participants