Announcing Rust 1.7
blog.rust-lang.org
blog.rust-lang.org
"Soundness fixes to the interactions between associated types and lifetimes, specified in RFC 1214, now generate errors for code that violates the new rules. This is a significant change that is known to break existing code, so it has emitted warnings for the new error cases since 1.4 to give crate authors time to adapt."
https://github.com/rust-lang/rust/blob/stable/RELEASES.md#co...
I think this is a fantastic example of the even-handed approach in the compiler stability promises/plans, and it's great to see one of the first real tests of those promises go so well.
We take breaking changes ridiculously seriously, and soundness is basically the only case where they make sense to do.
Rust does use semver. But as the concept of "breaking change" is ill-defined – as I've understood – in the definition, the Rust project is using the following heuristic:
* If it's a safety/soundness-releated bugfix, it's considered a minor (1.x.0-changing) change even if it makes some existing crates stop compiling. Because the crate was relying on broken/unsound functionality, that's acceptable.
* Impact of all such breaking changes are measured and assessed against the ecosystem using the Crater tool.
* Even if crates stop building, the changes should be such that it's trivial to fix them. (In the best case, one-liner type annotations etc.)
Btw. Rust sometimes deprecates APIs that have been supplanted by better alternatives. Deprecations are warnings, and they are allowed to go away only on a x.0.0 version change. Additionally, careful consideration for stability and breaking changes is done when designing new language features.
Both changes are very small; they do not impact most users and the users who are impacted can easily fix them unless they are exploiting the existing "bug" to do something unsound.
https://github.com/rust-lang/rfcs/blob/8e2d3a3341da533f846f6...
> MAJOR version when you make incompatible API changes,
But does not define what "compatible" means.In a statically typed language, virtually any change, including an addition, can be construed as a "breaking change". For any proposed change to Rust, I could write code that that change would break. Adding a new method is a breaking change, for example, because I could have written a method with that name previously.
Note that this is also consistent with other languages: Java, for example, regularly makes very small breaking changes, even though it's widely regarded as a language which takes compatibility extremely seriously.
So, with that definition of 'breaking' not being particularly useful, we've done what you're supposed to do with Semver: lay out what 'compatible' means. The primary documents for this are https://github.com/rust-lang/rfcs/blob/master/text/1122-lang... and https://github.com/rust-lang/rfcs/blob/master/text/1105-api-...
I quote:
> This RFC proposes that minor releases may only contain breaking changes
> that fix compiler bugs or other type-system issues.
Without a formal language spec, and with certain bits of the language being generally under-specified, you can language lawyer forever about a term like "breaking". That's why we went through all of the possible ways that we could change the language, and spelled out what kinds of versions we're allowed to make those changes in. I would argue that Rust is far more clear about its version guarantees than many, many other languages.It's important to remember that semver is a _social_ tool to communicate roughly what has changed. If this blog post were about a Rust 2.0, you would rightfully assume that it's going to be tough to upgrade to. That's not the case here. The actual impact of this particular change to the ecosystem is virtually nothing.
Then you should have used a way to namespace your method, as is done in Objective-C with category methods.
You can still write out a disambiguated form to distinguish the two, but it's not the default way. That's one of the reasons why adding a defaulted method to a trait is a minor change. See https://github.com/rust-lang/rfcs/blob/master/text/1105-api-... for more.
Categories do nothing to protect against breakage due to adding methods.
Imagine the trait (namespace) `Baz` defines a method `bar()`, and `Foo` is a type which implements `Baz`. `foo.bar()` is sugar for `<Foo as Baz>::bar(foo)`. Imagine `Foo` also implements `Quux`, another trait in scope, and `Quux` is extended to also define `bar()`. Now `foo.bar()` is ambiguous, because it could also mean `<Foo as Quux>::bar(foo)`. As you can imagine, though, this happens very rarely.
You can't avoid a conflict unless you require specifying the namespace at every call-site, which is in my estimation a much greater burden than editing your code to use the explicit namespace form if a conflict arises because of a new method in a dependency.
Remember, any bugfix is a breaking change if someone was relying on the buggy behavior.
Here's Crater's regression report for the linked soundness fix: https://gist.github.com/nikomatsakis/2f851e2accfa7ba2830d#ro... . It detected four root regressions, which means that there were four packages that were relying on unsound behavior. This isn't necessarily the full extent of the regressions, however, because if we ship a compiler that breaks those packages, then any other packages that have the formerly-unsound packages as dependencies will obviously also break.
Having a concrete list of regressions also allows us to go through the ecosystem and submit PRs ourselves to bring the affected packages back to building, which is usually quite easy. Crater is a really, really great tool.
This is one of the coolest and most practical things I've read in a while, seeing what happens to stable(ish) real wild code. So many practical applications and analytics are coming to mind in many areas.
Thank you. Sparks my interest in Rust again.
Not sure how much this is used in order to test impact language changes.
NM: after reading more carefully, it's clear that at least in the case where rust causes the "regression" you feedback the improvements, so likely the same for unstable tests.
I'm personally hoping the latter one manages to get into the beta release for the next cycle, so that I can use `?` rather than `try!()` for my Rust tutorial at OSCON this year. :)
The best part about rust is seeing the equally incredible work being done by the Servo team. To get a glimpse into some of their best work, here's a video where they talk about using the GPU to get better performance rendering a DOM than most native GUI toolkits can achieve on a sophisticated layout:
https://air.mozilla.org/bay-area-rust-meetup-february-2016/#...
In any case, let's not put too much stock on version numbers. :P
I don't think any one would argue with writing a web server in Go right now compared to Rust, given the maturity of the Go ecosystem around writing web servers.
Edited to add that Google's implementation targets Haswell and later (AVX-2), I don't know about the performance of an implementation that targets older CPUs which would of course be very relevant for Rust
What makes you say this? Many programmers don't use IDEs or anything.
However, some programmers like an IDE more. Which is fine, but for this type of programmer, Rust still has a long way to go. There are some immature plugins for existing IDEs, and even a couple "rust-specific" IDE projects, but nothing near what (say) Java or C# have.
[1]: https://github.com/murarth/rusti [2]: https://play.rust-lang.org/
This is a very hard feature for compiled languages, its just a con of this execution model (which is has a lot of pros).
It also has tools for code completion (Racer), build orchestration (Cargo again), benchmarking (the built-in benchmark runner), compiler version management (multirust), and automatic source code formatting (rustfmt, though this one's a WIP).
The way forward on that front would require, IMO, some external actor to smell profit in a Rust IDE. That has been sloooowly becoming more likely as the stdlib inches toward stability.
TL;DR: There exist Rust plugins for Eclipse, IntelliJ, Visual Studio, Atom, Emacs, Sublime Text, Vim, and VS Code.
We're also working on ways to improve the compiler to better support the IDE use case: https://github.com/rust-lang/rfcs/pull/1317
I will try to give another chance to Rust in half year and see if it improved.
But I would suggest to look at Swift SourceKit https://github.com/apple/swift/tree/master/tools/SourceKit or OmniSharp http://www.omnisharp.net/ SourceKit provides really nice Swift support in Xcode. If you can deliver same thing built on top of VSCode, Intellij IDEA with integrated debugger, I am sold.
- Be able to see inferred type
- Be able to see documentation for types and methods
- Better auto completion was sometimes suggesting non senses and after selecting it placed a cursor on wrong place
- Integrated debugger
- Go to definition (including Rust std)
- Syntax checking
- Integrated formatter
> - Be able to see inferred type
https://github.com/phildawes/racer/issues/304
> - Be able to see documentation for types and methods
https://github.com/phildawes/racer/issues/415
> - Better auto completion was sometimes suggesting non senses and after selecting it placed a cursor on wrong place
Seems like a bug, never experienced this myself though.
> - Integrated debugger
I'm currently using nemiver and atom-gdb to set breakpoints from within Atom and launch nemiver. But you're right: A great integrated debugger would be awesome :)
> - Go to definition (including Rust std)
This works with atom-racer: Ctrl+Shift+P and type "racer find definition"
> - Syntax checking
https://atom.io/packages/linter-rust
> - Integrated formatter
https://github.com/rust-lang-nursery/rustfmt/blob/master/ato...
> This works with atom-racer: Ctrl+Shift+P and type "racer find definition"
Nice, unfortunately it works only for my methods and not for std.
> - Syntax checking
Oh, you right, I got wrong path to Cargo so it didn't work out of box but still it is not like you have it in IDE and you don't see errors as you type but you need to save.
> - Integrated formatter
Cool, thanks!
That's strange. It works for me for std, too. Have you set RUST_SRC_PATH?
Among similarly new language, I think the strength of the tooling is one of the notable positives of Rust.
> and maybe introduced officially supported IDE
While I get that some programmers prefer IDEs and that IDEs might actually be generally preferable for some Rust use cases, I think there is a lot more utility in the Rust team focusing on lower-level tooling (which IDE and enhanced-editor-plugin developers can leverage) rather than focusing on an officially supported IDE.
Agreed, I hope that a good "Language service" API is on the horizon, so that tool authors don't need to reinvent the wheel in order to support parsing, error display, highlighting, completions and so on.
A step in the right direction is the possibility of getting machine-readable (json) error messages from the compiler.
Being able to just call the compiler as a library to produce AST's from source would be very handy, though it would probably complicate the compiler to be able to provide useful output from broken/incomplete source, which is critical for tool use.
https://github.com/rust-lang/rfcs/pull/1317
Nim does a good job with their IDE support
That said, in my brief experience with rust I got the impression that their tooling is very high quality for something so new. Have you seen how pretty their compiler error messages are, for example?
Java doesn't have really good canonical tools that ship with the JDK nor is there a necessarily an industry preferred choice (Javadoc is probably the only exception). This of course includes more than just build tools. The fragmentation is huge.
For example Java doesn't have a defined format tool like gofmt or rustfmt nor does it have a preferred build/dep system like crate (there are several ... maven, gradle, ant). Even more annoying is that unlike code completion and refactoring tools (Rust racer) for Java are tightly coupled with the IDE and there are really only two choices: morbidly obese and broke: Eclipse or trust fund expensive but works: intellij.
With Racer you can use whatever editor or IDE you like. I wish I had something like that for Java.
I think calling IntelliJ "trust fund" expensive is rather extreme. My company pays substantially more for my Visual Studio license than I do for my personal JetBrains All-Products subscription, $150/yr (which breaks down to $12.50/mo) saves me far more than 5 hours of time between all the work I do in IntelliJ, DataGrip, PyCharm, WebStorm and soon Rider (7 seconds to open a solution that takes Visual Studio 30 seconds to load and without the constant lockups - now I just need it to be able to run/debug ASP.net apps and run NUnit tests).
We too use intellij as well jrebel and these tools pay for themselves fairly quickly.
I would much rather they don't do that and instead offer tools that can answer IDE-like queries (e.g. "Who calls this function?", "Where is this identifier defined?", etc.) and let people integrate that into Emacs, Vim, Atom, and other editors and IDEs. This brings all the communities together and doesn't dictate one particular tool over all others.
https://www.rust-lang.org/ides.html
>We propose a new tool, an 'oracle' which takes input from the compiler, maintains a project-wide view of the code and it's type information, and provides data about the project to IDEs and other tools. The oracle is a long-running daemon and presents an API via IPC.
Which is great idea. But it is not implemented yet (AFAIK).
personal opinion : Rust with this pace, will be absolutely one of the best language in term of usage/tools in next 5 year.
In Swift you can just Cmd+Click to do this (assuming SourceKit hasn't crashed) and it's very useful for that kind of exploration.
Rust is a programming language. It's a general programming language, so it's good for a large variety of things. Different people have different reasons for using Rust. There are three large constituencies, as I see them: systems programmers, functional programmers, and scripting language programmers.
Before I get into details: all generalizations are false ;)
Systems programmers come to Rust because it's able to do the lowest levels of software: operating systems, device drivers, stuff like that. Where it improves on existing systems languages is "safety." The Rust compiler does a lot of compile-time checking to make sure you don't do things wrong. Existing languages force you, as the programmer, to double check your work. We have the compiler double-check your work, and force you to get it right.
Functional programmers see all that static checking, and it feels like home. But a home where they have significant speed gained. Functional languages can be fast, but not always C level fast. Rust is. It's easier to get that level of performance out of Rust.
Scripting language programmers come to Rust for two reasons: the first of which is to write extensions to their language for speed. You can write a Ruby gem in Rust, rather than in C. This is useful because this low-level stuff is not their expertise, and so the extra checks are really nice. Related: we have a lot of the nice tooling that scripting language folks have come to expect from their language. No need to write makefiles, we have Cargo. The second is sort of related, but these checks also mean it's easier to learn low-level stuff, so if they want to expand their universe, Rust is a nice way to do so. We're seeing a lot of people for whom Rust is their first systems language.
I didn't know where to put this one, but Rust focuses on a concept called "zero-cost abstractions." This means that a lot of our features that feel very high level are extremely efficient. You don't write manual for loops, you se iterators. You don't deal with pointers directly, but with references. Structures like Box and Vec do memory management, but you don't need a garbage collector, and you don't need to manually manage it, but you also don't need to explicitly call free().
These are very broad strokes. Lots of other people have other reasons too. But that's some of them.
What does Cargo the rust package management tool have to do with make, the declarative build system? It would seem they are unrelated to an outsider such as myself.
Work goes on, and how I want to use, say, a library for a hashmap of some kind. In my C project, I would probably be adding a git submoule, and then modifying my make files to build the dependency, and configure how to link it in with my code. With Cargo, I add a line to my Cargo.toml, and "extern crate bar" to my source file, and upon the next "cargo build", Cargo will handle the downloading, compiling, and linking of that library, as well as any sub-dependencies it has.
Now, it's also true that make is broadly more general than Cargo, and so in some circumstances, you'll use them together. I have a hobby OS project, for example, and so I have a Makefile which calls nasm to compile the assembly, cargo to compile the Rust, and ld to link the two together. Eventually, I would hope that Cargo can do it all, and I could probably make it work, but it's not inherently bad to use make either. Stuff like operating systems are the only case where I've felt that need; Rust itself is currently built with Make, because it pre-dates Cargo, but we're in the process of cargo-ifying our build as well.
Does that make sense?
I am pleased to hear that Cargo, rather than attempting to be a rust-specific make replacement, is a tool that obviates the need for using make or make-like tools by automating the things you would have used it for, only.
Make and Cargo together sounds like just what I wanted to hear, and your hobby OS project sounds like fun.
Finally, I think it's great that Rust will be using Cargo itself soon, but I am curious if the reverse is possible -- if I want to put in the extra effort, can I build my own rust software in make alone WITHOUT Cargo?
Thanks again.
Sean Griffin, the current maintainer of ActiveRecord, has been writing an ORM in Rust. He specifically has been saying quite a bit that the safety aspect is almost irrelevant to him, he sees Rust as a "practical Haskell".
It's also true that there's a lot of stuff we have that's _because_ of safety but isn't interesting because of safety. For example, memory safety is at the core of our concurrency story, but the end result is "compile-time errors for concurrency bugs", which is much more interesting than "safety".
TL;DR: marketing is difficult. Messaging is tough.
I disagree. For the most part, you don't have to worry much about lifetimes in Rust once you have programmed in the language for a bit. It's a learning curve, like any other (functional languages have their own learning curve). There are cases now and then when you do have to think about it, but mostly it's either quickly fixing mistakes caught by the compiler (like any other type error, and this reduces as time goes by), or writing the correct code from the get-go.
That doesn't make Rust a better choice than the functional languages, but it certainly doesn't make it worse.
(of course, there are other reasons as to why Haskell/etc might be a better option for these people)
On the other hand, GC allows for faster and easier programming without the need to reason about lifetimes, like you would have to do in non-GC-languages like C and Rust. Java, Go and C# are fast enough to do a lot better than scripting languages, plus they are statically typed and safe.
I think that what Rust provides for user of those languages, has more limited scope: mainly squeezing the last drops of perf, and especially doing some realtime programming.
Edit: One additional pro of Rust is that it managed resources like files and sockets very robustly with its type system, which may help prevent bugs. That's a thing CG won't do for you.
For me it's become, "Anywhere I would use or have to directly interface with C; evaluate using Rust instead."
mind: blown.
There are still some rough edges on it, and if you see any obvious improvements, I would be more than happy to take suggestions or push requests :)
It's a reasonable first choice for when you absolutely need to avoid GC, or need code without a runtime (e.g. for embedding into another language). IMO a lot of people overestimate their performance requirements though (or assume that all GC languages must be as slow as Python/Ruby, or as slow to start as Java), and would be more productive overall writing in a language that doesn't require manual memory management and then spending a little time profiling. So for general-purpose programming where the target is native code I would recommend starting with OCaml or Haskell (if VM languages are suitable then also consider F# or Scala), and only falling back to Rust if you've spend a bit of time profiling and optimizing your app (or a representative benchmark/example) and find you really can't get the performance you absolutely need.
I am amazed with how easy it to cross compile to different platforms supported by golang. Curious how rust compares.
A summary is "every Rust compiler is a cross-compiler, but you need a copy of the standard library for your target platform available." Getting said copy is what takes the work. In the future, we want it to be as easy as a call to the command-line, but for now, https://github.com/japaric/rust-cross is a good resource.
See also https://github.com/japaric/rust-everywhere , which is very interesting.
The way I'm using it is: docker run --name rustpi2 -v `pwd`:/home/rustpi2/dev/source -v $HOME/.cargo:/home/rustpi2/.cargo fabricedesre/rustpi2 cargopi build (cargopi is just equivalent to cargo --target=armv7-unknown-linux-gnueabihf)
I am sure it can be trimmed, but we are getting oblivious to common sense a little. This is system language.
Binary size is not a major concern for most programs, even those written in a systems language. If it is a concern for your use case, you can use dynamic linking and the system allocator to get the size down to the same scale as C.
The size is due to a statically linked stdlib (also jemalloc, which you can decide not to use) -- your C program is tiny because your system has a stdlib it can dynamically link to. Rust can do this too, it's just not the default since in most cases this additive extra binary size isn't a problem.
Being a systems language does mean we should forgo sensible defaults.
https://github.com/japaric/rust-on-openwrt/issues/1#issuecom...
https://github.com/japaric/std-with-cargo#making-rust-binari...
$ cat hello.rs
fn main() { println!("Hello, world!") }
$ rustc hello.rs -C prefer-dynamic
$ ./hello
Hello, world!
$ ls -al hello
-rwxrwxr-x 1 lifthrasiir 9064 Mar 4 14:24 hello*
See other comments for the explanation.