I feel like these two statements are at odds with each other. The first part, never dreading to upgrade the compiler, should be true for projects that have laid dormant for months. Imagine building a binary that fulfills its purpose, doesn’t have any big crashes, and so you just put the binary in production or wherever and forget about it for a year. Then, you decide you need to add some feature. Should you worry that upgrading the compiler after so long will mean features have been removed? Hopefully not!
Coming from a server development position, I can say that in many places that I’ve worked at (even at Mozilla, as forward reaching with technology as we are), it’s very common to not keep up with the latest version of a language. We actually specifically do not want to run the latest release in production. We want all horrible bugs and vulnerabilities to be patched out of new features before we ship that stuff. So, it’s actually quite common for us to upgrade huge versions at a time, often times from one LTS to the next. It’d be sad if someone in our position felt we couldn’t upgrade because then we’d need to do all this busywork fixing up our code for the newest compiler.
Calling these Epochs doesn’t do much for me. You’ve just changed the name of the thing we call “versions”. Instead of Rust v2.0, we just have Rust v2017. If Rust v2018 has features removed that existed in 2017, it’s essentially 2.0 (or 3.0 or whatever) and not backwards-compatible.
JavaScript has seemingly moved away from single digit version numbers to years as well. We had ES5, and ES6, but now we’re talking about ES2017 and ES2018. It doesn’t really matter. What matters is that JavaScript I write now, in 2017, will still do exactly what I told it to with a browser that implements ES2025. That’s backwards compatibility.
I care a lot about backwards compatibility of the libraries I write, perhaps more than many. While I appreciate the desire to get people to use the newer syntax, I’d dislike the compiler actively nagging me to use something that would make hyper no longer compile for users on older compiler versions. In this case, fixing the nagging requires me to completely remove support for the versions of the compiler that don’t understand dyn Trait. I think that to make such a change, I’d need a way to tell the compiler “OK sure, on #[cfg(has_dyn_trait)], I’ll use dyn Trait, but if not, please just use the older and keep working.”
If it were possible for the compiler to process cfg attributes before trying to parse the syntax gated by them, then this scheme could work. I can make use of the rustc_version crate to conditionally make use of new libstd APIs, but not to make use of new syntax features.