#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 ); }  trait Sortable {} fn sort<T: Sortable>(array: &mut [T]) {} fn main() { sort(&mut [1,2,3]); } demo: 5: 5: 5: 9 error: failed to find out
demo: 5 sort (& mut [1,2,3]);
 int main() { int *x = new int(1); delete x; *x = 0; }  Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 
 
      
  ++: 
 #include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); } 
  : 
 2, 2 
 
  Rust: 
 fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); } 
  : 
 demo:5:10: 5:11 error: `n` does not live long enough 
 demo:5 bar(&n) 
 ^ 
 demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23... 
 demo:4 fn foo(n: int) -> &int { 
 demo:5 bar(&n) 
 demo:6 } 
 demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23 
 demo:4 fn foo(n: int) -> &int { 
 demo:5 bar(&n) 
 demo:6 } 
 
   
 #include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); } 
   0  ,     , ,  .       Rust ( - ): 
 fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); } 
  , : use of possibly uninitialized variable: `currmin` 
   ( )      : 
 fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) } 
 
    
 struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; } 
 ,    : 
 *** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 *** 
 
     Rust: 
 struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // ,     ++ } fn main() { let a = A::new(1); let _b = a; } 
     .   ,     trait Copy . 
 Rust       .    Eq  Clone ?    deriving   : 
 #[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> } 
 
    
 #include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); } 
  : 
 2,2 
    ,    cc      .   ,   ,  99  restrict ,            :        . 
 
       Rust: 
 struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); } 
    : 
 demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable 
 demo:7 swap_from(&mut x, &x); 
 ^ 
 demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends 
 demo:7 swap_from(&mut x, &x); 
 ^ 
 demo:7:26: 7:26 note: previous borrow ends here 
 demo:7 swap_from(&mut x, &x); 
 
  ,             " &mut "  " & " ,   ,          ,   &mut .            .  ,    ,      C99  restrict  (Rust  LLVM    ),    . 
 
   
 #include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } } 
    ,    : 
 Segmentation fault (core dumped) 
 
    Rust: 
 fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } } 
      ,  ,        : 
 demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable 
 demo:7 v.push(5-*x); 
 ^ 
 demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends 
 demo:5 for x in v.iter() { 
 ^ 
 demo:10:2: 10:2 note: previous borrow ends here 
 demo:5 for x in v.iter() { 
 demo:6 if *x < 5 { 
 demo:7 v.push(5-*x); 
 demo:8 } 
 demo:9 } 
 demo:10 } 
 
 
  Switch 
 #include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); } 
   "2".  Rust          .  ,       ,    break .    Rust   : 
 enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); } 
 
     
 int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; } 
  Rust          . , ,     . 
 
  
 #include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); } 
     : 
 done 
 resource: 0x7f229c0008c0 
 resource: 0x7f22840008c0 
 resource: 0x7f228c0008c0 
 resource: 0x7f22940008c0 
 resource: 0x7f227c0008c0 
 
     ,        .      Rust: 
 struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } } 
  ,            . 
 demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable 
 demo:20 let ptr = res.acquire(); 
 
      ,   : 
 extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } } 
     Arc ( Atomically Reference Counted -        )  RWLock (   ).   : 
 resource: 0x7ff4b0010378 
 resource: 0x7ff4b0010378 
 resource: 0x7ff4b0010378 
 resource: 0x7ff4b0010378 
 resource: 0x7ff4b0010378 
 
  ,   ++    .    . Rust        ,    .  ,   ,   .           ,       (    ). 
 
     
 Rust        ,     unsafe{} .   ,     "  !  ,  . ".  ,  ""  (    ,    )    .    ,           ( )  . , ,        Cell  Mutex .             ,       (   TDD !). 
 
  
 Guaranteeing Memory Safety in Rust (by Niko Matsakis) 
 Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II) 
 Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup) 
 Lang-NEXT Panel: Systems Programming in 2014 and Beyond Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 
 
      
  ++: 
 #include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); } 
  : 
 2, 2 
 
  Rust: 
 fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); } 
  : 
 demo:5:10: 5:11 error: `n` does not live long enough 
 demo:5 bar(&n) 
 ^ 
 demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23... 
 demo:4 fn foo(n: int) -> &int { 
 demo:5 bar(&n) 
 demo:6 } 
 demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23 
 demo:4 fn foo(n: int) -> &int { 
 demo:5 bar(&n) 
 demo:6 } 
 
   
 #include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); } 
   0  ,     , ,  .       Rust ( - ): 
 fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); } 
  , : use of possibly uninitialized variable: `currmin` 
   ( )      : 
 fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) } 
 
    
 struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; } 
 ,    : 
 *** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 *** 
 
     Rust: 
 struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // ,     ++ } fn main() { let a = A::new(1); let _b = a; } 
     .   ,     trait Copy . 
 Rust       .    Eq  Clone ?    deriving   : 
 #[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> } 
 
    
 #include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); } 
  : 
 2,2 
    ,    cc      .   ,   ,  99  restrict ,            :        . 
 
       Rust: 
 struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); } 
    : 
 demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable 
 demo:7 swap_from(&mut x, &x); 
 ^ 
 demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends 
 demo:7 swap_from(&mut x, &x); 
 ^ 
 demo:7:26: 7:26 note: previous borrow ends here 
 demo:7 swap_from(&mut x, &x); 
 
  ,             " &mut "  " & " ,   ,          ,   &mut .            .  ,    ,      C99  restrict  (Rust  LLVM    ),    . 
 
   
 #include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } } 
    ,    : 
 Segmentation fault (core dumped) 
 
    Rust: 
 fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } } 
      ,  ,        : 
 demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable 
 demo:7 v.push(5-*x); 
 ^ 
 demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends 
 demo:5 for x in v.iter() { 
 ^ 
 demo:10:2: 10:2 note: previous borrow ends here 
 demo:5 for x in v.iter() { 
 demo:6 if *x < 5 { 
 demo:7 v.push(5-*x); 
 demo:8 } 
 demo:9 } 
 demo:10 } 
 
 
  Switch 
 #include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); } 
   "2".  Rust          .  ,       ,    break .    Rust   : 
 enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); } 
 
     
 int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; } 
  Rust          . , ,     . 
 
  
 #include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); } 
     : 
 done 
 resource: 0x7f229c0008c0 
 resource: 0x7f22840008c0 
 resource: 0x7f228c0008c0 
 resource: 0x7f22940008c0 
 resource: 0x7f227c0008c0 
 
     ,        .      Rust: 
 struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } } 
  ,            . 
 demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable 
 demo:20 let ptr = res.acquire(); 
 
      ,   : 
 extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } } 
     Arc ( Atomically Reference Counted -        )  RWLock (   ).   : 
 resource: 0x7ff4b0010378 
 resource: 0x7ff4b0010378 
 resource: 0x7ff4b0010378 
 resource: 0x7ff4b0010378 
 resource: 0x7ff4b0010378 
 
  ,   ++    .    . Rust        ,    .  ,   ,   .           ,       (    ). 
 
     
 Rust        ,     unsafe{} .   ,     "  !  ,  . ".  ,  ""  (    ,    )    .    ,           ( )  . , ,        Cell  Mutex .             ,       (   TDD !). 
 
  
 Guaranteeing Memory Safety in Rust (by Niko Matsakis) 
 Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II) 
 Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup) 
 Lang-NEXT Panel: Systems Programming in 2014 and Beyond
 Box)     ,       (     ).        (std::rc::Rc)    (std::gc::Gc),      (   ). 
 
      
  ++: 
 #include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
  : 
 2, 2 
 
  Rust: 
 fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); } 
  : 
 demo:5:10: 5:11 error: `n` does not live long enough 
 demo:5 bar(&n) 
 ^ 
 demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23... 
 demo:4 fn foo(n: int) -> &int { 
 demo:5 bar(&n) 
 demo:6 } 
 demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23 
 demo:4 fn foo(n: int) -> &int { 
 demo:5 bar(&n) 
 demo:6 } 
 
   
 #include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); } 
   0  ,     , ,  .       Rust ( - ): 
 fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); } 
  , : use of possibly uninitialized variable: `currmin` 
   ( )      : 
 fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) } 
 
    
 struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; } 
 ,    : 
 *** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 *** 
 
     Rust: 
 struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // ,     ++ } fn main() { let a = A::new(1); let _b = a; } 
     .   ,     trait Copy . 
 Rust       .    Eq  Clone ?    deriving   : 
 #[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> } 
 
    
 #include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); } 
  : 
 2,2 
    ,    cc      .   ,   ,  99  restrict ,            :        . 
 
       Rust: 
 struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); } 
    : 
 demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable 
 demo:7 swap_from(&mut x, &x); 
 ^ 
 demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends 
 demo:7 swap_from(&mut x, &x); 
 ^ 
 demo:7:26: 7:26 note: previous borrow ends here 
 demo:7 swap_from(&mut x, &x); 
 
  ,             " &mut "  " & " ,   ,          ,   &mut .            .  ,    ,      C99  restrict  (Rust  LLVM    ),    . 
 
   
 #include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } } 
    ,    : 
 Segmentation fault (core dumped) 
 
    Rust: 
 fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } } 
      ,  ,        : 
 demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable 
 demo:7 v.push(5-*x); 
 ^ 
 demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends 
 demo:5 for x in v.iter() { 
 ^ 
 demo:10:2: 10:2 note: previous borrow ends here 
 demo:5 for x in v.iter() { 
 demo:6 if *x < 5 { 
 demo:7 v.push(5-*x); 
 demo:8 } 
 demo:9 } 
 demo:10 } 
 
 
  Switch 
 #include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); } 
   "2".  Rust          .  ,       ,    break .    Rust   : 
 enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); } 
 
     
 int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; } 
  Rust          . , ,     . 
 
  
 #include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); } 
     : 
 done 
 resource: 0x7f229c0008c0 
 resource: 0x7f22840008c0 
 resource: 0x7f228c0008c0 
 resource: 0x7f22940008c0 
 resource: 0x7f227c0008c0 
 
     ,        .      Rust: 
 struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } } 
  ,            . 
 demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable 
 demo:20 let ptr = res.acquire(); 
 
      ,   : 
 extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } } 
     Arc ( Atomically Reference Counted -        )  RWLock (   ).   : 
 resource: 0x7ff4b0010378 
 resource: 0x7ff4b0010378 
 resource: 0x7ff4b0010378 
 resource: 0x7ff4b0010378 
 resource: 0x7ff4b0010378 
 
  ,   ++    .    . Rust        ,    .  ,   ,   .           ,       (    ). 
 
     
 Rust        ,     unsafe{} .   ,     "  !  ,  . ".  ,  ""  (    ,    )    .    ,           ( )  . , ,        Cell  Mutex .             ,       (   TDD !). 
 
  
 Guaranteeing Memory Safety in Rust (by Niko Matsakis) 
 Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II) 
 Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup) 
 Lang-NEXT Panel: Systems Programming in 2014 and BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondBox) , ( ). (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 BeyondSource: https://habr.com/ru/post/225003/
All Articles