Description
UPDATE: Mentoring instructions for removing the various bits of dead code found below.
This is the summary issue for the removal of temporary lifetime extension by borrow hint.
What is this issue about
One issue that languages with deterministic destruction have to face is the lifetime of expression temporaries. To avoid confusion, temporaries have to be destroyed in some definite time, and temporaries living for too short or too long a time can cause subtle errors. The Rust rules for that - nikomatsakis/rust-memory-model#17 - are somewhat complicated.
The implementation used to follow the rules, but it also contained a leftover from the old days of Rust - issue #36082:
Normally, temporaries in Rust live until the containing arena, which in simple cases is the containing statement. For example, in this code the RefCell
borrows only live to the end of their containing statements, so this code does not panic:
use std::cell::RefCell;
fn main() {
let r = 0;
let s = 0;
let x = RefCell::new((&r,s));
let val = x.borrow().0;
println!("{}", val);
x.borrow_mut().1 += 1;
}
However, due to said leftover, adding an &_
or &mut _
type hint would make the borrow live until the end of the containing block, which means this code would keep a long borrow and panic due to a double borrow:
use std::cell::RefCell;
fn main() {
let r = 0;
let s = 0;
let x = RefCell::new((&r,s));
let val: &_ = x.borrow().0; //~ WARN this temporary used to live longer
println!("{}", val);
x.borrow_mut().1 += 1;
}
This "feature" is an oversight from the old days of Rust, and therefore it is removed starting from Rust 1.16.
However, some code might be relying on the changed temporary lifetimes, and in some cases might not even compile without it:
use std::cell::RefCell;
fn main() {
let mut r = 0;
let s = 0;
let x = RefCell::new((&mut r,s)); //~ WARN this temporary used to live longer
let val: &_ = x.borrow().0;
println!("{}", val);
}
How to fix this warning/error
Use an explicit variable with an explicit lifetime instead of the temporary:
use std::cell::RefCell;
fn main() {
let r = 0;
let s = 0;
let x = RefCell::new((&r,s));
{
let b = x.borrow();
let val: &_ = b.0;
println!("{}", val);
}
x.borrow_mut().1 += 1;
}
and
use std::cell::RefCell;
fn main() {
let mut r = 0;
let s = 0;
let x = RefCell::new((&mut r,s));
let b = x.borrow();
let val: &_ = b.0;
println!("{}", val);
}