diff --git a/src/main.rs b/src/main.rs index 18a4de1..da20e99 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,83 @@ mod fmt_debug; +// when a String is passed to this function a move occurs: +// BUT only the stack allocation (ptr, len, cap) is copied over +// AND the underlying heap is preserved, without copy +// +// Why do we call it a "move"? +// A move indicates ownership transfer, not data transfer +fn takes_string(_s: String) { + +} + +fn takes_string_ref(_s: &String) { + +} + +// Compilation error and warning: +// rustc: the size for values of type `str` cannot be known at compilation time +// the trait `Sized` is not implemented for `str` [E0277] +// rustc: function arguments must have a statically known size, +// borrowed types always have a known size: `&` [E0277] +// +// Ok, so rust is an unsized type, +// and compiler requires sized types for function params at compile time +// +// Why is this a problem? +// rust doesn't know how much space to allocate for the variable +// +// str inactuality is the raw (UTF-8) bytes, not a container +// fn takes_str(s: str) { } + +// this is fine because now the variable is a fat pointer: pointer + length +// it's the length aspect that makes us abot to work on the str +fn takes_str_ref(_s: &str) { + +} + +// yeah, we can do this +fn _get_static_str() -> &'static str { + "hello" +} + fn main() { fmt_debug::test_report(); + + let s = String::new(); // no heap allocation until we add characters (capacity > 0) + + // let s_r: str; // ERROR: size not known at compile time + let _s_rr: &str; // allowed + let _s_rrr: &String; // allowed + + takes_string_ref(&s); + takes_string_ref(&s); // works because the string was not moved in first call + + let ss = String::from("1"); // one heap allocation! + takes_string(ss); // move occurs here + // takes_string(ss); // ERROR: use of moved value here + // takes_string_ref(&ss); // ERROR: borrow of moved value here + + let sss = String::new(); + // deref coersion: + // because String implements the trait Deref + takes_str_ref(&sss); + // *sss dereferences the String into its underlying str + takes_str_ref(&*sss); // same as this! + takes_str_ref(sss.as_ref()); // and this! + + let s4 = String::from("string4"); + //let s4_slice = s4[0..]; // again we hit no size problem at compile time + let _s4_slice = &s4[0..]; // but this works, because the &str has the length! + + // literals + // &'static str is held onto by &str: + // that's the programs read-only binary + let s_lit = "easy as pie, right?"; + let _s_lit2 : &str = "easy as pie, right?"; // same, data not copied, we just point to it + let _s5 = String::from("literal is copied to heap"); // data copied to heap + let _s6 = String::from(s_lit); //underlying data copied to heap + + // todo: Cow + + println!("Hello, world!"); }