[Pre-RFC] Genericity over static values

The simple answer to your question is that if you write let x = 1 >> 2; the parser knows that the expression continues as soon as it hits the >>, purely by knowing that no type context has been established, without needing any other context at all, whereas in a parameter list it would have to look ahead to see if whatever is farther to the right is an expression or something that can follow a type. (A similar kind of difficulty is why we have to write Vec::<usize>::new() instead of Vec<usize>::new().)

My understanding is that right now the rustc parser expects to be able to tell whether it's in an expression or type context without having to do lookahead. This is admittedly a property of the current reference compiler that sometimes seems to be too restrictive, and could change, but it does have its good points (besides the reference compiler, other parsing tools are easier to create if the language is designed this way).

Regarding your "austere" solution, I don't think that allowing only literals and named constants will give you the same expressiveness, because there would be no way to translate something like this:

trait SomeTrait {
    fn do_stuff<const N: usize>(x: Foo<N>) -> Foo<{N-1}>;
}

I will think about where clauses and your comments some more tonight. It occurs to me that the ability of match patterns to overlap might not be such a big deal after all. What's important for coherence checks is that it has to be possible to give some kind of verdict on whether two constraints can overlap, whether or not match patterns do the same thing. Furthermore, we could recover something approximating the fuller match pattern semantics if negative bounds eventually become possible:

// Don't worry about the syntax for this example.
// The point is that you can define overlapping impls, then make them compatible by giving one a negative bound that handles it.
impl<const N: usize> SomeTrait<N> for Foo<5>
      where const N: 5...7 {/* ... */}
impl<const N: usize> SomeTrait<N> for Foo<N>
      where const !N: 5...7, const N: 2...10 { /* ... */ }