Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Closed
arielb1 opened this issue Jan 25, 2017 · 10 comments · Fixed by #42396
Closed

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

arielb1 opened this issue Jan 25, 2017 · 10 comments · Fixed by #42396
Labels
C-cleanup Category: PRs that clean code up or issues documenting cleanup. E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@arielb1
Copy link
Contributor

arielb1 commented Jan 25, 2017

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);
}
bors added a commit that referenced this issue Jan 26, 2017
End temporary lifetimes being extended by `let X: &_` hints

cc #39283

r? @nikomatsakis
@nikomatsakis
Copy link
Contributor

Given that this behavior has been changed, and is unlikely to be changed back, I am going to close this issue -- there is (at this moment) no further work to be done here. However, if you encounter this error and have questions or concerns, please feel free to comment. If we find there is further work to be done, we will re-open the issue. Thanks!

@nikomatsakis
Copy link
Contributor

Actually, I take that back. The further work to be done is probably removing the error message that sends users to this issue after a suitable period of time. In particular, I think it would be a good thing to remove after the current nightly reaches beta.

@nikomatsakis nikomatsakis reopened this Jan 27, 2017
@Mark-Simulacrum
Copy link
Member

I think that it's perhaps time to consider removing this message. cc @rust-lang/compiler (and nominating).

@Mark-Simulacrum Mark-Simulacrum added I-nominated T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels May 20, 2017
@nikomatsakis
Copy link
Contributor

I agree. Thank you @Mark-Simulacrum for bringing it up, I've been meaning to do the same. The main thing that's been holding me from making an "rfcbot" motion is that the typical procedure is to do a crater run to estimate the impact and I've not gotten around to it yet.

@Mark-Simulacrum
Copy link
Member

@nikomatsakis That looks like a potential easy or at least mentorable issue to make this a hard error so we can do the crater run; does that sound correct? Could you write up some quick steps?

@nikomatsakis
Copy link
Contributor

I was wrong, we don't need a crater run. We already made it a hard error. We just have to kill code related to this. I'll provide a few pointers, this is indeed a good mentoring issue.

@nikomatsakis
Copy link
Contributor

Tracking this change introduced a small amount of cruft in the compiler. In particular, some data structures track the 'temporary region', and since that changed, those structures are updated to have both the old and new values. In particular, the Categorization<'tcx> structure contains a variant with an extra field:

#[derive(Clone, PartialEq)]
pub enum Categorization<'tcx> {
    // temporary val, argument is its scope
    Rvalue(ty::Region<'tcx>, ty::Region<'tcx>),
    //     ^^^^^^^^^^^^^^^^ this data is the new temporary lifetime, after the change
    //                       ^^^^^^^^^^^^^^^^ this data is the *old* lifetime, before the change
    ...
}

If you ripgrep around, you will see that this field is mostly unused, except in borrowck where it is used to report this warning.

If we remove that variant, you'll be able to follow a trail of breadcrumbs of code that can be removed. For example, MemCategorizationCx::cat_rvalue no longer needs this argument. Eventually, following this trail should let us delete cruft like temporary_scope2() in region.rs.

@nikomatsakis nikomatsakis added E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. C-cleanup Category: PRs that clean code up or issues documenting cleanup. and removed I-nominated labels May 26, 2017
@venkatagiri
Copy link
Contributor

@nikomatsakis I would like to work on this.
From going over the code and removing the extra field in Categorization structure, feels like all the changes done by #39066 needs to be removed.
Everything from shrunk_rvalue_scopes to temp_lifetime_was_shrunk.
I wasn't able to figure out where exactly the lifetime was shrunk that needs to be retained so that they continue to show errors.
Am I in the right direction?

@nikomatsakis
Copy link
Contributor

@venkatagiri

From going over the code and removing the extra field in Categorization structure, feels like all the changes done by #39066 needs to be removed.

Yes, that is basically correct. This is the PR that introduced this infrastructure, because we were changing some values from one thing to another and we wanted to give warnings to the affected code.

But, that said, we don't want to revert that PR. In other words, we want to keep the new values that the PR introduced, we just want to stop tracking the old values that got replaced (and stop warning about it).

I wasn't able to figure out where exactly the lifetime was shrunk that needs to be retained so that they continue to show errors.

I'm not sure I understand your question here.

Am I in the right direction?

Sounds like it!

@nikomatsakis
Copy link
Contributor

@venkatagiri (ps, feel free to ping me on IRC or gitter sometime -- gitter is maybe better if you don't have a persistent IRC connection)

bors added a commit that referenced this issue Jun 3, 2017
rustc: remove temporary lifetime extension by borrow hint

closes #39283.

Thanks to @nikomatsakis for mentoring on this one.

r? @arielb1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-cleanup Category: PRs that clean code up or issues documenting cleanup. E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants