рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЗ рд╕рд╛рде рд░рд╕реНрдЯ рдФрд░ рд╕реА ++ рдХреА рддреБрд▓рдирд╛ рдХрд░рдирд╛

рдкреНрд░рд╕реНрддрд╛рд╡рдирд╛


рдпрд╣рд╛рдБ рд╡рд╛рджрд╛ рдХрд┐рдпрд╛ рдЧрдпрд╛ рднрд╛рд╖рд╛ рддреБрд▓рдирд╛ рд╣реИред рдЙрджрд╛рд╣рд░рдг, рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ, рдХреГрддреНрд░рд┐рдо рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд╡рд╛рд╕реНрддрд╡рд┐рдХ рджреБрдирд┐рдпрд╛ рдореЗрдВ рдЦрддрд░реЗ рдХреА рднрдпрд╛рд╡рд╣рддрд╛ рдХреА рд╕рд░рд╛рд╣рдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдкрдиреА рдХрд▓реНрдкрдирд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВред

рд╕рднреА C ++ рдкреНрд░реЛрдЧреНрд░рд╛рдореЛрдВ рдХреЛ рдСрдирд▓рд╛рдЗрди рдХрдВрдкрд╛рдЗрд▓рд░ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ c ++ 11 рдореЛрдб рдореЗрдВ gcc-4.7.2 рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕рдВрдХрд▓рд┐рдд рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдЬрдВрдЧ рдХрд╛рд░реНрдпрдХреНрд░рдореЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдЬрдВрдЧ рдХреЗ рдирд╡реАрдирддрдо рд╕рдВрд╕реНрдХрд░рдг (рд░рд╛рдд, 0.11-рдкреВрд░реНрд╡) рдХреЗ рд╕рд╛рде рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред

рдореБрдЭреЗ рдкрддрд╛ рд╣реИ рдХрд┐ C ++ 14 (рдФрд░ рдЙрд╕рд╕реЗ рдЖрдЧреЗ) рднрд╛рд╖рд╛ рдХреА рдХрдордЬреЛрд░рд┐рдпреЛрдВ рдХреЛ рджреВрд░ рдХрд░реЗрдЧрд╛, рд╕рд╛рде рд╣реА рдирдИ рд╕реБрд╡рд┐рдзрд╛рдУрдВ рдХреЛ рднреА рдЬреЛрдбрд╝реЗрдЧрд╛ред рдкрд┐рдЫрдбрд╝реЗ рд╕рдВрдЧрддрддрд╛ рд╕реА ++ рдХреЛ рд╕рд┐рддрд╛рд░реЛрдВ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рд╕реЗ рд░реЛрдХрддрд╛ рд╣реИ (рдФрд░ рдЗрд╕рдХреЗ рд╕рд╛рде рд╣рд╕реНрддрдХреНрд╖реЗрдк рдХрд░рддрд╛ рд╣реИ) рдкрд░ рд╡рд┐рдЪрд╛рд░ рдЗрд╕ рд▓реЗрдЦ рдХреЗ рджрд╛рдпрд░реЗ рд╕реЗ рдкрд░реЗ рд╣реИрдВ, рд╣рд╛рд▓рд╛рдВрдХрд┐, рдореБрдЭреЗ рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдЖрдкрдХреА рд╡рд┐рд╢реЗрд╖рдЬреНрдЮ рд░рд╛рдп рдкрдврд╝рдиреЗ рдореЗрдВ рджрд┐рд▓рдЪрд╕реНрдкреА рд╣реЛрдЧреАред рдбреАред рдкрд░ рдХреЛрдИ рднреА рдЬрд╛рдирдХрд╛рд░реА рднреА рд╕реНрд╡рд╛рдЧрдд рдпреЛрдЧреНрдп рд╣реИред


рдЯреЗрдореНрдкрд▓реЗрдЯ рдкреНрд░рдХрд╛рд░реЛрдВ рдХреА рдЬрд╛рдБрдЪ рдХрд░рдирд╛


C ++ рд▓реЗрдЦрдХ рд▓рдВрдмреЗ рд╕рдордп рд╕реЗ рдЕрд╕рдВрддреБрд╖реНрдЯ рд╣реИ рдХрд┐ рд▓реИрдВрдЧ-рдиреЗрдХреНрд╕реНрдЯ рдХреЗ рд╣рд╛рд▓рд┐рдпрд╛ рднрд╛рд╖рдг рдореЗрдВ рдЙрдиреНрд╣реЗрдВ " рд╕рдВрдХрд▓рди-рд╕рдордп рдмрддрдЦ рдЯрд╛рдЗрдкрд┐рдВрдЧ " рдХрд╣рддреЗ рд╣реБрдП рднрд╛рд╖рд╛ рдореЗрдВ рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреИрд╕реЗ рд▓рд╛рдЧреВ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рд╕рдорд╕реНрдпрд╛ рдпрд╣ рд╣реИ рдХрд┐ рдпрд╣ рд╣рдореЗрд╢рд╛ рд╕реНрдкрд╖реНрдЯ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдЕрдкрдиреЗ рд╡рд┐рдЬреНрдЮрд╛рдкрди рдХреЛ рджреЗрдЦрдХрд░ рдХрд┐рд╕реА рдЯреЗрдореНрдкрд▓реЗрдЯ рдХреЛ рдХреИрд╕реЗ рддреНрд╡рд░рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПред рд╕реНрдерд┐рддрд┐ рд░рд╛рдХреНрд╖рд╕реА рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢реЛрдВ рд╕реЗ рдмрдврд╝ рдЬрд╛рддреА рд╣реИред рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреЛ рдмрдирд╛рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░реЗрдВ:
#include <vector> #include <algorithm> int main() { int a; std::vector< std::vector <int> > v; std::vector< std::vector <int> >::const_iterator it = std::find( v.begin(), v.end(), a ); } 

рдмрд╣реБ-рдкреГрд╖реНрда рддреНрд░реБрдЯрд┐ рд╕рдВрджреЗрд╢ рдкрдврд╝рдиреЗ рд╡рд╛рд▓реЗ рд╡реНрдпрдХреНрддрд┐ рдХреА рдЦреБрд╢реА рдХреА рдХрд▓реНрдкрдирд╛ рдХрд░реЗрдВ рдпрджрд┐ рдЙрд╕рдиреЗ рджреБрд░реНрдШрдЯрдирд╛ рд╕реЗ рдпрд╣ рд╕реНрдерд┐рддрд┐ рдмрдирд╛рдИ рд╣реИред

Rust рдореЗрдВ рдЯреЗрдореНрдкреНрд▓реЗрдЯреНрд╕ рдХреЛ рдЗрдВрд╕реНрдЯреЗрдВрдЯ рдХрд░рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ рд╢реБрджреНрдзрддрд╛ рдХреЗ рд▓рд┐рдП рдЬрд╛рдБрдЪ рдХреА рдЬрд╛рддреА рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЯреЗрдореНрдкреНрд▓реЗрдЯ рдореЗрдВ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЗ рдмреАрдЪ рдПрдХ рд╕реНрдкрд╖реНрдЯ рдЕрд▓рдЧрд╛рд╡ рд╣реЛрддрд╛ рд╣реИ (рдЬреЛ рдХрд┐ рдХрд┐рд╕реА рдЕрдиреНрдп / рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдЯреЗрдореНрдкрд▓реЗрдЯ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдкрд░ рдирд╣реАрдВ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП) рдФрд░ рддрд╛рддреНрдХрд╛рд▓рд┐рдХ рд╕реНрдерд╛рди рдкрд░, рдЬрд╣рд╛рдБ рдЖрдкрдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╕рднреА рдХреЛ рдЖрд╡рд╢реНрдпрдХрддрд╛рдУрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░рдирд╛ рд╣реИ рдЯреЗрдореНрдкрд▓реЗрдЯ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдкреНрд░рдХрд╛рд░:
 trait Sortable {} fn sort<T: Sortable>(array: &mut [T]) {} fn main() { sort(&mut [1,2,3]); } 

рдпрд╣ рдХреЛрдб рд╕реНрдкрд╖реНрдЯ рдХрд╛рд░рдг рдХреЗ рд▓рд┐рдП рд╕рдВрдХрд▓рд┐рдд рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
рдбреЗрдореЛ: рел: рел: рел: реп рддреНрд░реБрдЯрд┐: рдЗрдВрдЯ рдХреЗ рд▓рд┐рдП рдЫрд╛рдБрдЯреЗ рдЬрд╛рдиреЗ рдпреЛрдЧреНрдп рдЧреБрдг рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдХреЛ рдЦреЛрдЬрдиреЗ рдореЗрдВ рд╡рд┐рдлрд▓ рд░рд╣рд╛
рдбреЗрдореЛ: 5 рд╕реЙрд░реНрдЯ (рдФрд░ рдореНрдпреВрдЯ [1,2,3]);


рд░рд┐рдореЛрдЯ рдореЗрдореЛрд░реА рддрдХ рдкрд╣реБрдВрдЪ


рд╕реА ++ рдХреЗ рд╕рд╛рде рд╕рдорд╕реНрдпрд╛рдУрдВ рдХреА рдПрдХ рдкреВрд░реА рд╢реНрд░реЗрдгреА рд╣реИ, рдЕрдкрд░рд┐рднрд╛рд╖рд┐рдд рд╡реНрдпрд╡рд╣рд╛рд░ рдФрд░ рджреБрд░реНрдШрдЯрдирд╛рдУрдВ рдореЗрдВ рд╡реНрдпрдХреНрдд рдХреА рдЧрдИ рдЬреЛ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рд╣рдЯрд╛рдП рдЧрдП рдореЗрдореЛрд░реА рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рд╕реЗ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИрдВред
рдПрдХ рдЙрджрд╛рд╣рд░рдг:
 int main() { int *x = new int(1); delete x; *x = 0; } 

рд░рд╕реНрдЯ рдореЗрдВ, рдЗрд╕ рддрд░рд╣ рдХреА рд╕рдорд╕реНрдпрд╛ рдЕрд╕рдВрднрд╡ рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рдореЗрдореЛрд░реА рдбрд┐рд▓реАрд╢рди рдХрдорд╛рдВрдб рдирд╣реАрдВ рд╣реИрдВред рд╕реНрдЯреИрдХ рдкрд░ рдореЗрдореЛрд░реА рддрдм рд░рд╣рддреА рд╣реИ рдЬрдм рд╡рд╣ рджрд╛рдпрд░реЗ рдореЗрдВ рд╣реЛрддреА рд╣реИ, рдФрд░ рд░рд╕реНрдЯ рдЗрд╕ рд▓рд┐рдВрдХ рдХреЛ рдЗрд╕ рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рдЬреАрд╡рд┐рдд рд░рд╣рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддрд╛ рд╣реИ (рдХрд┐рд╕реА рдЦреЛрдП рд╣реБрдП рдкреЙрдЗрдВрдЯрд░ рдХреЗ рд▓рд┐рдП рдЙрджрд╛рд╣рд░рдг рджреЗрдЦреЗрдВ)ред рдпрджрд┐ рд╕реНрдореГрддрд┐ рдХреЛ рдвреЗрд░ рдкрд░ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдпрд╣ рдПрдХ рд╕рдВрдХреЗрддрдХ рд╣реИ (
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).


++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }

:
2, 2

Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }


#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }


struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***

Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy .
Rust . Eq Clone ? deriving :
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }


#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .

Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);

, " &mut " " & " , , , &mut . . , , C99 restrict (Rust LLVM ), .


#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)

Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }


Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break . Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }


int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .


#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0

, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();

, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc ( Atomically Reference Counted - ) RWLock ( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378

, ++ . . Rust , . , , . , ( ).


Rust , unsafe{} . , " ! , . ". , "" ( , ) . , ( ) . , , Cell Mutex . , ( TDD !).


Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What тАУ if anything тАУ have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond

Source: https://habr.com/ru/post/In225003/


All Articles