Rust is a young programming language developed by Mozilla with the open source community support. According to a survey of StackOverflow, in 2016 was the most loved among developers language! The goal of Rust is to combine control and performances, that is, operate at low level with high-level constructs. The actual applications vary from operating system to web development. Rust natively includes tools for Agile development, such as dependency management, testing and much more. The gap with other popular languages is filling up quickly thanks to the community, very active and fantastic :)
In this introductory presentation we will discuss the characteristics that make Rust unique, including the concepts of Ownership, Borrowing, and Lifetimes.
These slide has be presented for a talk in BIC Lazio Casilina, that has been also the first meetup of Rust Rome!
2. Who we are
Claudio Capobianco
wbigger@gmail.com
@settevolte
Enrico Risa
enrico.risa@gmail.com
@wolf4ood
3. When and why I did meet Rust
Last September, within my startup.
We were looking for a replacement for C/C++ code for our
multi-platform software library for IoT.
We considered Rust, Go, and Swift.
4. Why a replacement for C/C++?
Not only verbosity and safety, but also:
- test were not straightforward
- dependences management was a nightmare
- in general, continuous integration was really difficult to
obtain
5. More problems to tackle...
Much of time spent on debugging.
Several languages mixed in the same project.
Often modern languages are easy to learn but stucks
when software become complex.
6. What is Rust
Sponsored by Mozilla Research
The 0.1 release was in January 2012
The 1.0.0 stable release was in May 2015, since then the
backward compatibility is guaranteed
Most programming language by StackOverflow survey:
third place in 2015, first place in 2016!
9. Just to mention a few:
and many others, look at https://www.rust-lang.org/en-US/friends.html
RUST is already in production!
10. RUST applications
Few of applications written completely in Rust:
Servo, a web browser engine by Mozilla
Rocket, a web framework, focus on easy-to-use and fast
Redox, full fledged Operating System, 100% Rust
Habitat, application automation framework
and many others, look at https://github.com/kud1ing/awesome-rust
15. What control means?
vector data
length
Java
capacity
[0]
...
data capacity
‘H’
‘e’
...
Ability to define abstractions that optimize away to
nothing.
16. What control means?
vector data
length
Java
capacity
[0]
...
data capacity
‘H’
‘e’
...
Ability to define abstractions that optimize away to
nothing.
17. What safety means?
void example() {
vector<string> vector;
…
auto& elem = vector[0];
vector.push_back(some_string);
cout << elem;
}
data
length
capacity
elem
[0]
vector
C++
18. What safety means?
void example() {
vector<string> vector;
…
auto& elem = vector[0];
vector.push_back(some_string);
cout << elem;
}
data
length
capacity
elem
[0]
vector
C++
19. What safety means?
void example() {
vector<string> vector;
…
auto& elem = vector[0];
vector.push_back(some_string);
cout << elem;
}
data
length
capacity
elem
[0]
vector
C++
[0]
[1]
20. What safety means?
void example() {
vector<string> vector;
…
auto& elem = vector[0];
vector.push_back(some_string);
cout << elem;
}
data
length
capacity
elem
[0]
vector
C++
[0]
[1]
dangling pointer!
21. What safety means?
void example() {
vector<string> vector;
…
auto& elem = vector[0];
vector.push_back(some_string);
cout << elem;
}
data
length
capacity
elem
[0]
vector
C++
[0]
[1]
aliasing
mutating
22. What safety means?
Problem with safety happens when we have a resource
that at the same time:
● has alias: more references to the resource
● is mutable: someone can modify the resource
That is (almost) the definition of data race.
23. What safety means?
Problem with safety happens when we have a resource
that at the same time:
● has alias: more references to the resource
● is mutable: someone can modify the resource
That is (almost) the definition of data race.
alias + mutable =
24. What about the garbage collector?
With the garbage collector:
● we lose control
● requires a runtime!
Anyway, it is insufficient to prevent data race or iterator
invalidation.
25. The Rust Way
Rust solution to achieve both control and safety is to push
as much as possible checks at compile time.
This is achieved mainly through the concepts of
● Ownership
● Borrowing
● Lifetimes
32. fn take(vec: Vec<i32>) {
//…
}
Ownership
fn give() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
take(vec);
}
data
length
capacity
[0]
[1]
vec
data
length
capacity
vec
take ownership
33. fn take(vec: Vec<i32>) {
//…
}
Ownership
fn give() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
take(vec);
}
data
length
capacity
[0]
[1]
vec
data
length
capacity
vec
34. fn take(vec: Vec<i32>) {
//…
}
Ownership
fn give() {
let mut vec = Vec::new();
vec.push(1);
vec.push(2);
take(vec);
}
data
length
capacity
vec
cannot be used
because data is
no longer
available
52. Lifetimes
Remember that the owner has always the ability to destroy
(deallocate) a resource!
In simplest cases, compiler recognize the problem and
refuse to compile.
In more complex scenarios compiler needs an hint.
57. Lifetime - first example
fn skip_prefix(line: &str, prefix: &str) -> &str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
58. Lifetime - first example
fn skip_prefix(line: &str, prefix: &str) -> &str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
59. fn skip_prefix(line: &str, prefix: &str) -> &str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
Lifetime - first example
first borrowing
second borrowing
(we return something that is
not ours)
60. fn skip_prefix(line: &str, prefix: &str) -> &str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
Lifetime - first example
first borrowing
second borrowing
(we return something that is
not ours)
we know that “s2” is valid as long
as “line” is valid, but compiler
doesn’t know
61. fn skip_prefix(line: &str, prefix: &str) -> &str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
Lifetime - first example
refuse to
compile
62. fn skip_prefix(line: &str, prefix: &str) -> &str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
Lifetime - first example
63. Lifetime - example reviewed
fn skip_prefix<'a>(line: &'a str, prefix: &str) -> &'a str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
64. Lifetime - example reviewed
fn skip_prefix<'a>(line: &'a str, prefix: &str) -> &'a str {
let (s1,s2) = line.split_at(prefix.len());
s2
}
fn print_hello() {
let line = "lang:en=Hello World!";
let v;
{
let p = "lang:en=";
v = skip_prefix(line, p);
}
println!("{}", v);
}
borrowing source is now
explicit, through the
lifetime parameter
Hello World!
66. Traits
“A trait is a language feature that tells the Rust compiler
about functionality a type must provide.”
https://doc.rust-lang.org
Rust is really conservative about what a generic type can
do!
72. Lock data not code
The technique to lock data instead of code is widely used,
but generally is up to responsibility of developers.
“Lock data, not code” is enforced in Rust
73. No runtime
Unlike many other languages as Java, Go or JavaScript,
Rust doesn’t have a runtime environment.
This make much easier to write a library in Rust and
integrate it anywhere!
74. Option type
null does not exist in Rust
Rust uses the Option type instead.
enum Option<T> {
None,
Some(T),
}
let x = Some(7);
let y = None;
75. Result type
exceptions do not exist in Rust
Rust uses Result type instead.
enum Result<T, E> {
Ok(T),
Err(E),
}
let x = Ok(7);
let y = Error(“Too bad”);
76. Minimal core
Rust philosophy is to have a only few functionalities
built-in in the language, and delegates a lot to libraries.
It also uses macro! as a clean way to reduce boilerplate
code without “dirty” the language syntax.
According to me, this is one reason why it is loved
78. Cargo
Rust’s package manager.
Manages dependencies and gives reproducible builds.
Cargo is one of the most powerful feature of Rust and it is
the result of an awesome community!
79. Cargo
In Cargo, each library is called “crate”.
Stabilization pipeline for features is very quickly and nightly
(as Rust language development itself).
“Stability without stagnation”
80. Crates
Can be either a binary or a library.
libc, types and bindings to native C functions
xml-rs, an XML library in pure Rust
time, utilities for working with time-related functions
serde, a generic serialization/deserialization framework
… and more like winapi, regex, url, rustc-serialize, etc.
81. Rustup is the Rust toolchain installer.
Easily switch between stable, beta, and nightly.
Cross-compiling is much simpler.
It is similar to Ruby's rbenv, Python's pyenv, or Node's nvm.
Install rustup by
curl https://sh.rustup.rs -sSf | sh
Rustup
82. Test
Rust objective is to ensure a high quality products.
Cargo has built-in a simple but efficient mechanism to write
and run test
cargo test
90. Community
Rust has an active and amazing community.
https://this-week-in-rust.org/blog/2017/02/14/
91. Community
There are a lot of active channels, including:
forum, reddit, IRC, youtube, twitter, blog
And initiative like:
● crate of the week
● rust weekly