Please don't include things like this in comments.
Changing the size of int. Changing methods to introspect the type of their arguments and do things differently. And so on.
> There were only 7 releases since go1 and I fail to find any breaking change in the language specification. On the other side each Rust release has a fat list with "BREAKING CHANGES".
Because we have a very specific definition of "breaking change" that is primarily concerned with the practical effect of changes we make. Go does not consider these changes "breaking". Using Go's definition (changes to the language definition), we have no "breaking changes".
If we were to change the size of int (something we will not do, by the way, due to the practical effects of making such a change), then we would list it under "breaking changes", even if we were technically allowed to do it. That's because we care about the practical effects of our changes, not just the letter of the language definition.
> Many Rust packages only work with specific Rust versions(i.e. nightly).
Because they are explicitly opting into unstable features that are carefully marked as such. We can't stop packages from doing that. Nor can any other language.
> The rust ecosystem(std lib, tools etc) is also way behind Go in terms of stability.
The parts of the Rust standard library that are marked stable have remained completely backwards compatible, in both interface and implementation.
> Why do you need rustup if Rust is so backward compatible?
Because it's nice to keep your compiler up to date and to target different platforms?
>> The parts of the Rust standard library that are marked stable have remained completely backwards compatible, in both interface and implementation.
This looks like a breaking change on a stable API. Am I wrong? https://github.com/rust-lang/rust/pull/28811
Rust doesn't have backwards incompatible language changes.
> This looks like a breaking change on a stable API.
No. It is a method addition. It is breaking only in the sense that code that didn't explicitly invoke the previous "as_ref" method might call this new method instead. It's the moral equivalent of:
type A struct { ... }
type B struct {
A
}
func (a ﹡A) Foo() {}
and then a later version of Go adds a method: func (b ﹡B) Foo() {}
Such that code that called Foo() on an instance of ﹡B might call the new method instead. Go can make those changes.Compiler changes are the norm everywhere? I'm not sure what you're trying to say here.
> This looks like a breaking change on a stable API. Am I wrong?
Yes and no.
Rust's policy on breaking changes is that changes that can be fixed by properly qualifying an implicit path are not breaking. Otherwise, adding any method to anything would be a breaking change. In this case, you can use the UFCS syntax to disambiguate.
So it's an "allowed" kind of breakage because not allowing this means freezing the stdlib.
(Go doesn't have this issue due to lack of generics, overloading, and interface-based overloading. Edit: actually, go does too, due to inheritance, but that is easier to avoid and isolate. In rust you can always write client code that breaks if the stdlib adds a method, anywhere. This is true for most typed languages).
Anything that has the chance of practically breaking things is still run through crater (which tests impact on the ecosystem) and as you can see that PR had minimal impact.
Steve has pointed out that go did have this issue as it has a limited level of auto-deref, which it has changed in the past: implementations performed two levels of auto-deref when executing methods when the spec only requires one, the implementations were changed to only allow a single auto-deref: https://golang.org/doc/go1.4#methodonpointertopointer
Rust (and C++, because SFINAE, and many other languages), on the other hand, technically has a breaking change each time any method is added to any public type in the stdlib. It's always possible that the client lib was using a trait method of the same name, and now has to fully qualify the method call.
> Why is it not accurate?
I said it _was_ accurate. It's just not neccesarily complete. It's not complete because I'm only one human, and I have more important work to do.
That's not what I've seen from your comments. Instead I've seen some confused arguments about what "prose only" means (anyone in the PL field would consider both Rust and Go's documentation "prose"), combined with incorrect statements about both Rust and Go and a completely baseless assertion that Rust is "a language in flux".
The Rust maintainers would have considered this a breaking change. The Go maintainers did not. This isn't to say either side is right or wrong, just that they are measuring different things.
Additionally, the Rust maintainers have been exceedingly cautious whenever making these types of changes. They literally download, compile, and test all published crates to look for indications that such a change might actually break existing code. In the very few cases it has, they've worked with crate authors to incorporate fixes.
The very low bar Rust sets for determining what is a breaking change directly reflects the extreme regard they have for this issue.
To cross compile. To have quick toolchain updates. To get bleeding edge compiler improvements (e.g. speed) quickly. To test out new features. To help find bugs in the compiler.
One very common use case of rustup is to use clippy. Clippy is a developer tool which hooks directly into the compiler and uses all sorts of private APIs, an inherently unstable thing. It only works on nightly. Lots of people write their code to work on stable, but want to use this tool so they use rustup. Note that no language has a stable way of hooking into the compiler.
Very few rust packages only work with nightly. Care to provide some examples?
> Why do you need rustup if Rust is so backward compatible?
For one, testing on various versions of Rust. For example, I have a kernel project that's pinned to a particular nightly version, while the rest of my projects build on stable. Rustup makes this Just Work.A staged release cadence with different levels of surety gives people the ability to play with features as they're developed to make sure those features solve the problems they're trying to solve (in the best way) by giving time for real-world experimentation and feedback. A feature can graduate from nightly-only to stable, and it then has a strong backwards compatibility requirement. The nightly experimentation period is valuable to get those features perfected before people can start relying on them more broadly.
(And dbaupp is correct that it's not always about testing; not all of the OS dev features are in stable yet, so nightly is the only option for that kind of project.)
>>What if I would like to guarantee this property for my own code?
I think that should be an exception if the backward compatibility is to be trusted.
Can you specify, in particular, what you think Rust is not doing that it should be doing?
Rust is doing exactly that.