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

regression 1.50: Borrow checker reports function param as not living long enough #80949

Closed
rylev opened this issue Jan 12, 2021 · 17 comments
Closed
Assignees
Labels
A-borrow-checker Area: The borrow checker P-high High priority regression-from-stable-to-beta Performance or correctness regression from stable to beta. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Milestone

Comments

@rylev
Copy link
Member

rylev commented Jan 12, 2021

This might not actually be a regression an instead the code may have previously erroneously compiled. I cannot find an an open issue obviously related to this though.

As you can see here this code does not compile with a "borrowed value does not live long enough" where it did previously. This comes from a call to diff::diff which has this signature.

The error message states that n may be dropped while the borrow in the next param state is still active. This fails to compile on both 1.50 and 1.49 if the param state is move to a local variable.

@rustbot modify labels: +regression-from-stable-to-beta

@rustbot rustbot added regression-from-stable-to-beta Performance or correctness regression from stable to beta. I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Jan 12, 2021
@jyn514 jyn514 added A-borrow-checker Area: The borrow checker T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jan 12, 2021
@apiraino
Copy link
Contributor

Let's try to reduce it @rustbot ping cleanup

@rustbot rustbot added the ICEBreaker-Cleanup-Crew Helping to "clean up" bugs with minimal examples and bisections label Jan 13, 2021
@rustbot
Copy link
Collaborator

rustbot commented Jan 13, 2021

Hey Cleanup Crew ICE-breakers! This bug has been identified as a good
"Cleanup ICE-breaking candidate". In case it's useful, here are some
instructions for tackling these sorts of bugs. Maybe take a look?
Thanks! <3

cc @AminArria @camelid @chrissimpkins @contrun @DutchGhost @elshize @ethanboxx @h-michael @HallerPatrick @hdhoang @hellow554 @imtsuki @JamesPatrickGill @kanru @KarlK90 @LeSeulArtichaut @MAdrianMattocks @matheus-consoli @mental32 @nmccarty @Noah-Kennedy @pard68 @PeytonT @pierreN @Redblueflame @RobbieClarken @RobertoSnap @robjtede @SarthakSingh31 @shekohex @sinato @smmalis37 @steffahn @Stupremee @tamuhey @turboladen @woshilapin @yerke

@hellow554
Copy link
Contributor

Still with dependency, but simplified code

use euca::diff;
use euca::dom::Dom;
use euca::vdom::DomIter;

#[test]
fn from_empty() {
    let new: Dom<(), (), &()> = Dom::elem("div");

    let n = new.dom_iter();
    let mut storage = vec![];
    let patch_set = diff::diff(std::iter::empty(), n, &mut storage);
}

let's see what I can get from there

@hellow554
Copy link
Contributor

hellow554 commented Jan 13, 2021

searched nightlies: from nightly-2020-12-01 to nightly-2021-01-06
regressed nightly: nightly-2020-12-06
searched commits: from 3ff10e7 to e792288
regressed commit: 9122b76

bisected with cargo-bisect-rustc v0.6.0

Host triple: x86_64-unknown-linux-gnu
Reproduce with:

cargo bisect-rustc 2021-01-06 --without-cargo --access github --regress error

The code I tested:

struct Dom;
impl Dom {
    fn dom_iter(&self) -> Box<dyn Iterator<Item = &()>> {
        todo!()
    }
}

fn diff<'a, M, O, N, S>(_: O, _: N, _: S)
where
    M: 'a,
    O: IntoIterator<Item = M>,
    N: IntoIterator<Item = &'a M>,
    S: IntoIterator<Item = &'a M>,
{
    todo!()
}

fn main() {
    let n = Dom.dom_iter();
    let storage = vec![];

    diff(std::iter::empty(), n, &storage);
}

cc #78373 @matthewjasper

@rustbot
Copy link
Collaborator

rustbot commented Jan 13, 2021

Error: Label ICEBreaker-Cleanup-Crew can only be set by Rust team members

Please let @rust-lang/release know if you're having trouble with this bot.

@jonas-schievink jonas-schievink removed the ICEBreaker-Cleanup-Crew Helping to "clean up" bugs with minimal examples and bisections label Jan 13, 2021
@matthewjasper
Copy link
Contributor

So #78373 resulted in MIR having one fewer block, which is making borrowck be less precise with how long the borrow lasts. There are a few possible fixes here for me to look at.

@apiraino apiraino added P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Jan 14, 2021
@apiraino
Copy link
Contributor

Assigning P-high as discussed as part of the Prioritization Working Group procedure and removing I-prioritize.

@Mark-Simulacrum
Copy link
Member

@rylev how common was this bug in the crater report? just the one crate?

@rylev
Copy link
Member Author

rylev commented Jan 14, 2021

Yes the linked crate was the only crate to show signs of this issue in the crater run.

@Mark-Simulacrum Mark-Simulacrum added this to the 1.50.0 milestone Jan 14, 2021
@matthewjasper
Copy link
Contributor

@nikomatsakis @pnkfelix @nagisa wanted a longer explanation of what's going on here.

When we type check the MIR we find that:

  • The lifetime of the borrow at bb3[3] must outlive the lifetime in the type of _8
  • the lifetimes in the types of _8 and _7 are the same because of the signature of diff
  • The lifetime in the type of _7 is the same as the lifetime in the type of _1 (from the assignment at bb3[1])

So the lifetime of the borrow contains all points where _8, _7 and _1 are live and initialized, which I have marked in green. The borrow therefore lasts only for bb3[3] and bb3[4] (borrows only start at the statement with the borrow rvalue).

old-mir

In the new MIR the drop of _7 is gone, so there's no longer a gap in the lifetime between bb3 and the drop of _4. This results in the borrow of _4 including bb7 and bb8, which conflicts with the drop of _4 in bb7.

new-mir

@pnkfelix pnkfelix self-assigned this Jan 21, 2021
@pnkfelix
Copy link
Member

discussed at T-compiler meeting. We want to resolve this issue, and plan to revert PR #78373 as a short-term resolution. Longer term will be to re-land PR #78373 with hopefully some further modifications so that we don't cause regressions like this in the process.

@pnkfelix
Copy link
Member

While setting up my system for the revert, I narrowed the MCVE down a bit further. I don't think I illuminated much more in the process, though I do find it curious that I wasn't able to easily find a way to take the Box<dyn Trait> out of the equation for reproducing the bug:

playground

trait Trait { type Item; }

impl<'a, X> Trait for &'a Vec<X> {
    type Item = &'a X;
}

impl<X> Trait for Box<dyn Trait<Item = X>> {
    type Item = X;
}

fn make_dyn_trait(_: &()) -> Box<dyn Trait<Item = &()>> {
    todo!()
}

fn diff<'a, M, N, S>(_: N, _: S)
where
    M: 'a,
    N: Trait<Item = &'a M>,
    S: Trait<Item = &'a M>,
{
    todo!()
}

fn may_panic<X>(_: X) { }

fn main() {
    let dyn_trait = make_dyn_trait(&());
    let storage = vec![()];
    let _x = may_panic(());
    let storage_ref = &storage;
    diff(dyn_trait, storage_ref);
}

@pnkfelix
Copy link
Member

(landing PR #81257 and backporting it to the beta channel would resolve this.)

@mzabaluev
Copy link
Contributor

Here is a minified example of a regression I have run into, not sure if it's the same issue:

use std::error::Error;
use std::iter;

fn walk_source_chain(error: &impl Error) {
    for e in iter::successors(error.source(), |e| e.source()) {
        println!("{}", e);
    }
}

Changing the closure parameter pattern to match &e fixes the borrow checker error in nightly.

@camelid
Copy link
Member

camelid commented Jan 28, 2021

Hmm, that example compiles on beta though.

@camelid
Copy link
Member

camelid commented Jan 28, 2021

I believe that's an unrelated issue. Opened #81460 to track it. Thanks for reporting it!

bors added a commit to rust-lang-ci/rust that referenced this issue Feb 5, 2021
…ution-via-revert-of-pr-78373, r=matthewjasper

Revert 78373 ("dont leak return value after panic in drop")

Short term resolution for issue rust-lang#80949.

Reopen rust-lang#47949 after this lands.

(We plan to fine-tune PR rust-lang#78373 to not run into this problem.)
ehuss pushed a commit to ehuss/rust that referenced this issue Feb 5, 2021
…ution-via-revert-of-pr-78373, r=matthewjasper

Revert 78373 ("dont leak return value after panic in drop")

Short term resolution for issue rust-lang#80949.

Reopen rust-lang#47949 after this lands.

(We plan to fine-tune PR rust-lang#78373 to not run into this problem.)
@pietroalbini
Copy link
Member

Fix backported to 1.50 and landed in 1.51, closing this.

zeegomo added a commit to zeegomo/rust that referenced this issue Feb 23, 2023
Only remove unreachable blocks after drop elaboration but
avoid merging blocks, as that sometimes confuses borrowck
precomputation of borrows_out_of_scope.
See issue rust-lang#80949 for more details.
bors added a commit to rust-lang-ci/rust that referenced this issue Jun 4, 2024
Fix leaks from panics in destructors

Resurrects rust-lang#78373.

This avoids the problem with rust-lang#80949 by not unscheduling drops of function arguments until after the call (so they still get a drop terminator on the function unwind path).

Closes rust-lang#47949

r? `@lcnr`
bors added a commit to rust-lang-ci/rust that referenced this issue Jun 14, 2024
Fix leaks from panics in destructors

Resurrects rust-lang#78373.

This avoids the problem with rust-lang#80949 by not unscheduling drops of function arguments until after the call (so they still get a drop terminator on the function unwind path).

Closes rust-lang#47949

r? `@lcnr`
bors added a commit to rust-lang-ci/rust that referenced this issue Jun 20, 2024
Fix leaks from panics in destructors

Resurrects rust-lang#78373.

This avoids the problem with rust-lang#80949 by not unscheduling drops of function arguments until after the call (so they still get a drop terminator on the function unwind path).

Closes rust-lang#47949

r? `@lcnr`
bors added a commit to rust-lang-ci/rust that referenced this issue Jun 26, 2024
Fix leaks from panics in destructors

Resurrects rust-lang#78373.

This avoids the problem with rust-lang#80949 by not unscheduling drops of function arguments until after the call (so they still get a drop terminator on the function unwind path).

Closes rust-lang#47949

r? `@lcnr`
bors added a commit to rust-lang-ci/rust that referenced this issue Jul 15, 2024
Fix leaks from panics in destructors

Resurrects rust-lang#78373.

This avoids the problem with rust-lang#80949 by not unscheduling drops of function arguments until after the call (so they still get a drop terminator on the function unwind path).

Closes rust-lang#47949

r? `@lcnr`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-borrow-checker Area: The borrow checker P-high High priority regression-from-stable-to-beta Performance or correctness regression from stable to beta. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests