Theory and Design of PL (CS 538)
March 30, 2020
This assignment is big, with lots of compiler errors.
&mut self is ref. to Option<T>None to selftake:
Some(...)Some(...), someone else owns None.std::mem::replace, std::mem::swaplet my_str = String::from("Hello world!");
let maybe_str = Some(my_str);
match maybe_str {
None => println!("Nothing!"),
Some(s) => println!("Something!"), // String *moved* into s
// s dropped here
}
println!("Still there? {}", maybe_str.is_none()); // Not OK!maybe_str is dropped: inner s is gone!take the maybe_str instead?let mut maybe_str = Some(String::from("Hello world!"));
let mut_str_ref = &mut maybe_str; // type: &mut Option<String>
let took_str = mut_str_ref.take(); // type: Option<String>
// maybe_str is now None
match took_str {
None => println!("Nothing here!"),
Some(s) => ... s owns String ...,
}
println!("Still there? {}", maybe_str.is_none()); // Now OK[a], Maybe a, …Option<T>, …foo<T>(t: T) to foo_i32(t: i32)One or the other: not both!
fn compute(input: &u32, output: &mut u32) {
if *input > 10 { *output = 1; } // lookup input
if *input > 5 { *output *= 2; } // lookup again
}
fn compute_opt(input: &u32, output: &mut u32) {
let cached_input = *input; // cache *input
if cached_input > 10 {
*output = 2;
} else if cached_input > 5 {
*output *= 2;
}
}High-level: how Rust analyzes aliasing
'static is global scope (biggest)'a refer to some scope
'static'b:'a for 'b contains 'a
'b lives longer than 'a'static:'a, global scope is longest{ // < 'a1
let foo = 1; // |
{ // < 'a2 |
let bar = 2; // | |
{ // < 'a3 | |
let baz = 3; // | | |
} // < | |
} // < |
} // <'a1:'a2 and 'a2:'a3static NAME: &'static str = "Steve";
// Omitting lifetimes
fn foo (arg: &String) -> &String { NAME }
// Annotating lifetimes
fn annot_foo<'a> (arg: &'a String) -> &'static String { NAME }
// Return ref doesn't depend on input, lives forever'a
// Omitting lifetimes
fn plus_foo (arg: &mut String) -> &mut String {
arg.push_str(" and foo");
arg
}
// Annotating lifetimes
fn annot_plus_foo<'a> (arg: &'a mut String) -> &'a mut String {
arg.push_str(" and foo");
arg
}argfn bad_foo () -> &String {
let too_short = String::from("too short");
&too_short
} // too_short goes out of scope, is dropped heretoo_short is dropped
fn bad_foo<'a> () -> &'a String {
let too_short = String::from("too short");
&too_short
} // too_short goes out of scope, is dropped here'a for all possible lifetimes 'a
'static lifetimefn longest<'a> (x: &'a String, y: &'a String) -> &'a String {
if x.len() > y.len() {
x
} else {
y
}
}x and y live at least as long as 'a, then returned string also lives at least as long as 'aSelf (in caps) is the type with this trait+/-/*): Add/Sub/Mult// Sized trait: T has size known at compile time
// negative annotation `?Sized`: T *doesn't* need to be Sized
fn foo<T: ?Sized>(t: &T) { ... }