[swift-evolution] [Idea] Generic associated types

Xiaodi Wu xiaodi.wu at gmail.com
Sun Mar 12 01:50:02 CST 2017


On Sun, Mar 12, 2017 at 1:39 AM, Karl Wagner <razielim at gmail.com> wrote:

>
> On 12 Mar 2017, at 08:21, Xiaodi Wu <xiaodi.wu at gmail.com> wrote:
>
> Sorry, I'm confused. The following works:
>
> ```
> protocol Promise {
>   associatedtype Result
> }
>
> protocol Scanner {
>   associatedtype ScannerPromise : Promise
>   func frobnicate<T>(_: T) -> ScannerPromise
>     where ScannerPromise.Result == T
> }
> ```
>
> Why does it matter if `ScannerPromise` is generic or not?
>
>
> That’s some pretty strange syntax. I admit I didn’t even try that.
> ScannerPromise would necessarily have to be generic in this context,
> because I want to bind one of its associated types to a generic parameter
> from a function. There is no way a non-generic type could do that.
>
> That said, even though the compiler accepts your code, it doesn’t seem to
> actually work:
>
> protocol Promise {
>   associatedtype Result
>   func await() -> Result
> }
>
> protocol Scanner {
>   associatedtype ScannerPromise : Promise
>   func frobnicate<T>(_: T) -> ScannerPromise
>     where ScannerPromise.Result == T
> }
>
> func use<S: Scanner, T>(_ s: S, _ t: T) -> T {
> return s.frobnicate(t).await()
> }
>
>
>
> 3.0.2: Segfault
>
> 3.1:
>
> error: repl.swift:13:14: error: cannot invoke 'frobnicate' with an
> argument list of type '(T)'
>     return s.frobnicate(t).await()
>              ^
>
> repl.swift:13:14: note: expected an argument list of type '(T)'
>     return s.frobnicate(t).await()
>

That's because your `T` in `use` has no relationship with your `T` in
`protocol Scanner`; you just happen to have chosen the same letter of the
alphabet. This becomes clear if you rename:

```

func use<S: Scanner, U>(_ s: S, _ t: U) -> U {

  return s.frobnicate(t).await()

}


*// cannot invoke 'frobnicate' with an argument list of type '(U)'*

*// expected an argument list of type '(T)'*
```

However, this works:

```

func use<S: Scanner, T>(_ s: S, _ t: T) -> T

  where S.ScannerPromise.Result == T {

  return s.frobnicate(t).await()

}
```

...or just this:

```

func use<S: Scanner>(

  _ s: S, _ t: S.ScannerPromise.Result

) -> S.ScannerPromise.Result {

  return s.frobnicate(t).await()

}
```

- Karl
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-evolution/attachments/20170312/dde4b9a1/attachment.html>


More information about the swift-evolution mailing list