📜 ⬆️ ⬇️

Comparing Rust and C ++ with examples

Foreword


Here is the promised comparison of languages. Examples, of course, are artificial, so use your imagination to appreciate the scale of the threat in the real world.

All C ++ programs were compiled using gcc-4.7.2 in c ++ 11 mode using an online compiler . Rust programs were compiled with the latest version of Rust (nightly, 0.11-pre) using the rust playpen .

I know that C ++ 14 (and further) will patch up the weak points of the language, as well as add new features. Reflections on how backward compatibility prevents C ++ from reaching the stars (and preventing it) are beyond the scope of this article, but I would be interested to read your expert opinion in the comments. Any information on D. is also welcome.
')

Check Template Types


Author C ++ has long been displeased with how templates are implemented in the language, calling them " compile-time duck typing " in a recent speech on Lang-NEXT. The problem is that it is not always clear how to instantiate a template by looking at its declaration. The situation is worsened by monstrous error messages. Try building, for example, this program:
#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 ); } 

Imagine the joy of a person reading a multipage error message if he created such a situation by accident.

Templates in Rust are checked for correctness prior to their instantiation, so there is a clear separation between errors in the template itself (which should not be if you use someone else's / library template) and in the place of instantiation, where all that is required of you is to meet the requirements for type described in the template:
 trait Sortable {} fn sort<T: Sortable>(array: &mut [T]) {} fn main() { sort(&mut [1,2,3]); } 

This code is not compiled for an obvious reason:
demo: 5: 5: 5: 9 error: failed to find out
demo: 5 sort (& mut [1,2,3]);


Access to remote memory


There is a whole class of problems with C ++, expressed in indefinite behavior and falls, which arise from the attempt to use memory that has already been deleted.
Example:
 int main() { int *x = new int(1); delete x; *x = 0; } 

In Rust, this kind of problem is impossible, since there are no memory removal commands. The memory on the stack lives while it is in scope, and Rust does not allow references to it to survive this area (see the example of a lost pointer). If the memory is allocated in the heap - then a pointer to it (
 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/225003/


All Articles