rfcs icon indicating copy to clipboard operation
rfcs copied to clipboard

Fragment Specifiers for Generic Arguments

Open JarredAllen opened this issue 2 years ago • 5 comments

I wrote up my thoughts from this rust-internals thread into an RFC.

Rendered

JarredAllen avatar Jun 01 '23 20:06 JarredAllen

This RFC does not include specifiers for where-clause, which is highly related to generics. Is this intentional? Maybe we should mention this in text.

I think this would be nice longer-term, but at least for now, the extremely simple case of being able to check for pieces like <T, const N> without resorting to using token-trees is pretty good on its own. That said, the inclusion of bounds in this RFC does beg the inclusion of where bounds too.

clarfonthey avatar Jun 03 '23 00:06 clarfonthey

I like the general idea of this RFC, but I don't like that a macro accepting $( $p:generic_param $( : $b:generic_bound )? ),* can accept illegal syntax (like a lifetime followed by a trait bound, or a const generic followed by a lifetime bound).

I also don't like that matching all generics syntax with the more granular fragments is pretty verbose:

< $(
    $( #[$m:meta] )*
    $p:generic_param
    $( : $( $b:generic_bound )? )?
    $( = $d:generic_default )?
),* $(,)? >

a where clause could be written like this, if we require trailing commas:

where $(
    $( $l:lifetime $( : $( $b1:generic_bound )? )? , )?
    $( $( for $f:generic )? $t:ty $( : $( $b2:generic_bound )? )? , )?
)*

But this isn't forward compatible with

Aloso avatar Jun 04 '23 14:06 Aloso

Maybe it would be best to remove :generic_param, :generic_bound and :generic_default from the RFC (unless you can give an example where they're useful), and instead add :where_clause.

Aloso avatar Jun 04 '23 14:06 Aloso

I added a :where_clause, as per multiple requests. They were excluded initially because I forgot that they existed, not for any real reason.

JarredAllen avatar Jun 06 '23 00:06 JarredAllen

I like the general idea of this RFC, but I don't like that a macro accepting $( $p:generic_param $( : $b:generic_bound )? ),* can accept illegal syntax (like a lifetime followed by a trait bound, or a const generic followed by a lifetime bound).

I also don't like that matching all generics syntax with the more granular fragments is pretty verbose:

Yeah, sadly the only way to prevent it from accepting illegal syntaxes like const N: 'a or 'a: usize would make it even more verbose and complicated to match the entire generics syntax, which makes your other point worse. Though, you don't need the $()? around :generic_bound anymore, I didn't know that nothing could be put there and have since updated it to allow that, so it's slightly less verbose.

I tried to strike a happy medium where relatively few illegal syntaxes are allowed (I think they've all been said on this page? Unless I'm missing some) but also it's reasonably non-verbose to parse the full generic parameter definition syntax and we're not adding too many new fragment specifiers into the language, and the split is done in such a way that it could be useful for implementing macros.

I'm open to any suggestions you have for making that trade-off better, but this was the best balance between the two goals I could think of.

JarredAllen avatar Jun 06 '23 00:06 JarredAllen