#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 Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Source: https://habr.com/ru/post/225003/
All Articles