> So what exactly is the "much smaller and cleaner language struggling to get out" of Rust? If I'm understanding the post right, that language still has references, lifetimes, traits, enums, etc., because all of those features cohere; you can't remove just one and expect the rest of the language to still work. Once you grant all those features, your language isn't much smaller or cleaner than Rust; your language pretty much is Rust.
I think there's an argument to be made that you could in fact make a simpler language than Rust while keeping the core concept. This variant of the language would remove:
- the Copy trait
- reborrowing
- deref coercion
- automagic insertion of `into_iter` in loops
- automatic call to drop at the end of scope (instead you'd have to call it by yourself or get an compiler error)
- trait bounds having an automatic `:Sized` bound by default.
- lifetime elision
- no “match ergonomics”
- and likely a few other pieces of “magic” that can be hard for beginner to grasp, but that's what I had at the top of my head.
This language would be much simpler, by having fewer concepts and a lot less “magic”, but it would also be much more cumbersome to use in a day to day basis, as all of the above are clever workaround designed to make common tasks as straightforward as possible, and I don't think anyone would prefer to use it than using Rust itself. It may be useful as an instructional tool when introducing Rust to students though.
I'm actually unconvinced you could do without `Copy`. It's both in the core of the language and essentially required for stuff like shared references to work correctly. Copying could be replaced by a keyword instead of happening implicitly, but that's different from removing the concept entirely from Rust.
The rest, sure, you could do without (reborrowing can't be emulated but I don't think it's strictly necessary to write real code). I'd add catchable exceptions and the use of traits instead of explicit modules as things that I think tremendously complicate the language semantics and are almost certainly not strictly necessary to achieve Rust's language goals.
You can already write a Rust program that never relies on Copy, by explicitly calling .clone() whenever you need to copy something. It's just that this would be insane.
`.clone()` is usually implemented in terms of `Copy`, but the real problem that I don't know how to solve without `Copy` is the use of references. Every time you call a function on a shared reference (including the one used by `clone`) you are implicitly copying the reference. It only works because of `Copy`. Without it, I think you would need unsafe code or something in order to call a shared method and retain access to the original reference, which would pretty much no longer be Rust since the vast majority of methods wouldn't be correctly expressible in the safe subset. There might be reborrowing style tricks you could use to get around this, but as you said the "core" of Rust shouldn't have reborrowing. Or maybe you could implement clone on references in unsafe code and then just explicitly take a reference to the reference every time you needed to duplicate it... There is also the linear type trick you can use to copy a value by pattern matching it destructively, explicitly enumerating all possibilities, and then generating a fresh product with each possibility listed twice, but that cannot implement copy for references.
In any case, I think it's just true that `Copy` is quite fundamental to Rust. IMO even if you could somehow turn all instances of it into syntactic sugar (which I think is not true, as the `Cell` example shows), the surface language you used would be sufficiently unlike Rust that it wouldn't really be Rust anymore.
Well no, some objects (notably Cell<>) require Copy, because clone(&self) takes a reference and can do arbitrary things with the Cell (including overwriting the data its ref points to via Cell::set())
Do those features actually cause difficulty for anyone other than compiler engineers, compared to not having them? I haven't personally seen, e.g., newbies stumbling over them; they're actually designed remarkably well to fade into the background and Just Work (i.e., you don't notice they're there, but you definitely would notice if they went away). Yes, there's something to be said for minimalism in language design, but Rust without those features still isn't very minimalistic, so dropping them would seem to bring about most of the costs of minimalism without the benefits.
> Do those concepts actually cause difficulty for anyone other than compiler engineers, compared to not having them? I haven't personally seen, e.g., newbies stumbling over them;
Pretty much all of the features in the list are things that either I have struggled with when learning Rust (the Copy trait and lifetime elision), or I've seen beginner struggle understanding (both new hires, or students at the place when I gave Rust lectures).
I think there's an argument to be made that you could in fact make a simpler language than Rust while keeping the core concept. This variant of the language would remove:
- the Copy trait
- reborrowing
- deref coercion
- automagic insertion of `into_iter` in loops
- automatic call to drop at the end of scope (instead you'd have to call it by yourself or get an compiler error)
- trait bounds having an automatic `:Sized` bound by default.
- lifetime elision
- no “match ergonomics”
- and likely a few other pieces of “magic” that can be hard for beginner to grasp, but that's what I had at the top of my head.
This language would be much simpler, by having fewer concepts and a lot less “magic”, but it would also be much more cumbersome to use in a day to day basis, as all of the above are clever workaround designed to make common tasks as straightforward as possible, and I don't think anyone would prefer to use it than using Rust itself. It may be useful as an instructional tool when introducing Rust to students though.