Skip to content

Instantly share code, notes, and snippets.

@jiahaog
Last active January 6, 2019 20:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jiahaog/b30d40f9558112878ba526cbaa6b27fc to your computer and use it in GitHub Desktop.
Save jiahaog/b30d40f9558112878ba526cbaa6b27fc to your computer and use it in GitHub Desktop.
#![allow(dead_code)]
// Using Rust without NLL (2015 edition)
// Playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2015&gist=b30d40f9558112878ba526cbaa6b27fc
fn consume<T>(_: T) {}
struct SimpleStruct {}
fn borrow_simple(_: &SimpleStruct) -> SimpleStruct {
unimplemented!()
}
fn example_simple(input_struct: SimpleStruct) {
let struct_from_borrow = borrow_simple(&input_struct);
// In the simplest case, borrowing the lifetime of input_struct and
// struct_from_borrow are not linked
consume(input_struct);
consume(struct_from_borrow);
}
struct ComplexStruct<'a> {
name: &'a str,
}
// In this function, we have declared the lifetimes of the input and output to be unlinked
fn borrow_complex_struct<'a, 'b>(_: &'a ComplexStruct<'a>) -> ComplexStruct<'b> {
unimplemented!()
}
fn example_complex(input_struct: ComplexStruct) {
let struct_from_borrow = borrow_complex_struct(&input_struct);
// borrow &input_struct is released
consume(input_struct);
consume(struct_from_borrow);
}
// DOES NOT COMPILE
// What happens if we want to put a reference to the input in the output?
// Conflicting lifetimes, because 'a cannot be more than 'b, but they are unrelated
// fn borrow_complex_struct<'a, 'b>(input: &'a ComplexStruct<'a>) -> ComplexStruct<'b> {
// ComplexStruct { name: input.name }
// }
// Hence, we need to use lifetime subtyping https://doc.rust-lang.org/book/ch19-02-advanced-lifetimes.html#ensuring-one-lifetime-outlives-another-with-lifetime-subtyping
fn borrow_complex_struct_with_ref<'a, 'b>(input: &'a ComplexStruct<'a>) -> ComplexStruct<'b>
where
'a: 'b,
{
ComplexStruct { name: input.name }
}
// DOES NOT COMPILE
// However, with the lifetime subtyping, we are unable to consume the input_struct
// fn example_complex_with_ref(input_struct: ComplexStruct) {
// let struct_from_borrow = borrow_complex_struct_with_ref(&input_struct); // 'borrow
// consume(input_struct); // |
// consume(struct_from_borrow); // v
// }
// DOES NOT COMPILE WITHOUT NLL
// struct_from_borrow has to live for as long as the function closure, and hence
// &input_struct has to be borrowed for the at least as long as that, because of lifetime
// subtyping 'a: 'b.
// As a result, we are unable to consume input_struct while it is still borrowed
// However, if we choose to consume(struct_from_borrow) before consuming input_struct, the
// following code compiles only in the 2018 edition of Rust, with NLL, but not on the 2015
// edition.
// fn example_complex_with_ref_different_order(input_struct: ComplexStruct) {
// let struct_from_borrow = borrow_complex_struct_with_ref(&input_struct);
// consume(struct_from_borrow);
// consume(input_struct);
// }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment