RUST LANG

Nelson Corrêa Viana Júnior

@nelsonjr

github.com/ircnelson

Rust é uma linguagem de programação.

Está na categoria de system languages, multi-paradigma e compilada. Desenvolvida pela Mozilla Research.

 

A linguagem apareceu como um projeto pessoal de Graydon Hoare, funcionário da Mozilla.

 

Rust 1.0, a primeira versão estável, foi lançada em 15 de Maio de 2015.

 

A filosofia do Rust é: “Estável, mas nunca estagnado”. - Versão estável a cada 6 semanas.

O que é Rust?

Por que?

Onde usar?

Onde não usar?

Quem usa em produção?

Empresa Projeto
Mozilla Servo (Browser Engine integrado ao Firefox)
Coursera Ferramentas para provisionamento do ambiente Docker de produção
Chef Implementação do Delivery CLI
Canonical Monitoramento de servidores
NPM Mudaram de C para Rust em pontos críticos na arquitetura dos serviços de registry
Dropbox Otimização do cloud storage
Ceph (Storage)

Environment / Tooling

rustc Compilador
ex: rustc main.rs
rustup Gerenciador de versões do compilador
ex: rustup update stable/beta/nightly
cargo Gerenciador de pacotes
ex: cargo install nome_do_pacote

cargo run
cargo build
cargo new
cargo doc
cargo test
cargo bench
  • Memory safety
  • Não possui Garbage Collector!
  • Imutável por padrão
  • Move semantics
  • Concorrência sem data race
  • Inferência de tipo

Características

Memory safety sem Garbage Collector?

GARBAGE COLLECTOR

Não usa destruição determinística;
Exige muito recurso de memória pra poder ser eficiente (muitas vezes mais do que o seu próprio programa);
As pausas do GC não são aceitáveis para sistemas realtime;

OWNERSHIP

SHARED BORROW

SHARED MUTABLE BORROW

OWNERSHIP

​Regras

  1. Cada recurso no Rust tem uma variável chamada de owner.
  2. Um recurso pode ter somente um owner por vez.
  3. Quando um owner sai do escopo, o recurso será destruído (dropped).  
fn main() {

    let say_hello = "hello world"; // 'say_hello' é valido daqui pra frente

    println!("{}", say_hello);

} // 'say_hello' será liberado da memória

OWNERSHIP

fn main() {

    let s1 = String::from("hello");

    say_something(s1);

    say_something(s1); // error!
}

fn say_something(text : String) {
//                ^
//                |______________ move ownership

    println!("{}", text);

} // 'text' será liberado da memória

OWNERSHIP

fn main() {

    let s1 = String::from("hello");

    let s2 = say_something(s1);

    say_something(s2);
}

fn say_something(text : String) -> String {

    println!("{}", text);

    text

}

Solução 1

Solução cheia de cerimonia.

Insustentável ao longo do software.

OWNERSHIP

fn main() {

    let s1 = String::from("hello");

    let s2 = s1.clone();

    say_something(s1);

    say_something(s2);
}

fn say_something(text : String) {

    println!("{}", text);

} // 'text' será liberado da memória

Solução 2

Solução cara demais.

Todos os valores da Stack e Heap são clonados.

OWNERSHIP

fn main() {

    let n1 = 5;

    do_something(n1);

    do_something(n1);
}

fn do_something(n : i32) {

    println!("{}", n);

} // 'n' será liberado da memória

?

O que vai acontecer?

OWNERSHIP

fn main() {

    let n1 = 5;

    do_something(n1);

    do_something(n1);
}

fn do_something(n : i32) {

    println!("{}", n);

} // 'n' será liberado da memória

Tipos numéricos implementam

`Copy` trait por padrão.

SHARED BORROW (&)

fn main() {

    let s1 = String::from("hello");

    say_something(&s1);

    say_something(&s1);
}

fn say_something(s : &String) {

    println!("{}", s);

} // 's' será liberado da memória

SHARED BORROW (&)

fn main() {
    let s1 = String::from("hello");
    change(&s1);
}

fn change(s : &String) {

    println!("{}", s);

    s.push_str(" world"); // error!

}

error: cannot borrow immutable borrowed content `*s` as mutable
  --> src/main.rs:10:5
   |
6  | fn change(s : &String) {
   |               ------- use `&mut String` here to make mutable
...
10 |     s.push_str(" world"); // error!
   |     ^ cannot borrow as mutable

Shared borrow não é sinônimo de mutabilidade.

SHARED MUTABLE BORROW (&mut)

Esta regra previne data race em tempo de compilação.

Data race ocorre quando os três comportamentos abaixo ocorre:​

  1. Dois ou mais ponteiros acessam o mesmo dado ao mesmo tempo.

  2. Pelo menos um dos ponteiros está sendo usado para gravar os dados.

  3. Não há nenhum mecanismo sendo usado para sincronizar o acesso aos dados.

Regra: Só pode existir uma referência mutável para o mesmo recurso no escopo.

SHARED MUTABLE BORROW (&mut)

fn main() {
    let mut s = String::from("hello");
    let r1 = &mut s;
    let r2 = &mut s;
}

error[E0499]: cannot borrow `s` as mutable more than once at a time
 --> src/main.rs:4:19
  |
3 |     let r1 = &mut s;
  |                   - first mutable borrow occurs here
4 |     let r2 = &mut s;
  |                   ^ second mutable borrow occurs here
5 | }
  | - first borrow ends here

Regra: Só pode existir uma referência mutável para o mesmo recurso no escopo.

SHARED MUTABLE BORROW (&mut)

fn main() {

    let mut s1 = String::from("hello");

    change(&mut s1);

    println!("{}", s1);
}

fn change(s : &mut String) {

    println!("{}", s);

    s.push_str(" world");

}

Resolvendo o código da função 'change' usada no tópico de 'Shared borrow'.

Referências

Obrigado!

Rust Lang

By nelson correa v. júnior