Repository: rust
Issue: Surprising type inference on method call without explicit turbo-fish
Labels: C-enhancement,T-lang,A-inference

Please excuse the lack of specificity in the title, it reflects my lack of understanding what is going on here.

Here's a distilled example of what I'm going for:

```rust
trait FooMut {
    type Baz: 'static;

    fn bar<'a, I>(self, iterator: &'a I) where for <'b> &'b I: IntoIterator<Item= &'b &'a Self::Baz>;
}

struct DelegatingFooMut<T> where T: FooMut {
    delegate: T
}

impl<T> FooMut for DelegatingFooMut<T> where T: FooMut {
    type Baz = DelegatingBaz<T::Baz>;

    fn bar<'a, I>(self, collection: &'a I) where for <'b> &'b I: IntoIterator<Item= &'b &'a Self::Baz> {
        let collection = collection.into_iter().map(|b| &b.delegate);

        self.delegate.bar(&collection)
    }
}

struct DelegatingBaz<T> {
    delegate: T
}
```
([Play](https://play.rust-lang.org/?gist=3428bfa4fc81db0b73aaa66e76db7d5e&version=nightly))

This fails to compile (on stable and nightly) with:

```
error[E0271]: type mismatch resolving `for<'b> <&'b I as std::iter::IntoIterator>::Item == &'b &<T as FooMut>::Baz`
  --> src/main.rs:17:23
   |
17 |         self.delegate.bar(&collection)
   |                       ^^^ expected struct `DelegatingBaz`, found associated type
   |
   = note: expected type `&&'a DelegatingBaz<<T as FooMut>::Baz>`
              found type `&&<T as FooMut>::Baz`

error[E0308]: mismatched types
  --> src/main.rs:17:27
   |
17 |         self.delegate.bar(&collection)
   |                           ^^^^^^^^^^^ expected type parameter, found struct `std::iter::Map`
   |
   = note: expected type `&I`
              found type `&std::iter::Map<<&I as std::iter::IntoIterator>::IntoIter, [closure@src/main.rs:15:53: 15:68]>`
```

I played around a bit and found that changing the `bar` implementation to the following does compile:

```rust
fn bar<'a, I>(self, collection: &'a I) where for <'b> &'b I: IntoIterator<Item= &'b &'a Self::Baz> {
    let collection: Vec<&<T as FooMut>::Baz> = collection.into_iter().map(|b| &b.delegate).collect();

    self.delegate.bar::<Vec<&<T as FooMut>::Baz>>(&collection)
}
```
([Play](https://play.rust-lang.org/?gist=a2027c40f0fa2f0c07256d0e45328543&version=nightly))

But only with the turbo-fish on the call to `self.delegate.bar`; if I remove the turbo-fish it once again fails to compile:

```rust
fn bar<'a, I>(self, collection: &'a I) where for <'b> &'b I: IntoIterator<Item= &'b &'a Self::Baz> {
    let collection: Vec<&<T as FooMut>::Baz> = collection.into_iter().map(|b| &b.delegate).collect();

    self.delegate.bar(&collection)
}
```
([Play](https://play.rust-lang.org/?gist=d5bd0f6256af3c82dd4973be19269045&version=nightly))

This surprised me. From the error it seems like the compiler infers the type-parameter on the call to the delegate to be the same as the type parameter on the outer (delegating) method. I am not completely sure if this is a bug or intended behavior. If this isn't a bug I was hoping someone would perhaps be able to give me some insight into the what and why and a possible work-around. 

While collecting into a  `Vec` works as a workaround for now, I would really like to avoid having to allocate. I'm assuming that I might be able to make the original example work if I can work out a type for a turbo-fish there, but `std::iter::Map` seems to take the concrete type of its closure as a type parameter and I cannot figure out how to represent that in the turbo-fish type (if that's possible at all).