प्रस्तावना
यहाँ वादा किया गया भाषा तुलना है। उदाहरण, निश्चित रूप से, कृत्रिम हैं, इसलिए वास्तविक दुनिया में खतरे की भयावहता की सराहना करने के लिए अपनी कल्पना का उपयोग करें।
सभी C ++ प्रोग्रामों को ऑनलाइन कंपाइलर का उपयोग करके c ++ 11 मोड में gcc-4.7.2 का उपयोग करके संकलित किया गया था। जंग कार्यक्रमों का उपयोग जंग के नवीनतम संस्करण (रात, 0.11-पूर्व) के साथ किया गया था।
मुझे पता है कि C ++ 14 (और उससे आगे) भाषा की कमजोरियों को दूर करेगा, साथ ही नई सुविधाओं को भी जोड़ेगा। पिछड़े संगतता सी ++ को सितारों तक पहुंचने से रोकता है (और इसके साथ हस्तक्षेप करता है) पर विचार इस लेख के दायरे से परे हैं, हालांकि, मुझे टिप्पणियों में आपकी विशेषज्ञ राय पढ़ने में दिलचस्पी होगी। डी। पर कोई भी जानकारी भी स्वागत योग्य है।
टेम्पलेट प्रकारों की जाँच करना
C ++ लेखक लंबे समय से असंतुष्ट है कि लैंग-नेक्स्ट के हालिया भाषण में उन्हें " संकलन-समय बतख टाइपिंग " कहते हुए भाषा में टेम्पलेट कैसे लागू किए जाते हैं। समस्या यह है कि यह हमेशा स्पष्ट नहीं होता है कि अपने विज्ञापन को देखकर किसी टेम्पलेट को कैसे त्वरित किया जाए। स्थिति राक्षसी त्रुटि संदेशों से बढ़ जाती है। उदाहरण के लिए, इस कार्यक्रम को बनाने की कोशिश करें:
#include <vector> #include <algorithm> int main() { int a; std::vector< std::vector <int> > v; std::vector< std::vector <int> >::const_iterator it = std::find( v.begin(), v.end(), a ); }
बहु-पृष्ठ त्रुटि संदेश पढ़ने वाले व्यक्ति की खुशी की कल्पना करें यदि उसने दुर्घटना से यह स्थिति बनाई है।
Rust में टेम्प्लेट्स को इंस्टेंट करने से पहले शुद्धता के लिए जाँच की जाती है, इसलिए टेम्प्लेट में त्रुटियों के बीच एक स्पष्ट अलगाव होता है (जो कि किसी अन्य / लाइब्रेरी टेम्पलेट का उपयोग करने पर नहीं होना चाहिए) और तात्कालिक स्थान पर, जहाँ आपके लिए आवश्यक सभी को आवश्यकताओं को पूरा करना है टेम्पलेट में वर्णित प्रकार:
trait Sortable {} fn sort<T: Sortable>(array: &mut [T]) {} fn main() { sort(&mut [1,2,3]); }
यह कोड स्पष्ट कारण के लिए संकलित नहीं किया गया है:
डेमो: ५: ५: ५: ९ त्रुटि: इंट के लिए छाँटे जाने योग्य गुण के कार्यान्वयन को खोजने में विफल रहा
डेमो: 5 सॉर्ट (और म्यूट [1,2,3]);
रिमोट मेमोरी तक पहुंच
सी ++ के साथ समस्याओं की एक पूरी श्रेणी है, अपरिभाषित व्यवहार और दुर्घटनाओं में व्यक्त की गई जो पहले से ही हटाए गए मेमोरी का उपयोग करने की कोशिश से उत्पन्न होती हैं।
एक उदाहरण:
int main() { int *x = new int(1); delete x; *x = 0; }
रस्ट में, इस तरह की समस्या असंभव है क्योंकि मेमोरी डिलीशन कमांड नहीं हैं। स्टैक पर मेमोरी तब रहती है जब वह दायरे में होती है, और रस्ट इस लिंक को इस क्षेत्र में जीवित रहने की अनुमति नहीं देता है (किसी खोए हुए पॉइंटर के लिए उदाहरण देखें)। यदि स्मृति को ढेर पर आवंटित किया जाता है, तो यह एक संकेतक है (
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. , trait Copy
.
Rust . Eq
Clone
? deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, " &mut
" " &
" , , , &mut
. . , , C99 restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , , break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - ) RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust , unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , , Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by Felix Klock II)
Lang-NEXT: What – if anything – have we learned from C++? (by Bjarne Stroustrup)
Lang-NEXT Panel: Systems Programming in 2014 and Beyond
Box) , ( ). (std::rc::Rc) (std::gc::Gc), ( ).
++:
#include <stdio.h> int *bar(int *p) { return p; } int* foo(int n) { return bar(&n); } int main() { int *p1 = foo(1); int *p2 = foo(2); printf("%d, %d\n", *p1, *p2); }
:
2, 2
Rust:
fn bar<'a>(p: &'a int) -> &'a int { return p; } fn foo(n: int) -> &int { bar(&n) } fn main() { let p1 = foo(1); let p2 = foo(2); println!("{}, {}", *p1, *p2); }
:
demo:5:10: 5:11 error: `n` does not live long enough
demo:5 bar(&n)
^
demo:4:24: 6:2 note: reference must be valid for the anonymous lifetime #1 defined on the block at 4:23...
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
demo:4:24: 6:2 note: ...but borrowed value is only valid for the block at 4:23
demo:4 fn foo(n: int) -> &int {
demo:5 bar(&n)
demo:6 }
#include <stdio.h> int minval(int *A, int n) { int currmin; for (int i=0; i<n; i++) if (A[i] < currmin) currmin = A[i]; return currmin; } int main() { int A[] = {1,2,3}; int min = minval(A,3); printf("%d\n", min); }
0 , , , . Rust ( - ):
fn minval(A: &[int]) -> int { let mut currmin; for a in A.iter() { if *a < currmin { currmin = *a; } } currmin } fn main() { let A = [1i,2i,3i]; let min = minval(A.as_slice()); println!("{}", min); }
, : use of possibly uninitialized variable: `currmin`
( ) :
fn minval(A: &[int]) -> int { A.iter().fold(A[0], |u,&a| { if a<u {a} else {u} }) }
struct A{ int *x; A(int v): x(new int(v)) {} ~A() {delete x;} }; int main() { A a(1), b=a; }
, :
*** glibc detected *** demo: double free or corruption (fasttop): 0x0000000000601010 ***
Rust:
struct A{ x: Box<int> } impl A { pub fn new(v: int) -> A { A{ x: box v } } } impl Drop for A { fn drop(&mut self) {} // , ++ } fn main() { let a = A::new(1); let _b = a; }
. ,trait Copy
.
Rust .Eq
Clone
?deriving
:
#[deriving(Clone, Eq, Hash, PartialEq, PartialOrd, Ord, Show)] struct A{ x: Box<int> }
#include <stdio.h> struct X { int a, b; }; void swap_from(X& x, const X& y) { xa = yb; xb = ya; } int main() { X x = {1,2}; swap_from(x,x); printf("%d,%d\n", xa, xb); }
:
2,2
, cc . , , 99 restrict , : .
Rust:
struct X { pub a: int, pub b: int } fn swap_from(x: &mut X, y: &X) { xa = yb; xb = ya; } fn main() { let mut x = X{a:1, b:2}; swap_from(&mut x, &x); }
:
demo:7:24: 7:25 error: cannot borrow `x` as immutable because it is also borrowed as mutable
demo:7 swap_from(&mut x, &x);
^
demo:7:20: 7:21 note: previous borrow of `x` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x` until the borrow ends
demo:7 swap_from(&mut x, &x);
^
demo:7:26: 7:26 note: previous borrow ends here
demo:7 swap_from(&mut x, &x);
, "&mut
" "&
" , , ,&mut
. . , , C99restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , ,break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - )RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust ,unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , ,Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by 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
. . , , C99restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , ,break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - )RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust ,unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , ,Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by 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
. . , , C99restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , ,break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - )RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust ,unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , ,Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by 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
. . , , C99restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , ,break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - )RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust ,unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , ,Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by 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
. . , , C99restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , ,break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - )RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust ,unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , ,Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by 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
. . , , C99restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , ,break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - )RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust ,unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , ,Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by 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
. . , , C99restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , ,break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - )RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust ,unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , ,Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by 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
. . , , C99restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , ,break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - )RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust ,unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , ,Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by 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
. . , , C99restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , ,break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - )RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust ,unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , ,Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by 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
. . , , C99restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , ,break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - )RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust ,unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , ,Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by 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
. . , , C99restrict
(Rust LLVM ), .
#include <vector> int main() { std::vector<int> v; v.push_back(1); v.push_back(2); for(std::vector<int>::const_iterator it=v.begin(); it!=v.end(); ++it) { if (*it < 5) v.push_back(5-*it); } }
, :
Segmentation fault (core dumped)
Rust:
fn main() { let mut v: Vec<int> = Vec::new(); v.push(1); v.push(2); for x in v.iter() { if *x < 5 { v.push(5-*x); } } }
, , :
demo:7:13: 7:14 error: cannot borrow `v` as mutable because it is also borrowed as immutable
demo:7 v.push(5-*x);
^
demo:5:14: 5:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
demo:5 for x in v.iter() {
^
demo:10:2: 10:2 note: previous borrow ends here
demo:5 for x in v.iter() {
demo:6 if *x < 5 {
demo:7 v.push(5-*x);
demo:8 }
demo:9 }
demo:10 }
Switch
#include <stdio.h> enum {RED, BLUE, GRAY, UNKNOWN} color = GRAY; int main() { int x; switch(color) { case GRAY: x=1; case RED: case BLUE: x=2; } printf("%d", x); }
"2". Rust . , ,break
. Rust :
enum Color {RED, BLUE, GRAY, UNKNOWN} fn main() { let color = GRAY; let x = match color { GRAY => 1, RED | BLUE => 2, _ => 3, }; println!("{}", x); }
int main() { int pixels = 1; for (int j=0; j<5; j++); pixels++; }
Rust . , , .
#include <stdio.h> #include <pthread.h> #include <unistd.h> class Resource { int *value; public: Resource(): value(NULL) {} ~Resource() {delete value;} int *acquire() { if (!value) { value = new int(0); } return value; } }; void* function(void *param) { int *value = ((Resource*)param)->acquire(); printf("resource: %p\n", (void*)value); return value; } int main() { Resource res; for (int i=0; i<5; ++i) { pthread_t pt; pthread_create(&pt, NULL, function, &res); } //sleep(10); printf("done\n"); }
:
done
resource: 0x7f229c0008c0
resource: 0x7f22840008c0
resource: 0x7f228c0008c0
resource: 0x7f22940008c0
resource: 0x7f227c0008c0
, . Rust:
struct Resource { value: Option<int>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire<'a>(&'a mut self) -> &'a int { if self.value.is_none() { self.value = Some(1); } self.value.get_ref() } } fn main() { let mut res = Resource::new(); for _ in range(0,5) { spawn(proc() { let ptr = res.acquire(); println!("resource {}", ptr) }) } }
, .
demo:20:23: 20:26 error: cannot borrow immutable captured outer variable in a proc `res` as mutable
demo:20 let ptr = res.acquire();
, :
extern crate sync; use sync::{Arc, RWLock}; struct Resource { value: Option<Box<int>>, } impl Resource { pub fn new() -> Resource { Resource{ value: None } } pub fn acquire(&mut self) -> *int { if self.value.is_none() { self.value = Some(box 1) } &**self.value.get_ref() as *int } } fn main() { let arc_res = Arc::new(RWLock::new(Resource::new())); for _ in range(0,5) { let child_res = arc_res.clone(); spawn(proc() { let ptr = child_res.write().acquire(); println!("resource: {}", ptr) }) } }
Arc
( Atomically Reference Counted - )RWLock
( ). :
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
resource: 0x7ff4b0010378
, ++ . . Rust , . , , . , ( ).
Rust ,unsafe{}
. , " ! , . ". , "" ( , ) . , ( ) . , ,Cell
Mutex
. , ( TDD !).
Guaranteeing Memory Safety in Rust (by Niko Matsakis)
Rust: Safe Systems Programming with the Fun of FP (by 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