What is Rust and why is it so popular?
Rust has been Stack Overflow’s most loved language for four years in a row, indicating that many of those who have had the opportunity to use Rust have fallen in love with it. However, the roughly 97% of survey respondents who haven’t used Rust may wonder, “What’s the deal with Rust?”
The short answer is that Rust solves pain points present in many other languages, providing a solid step forward with a limited number of downsides.
I’ll show a sample of what Rust offers to users of other programming languages and what the current ecosystem looks like. It’s not all roses in Rust-land, so I talk about the downsides, too.
Coming from dynamically-typed languages
The arguments between programmers who prefer dynamic versus static type systems are likely to endure for decades more, but it’s hard to argue about the benefits of static types. You only need to look at the rise of languages like TypeScript or features like Python’s type hints as people have become frustrated with the current state of dynamic typing in today’s larger codebases. Statically-typed languages allow for compiler-checked constraints on the data and its behavior, alleviating cognitive overhead and misunderstandings.
This isn’t to say that all static type systems are equivalent. Many statically-typed languages have a large asterisk next to them: they allow for the concept of NULL
. This means any value may be what it says or nothing, effectively creating a second possible type for every type. Like Haskell and some other modern programming languages, Rust encodes this possibility using an optional type, and the compiler requires you to handle the None
case. This prevents occurrences of the dreaded TypeError: Cannot read property 'foo' of null
runtime error (or language equivalent), instead promoting it to a compile time error you can resolve before a user ever sees it. Here’s an example of a function to greet someone whether or not we know their name; if we had forgotten the None
case in the match
or tried to use name
as if it was an always-present String
value, the compiler would complain.
fn greet_user(name: Option<String>) {
match name {
Some(name) => println!("Hello there, {}!", name),
None => println!("Well howdy, stranger!"),
}
}
Rust’s static typing does its best to get out of the programmer’s way while encouraging long-term maintainability. Some statically-typed languages place a large burden on the programmer, requiring them to repeat the type of a variable multiple times, which hinders readability and refactoring. Other statically-typed languages allow whole-program type inference. While convenient during initial development, this reduces the ability of the compiler to provide useful error information when types no longer match. Rust learns from both of these styles and requires top-level items like function arguments and constants to have explicit types, while allowing type inference inside of function bodies. In this example, the Rust compiler can infer the type of twice
, 2
, and 1
because the val
parameter and the return type are declared as 32-bit signed integers.
fn simple_math(val: i32) -> i32 {
let twice = val * 2;
twice - 1
}
Coming from garbage-collected languages
One of the biggest benefits of using a systems programming language is the ability to have control over low-level details.
Rust gives you the choice of storing data on the stack or on the heap and determines at compile time when memory is no longer needed and can be cleaned up. This allows efficient usage of memory as well as more performant memory access. Tilde, an early production user of Rust in their Skylight product, found they were able to reduce their memory usage from 5GiB to 50MiB by rewriting certain Java HTTP endpoints in idiomatic Rust. Savings like this quickly add up when cloud providers charge premium prices for increased memory or additional nodes.
Without the need to have a garbage collector continuously running, Rust projects are well-suited to be used as libraries by other programming languages via foreign-function interfaces. This allows existing projects to replace performance-critical pieces with speedy Rust code without the memory safety risks inherent with other systems programming languages. Some projects have even been incrementally rewritten in Rust using these techniques.
With direct access to hardware and memory, Rust is an ideal language for embedded and bare-metal development. You can write extremely low-level code, such as operating system kernels or microcontroller applications. Rust’s core types and functions as well as reusable library code shine in these especially challenging environments.

Coming from other systems programming languages
To many people, Rust is largely viewed as an alternative to other systems programming languages, like C or C++. The biggest benefit Rust can provide compared to these languages is the borrow checker. This is the part of the compiler responsible for ensuring that references do not outlive the data they refer to, and it helps eliminate entire classes of bugs caused by memory unsafety.
Unlike many existing systems programming languages, Rust doesn’t require that you spend all of your time mired in nitty-gritty details. Rust strives to have as many zero-cost abstractions as possible—abstractions that are as equally as performant as the equivalent hand-written code. In this example, we show how iterators, a primary Rust abstraction, can be used to succinctly create a vector containing the first ten square numbers.
let squares: Vec<_> = (0..10).map(|i| i * i).collect();
When safe Rust isn’t able to express some concept, you can use unsafe Rust. This unlocks a few extra powers, but in exchange the programmer is now responsible for ensuring that the code is truly safe. This unsafe code can then be wrapped in higher-level abstractions which guarantee that all uses of the abstraction are safe.
Using unsafe code should be a calculated decision, as using it correctly requires as much thought and care as any other language where you are responsible for avoiding undefined behavior. Minimizing unsafe code is the best way to minimize the possibilities for segfaults and vulnerabilities due to memory unsafety.
Systems programming languages have the implicit expectation that they will be around effectively forever. While some modern development doesn’t require that amount of longevity, many businesses want to know that their fundamental code base will be usable for the foreseeable future. Rust recognizes this and has made conscious design decisions around backwards compatibility and stability; it’s a language designed for the next 40 years.
The Rust ecosystem
The Rust experience is larger than a language specification and a compiler; many aspects of creating and maintaining production-quality software are treated as first-class citizens. Multiple concurrent Rust toolchains can be installed and managed via rustup. Rust installations come with Cargo, a command line tool to manage dependencies, run tests, generate documentation, and more. Because dependencies, tests, and documentation are available by default, their usage is prevalent. crates.io is the community site for sharing and discovering Rust libraries. Any library published to crates.io will have its documentation built and published on docs.rs.
In addition to the built-in tools, the Rust community has created a large number of development tools. Benchmarking, fuzzing, and property-based testing are all easily accessible and well-used in projects. Extra compiler lints are available from Clippy and automatic idiomatic formatting is provided by rustfmt. IDE support is healthy and growing more capable every day.
Going beyond technical points, Rust has a vibrant, welcoming community. There are several official and unofficial avenues for people to get help, such as the chat, the user’s forum, the Rust subreddit, and, of course, Stack Overflow questions and answers and chatroom. Rust has a code of conduct enforced by an awesome moderation team to make sure that the official spaces are welcoming, and most unofficial spaces also observe something similar.
Offline, Rust has multiple conferences across the globe, such as RustConf, Rust Belt Rust, RustFest, Rust Latam, RustCon Asia, and more.
It’s not all roses
Rust’s strong type system and emphasis on memory safety—all enforced at compile time—mean that it’s extremely common to get errors when compiling your code. This can be a frustrating feeling for programmers not used to such an opinionated programming language. However, the Rust developers have spent a large amount of time working to improve the error messages to ensure that they are clear and actionable. Don’t let your eyes gloss over while reading Rust errors!
It’s especially common to hear someone complain that they’ve been “fighting the borrow checker.” While these errors can be disheartening, it’s important to recognize that each of the locations identified had the potential to introduce bugs and potential vulnerabilities in a language that didn’t perform the same checks.
In this example, we create a mutable string containing a name, then take a reference to the first three bytes of the name. While that reference is outstanding, we attempt to mutate the string by clearing it. There’s now no guarantee that the reference points to valid data and dereferencing it could lead to undefined behavior, so the compiler stops us:
fn no_mutable_aliasing() {
let mut name = String::from("Vivian");
let nickname = &name[..3];
name.clear();
println!("Hello there, {}!", nickname);
}
error[E0502]: cannot borrow `name` as mutable because it is also borrowed as immutable
--> a.rs:4:5
|
3 | let nickname = &name[..3];
| ---- immutable borrow occurs here
4 | name.clear();
| ^^^^^^^^^^^^ mutable borrow occurs here
5 | println!("Hello there, {}!", nickname);
| -------- immutable borrow later used here
For more information about this error, try `rustc --explain E0502`.
Helpfully, the error message incorporates our code and tries its hardest to explain the problem, pointing out exact locations.
Prototyping solutions in Rust can be challenging due to its statically-typed nature and because Rust requires covering 100% of the conditions, not just 99%. Edge cases must have applicable code, even when the programmer doesn’t yet know what the happy path should do. During early development, these edge cases can often be addressed by causing the program to crash, and then rigorous error handling can be added at a later point. This is a different workflow than in languages such as Ruby, where developers often try out code in a REPL and then move that to a prototype without considering error cases at all.
Rust is still relatively new, which means that some desired libraries may not be available yet. The upside is there’s plenty of fertile ground to develop these needed libraries, perhaps even taking advantage of recent developments in the relevant computer science fields. Due to this and Rust’s capabilities, some of Rust’s libraries, such as the regex crate, are the best-in-breed across any language.
While Rust has a strong commitment to stability and backwards compatibility, that doesn’t imply the language is finalized. A specific problem may not have access to language features that would make it simpler to express or perhaps even possible to express. As an example, Rust has had asynchronous futures for over three years, but stable async
/ await
support in the language itself is only a few months old.
The Rust compiler is built on top of LLVM, which means that the number of target platforms will be smaller than C or C++.
Come and join us!
Regardless of which programming languages you love now, there’s bound to be something that excites or intrigues you about Rust. These are some of the reasons why I and others love Rust so much, and there’s many more. If you are looking for extra structure in your project, faster or more efficient code, or the ability to write performant code more quickly and safely, it’s time for you to see if Rust will be your next most-loved language!
83 Comments
Two questions:
1. Why is code embedded as images, a terrible practice that we frequently edit to fix on Stack Overflow?
2. Why are those images so tiny that they’re completely unreadable?
Sorry about that — I was making last-minute changes in the post editor late last night and broke the embedded code blocks and couldn’t put them back myself. I needed to wait for a blog admin’s help. I added the screenshots so that the post wasn’t completely unintelligible without the code. They happened to be the width of the Gists on my screen, thus the small size.
The embeds should be live now, again (thanks Ryan!)
Fairy nuff. At least it’s working now.
Interesting article.
This is the kind of content I love to see on this blog. Thanks for all you do, Shep
How good is rust for scientific and mathematical computing operations ?
This is always a hard question to answer. I’m not deeply involved in those areas, so I don’t have any first-hand knowledge, but I do know that there are some crates aimed at medical-related tasks.
I do think that Rust the language is a good fit for those domains, as correctness and speed both seem important here. However, the ecosystem of off-the-shelf libraries to do existing tasks may be a bit sparse.
Like many other languages, Rust can make use of existing libraries that have a C ABI, which is a powerful tool for reusing existing code. The interaction with these libraries from Rust is very lightweight, allowing for high performance.
idiomatic Rust, it’s metal development, cargo and borrow checker make Rust so important in this century. I’m new to Rust and would like to join Crates.Io and learn about its libraries or any new development.
Regarding mathematical computing: this person did an excellent series of articles about porting a *very* highly optimized N-body solver from C to Rust, showing how Rust can give you all the same performance characteristics in a form that is both much more safe and much more readable: http://cliffle.com/p/dangerust/
This series happens to also be linked in the post itself (“you can use unsafe Rust”), but I confess that I didn’t spend enough time reading it to realize what the domain was! I mostly read it and got the gist of “you can transform C to Rust and get reasonable performance” and “if you write it idiomatically, you might be able to go faster”. 🙂
> The Rust compiler is built on top of LLVM, which means that the number of target platforms will be smaller than C or C++.
I don’t really understand this statement – building Rust on top of LLVM meant that Rust immediately supports all (or most) of the targets that LLVM supports. Which is also the same set of targets as Clang.
Maybe you meant to say that Rust does not support as many targets as (say) gcc?
There’s currently only one Rust compiler,
rustc
, which happens to be built using LLVM. There are other alternative implementations in various states of progress, but none are yet at reasonable parity with the official compiler.Contrast this to C, which has a huge number of compilers, and that may not be counting the huge number of compiler forks tailored for a specific embedded device.
The paragraph is highlighting that the comparison is between the targets supported by the single Rust compiler and all existing C compilers.
I always feel the fact there is so many compilers for C/C++ was more a disadvantage than an advantage…
As a developper you ends up finding the library you want, not being easily compatible with your code… I think it’s a better idea to push a single compiler as much as you can rather than creating your own, especially considering they are not even that different now performance and feature wise…
Look C# or Java, the vast majority use a single compiler, the one given with the program/sdk. And everyone seems to live in a better world.
@charles, no in C/C++ there is no way any library can ever be incompatible, even if made with a different compiler. There is no way a single compiler could be an advantage, and C# and Java are not dependent upon a compiler, even though they can perform run time compiling. They are based on run time code that insulates the programmer from things like the operating system. They are best described as “managed code”. Not good in my opinion.
There are a fair number of compiler-specific features in C and C++. It’s very possible to have a program that only builds with one compiler.
I think having multiple compilers is an advantage, but the point you are making is valid. The disconnect comes from relying on compiler-specific behavior, whether you intended to or not.
In an ideal world, there would be a single language specification for each language and the compilers / interpreters would adhere to it completely. Anything beyond the specification could only be used with a flashing red warning to make sure it’s not accidental.
One pseudo-example of that in Rust is
std::os::unix::fs::MetadataExt
. This is an extension trait that only exists on UNIX-like systems. Importing it should send that signal that you are doing something non-portable.They may be now, but having multiple competing implementations can drive each to outdo the other, creating net wins for us programmers and the users of our software. A good example is the GCC / EGCS fork.
I do agree that we don’t really need hundreds of compilers, but more than one would be good.
Which major tech companies are the lead committers/contributors to Rust?
If you are interested in which companies publicly use Rust, there’s a page of production users. There’s also big name companies like Mozilla, Microsoft, Facebook, Oracle, etc. that we know use Rust in some fashion but aren’t on that list.
I don’t have a great mental list of which companies contribute to the Rust ecosystem. For the compiler itself, we maintain a list of contributors, but that’s broken down by person; you’d have to do some work to get companies from that. Then you’d need to look out at which companies provide crates or some kind of Rust-related service.
I don’t remember the link, but I’ve just saw an article a few days ago about Microsoft porting some parts of windows to rust, at least as an internal test of the language
How does performance and safety compare to Ada?
Unfortunately, I don’t have any real-world experience with Ada, so I wouldn’t want to say something incorrect. What I do feel comfortable saying is that I’ve personally seen much more usage of Rust than Ada in industry (again, with a very biased eye). Perhaps Rust is more palatable to programmers for some reason? Maybe it was just the right time?
I’d start by looking at this comment by someone who’s used both a lot:
https://users.rust-lang.org/t/if-ada-is-already-very-safe-why-rust/21911/64?u=ssokolow
Is there a book / online course, you can recommend, to learn Rust for a seasoned developer (specifically, Python)?
the best resource imo is available over at https://doc.rust-lang.org/book/ 🙂
more can be found at https://www.rust-lang.org/learn !
I agree that The Rust Programming Language should be your first stop. It’s available for free online and there are physical copies you can buy as well.
If you are interested in a video series focused on some of the parts of what make Rust different, I’d recommend my own Rust in Motion video series.
You are in good company! During our most recent survey, Python was the language that most respondents were comfortable with, beating out Rust itself!
I also suggest Learning Rust With Entirely Too Many Linked Lists once you’ve read The Rust Programming Language.
http://cglab.ca/~abeinges/blah/too-many-lists/book/
It does a great job of helping you to understand what Rust’s ownership and borrowing rules mean in real-world terms.
There is also good course Rustlings, that available through Clion
https://blog.jetbrains.com/blog/2019/12/19/rustlings-course-adaptation/
This seems to me the same workflow as Ruby, with the one difference being that in Rust you must annotate the parts where unhandled cases arise, whereas in Ruby and similar languages you usually just try to remember where you need to go back and add missing error checking.
Perhaps a quibble, but null pointers do not add a second type: they simply add another inhabitant (possible value) to every reference type: the type you wanted to be inhabited by “all signed 64-bit integers” becomes the type inhabited by “all signed 64-bit integers and null.”
C.A.R. Hoare, in 2009, ‘fessed up to creating the problem:
(I think he may be underestimating the cost of the mistake. :-))
I hope my formatting in this post works out; there seems to be no preview, nor anything on this page I can find that tells me which markup stackoverflow.blog uses in its comments.
Yep, and likely in many (most?) other other languages. Rust has a few macros (
panic!
,unimplemented!
,unreachable!
,assert!
, etc.) that all ultimately result in a panic. The only difference is programmer semantics — you can useunimplemented
to denote those temporary places where you need to go back and think deeper,unreachable
for places that the compiler isn’t clever enough to see aren’t possible, orassert
for places where some invariant isn’t upheld.Thank you for the polite correction! I don’t claim to be a type theorist (but I do play one on Stack Overflow!). In my daily life, this particular distinction doesn’t seem useful. When I have a type
Foo
that has a memberbar
, I expect that every instance ofFoo
, behind a reference or not, is guaranteed to also have that field.Well, if you define the type that way, sure. But it’s very normal to define types that only sometimes have “fields” or other attributes like that. In Haskell I might have, e.g.,
data Compression = Uncompressed | Level Int
where valueLevel 5
would have a “field” containing 5 as the compression level, but valueUncompressed
has no such field; there is no compression level for something uncompressed. The type system ensures that if you try to access that “field” on value “Uncompressed” your code won’t compile.Yep, and Rust has something similar with enums:
enum Compression {
Uncompressed,
Level(i32),
}
In fact, enums are how
Option
is defined; it’s the equivalent of Haskell’sMaybe
monad. There are some small differences in that Rust’s enum variants are not themselves standalone types (there’s an RFC proposing opting into that).I think the root problem (that we seem to agree on), is that a reference in many languages implicitly adds the concept of “not there” without any support from the compiler / type system to ensure that the check for “not there” is performed.
I’m saddened by that “null creates a second type” thing. It broke the credibility of an otherwise very interesting article. =(
I apologize that my simplification of a nuanced point invalidated all of the other points in rest of the post for you. I hope that you are able to find a programming language that doesn’t suffer from this problem!
I don’t understand your comment, what Jake actually stated is 100% correct. Could you expand and argument on why it broke the credibility of the article for you?
I may not be technically correct. See this sibling comment with a bit more explanation.
As well as my sibling comment that Jake mentioned, I’ve posted another top-level comment (awaiting moderation so I can’t provide a link) with an explanation of the difference between languages where types attach to names (and their allocated storage, for languages that do that) and where types attach to values and references are, effectively, untyped. Both posts may be helpful background.
But the basic problem with the “second type” statement is that the there is only one type in the language itself. In Java
Integer i
declaresa reference of type whose set of possible values is every possible instance of the
Integer
class and also the valuenull
, which is clearly not a possible instance ofInteger
. You may have in your mind another, different type whose set of possible values are only all possible instances ofInteger
, which set doesn’t includenull
, but that type never exists to the Java compiler.The link is https://stackoverflow.blog/2020/01/20/what-is-rust-and-why-is-it-so-popular/#comment-559819
Nice article, however you failed to mention system languages like Ada and SPARK.
Also on the GC front, languages like D, Nim, Swift, Modula-3, Active Oberon, .NET Native, do offer C++ like capabilities to manage memory and other resources, alongside their GC.
I didn’t want to really focus on any specific language, especially languages where I don’t have personal experience. Doing so would most likely end up breaking my credibility.
Thanks for sharing other languages and features that people can use to solve the same or similar problems!
Unfortunately Franklin Chen’s presentation to which you linked has a key misunderstanding. The “billion dollar mistake” applies only to statically checked languages: it’s nothing to do with Lisp and other dynamically-checked languages (such as Python and Ruby), because with those languages all references have the top type ⊤, the supertype of all types, which can and does reference any value. (The type restrictions are not on the references but the values to which the references point. this used to be called “object oriented” before that took on a new meaning in the 1980s.)
In fact, most (all?) of those languages do not actually have null references; that is to say, unlike Java, a reference always points to a valid object. (Remember, in Ruby and Python,
nil
andNone
are actual objects, just like any other.) You can crash such interpreters by setting an object pointer toNULL
from C code linked into the interpreter, but this is not possible to do from within the langauge. Obviously, in these cases removingnil
doesn’t change anything at all; the interpreter can just as easily throw an exception when messaging any other object that doesn’t support the desired request.Also, contrary to what Chen seems to be saying, Lisp’s
nil
is not at all like Ruby’snil
or Python’sNone
; it’s much more similar to the object returned byArray.new
orlist()
, respectively. Consider:(length nil)
in Lisp evaluates to0
; that’s certainly not whatnil.length
orlen(None)
do!(This doesn’t affect the rest of your post too much, though it does indicate that, like Chen, you may not completely understand the issues here.)
Shameless plug (I work there) but relevant understanding the Rust ecosystem. In addition to crates.io for public packages; cloudsmith.com supports Cargo private package registries if you want to secure your IP.
So if Rust is so popular, where is the Rust compiler for Solaris?
I believe that the main issue here is that there’s not enough interest in Solaris for anyone to have driven the work to get it to a useful state. For example, after a brief search, I couldn’t find any commercial CI/CD providers that support Solaris or Illumos. Fully supporting Solaris would require that, among many other things.
Rust does support SPARC / x86_64 Solaris 10 and 11 as a cross-compilation target. If you’d like to see the compiler work directly on your system, you are encouraged to join our community and help see it through to fruition!
> each of the locations identified had the potential to introduce bugs and potential vulnerabilities in a language that didn’t perform the same checks.
This is untrue, even though I see this assertion a lot among the promoters of rust.
Sometimes, the checks catch real errors. But rust has a very restrictive set of rules about how memory is managed. So :
– almost all the programs that follow the rules are safe (the compiler has several known soundness holes)
– some of the programs that do not follow the rules are safe, some others are not.
The borrow checker has a very limited understanding of the control flow of the program, so very often, rust programmers end up in a situation that is indeed perfectly safe, but where the borrow checker fails to realize what is going on.
The example given in this article is one where the borrow checker catches a real error. But let’s say we wanted to clear the `name` variable and print the nickname in two different incompatible cases :
fn no_mutable_aliasing() {
let mut name = String::from(“Vivian”);
let nickname = &name[..3];
if false {
name.clear();
}
if true {
println!(“Hello there, {}!”, nickname);
}
}
This program would be totally safe to execute, but it is still rejected by the compiler.
Now I am aware that it is not possible for the rust compiler to reject all unsafe programs and ONLY unsafe programs. I am just saying that we should stop lying about rust to promote it. Yes, it rejects a lot of valid programs, and you’ll have to spend a lot of time just trying to make the compiler realize that what you are doing is indeed safe. But this time is worth it, when you compare it to the status quo of the compiler not even trying to find memory errors in your code.
A real-life case of that example you show would indeed by annoying to encounter, but like you I can happily live with a compiler that prevents a whole class of hard-to-find bugs!
Wonderful post! Very helpful and exciting. I’m just starting my Rust journey and have really enjoyed it so far, coming from a mostly JavaScript background. I’ve found the safety, performance, code of conduct / community very refreshing. I actually love when the compiler yells at me haha. Thanks for the thoughtful post and acknowledgment of tradeoffs and the respectful and non-dogmatic responses to comments Jake 🙂
Rust, Python, etc, that do garbage collection, dynamic typing, etc., are not any good at all and are really just scripting languages. You can not do real programming unless you can explicitly manipulate types and memory management. No real programmer would ever want garbage collection or dynamic typing, that prevents real programming.
Safe programming is done by learning safe methods, not taking programming out of the hands of the programmer. This is silly. You can’t write an OS in any language with garbage collection of dynamic typing.
I’m mostly sure that this comment is a reasonable attempt at trolling, but on the off chance it isn’t…
I strenuously disagree with your unfounded assertions. I want to make it abundantly clear that the types of opinions you are expressing are not part of the Rust community and are actively discouraged.
– I don’t know why you’d categorize Rust as a scripting language
– Scripting languages power a huge chunk of the internet (and thus likely the global economy). Waving them off as “not good at all” seems to be an act of willful ignorance.
– Plenty of “real programming” is done at levels of abstraction both above and below systems languages like Rust. This appears to be the stock no true Scotsman fallacy.
I also simply don’t follow what your comment has to do with anything discussed in this post. It appears to just be a rant disjoint from the contents of the page.
“You can’t write an OS in any language with garbage collection of dynamic typing.”
Check the Midori project from MSFT. It was written in C# and was reasonably performant.
I love this reply so much.
Who could clarify (1) foreign function interface library (or reusable codes ) in Rust and (2) an idiomatic Rust (rewriting certain Java HTTPS end points in Rust or an incremental development in Rust)?
Am I misreading this or … I mean, how is it possible to determine "at compile time" when memory is no longer needed. You don't need any memory until runtime…
You are right that the allocation of memory occurs at runtime, but in many cases you can tell at compile time the duration of the allocation. As a quick example:
fn main() {
let s = String::from("an allocated string");
println!("{}", s);
}
Here,
s
refers to a string with data on the heap. The compiler sees thats
goes out of scope at the end ofmain
, and so it inserts code to deallocate it at that point.In fact, all types in Rust have this drop glue inserted (simple types like integers get optimized away). This is a technique called resource acquisition is initialization (RAII), and applies to concepts beyond memory, such as file handles, network sockets, and mutexes.
So…it’s not quite garbage collection, but “smart” deallocation, like you’d find in older 3GLs (Delphi has something like this).
I don’t know if it’s a trend but between this and Go, I get a real neo-retro vibe. Retro-neo? Everything old is new again…
Yep! And you’ll find the same concept in languages like C++ via smart pointers. C++ uses
std::unique_ptr
andstd::string
, for example.Rust also has types with “shared ownership”, where there are multiple immutable handles to one resource. When a new handle is created, a reference counter is incremented; when a handle is dropped the counter is decremented. When the counter hits zero, the resource is deallocated.
I think part of the “neo-retro” sense you get is that some languages deliberately tried to be similar to existing languages like C or C++. For example, Rust deliberately picked curly braces and semicolons to be familiar to programmers coming from languages with those. There was an implicit concept of a “strangeness budget” that we didn’t want to overtax.
Concept-wise, there are many solid concepts in almost all existing languages. Rust does a great job of taking those ideas and polishing them or improving them to be less difficult.
Another language of the day – tomorrow will give rise to another one.
You make that blasé statement like it’s a bad thing. Creating new languages with new capabilities while learning from previous experiences is how our profession improves. Without new languages, we’d still be writing machine code!
Rust isn’t the only language that should exist, nor should it be the final language ever created. It’s a strong improvement on the status quo, and yet I look forward to tomorrow’s language with great anticipation to see what we can learn from it.
Why does the second example compile? The return value requires at least 33 bits. Why is the developer allowed to clamp it to 32 bits without placing any bounds restriction on the input? It will create weird bugs at runtime. For me that throws the whole safe programming environment premise to the bin…
Actually, make it 34 in case the input is the largest allowed negative value.
Rust is still a systems programming language, and the notion of types with specific sizes plays a heavy part. There is no arbitrary-sized integer type in the standard library, nor is the there the possibility of creating “oddball” sized types like
i42
.By default, debug builds introduce a runtime check for integer over and underflow. Unfortunately, the current implementations of these checks is a bit heavy for us to be comfortable enabling them in production, although you can profile and opt into it for your own binary if it seems reasonable. If you know that your algorithm is likely to hit these limits, the integer types have inherent methods to performed checked arithmetic (in addition to overflowing and wrapped).
This isn’t the only kind of runtime check that is performed — out of bounds checks generally have to happen at runtime as well, unless the optimizer can remove them.
Rust has a very specific meaning of satefy, namely that of memory safety. Having an integer wrap cannot introduce memory safety on its own, so this does not pose a problem.
Many people also point to the fact that the program can abruptly exit (via a panic, for example) as “proof” that Rust isn’t a safe language. English is a tricky language; you’ll note that even in my post I attempted to consistently say “memory safety” but quickly fell back to just “safety”.
If the guarantees that Rust provides don’t meet your criteria, I encourage you to investigate other languages — there are a myriad of them available, each with a horde of supporters who are willing to tell you why their language is the best ever created!
Very interesting article – great overview!
On thing though that bothers me is the “It’s not all roses” section: You list a few minor downsides, and then basically turn them around.
I understand that this article is here to give a positive image about Rust, but I wonder if there’s good(!) articles about some current and “real” negatives of the language? See, I work extensively in C# and C++, I think both are great, and I could give quite some rants on both, because they both have quite some warts IMHO. Would be interesting to see if someone who knows, and loves, the language has written a decent rant about it? 🙂
There are quite a few people who would disagree that their specific bugbear is minor! There are even points that I’ve listed as positives that people will complain about as negatives. There’s never a shortage of negativity to be found if you go looking for it. For concrete examples, check out the comment threads on Reddit or Hacker News for any Rust-related article.
Some things that people pointed out that I neglected to mention were the lack of object-oriented paradigms (although I’ll argue to the end that Rust is an OO language) as well as the fact that the borrow checker is conservative, meaning that it prevents programs that are actually safe (although I tried to touch on that via
unsafe
). Another is that the Rust compiler can be slow (although we are of course trying to make it faster)I don’t know of any great articles that consist mostly of Rust’s downsides; I’d search for “I’m quitting Rust” or “the good the bad or the ugly” style articles, then check to see if /r/rust or the User’s Forum discuss them. Our community often tries to extract places we can improve from those articles, to make the best out of a bad situation.
You mention that the compiler is slow: How does it compare with the major C++ compilers (msvc, clang, gcc) for large codebases? For me, one of the biggest problems of C++ is the horrible compilation times. Will Rust offer me an improvement in that specific regard?
What is the best Rust IDE written in Rust? Something comparable to Qt Creator as a C++ IDE.
I think I could fall in love if it:
– Stopped overabbreviating things to the point of unreadability. What in the world is a “fn”? That’s not even pronounceable. C abbreviates many types (struct, char…), but at least their abbreviated forms can still be read as some fragment of a word. Swift goes with “func”, Python with “def”. I’m surprised Rust didn’t call “enum” an “en”.
– Let go of the handcuffs of mutable moral purity, and stop making us type “let mut” for the common case of declaring a variable (which is something that by definition … varies). I like the constant immutable “let” option too, but we shouldn’t force the mutable case to be longer everywhere it’s frequently typed.
– Held consistency with type definitions via the “:type” pattern, used nearly everywhere except the type of functions, which for some reason is “->” instead of the logical “:” o_O.
Those are all specific instances, but the general rules apply for good languages (a) choose readable identifiers (b) favor the common case (c) be internally consistent. It would actually be fairly easy to fix most of the warts.
“The arguments between programmers who prefer dynamic versus static type systems are likely to endure for decades more”
Do you expect the world to end within just a few decades or something? 😉
is it because of Game dev’s moving to Rust-lang ?
Different languages exist to cater for different sections of low skill programming.
Experienced developers do not require yet another mechanism to stop bad coding and buggy programs.
Speaking as someone who regularly codes enterprise applications in assembly just because it’s easy to me I am looking for a reason to like this new language.
But that’s just me I guess
Graham,
You code “enterprise applications in assembly”? And the reason is “just because it’s easy to me”? Absolutely impressive might not be the best way to put it, but it’s the first that comes to mind.
I am starting with Rust right now, and I believe in the claims for maintainability and runtime error suppression, but the initial stage is hard. NOTHING WORKS! When you started writing code back in 1982, this sucks, but only for the first week or so.
With regards to your Superman skill, I have to say that, on one hand, when it comes to performance, nobody beats your code. But, on the other hand, that is not sustainable. Teams can’t work on a large Assembly codebase, architecture makes a difference, portability is way off the picture and code intelligibility becomes a matter of Faith.
Rust, like C (and more than C++) seems to deliver HPC through something readable, extensible and friendly community-supported. It’s designed to last and it’s still getting better.
I’d say now is the time!
Everyone who uses Rust or is going to, and is so excited about features that Rust offers might find interesting what Ada had in 1983. and still has:
[Ada ’83 Quality and Style: Guidelines for Professional Programmers](http://archive.adaic.com/docs/style-guide/83style/html/)
Read article:
[WHY ADA IS THE LANGUAGE YOU WANT TO BE PROGRAMMING YOUR SYSTEMS WITH by Maya Posch](https://hackaday.com/2019/09/10/why-ada-is-the-language-you-want-to-be-programming-your-systems-with/)
Definition from [Wikipedia](https://en.wikipedia.org/wiki/Ada_(programming_language)):
*Ada is a structured, statically typed, imperative, and object-oriented high-level programming language, extended from Pascal and other languages. It has built-in language support for design by contract (DbC), extremely strong typing, explicit concurrency, tasks, synchronous message passing, protected objects, and non-determinism. Ada improves code safety and maintainability by using the compiler to find errors in favor of runtime errors. Ada is an international technical standard, jointly defined by the International Organization for Standardization (ISO), and the International Electrotechnical Commission (IEC).*
Using [AWS-Ada Web Server](https://www.adacore.com/gnatpro/toolsuite/ada-web-server) You can get **web server and application server in single executable file** (the same source code can be compiled on multiple platforms).
[Industry and Ada: Ada Success Stories](https://people.cs.kuleuven.be/~dirk.craeynest/ada-belgium/success/success.html)
I haven’t read the whole article yet but I had to stop to write this comment because your embedded code snippets are broken in dark mode. The theme for the embedded codes has a black alternate row background color which makes the black text on black bg unreadable.
Unfortunately, this is a Github gist issue. We’ve since updated our own code formatting, so I’ll look into adding the code samples to the article directly.
Thank you for the nice blog and information provided here. As a newbie in programming ( 2 years) I want to have you opinion about investing on learning Rust or not in country with least tech companies.
Until I start seeing job descriptions with “Rust experience is absolute must” yall are on your own. Good luck with that. I was late to adopt NodeJS and Docker and man am I glad I was. Had I been an early adopter I would have experienced tons of pain. It still has issues but nothing like pre node v8 issues.
Since there are plenty of alternatives, there is literally no reason at all for me to adopt or even try out rust.
Yes, Ada is very good language. Really good. But: 1) no libraries (very big problem) 2) complex (time to learn it is definitely longer than in many other langs) 3) GNATS Studio is owned by one company, so actually you will deal with just one implementation/company. It’s a lock. And 4) ecosystem is not modern enough (there are several package managers but they are not mature, no big central packages repo…). But at the same time: 1) it’s highly human readable lang, so easy supportable 2) structure of programs is simple and “flat”, “block-oriented”, so refactoring and understanding of the code is very easy (compare with Haskell where often no way to understand what the hell is happening in some code) 3) it’s really SAFE – you will be signaled for integer overflows even (missing in Fortran) 4) IT HAS INDEPENDENT IDE where you can debug your application for a pleasure!!!! “Independent” means that it works, it is supported, it works on different OSes, and your language support there (Ada) cannot stop work because IDE contributor changed something in the new version. This permanently happens with Haskell in different editors – Emacs/Spacemacs, Atom, Visual Studio Code, vim/neovim, etc. Because the creator of the IDE and compiler is the same – AdaCore. And last – sure SPARK. So, there are big cons and pros. But biggest problem is libraries/packages, repo for them and package manager. And documentation, it’s so complex that better to have a big number of simple tutorials with simple English and a lot of short examples 🙂
If rust is so popular, where are all the jobs? On stackoverflow jobs, there are 1000 job offers, and only 13 of them are matching rust filter. You are talking about 1% popularity. You should call your article “What is Rust and why is it so unpopular?”
being the most loved programming language on stack overflow amounts to almost nothing. Coming out the door the language already has some annoyances that should been addressed.
Thank you for publishing this informative article that addressed a question I’ve always had when I read the SO developer survey! I’d also like to compliment you on the way you addressed some of the more negative comments in this feed–your responses made me chuckle and were well written.
One question I have is how common it is to use Rust for web development. Is anyone building web servers/APIs with Rust?
Having had extensive experience of maybe 10 languages in the course of the past 40 years (yikes), I’m not terribly impressed with Rust so far. As a replacement for the dreadful nonsense of C, and specifically its pointer arithmetic, something from the Stone Age (sorry, Stone Age, I know your people were far cleverer than that, otherwise I couldn’t write anything on a “blog”), of course it shines.
But that’s ALL. It’s still quite a lot, but we’re talking low-level languages here. It’ll never get beyond that.
I think the authors of Rust should have, instead, rewritten Python, or enhanced Python, or forked Python. YES, I know! It’s been done already: https://rustpython.github.io/. But as it says at the bottom of that page: “RustPython is in a development phase and should not be used in production or a fault intolerant setting. Our current build supports only about half of the Python standard library.”
Shades of Jython, methinks. I love Jython, but those guys got stuck at v 2.7 of Python, and they don’t have the time or the money to bring out a Jython version 3. Keeping up with a vast Juggernaut like Python 3 (CPython) is going to be a tall order for RustPython.
After having decided not to make a memory-safe version of Python they should then have gone for the next best option: to produce something that could be seamlessly integrated with Python (CPython) code. Most people know about the GIL, and the real limitations that that represents. But there are, in 2021, so many strategies for addressing that when you need high-performance, multi-threading, etc.
This popularity rating each year on SO is beginning to make me suspicious: correlation with…? Maybe people with lots of time on their hands to answer aimless “surveys” are the same people as those who see the upside and, yes, hype behind Rust but are just also a little bit naive.
I also have to say that, after Python, Groovy and Javascript, the last 3 languages I learnt to any extent, the syntax of Rust is not attractive, and very old-fashioned seeming. The build infrastructure (cargo, crates) is nice enough, but those sorts of build tool hurdles were overcome years ago with perfectly satisfactory solutions for all the major languages (even combinations of them).
If you thought at any time since 2000 that the future was C, yes, Rust is something to get excited about.
I’ve been programming for nearly 40 years and have experience in almost every major language. I’ve been beating my head against Rust for several weeks now and it just isn’t clicking. It’s a very, very frustrating experience and, in my personal opinion, learning it is not worth the effort unless you’re locked in to an ecosystem that already uses Rust.
I don’t know why so many articles praise the language. The lifetime specifier syntax is truly horrible. The compiler will often set sane defaults for lifetimes but the truth is that if you want to do *anything* even remotely useful then you’ll find yourself hitting that brick wall of obscure compiler errors.
“Googling” for similar errors doesn’t tend to result in many matches either – possibly because the uptake for this language doesn’t match the hype.
Honestly, learning to manage memory properly in C++ is the nicer experience.
There are some things I like, such as the type parameters that can be passed to individual members in an enum but overall the negatives massively out way the pros and for the first time in my life, I’m actually considering giving up on a project rather than continue fighting this language.
Hi, it’s 2022 already, do you still think rust language is still great ? How has it changed from two years ago ?
Rust sucks. the syntax is SO ugly, the compiler is slow, the people who like it treat it like a religion, and think it’s a crime to start a new project in C++. You also need to use “unsafe” to do anything, and did I mention it looks horrible?
The ugliest and the most unreadable language I have seen so far.
I worked with many languages over the 25 years of my career, including the support of a huge system written in Scheme, debugging some code written entirely with Scala DSLs, understanding pieces of OCaml code without any access to the developers who knew anything about it. That was at times annoying but ultimately not a problem. But Rust is the whole other level. The syntax seems to be purposefully confusing — there is no way you can understand a random piece of Rust code on github without spending ~40 hours getting into basics first. And I get it: once you are into basics it’s not a big of a deal. Which is not an excuse. This syntax seems to be almost deliberately obfuscated to make the language niche and viral. And that’s even before you encounter the toxic community.
The only good thing about it: good salaries to maintain this inevitable piles of code left by developers lacking any kind of soft skills. I guess, this is something I’m looking forward to.
“some of Rust’s libraries, such as the regex crate, are the best-in-breed across any language”
What ? How do you reach that conclusion ? From what I read, Rust’s doesn’t even support look-around expressions… Look at Perl, Python and .NET regex engines who are more complete, feature-wise.