• Can take a reference to an owned thing

  let y = 5;
let ry = &y;

• Now you have an obligation: ry must not outlive y

• C/C++ will happily let you write things like

int y = 5; int *ry = &y; return ry;

even though the returned pointer is now pointing into whereever on the stack the now-lost y was

• Rust compiler tracks this for you, so that e.g.

  let y = 5;
let ry = &y;
return ry;


will give a compile-time error

## Mutable Refs

• Refs come in two varieties: "mutable" and "immutable" (really "exclusive" and "shared")

• Can only take mutable ref to mutable thing

  let mut y = 5;
let ry = &mut y;

• Once you take a mutable ref, you've essentially "borrowed" the value referred to

• Must not go out of scope
• Cannot take any more references while it is live
• Owner can't do anything with the value while it is live (read it, change it, move it, drop it)

## Immutable Refs

• An immutable ref is essentially "shared". You can take lots of them if you want

  let y = 5;
let ry1 = &y;
let ry2 = &y;

• You are still restricted for safety

• Owner cannot drop or move value (nor mutate, duh) while refs are live

• A lot of automatic derefing happens

• With the "." structure / enum operator
• With comparison operators
• etc

let y = 10; let ry = &y; let rry = &ry; assert!(9 < rry);

• There's no such thing as a "null reference" (in safe code): no way to produce one, no need to guard against them

• If you need a "nullable" value, use the Option type

let y = 10; let ory = Some(&y);

• This is true for refs or anything else

• You can get a reference to an anonymous variable implicitly defined by an expression

  let ry = &10;


• The machinery that the compiler uses to check lifetimes is by default "under the hood": does the checking for you without intervention

• Sometimes, though, you need (or want) to get explicit access to that machinery to allow a program to compile that is safe but won't by default

• "Named lifetimes" start with a tick, e.g. 'a ("tick-a")

• In many contexts, explicit lifetime names can be declared

  fn f<'a, 'b>(x: &u64, y: &u64) -> &u64

• These names can then be used to describe lifetime constraints for referenced data

  fn f<'a, 'b>(x: &'a u64, y: &'b u64) -> &'a u64


In this example, the lifetime of the returned data must the same as the lifetime of x's data

  fn f<'a, 'b: 'a>(x: &'a u64, y: &'b u64) -> &'a u64


We can also require that result's data live at least as long as y's

  fn f<'a, 'b: 'a>(x: &'a u64, y: &'b u64) -> &'b u64


https://play.rust-lang.org/?gist=59636f6153699652df21d05ea61f3428&version=stable

## Rust Parametric Types

• Actually "monomorphic" or "template" types, but…

• Just like we can provide lifetime variables, can provide type variables to get "generic" thingies

  fn id<T>(x: T) -> T {
x
}


Can now call with whatever type as long as they match

  assert_eq!(id(5u32), 5u32);
assert_eq!(id("hello"), "hello");