an introduction to rust: the modern programming language to develop safe and efficient applications
TRANSCRIPT
An Introduction to RustBIC Lazio Roma Casilina
February 16, 2016
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.
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
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.
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!
Rust goalRuby, Javascript, Python, ...C C++ Java
Control Safety
Rust goal
Rust
Ruby, Javascript, Python, ...C C++ Java
Control Safety
Just to mention a few:
and many others, look at https://www.rust-lang.org/en-US/friends.html
RUST is already in production!
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
Hello world!
fn main() {
// Print text to the console
println!("Hello World!");
}
Key concepts
Rust is born with the aim to balance control and security.
That is, in other words:
operate at low level with high-level constructs.
What control means?void example() { vector<string> vector; … auto& elem = vector[0];}
data
length
capacity
elem
[0]
[1]
[2]
...
Stack Heap
vector
C++
string
What control means?
Ability to define abstractions that optimize away to nothing.
What control means?
vector data
length
Javacapacity
[0]
...
data capacity
‘H’
‘e’
...
Ability to define abstractions that optimize away to nothing.
What control means?
vector data
length
Javacapacity
[0]
...
data capacity
‘H’
‘e’
...
Ability to define abstractions that optimize away to nothing.
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++
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++
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]
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!
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
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.
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 =
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.
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
Ownership
Ownership
Ownership
Ownership
Green doesn’t own the book anymore and cannot use it
fn take(vec: Vec<i32>) {//…
}
Ownershipfn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec);}
data
length
capacity
vec
fn take(vec: Vec<i32>) {//…
}
Ownershipfn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec);}
data
length
capacity
[0]
[1]vec
fn take(vec: Vec<i32>) {//…
}
Ownershipfn 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
fn take(vec: Vec<i32>) {//…
}
Ownershipfn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec);}
data
length
capacity
[0]
[1]vec
data
length
capacity
vec
fn take(vec: Vec<i32>) {//…
}
Ownershipfn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec);}
data
length
capacity
veccannot be used because data is no longer available
fn take(vec: Vec<i32>) {//…
}
Ownership - errorfn give() { let mut vec = Vec::new(); vec.push(1); vec.push(2); take(vec); vec.push(3);}
Borrowing
Borrowing with &T
one or more references to a resource
Borrowing with &T
read
read
read
&T
Borrowing with &T
Green can use its book again
Borrowing with &mut T
exactly one mutable reference
Borrowing with &mut T
Borrowing with &mut T&mut T
Borrowing with &mut T
&mut T
Borrowing with &mut T
Green can use its book again
fn user(vec: &Vec<i32>) {//…
}
Borrowingfn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); user(&vec);} data
length
capacity
vec
Borrowing
data
length
capacity
[0]
[1]vec
fn user(vec: &Vec<i32>) {//…
}
fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); user(&vec);}
Borrowing
data
length
capacity
[0]
[1]vec
datavec
fn user(vec: &Vec<i32>) {//…
}
fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); user(&vec);}
fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); user(&vec);}
fn user(vec: &Vec<i32>) {//…
}
Borrowing
data
length
capacity
[0]
[1]vec
datavec
shared ref to vec
loan out vec
fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); user(&vec);}
fn user(vec: &Vec<i32>) {vec.push(3);
}
Borrowing
data
length
capacity
[0]
[1]vec
datavec
what happens if I try to modify it?
loan out vec
Borrowing - error fn lender() { let mut vec = Vec::new(); vec.push(1); vec.push(2); user(&vec);}
fn user(vec: &Vec<i32>) {vec.push(3);
}
Lifetimes
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.
Lifetimes
Lifetimes&T
first borrowing
Lifetimes
&T
second borrowing
!
Lifetimes
&T
dangling pointer!
Lifetime - first examplefn 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 examplefn 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);}
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 examplefirst borrowing
second borrowing(we return something that is not ours)
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 examplefirst 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
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
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
Lifetime - example reviewedfn 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);}
Lifetime - example reviewedfn 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!
Other key concepts
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!
Traitsfn is_equal<T>(a:T,b:T)->bool { a==b}
Traitsfn is_equal<T>(a:T,b:T)->bool { a==b}
generic type
Traitsfn is_equal<T>(a:T,b:T)->bool { a==b}
can T type be compared?we are not sure...
fn is_equal<T>(a:T,b:T)->bool { a==b}
Traitsdo not compile!
Traitsfn is_equal<T:PartialEq>(a:T,b:T)->bool { a==b}
type functionality is now explicit
OK!
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
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!
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;
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”);
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
Ecosystem
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!
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”
Crates
Can be either a binary or a library.
libc, types and bindings to native C functionsxml-rs, an XML library in pure Rusttime, utilities for working with time-related functionsserde, a generic serialization/deserialization framework
… and more like winapi, regex, url, rustc-serialize, etc.
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 bycurl https://sh.rustup.rs -sSf | sh
Rustup
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
Test#[test]fn it_works() { assert!(true)}
Test#[test]fn it_works() { assert!(false)}
Test#[test]#[should_panic]fn it_works() { assert!(false)}
Test can be also run on documented example!
Test
/// # Examples/// ``` /// use adder::add_two; /// assert_eq!(4, add_two(2)); /// ```
A full ecosystem
Formatter: rustfmt
Code completion: racer
Linter: clippy
Community
Community
Rust has an active and amazing community.
https://this-week-in-rust.org/blog/2017/02/14/
Community
There are a lot of active channels, including:
forum, reddit, IRC, youtube, twitter, blog
And initiative like:
● crate of the week● rust weekly
Credits
YoutubeThe Rust Programming Language by Alex Crichton
SpeakerDeckHello, Rust! — An overview by Ivan Enderlin
This presentation is online!
Slidesharehttps://www.slideshare.net/wbigger
Google Drive (public, comments enabled) https://goo.gl/tKuHkI