Using type with local type parameters has confusing error

7429394
Opened by bluss at 2022-02-10 12:45:18

Using type with local type parameters or Self should have a clearer error.

Reproduce with: (playpen link)

struct Foo;

impl Foo {
    fn method<T>(&self) {
        type X = (Self, T);
    }
}

Current errors have a suggestion ("try..") that doesn't apply.

error[E0401]: can't use type parameters from outer function; try using a local type parameter instead
 --> <anon>:6:19
  |
6 |         type X = (Self, T);
  |                   ^^^^ use of type variable from outer function

error[E0401]: can't use type parameters from outer function; try using a local type parameter instead
 --> <anon>:6:25
  |
6 |         type X = (Self, T);
  |                         ^ use of type variable from outer function
  1. Why is this disallowed?

    Alexey at 2016-12-05 17:43:21

  2. @KalitaAlexey

    Nested items are independent from their parent item for everything except for privacy and name resolution. This includes type parameters.

    The suggestion is in fact correct - this can be fixed by something like

    struct Foo;
    
    impl Foo {
        fn method<T>(&self) {
            type X<This, T> = (This, T);
        }
    }
     
    fn main() { }
    

    Ariel Ben-Yehuda at 2016-12-05 18:24:58

  3. I don't think the user will understand This in type X<This> to be a "local type parameter"; I didn't. If that's just the issue, it could call it something else.

    bluss at 2016-12-05 18:30:44

  4. Hi @arielb1, I meant that I think that type X = (Self, T) in a function's body can be useful. You said that nested items are independent. What's a reason?

    Alexey at 2016-12-05 20:32:58

  5. cc https://github.com/rust-lang/rust/pull/47574 current error message:

    error[E0401]: can't use type parameters from outer function
     --> src/main.rs:6:19
      |
    4 | impl Foo {
      | ---- `Self` type implicitly declared here, by this `impl`
    5 |     fn method<T>(&self) {
    6 |         type X = (Self, T);
      |                   ^^^^
      |                   |
      |                   use of type variable from outer function
      |                   use a type here instead
    
    error[E0401]: can't use type parameters from outer function
     --> src/main.rs:6:25
      |
    5 |     fn method<T>(&self) {
      |        ------ - type variable from outer function
      |        |
      |        try adding a local type parameter in this method instead
    6 |         type X = (Self, T);
      |                         ^ use of type variable from outer function
    
    error: aborting due to 2 previous errors
    

    csmoe at 2018-09-17 11:29:36

  6. It seems to me what this is missing is a note explaining the same thing as https://github.com/rust-lang/rust/issues/37892#issuecomment-264934123.

    Esteban Kuber at 2019-10-11 19:59:16

  7. Just had the same issue, just a little different implementation:

    enum MyEnum {}
    
    impl MyEnum {
        fn do_something(result: impl FnOnce()) {
            result();
        }
    
        fn do_something_extra() {
            fn inner() {
                Self::do_something(move || {}); // can't use generic parameters from outer function E0401
                MyEnum::do_something(move || {}); // no error
            }
            inner();
        }
    }
    

    It seams that accessing Self from inner functions is not allowed. This doesn't seem logical and error is way too confusing (or probably describing something else completely).

    Rostyslav Lesovyi at 2022-02-10 12:45:18