With the caveat that syntax is the ultimate bikeshed topic, one (IMO) syntactic wart is the special pattern syntax:
1. "Operators" have different meanings. `1 | 2` and `1..=2` mean something different in patterns than in expressions. Here is a silly example: https://rust.godbolt.org/z/76Ynrs71G
2. Ambiguity around when bindings are introduced. Notice how changing a `const` to a `let` breaks the function: https://rust.godbolt.org/z/aKchMjTYW
3. Can't use constant expressions, only literals. Here's an example of something I expect should work, but does not: https://rust.godbolt.org/z/7GKE73djP
I wish the pattern syntax did not overlap with expression syntax.
This actually bit me in the a__ when I misspelled my enum variant and instead match created a variable named like that, that captured everything and I got only a warning and very wrong code.
I think there should be `let`s inside match block if matching creates some variables.
fn func<'a>() means that 'a must outlive execution time of func
but
T:'a means that references contained in T must live longer than 'a
and
'a:'b means 'a must live longer than 'b (that's consistent at least)
Maybe:
fn 'a:func() {
or
fn func() 'a:{
would be better for indicating that 'a should outlive function execution.
Maybe some directional character would be better than : (> is probably out of question because of <> generics)
----
I feel like structs that don't have 'static lifetimes because they contain some borrows should have it indicated in their name.
For example:
struct Handle&<'a> { n:&'a Node }
or even
struct Handle&'a { n:&'a Node }
or
struct Handle& 'a:{ n:&'a Node }
to indicate that 'a must outlive the struct.
Then you could use it:
let h = Handle& { n: &some_node };
Maybe functions that create non-static struct might have & at the ends in their names.
Like
vec![].into_iter().map()
but
vec![].iter&().map()
You could easily see that you are dealing with something you should treat like a borrow because it contains borrows. Such structs would be sort of named, complex borrow and raw '&' borrow would be anonymous or naked borrow.
Not sure if it would also be nice to differentiate structs with &mut
----
I would just like to separate lifetimes syntax from generics syntax because those two things have nothing to do with each other from the point of view of the user of the language.
----
I would also like to have
while cond {} else {}
where else is only entered if cond was false from the start. But that's a wish not specific to Rust.
Using clearly defined bit sizes (i32, f64) rather than legacy naming conventions (int, double) is a good idea, the language could be really quite something if they switch to S-expressions.
Syntax or semantics? Not a lot for syntax... maybe the "turbofish" syntax with generic types is a bit too much line noise: <Foo<_> as Bar<_>>::baz<_>()
1. "Operators" have different meanings. `1 | 2` and `1..=2` mean something different in patterns than in expressions. Here is a silly example: https://rust.godbolt.org/z/76Ynrs71G
2. Ambiguity around when bindings are introduced. Notice how changing a `const` to a `let` breaks the function: https://rust.godbolt.org/z/aKchMjTYW
3. Can't use constant expressions, only literals. Here's an example of something I expect should work, but does not: https://rust.godbolt.org/z/7GKE73djP
I wish the pattern syntax did not overlap with expression syntax.