Sure, "bug in the language" is hangs on very subjective judgement whether something is wrong or merely missing/different by design.
But I wanted to highlight that adding of const generics would make things like derive Debug just work for any array — as one would expect. Compared to that, a derive that works only for arbitrary limit of 32 elements doesn't look like a good feature or a more elegant design.
I didn't imply Daniel did; I was providing context What constitutes a major breaking change according to semver is not necessarily the same as "broke my code"; in our case, it is defined by several official policy documents.
If you said RFC: `Self` in type definitions allowing `enum List<T> { Nil, Cons(T, Box<Self>) }` by Centril · Pull Request #2300 · rust-lang/rfcs · GitHub, https://github.com/rust-lang/rfcs/pull/2302, or even RFC: Or patterns, i.e `Foo(Bar(x) | Baz(x))` by Centril · Pull Request #2535 · rust-lang/rfcs · GitHub were bug fixes I would agree. Const generics, while adding neccessary power and fixing inconsistencies, require massive changes to the rustc codebase.
Thank you all for these kind responses and different points of views.
I think the best thing I can do now is giving it a try for some months.
If some maintainers hear me, as a newcomer, the thing I miss the most coming from go is a mature and stable ecosystem, with a rich stdlib (HTTP, only ~10 checks on stable for rustfmt, testing framework not available in stable...) where everyone build on a common foundation instead of 'reinventing the wheel' every time.
Examples taken from the past and the present:
- should I
error_chain
or should Ifailure
? - should I
serde
or should Irustc-serialize
? - should I
time
or should Ichrono
? - should I
url::Url
or should Ihttp::uri::Uri
?
Enterprises need stability and guarantees and so Rust should provide to win users.
I now understand better the role of editions, but despite what have been said, I think that having nightly and a too small stdlib create a real fragmentation among the community and the projects.
That being said is it practicable, in an application backend, to have multiple services, some targeting stable, some nightly, or does it seems too much headache ?
Yes! In my opinion and experience, this is an important point and a point that is often glossed over.
Crate authors often expect you to use a recent version of the compiler, and this has again and again meant that my code "randomly" failed to compile. Random in the sense that it worked in CI yesterday, but today it fails despite the fact that there was no changes to my code and no changes to the compiler.
So where was the change? It was of course in the dependencies, which no longer support the version of the compiler I happen to use. Cargo can use a lock file, yes, but libraries are not expected to commit a lock file (last I checked).
I know people are working on this, so it'll probably become better over time. I also hope people will begin treating a change to the minimum supported rustc
version as something that requires at a major version bump. That way, a dependency on foobar = "1.2.3"
won't suddenly install foobar
version 2.0.0
, which might require a newer version of the compiler.
I believe the situation here is similar to above: what you say is absolute correct, but only if I use a recent compiler. If I introduce a dependency on a Rust 2018 edition crate, then I also introduce a dependency on a compiler that is new enough to know about that edition.
So while I can keep using the Rust 2015 syntax, I must now use a recent version of the compiler. People never seem to mention this since it's super easy to install Rust using rustup
.
However, while rustup
is fine on a developer laptop, I doubt that it'll fly in a corporate environment where tools are centrally managed and audited. There it becomes important what RHEL is shipping, and as such, it ought to be normal for users to use a compiler that is a few years old. Rust is still new and young, and the mentality I see is that people are still enjoying that freedom to continuously push the entire ecosystem towards the latest compiler releases.
I hope this will settle down with Rust 2018: crates can start depending on Rust 1.31.0 which introduced the 2018 edition. If they do that and avoid depending on anything later, then we'll finally have the ecosystem stability I hope for. Later, crates can then decide to jump to Rust 2020 or whatever the next edition is called.
If you update your code, you will (of course) also start requiring Rust 1.30.0 where trim_start_matches
was introduced in the first place. This now means that all downstream dependencies must also upgrade their compiler. Again, this is probably fine when you know all the code that depends on you, or when everybody is using rustup
, but I don't think it's a good long-term strategy.
Aside: that is a major version bump. The major version number is the first non-zero component, then minor, then revision. The only way to stop what you're describing is a major version bump, not a minor one. But people generally don't like major bumps, because it causes friction (see the fallout from the last time libc
bumped its major version).
This is why Cargo desperately needs to take the language/compiler version into account when resolving dependencies.
Thanks, I've corrected my post!
Yes, hopefully the Rust team will make decision on this RFC soon:
Considering const generics and async/await I highly doubt it will happen.
Requiring an always-up-to-date compiler, as fresh as 6 weeks, is shocking compared to C projects that support 20-year-old compilers. Maybe that makes Rust appear unstable?
It's a dramatically different approach, but IMHO it works well enough. Upgrades are easy and backwards-compatible enough that it's not unreasonable to ask users to run rustup update
once in a while.
Yes, I think it does, and I'm not even used to working in C
Instead I used Python a lot, and there projects would also declare that they're compatible with "Python 2.7" or "Python 3.4+" or something similar. The difference is that Python releases come about once a year, not every six weeks.
I plan to update my own crates to the Rust 2018 edition at some point and then hopefully be done with it until the next edition comes out. That should give people a solid foundation in case they want to depend on my crates.
I'm not sure what your parenthetical means. Are those items you think are lacking in Rust? What are "checks on stable", and what testing framework isn't available on the stable channel? (The standard Rust test functionality has been stable since 1.0, I believe.)
From the opposite point of view, "stability" is just a fancy word for "stagnation". A stable product cannot evolve. The example given with C projects that support 20-year-old compilers is perfect, because it invariably involves several layers of preprocessor directive and boilerplate that has nothing to do with the application's business logic.
Similarly, Python 2 is stagnant (or even EoL, depending on your perspective). Projects written for Python 3 typically contain their own set of exception handlers and conditions to remain backward-compatible with Python 2. Or they depend on a library like six
that implements an abstraction layer over the standard library.
What it really comes down to is "dependency management is hard." Perhaps the cleanest approach to avoiding the problem altogether is to depend on fewer crates; Do you really need to depend on a crate that can add whitespace to the head of a string? This is of course an extreme example, but it's a hilarious one. It is not always possible to write useful code without depending on something.
Side note: The core idea behind culling dependencies is practical for many other reasons. Including reducing code surface area/security attack vectors, minimizing compile times/download times/executable size/memory utilization/etc., and overall just keeping it simple, stupid.
Obligatory link to the rust blog post about this:
And to an old discussion on reddit:
https://www.reddit.com/r/rust/comments/8lgbej/it_took_me_a_while_to_really_appreciate_the/
Yes they are lacking.
Look the ratio of stable / nightly options here: rustfmt/Configurations.md at master · rust-lang/rustfmt · GitHub
It means that in practice, in order to have my linting step working in CICD I need another step to download the nightly toolchain, without guarantees that it will not break for any reason.
As a newcomer I don't understand why I need to be on nightly to use #![feature(test)]
.
So I need another hour to figure it out and install a nightly toolchain on my devlopment machine.
It really looks like the rust ecosystem is fighting against me to be productive and start the real code.
What if I replace the word stability
with productivity
.
Rustup is a nice thing, but in reality for a new user there is a lot of more subtle notions to acquire before becoming productive (like acknowledging that you need a stable toolchain to compile your code + a nightly one to lint / test / benchmark).
The second thing is the ecosystem fragmentation, having some users using nightly and other stable is maybe nice for hobbyists but not for world scale collaboration scenarios. From an external point of view it really looks like the python 2/3 problem.
Here again as a newcomer I feel that the rust ecosystem is fighting against my productivity.
Error handling is not even stabilized / a consensus in Rust (failure vs error_chain).
You can call it stagnation, but on the other hand it's one of the reason that go is so successful compared to Rust: users have all access to the same set of stable and (almost) bug free features used by modern applications (HTTP, crypto, database, encoding, language parsing, templates, math... In stdlib), and develop frameworks arround this without being worried that their work will become obsolete in 12 weeks (because it will not). There are things far from perfect (error handling for example), but it works, it just works!
On the other hand, in rust the http
library which seems to be the consensus (today, but what about in 18 weeks ?) Is 0.1.14
. And it doesn't even include a client and a server.
So if I want to create an HTTP application in rust today I should be okay with the fact that either I need to reinvent the wheel and recreate an HTTP stack (actix web) incompatible with the most popular one, either I should accept that maybe the popular one is buggy and I will need to upgrade all my code in 2 months because the fix will land in a release breaking the API.
I do not see "nightly" mentioned there. Are you perhaps misinterpreting the "stability" of each lint? The page says:
Each configuration option is either stable or unstable. Stable options can be used directly, while unstable options are opt-in. To enable unstable options, set
unstable_features = true
inrustfmt.toml
or pass--unstable-features
to rustfmt.
This is not related to which toolchain (stable/beta/nightly) you're using.
I wasn't aware of this feature, but looking into it, this is for access to the internals of the Rust test framework. As I said, the framework itself has been stable for quite some time and requires no special opt-in. Including unit tests and functional tests in your code, which can be run by cargo test
, is trivial.
What are you using #![feature(test)]
for, or planning to use it for?
#[bench]
tests.
Since they're not stable and not documented in the book, most people have never even heard of them. And it's available as a crate, though the bencher crate is probably even less widely-known than the one built into rustc's libtest, so not many people use it, either.
Ooops, sorry I totally missed this point and effectively misinterpreted the unstable
word.
The feature(test)
is required to run benchmarks and thus ensure non regression
To prove my point, look at the most popular rust programs on Github: they are all CLI apps because fs
is in stdlib.
With a richer and stable stdlib Rust could become the perfect mix between go and Scala!
That is the stability thing in the title and IMHO what blocks broader adoption (and here Im not talking about Google/Mozilla/Amazon which have a lot of money but all the other enterprises with normally sized dev teams and want things to get done).
I don't know of any mainstream language with a "consensus view" on error-handling, except maybe Python, where throwing exceptions on non-exceptional/non-fatal conditions, then catching them, is considered "Pythonic".
This is fundamentally because Go serves a different purpose than Rust does. It was designed to be a fairly simple language with a robust runtime that focuses on making inter-process communication trivial. Rust is a fairly complex language with no runtime that focuses on giving the programmer a C- or C++ like level of control over the hardware, particularly in-memory data layouts and pointer-accesses.
That's because the Crate ecosystem is highly modular (which I believe is generally a good thing, though the npm
ecosystem has had some severe problems with over-reliance on small packages), and http
is a pretty low-level crate. There are many higher-level crates that provide client/server code.
...since actix-web
is a full-featured web framework, I assume you meant to put "(actix web)" after your comment about incompatibility? In any case, since actix-web
itself relies on smaller crates, you don't have to be incompatible with actix-web
if you wish to create your own framework; you can just use the same dependency crates in your framework.
I'm sorry, but I don't understand what this has to do with Rust or the ecosystem at all. "Maybe popular packages are buggy" is a problem with software in general.
However, your assumption that a bugfix would necessarily break an API is completely incorrect (again, in any language ecosystem, but particularly in one like Rust that tries to follow SemVer-like principles). Please look at the links above about SemVer.