Skip to content

Tracking issue for removing temporary lifetime extension by borrow hint #39283

Closed
@arielb1

Description

@arielb1

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);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    C-cleanupCategory: PRs that clean code up or issues documenting cleanup.E-easyCall for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue.E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions