Use of ty macro non-terminal in trait bounds

2fc4b59
Opened by Stuart Glaser at 2020-04-30 18:43:15
macro_rules! impl_somethingable {
    ($Base: ty, $Block:ty) => {
        impl<'a, T> Somethingable for $Block where T: $Base {
        }
    }
}

impl_somethingable!(ATrait, A);
<anon>:15:52: 15:60 error: each predicate in a `where` clause must have at least one bound in it
<anon>:15         impl<'a, T> Somethingable for $Block where T: $Base {
                                                             ^~~~~~~~
<anon>:15:56: 15:60 error: expected one of `,` or `{`, found `ATrait`
<anon>:15         impl<'a, T> Somethingable for $Block where T: $Base {
                                                                 ^~~~

The solution is to use $ident instead of $ty, but this is non-obvious to the user, especially since it's perfectly ok to have ATrait in that location.

Playpen: http://is.gd/AMUJDw

cc @huonw

  1. Triage: still an issue.

    Huon Wilson at 2015-11-18 06:49:29

  2. Current output, still doesn't point at the possibility of changing $Base:

    error: expected one of `(`, `,`, `?`, `for`, `{`, lifetime, or path, found `ATrait`
     --> src/main.rs:4:55
      |
    4 |         impl<'a, T> Somethingable for $Block where T: $Base {
      |                                                       ^^^^^ expected one of 7 possible tokens here
    ...
    9 | impl_somethingable!(ATrait, A);
      | ------------------------------- in this macro invocation
    

    Esteban Kuber at 2017-08-10 17:05:32

  3. I removed <kbd>A-diagnostics</kbd> because I would like the original code using $:ty to work as written. Refusing to treat $:ty containing path as a trait bound is an unnecessary limitation.

    David Tolnay at 2018-06-09 19:36:31

  4. Also ident is not always a possible solution, like if I modify the example slightly:

    trait ATrait {
        type AType;
    }
    
    macro_rules! impl_somethingable {
        ($Base: ident, $Block:ty) => {
            impl<'a, T> Somethingable for $Block where T: $Base {
            }
        }
    }
    
    impl_somethingable!(ATrait<AType=u32>, A);
    

    diwic at 2018-06-17 08:30:49