associated type not normalized when a where-clause is present

3e81377
Opened by Ariel Ben-Yehuda at 2024-08-28 05:04:05

Affected Versions

At least 1.3, 1.4, rustc 1.5.0-nightly (11a612795 2015-10-04)

STR

trait Foo { type Bar; }
impl<T> Foo for T { type Bar = u64; }
fn foo<T>() -> <T as Foo>::Bar
    where T: Foo // <- the code compiles if this is removed
{ 1 }
fn main() {}

Expected Result

the code should compile

Actual Result

<anon>:7:14: 7:15 error: mismatched types:
 expected `<T as Foo>::Bar`,
    found `_`
(expected associated type,
    found integral variable) [E0308]
<anon>:7     x = Some(1);
                      ^

cc @nikomatsakis

  1. The root cause is that selection picks the where-clause candidate over any impl candidate, and this does not allow projection to make progress. This looks to be hard to fix.

    Ariel Ben-Yehuda at 2015-10-07 22:03:10

  2. Yes, this is to some extent a known limitation and the "expected result", but I would still classify it as a bug.

    Niko Matsakis at 2015-10-08 18:47:47

  3. (Note: Deleted and reposted since I screwed up the first version, and realized I could minimize it more)

    I hit this case while trying to work around #68375 - I'm pretty sure it's the same bug

    pub trait Data {
        type Elem;
    }
    
    pub struct ViewRepr<A>(A);
    
    impl<'a, A> Data for ViewRepr<&'a A> {
        type Elem = A;
    }
    
    type ArrayBase<S> = ArrayBaseInner<S, <S as Data>::Elem>;
    pub struct ArrayBaseInner<S: Data<Elem = Elem>, Elem> {
        ptr: *mut Elem,
        d: S,
    }
    
    fn std1d<'a>(_: ArrayBase<ViewRepr<&'a f64>>) {}
    
    fn map_axis<'a, F>(f: F)
    where 
        F: FnMut(ArrayBase<ViewRepr<&'a f64>>)
    {}
    
    fn std() {
        map_axis(std1d);
    }
    
    error[E0631]: type mismatch in function arguments
      --> test.rs:25:14
       |
    17 | fn std1d<'a>(_: ArrayBase<ViewRepr<&'a f64>>) {}
       | --------------------------------------------- found signature of `for<'a> fn(ArrayBaseInner<ViewRepr<&'a f64>, <ViewRepr<&'a f64> as Data>::Elem>) -> _`
    18 | 
    19 | fn map_axis<'a, F>(f: F)
       |    --------
    20 | where 
    21 |     F: FnMut(ArrayBase<ViewRepr<&'a f64>>)
       |        ----------------------------------- required by this bound in `map_axis`
    ...
    25 |     map_axis(std1d);
       |              ^^^^^ expected signature of `fn(ArrayBaseInner<ViewRepr<&f64>, f64>) -> _`
    

    Greg Morenz at 2020-01-20 14:53:49

  4. Nope, you have a return value in std1d but not in the where clause for map_axis

    RustyYato at 2020-01-20 15:09:35

  5. Oops, you're right, minification mistake. Fixed that above, it doesn't substantially change the error message.

    Greg Morenz at 2020-01-20 15:26:27

  6. @gmorenz this is because of the lifetime parameter. Because the associated type could depend on the choice of lifetime parameter, it doesn't get normalized.

    That does seem related to this Issue.

    RustyYato at 2020-01-20 16:41:12

  7. Triage: no change

    Maayan Hanin at 2022-10-17 19:30:59

  8. Current output:

    error[E0308]: mismatched types
     --> src/main.rs:7:3
    5 | fn foo<T>() -> <T as Foo>::Bar
      |                --------------- expected `<T as Foo>::Bar` because of return type
    6 |     where T: Foo // <- the code compiles if this is removed
    7 | { 1 }
      |   ^ expected associated type, found integer
      |
      = note: expected associated type `<T as Foo>::Bar`
                            found type `{integer}`
    help: consider constraining the associated type `<T as Foo>::Bar` to `{integer}`
      |
    

    Dylan DPC at 2024-08-28 05:03:39