Last active
January 6, 2019 20:16
-
-
Save jiahaog/b30d40f9558112878ba526cbaa6b27fc to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#![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