withoutboats: withoutboats: [T; {N * foobar(N, 2)}]

Are you suggesting that [T; N * foobar(N, 2)] is… an error?

withoutboats: withoutboats: Expressions containing no params can also be wrapped in braces, but it is not necessary except for parsing reasons (e.g. Foo<6 > 7> ).

To give some background, the use of braces came up as a solution to the parsing problem: e.g. Foo<CONST_A + CONST_B> is very annoying and complicated to parse correctly. You end up needing what is sometimes called a “cover grammar”, where you have “type or expression” in your grammar which parses all valid types and all valid expressions, and some syntax overlaps in a way that requires name resolution output (or worse, type resolution for T::Assoc ) to tell between types and expressions. But we can side-step that requirement for just literals and single identifiers, where {1} and {N} would be too jarring.

We came up with {expr} to avoid the whole question, but that makes it unnecessary and irrelevant for [T; expr] . The unification implications of {expr} were just a cute hack piggybacking on the fact that expressions require braces, but referring to a const parameter doesn’t, so that can be reused to distinguish between “potentially unknowable (before instantiation) expressions” and “definitely a const generic parameter” quite easily.