Some comments (speaking as someone who has followed rust for a while, but isn't heavily involved):
In general, rust wants to enable people to write code with unsurprising performance. So leaving it to the compiler to decide whether a value lives on the ~ heap wouldn't be appropriate for all use cases.
Similarly, the thing about the complicated lifetimes and borrowing shenanigans is that they exist to enable safe, efficient code that doesn't require a garbage collector.
Move semantics distinguish copyable-by-memcpy types, those can be primitives or user-defined types. It just can't be something like a ~ pointer or a type with a custom destructor or whatever, since having duplicates show up arbitrarily would mess up the associated bookkeeping. Primitive types also tend to implement the Clone trait so they can be explicitly copied with the .clone() method just like user-defined types implementing it.
Syntax is always a matter of taste... I think most people are happy with "let", there's always people who'd rather have s-expressions or significant-whitspace-delimited blocks instead of curly braces but also the other way around, I sympathize with distaste for the generics syntax to some extent... in the end you can't please everybody and you could probably do worse than making your language that is aimed at C++'s niche look a bit like C++.