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

Source of lifetime coercion is not reported starting in 1.63 #99256

Open
mqudsi opened this issue Jul 14, 2022 · 7 comments
Open

Source of lifetime coercion is not reported starting in 1.63 #99256

mqudsi opened this issue Jul 14, 2022 · 7 comments
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: Lifetimes / regions C-bug Category: This is a bug. P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics
Milestone

Comments

@mqudsi
Copy link
Contributor

mqudsi commented Jul 14, 2022

When the lifetime of a value is coerced to a longer one due to the use of an associated function or trait member and the previous lifetime used by other call sites is no longer sufficient, rustc no longer includes any mention of the coercion site (and includes a red herring that forces one to go chasing after the wrong goose). This makes it much, much harder to figure out why code is not working as all the locations rustc mentions are perfectly fine and have nothing to do with the actual cause of the error.

Code

use std::path::{Path, PathBuf};

enum PolyStr<'a> {
    Str(&'a str),
}

impl<'a> From<&'static str> for PolyStr<'static> {
    fn from(s: &'static str) -> Self {
        PolyStr::Str(s)
    }
}

#[derive(Default)]
struct Ffcommand<'a> {
    inputs: Vec<&'a Path>,
    output: Option<PolyStr<'a>>,
}

impl<'a> Ffcommand<'a> {
    pub fn run(&self) -> bool {
        true
    }

    pub fn input(mut self, p: &'a Path) -> Self {
        self.inputs.push(p);
        self
    }

    pub fn output<P>(mut self, p: P) -> Self
    where
        P: Into<PolyStr<'a>> + 'a
    {
        self.output = Some(p.into());
        self
    }
}

#[derive(Default)]
struct Ffinfo<'a> {
    cmd: Ffcommand<'a>,
    path: PathBuf,
}

impl Ffinfo<'_> {
    fn foo(&self) -> bool {
        let cmd = Ffcommand::default()
            .input(&self.path)
            // uncomment the next line to see the error
            // .output("pipe:1")
            ;
            
        cmd.run()
    }
}

fn main() {
    let mut info = Ffinfo::default();
    info.path = PathBuf::from("./hello.world");
    info.foo();
}

When the commented-out line is added back in, rustc will emit the following error:

error[[E0521]](https://doc.rust-lang.org/beta/error-index.html#E0521): borrowed data escapes outside of associated function
  --> src/main.rs:46:19
   |
45 |       fn foo(&self) -> bool {
   |              -----
   |              |
   |              `self` is a reference that is only valid in the associated function body
   |              let's call the lifetime of this reference `'1`
46 |           let cmd = Ffcommand::default()
   |  ___________________^
47 | |             .input(&self.path)
   | |                              ^
   | |                              |
   | |______________________________`self` escapes the associated function body here
   |                                argument requires that `'1` must outlive `'static`

For more information about this error, try `rustc --explain E0521`.
error: could not compile `playground` due to previous error

Try on playground.

The error message points to self and .input() as the locations pertaining to this error, when in fact the error stems entirely from the usage of .output(), which coerces the lifetime to 'static due to the trait impl, at the same time as .input(), which doesn't last as long.

rustc stable (1.62) emits the following error message instead, which is infinitely more helpful:

error[[E0759]](https://doc.rust-lang.org/stable/error-index.html#E0759): `self` has an anonymous lifetime `'_` but it needs to satisfy a `'static` lifetime requirement
  --> src/main.rs:47:20
   |
45 |     fn foo(&self) -> bool {
   |            ----- this data with an anonymous lifetime `'_`...
46 |         let cmd = Ffcommand::default()
47 |             .input(&self.path)
   |                    ^^^^^^^^^^ ...is used here...
48 |             .output("pipe:1")
   |              ------ ...and is required to live as long as `'static` here

For more information about this error, try `rustc --explain E0759`.
error: could not compile `playground` due to previous error

Notice that here the correct call sites (.input() and .output()) are mentioned. In particular, the fact that .output() is where 'static is required is clearly mentioned, making it easy to figure out what is going on.

Needless to say, this is a highly stripped-down example for illustration purposes. It took me perhaps half-an-hour to chase down the actual issue in a real codebase; IIRC the .output() equivalent was part of the original code and .input() was added some months later, and there were a lot of false trails to chase down before finding the .output() lifetime coercion.

Version it worked on

It most recently worked on: 1.62.0

Version with regression

rustc --version --verbose:

1.63.0-beta.5 2022-07-10 93ef0cd7fd86d3d05cee
@mqudsi mqudsi added C-bug Category: This is a bug. regression-untriaged Untriaged performance or correctness regression. labels Jul 14, 2022
@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. and removed regression-untriaged Untriaged performance or correctness regression. labels Jul 14, 2022
@apiraino apiraino added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Jul 21, 2022
@apiraino
Copy link
Contributor

bisection seems to lead to commit bb55bd4 #95565 cc @jackh726

searched nightlies: from nightly-2022-05-01 to nightly-2022-07-27
regressed nightly: nightly-2022-06-08
searched commit range: 50b0025...5435ed6
regressed commit: bb55bd4

bisected with cargo-bisect-rustc v0.6.3

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

cargo bisect-rustc --start=2022-05-01 --script=./script.sh 

@apiraino
Copy link
Contributor

WG-prioritization assigning priority (Zulip discussion).

@rustbot label -I-prioritize +P-high +A-diagnostics

@rustbot rustbot added A-diagnostics Area: Messages for errors, warnings, and lints P-high High priority and removed I-prioritize Issue: Indicates that prioritization has been requested for this issue. labels Jul 27, 2022
@mqudsi
Copy link
Contributor Author

mqudsi commented Jul 27, 2022

@apiraino thanks for teaching me about cargo-bisect-rustc 👍

@estebank estebank added the A-lifetimes Area: Lifetimes / regions label Aug 4, 2022
@estebank
Copy link
Contributor

estebank commented Aug 4, 2022

This is of course fallout from removing the migrate borrowck.

CC @rust-lang/wg-diagnostics, I believe this should be high priority, but having looked at it in the past it will be non-trivial to get back to the same quality we had before :-/

@estebank estebank added the WG-diagnostics Working group: Diagnostics label Aug 4, 2022
@Mark-Simulacrum Mark-Simulacrum added this to the 1.63.0 milestone Aug 9, 2022
@pnkfelix
Copy link
Member

@rustbot label: -regression-from-stable-to-beta +regression-from-stable-to-stable

@rustbot rustbot added regression-from-stable-to-stable Performance or correctness regression from one stable version to another. and removed regression-from-stable-to-beta Performance or correctness regression from stable to beta. labels Aug 11, 2022
@pnkfelix
Copy link
Member

pnkfelix commented Dec 16, 2022

Visiting for P-high review

@estebank do you have any ideas on what wg-diagnostics might attempt to do to try to recover the quality here?

@estebank
Copy link
Contributor

estebank commented Jan 4, 2023

We need to investigate what E0521 is doing that diverges significantly from E0759. I suspect this won't be trivial to fix :-/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-diagnostics Area: Messages for errors, warnings, and lints A-lifetimes Area: Lifetimes / regions C-bug Category: This is a bug. P-high High priority regression-from-stable-to-stable Performance or correctness regression from one stable version to another. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. WG-diagnostics Working group: Diagnostics
Projects
None yet
Development

No branches or pull requests

6 participants