Talking about a standard that doesn't even exist yet makes little sense. If/when an official standard for Rust is created, questions like these will be taken into account. Until then, we can't make any claims about what a "conforming compiler" must to support.
editions => features
in cargo-aware std
?
Concern: 2018
and 202a
crates shouldn't see conflicting impl
-s of a trait
, etc. But these issues should already exist when features drive conditional compilation today..
That will require slowing the rate of improvements to rustc
. There is a wg-grammar chartered to create a quasi-standard syntax for Rust that is not dependent on rustc
. However, standardizing the semantics of things like borrow checking will require that improvements such as Polonius not occur. Otherwise Rust crates that compile on rustc
may not compile on a competing standard-conforming compiler.
Personally, given Rust's 6-week release train, I believe that Rust will need a few more years of development / improvement before Rustaceans can afford to slow its progress enough for an IETF standard, let alone an ISO standard.
Not necessarily. You can standardize "Rust 1.42" and still keep improving rustc, rustc just won't implement (just) "Rust 1.42" anymore. It's like how the Sealed Rust project is seeking to strictly formalize a subset of Rust; you can formalize a subset of what rustc actually implements, and call the rest implementation extensions. The difference only really comes up when you get people telling you to program to the specification instead of the compiler (of which there is benefit, I will not argue against.)
I think people overestimate the benefit of a standard and/or misattribute what they want to being the standard (when it's maybe multiple implementations, or maybe just a design specification distinct from the implementation). In either case, this isn't the thread to discuss a spec in.
I disagree with this. While there isn't a standard yet, planning for forward compatibility is always useful. Editions are an excellent way of planning for this, especially if the standard and the editions move together. This is entirely analogous to talking about K&R C (not a standard), or C99, C11, and C18 (all of which are standards). The only difference is that rust got the naming convention correct right from the start (full 4 digit years, so we don't have to worry about namespace collisions for another 10,000 years).
I fully agree with you on this! IMHO, rust hit 1.0 too soon, there are a number of weird things that don't feel very smooth to me (not wrong per se, just not smooth). That said, I agree with that @CAD97 said:
I also agree with:
In either case, this isn't the thread to discuss a spec in.
I was only stating that editions are good ways of marking what you're compatible with, and what you aren't compatible with, and noting that it would very useful whenever rust is fully specified in the future.
I was just looking at this post on users where someone was asking why a Range
was moved into the loop, and I thought that this could be solved with editions. We could provide a new set of range types and on the 202x+ edition we desugar range literals to the new types and on 2015/2018 we desugar range literals to the old types.
The new range types would have all public fields, and would implement Copy
. They would also implement IntoIterator
which would convert them into the old range types or some new custom range iterator.
I don't know if this is worth the churn, but the range types we have right now are a pain to use because they aren't Copy
and because RangeToInclusive
doesn't expose it's fields. This change wouldn't require any sort of api gating, so it should be relatively simple to implement.
If we want to clean up the api, we can move the old range types to a seperate module and rexport them out of core::ops
and eventually remove them from core::ops
, but that's a different dicussion.
OK, so if I understand this correctly, rustc version 1.N is able to compile code that was able to be compiled by version 1.0 - 1.N, inclusive, correct? Is this a requirement for any conforming rust compiler? Put another way, if I decided to write a new rust compiler, but only wanted to support edition2021 forwards, would that be a non-conforming compiler because it couldn't compile code that was valid earlier on?
To back up from the the whole "Rust has no formal spec yet" tangent, although there's obviously no official / de jure answer to this, we can very easily give a simple and clear de facto answer:
Yes, because one of the major goals of editions is to enable crates to interoperate across however many editions we end up creating in the future, and failing to support a large chunk of crates.io crates is clearly a non-starter for any competing Rust implementation.
Although I'd probably phrase it differently since the precise wording you chose arguably implies that it'd also have to be "bugward compatible" with any code that Rust 1.0 compiled but later versions intentionally broke for whatever reason other than edition changes. I think we can safely assume nobody would expect or ask for a competing compiler to attempt that.
Yes, because one of the major goals of editions is to enable crates to interoperate across however many editions we end up creating in the future, and failing to support a large chunk of crates.io crates is clearly a non-starter for any competing Rust implementation.
Oof... I think that would effectively mean that there will only ever be one rust compiler in the wild. Although I guess a non-conforming compiler could explicitly state that it only supports edition 20XX forwards, and give hard errors when it encounters code from earlier...
To be fair, there are very few breaking changes between editions. IIRC most of it is just stuff like "async
is a keyword in 2018 but a legal identifier in 2015". Compared to all the other things a competing Rust compiler would have to support, I doubt this comes anywhere near the list of hardest problems to solve.
Supporting multiple editions is specifically constrained to be a low burden for implementors. Only surface syntax is allowed to differ based on the edition flag:
The Rust compiler supports multiple editions, but must only support a single version of "core Rust". We identify "core Rust" as being, roughly, MIR and the core trait system; this specification will be made more precise over time. The implication is that the "edition modes" boil down to keeping around multiple desugarings into this core Rust, which greatly limits the complexity and technical debt involved.
Adding support for an older edition should be both easy and straightforward, especially compared to most of the other work required to implement a Rust compiler.
The Rust compiler supports multiple editions, but must only support a single version of "core Rust" . We identify "core Rust" as being, roughly, MIR and the core trait system; this specification will be made more precise over time. The implication is that the "edition modes" boil down to keeping around multiple desugarings into this core Rust, which greatly limits the complexity and technical debt involved.
Thank you for the link to that RFC, I'll read it over when I have time.
OK, so things like async
are sugar only, correct? Thus, since they can be lowered to MIR, they 'don't really count' as they can be added easily, correct? I just want to be sure I'm understanding things correctly.
That said, if I understand the statement 'must only support a single version of "core Rust".' correctly, then this is great news! Once core rust has stabilized a little more, the spec can be for that. Editions can just be sugar instead of a full ISO/IEC spec, kind of like how HTML 5 is a 'living spec'.
So, I know I'm hijacking this thread (I'll start another thread if there is enough interest), but has any work been done on making a real spec for core rust? Is that what Sealed Rust and RustBelt heading towards?
OK, so things like
async
are sugar only, correct? Thus, since they can be lowered to MIR, they 'don't really count' as they can be added easily, correct? I just want to be sure I'm understanding things correctly.That said, if I understand the statement 'must only support a single version of "core Rust".' correctly, then this is great news! Once core rust has stabilized a little more, the spec can be for that. Editions can just be sugar instead of a full ISO/IEC spec, kind of like how HTML 5 is a 'living spec'.
The short answer is probably "yes" to all of that, but the only way to "be sure you're understanding things" is to read the RFC on the subject. For example, whether async
is "sugar only" kinda depends on exactly what you mean by "async
" and "sugar", since it does affect borrow checking and in some sense was bundled with the std::futures
machinery and a generators feature that's still unstable. But in general, anything else I could say here would just be copy-pasting text from that RFC.
Feel free to start a new thread if you have additional questions after reading the RFC.
So, I know I'm hijacking this thread (I'll start another thread if there is enough interest), but has any work been done on making a real spec for core rust? Is that what Sealed Rust and RustBelt heading towards?
Depends on what "real spec" means. If we're talking a formal ISO specification document like C++, probably not. If we're talking an officially endorsed exhaustive and normative description of Rust semantics, then absolutely yes. The Grammar working group is yet another project tackling a piece of this spec work.
I don't know if this is worth the churn, but the range types we have right now are a pain to use because they aren't
Copy
and becauseRangeToInclusive
doesn't expose it's fields. This change wouldn't require any sort of api gating, so it should be relatively simple to implement.
Would adding a Copy
bound be a breaking change? Why?
No, it wouldn't, but it is an explicit design decision not to add Copy
to iterators directly. You can see this with other iterators like std::iter::Empty
and std::iter::Once
, even though both of those could be Copy
they aren't. This is fine for iterators because they are usually one shots, but ranges have a much broader use than just iterators. So forcing them inline makes them harder to use.
If we're talking an officially endorsed exhaustive and normative description of Rust semantics, then absolutely yes.
I'm completely comfortable with this, as long as it is mathematically unambiguous. Note that UB is actually unambiguous in many cases; I know that if I do certain things, then I know without ambiguity that I'll be getting UB. I just get really annoyed when I can't decide if something is legal rust or not, and when I can't decide what something actually means.
It would cause churn, and async has used up all of Rust's churn budget for the next decade.
What about potential massive drastic refactorings after stabilisation of const generics and GATs?
Rust is currently missing some fundamental pieces needed for good design, so I think more waves of churn is inevitable if Rust is going to evolve.
Both will cause churn in the wild, but the important difference is that removal of deprecated APIs forces code changes before adopting a new edition. Use of cool new features is voluntary, and doesn't have to be done before switching editions.
Are you suggesting that the new range type doesn't implement Iterator
directly? That would break a lot of code, since code like (1..n).enumerate()
no longer compiles. If you really need the Copy
bound, you could create a struct that implements Copy
and From<Range>
.
Yes, but only on the new edition. We could have rustfix automatically add into_iter
if it detects any of Iterator
's methods being used on ranges. So there isn't breakage, but it will require some more work to migrate.
If you really need the
Copy
bound, you could create a struct that implementsCopy
andFrom<Range>
.
That's true, I just find that to be really inconvenient, especially when the whole point of Range*
is convenience.
There is also the problem that RangeToInclusive
has private fields, which make it less ergonomic to use than any other range type.
Admittedly, these are not really a huge deal, I just thought they would make the range sugar much easier to use. (As I said in the op, I don't know if this is worth the cost)