Skip to content

Confusing error messages when invariant type is involved #26804

@jonas-schievink

Description

@jonas-schievink

Reproducer

use std::{cell::RefCell, fmt::Debug};

#[derive(Default)]
struct S<'a> {
    c: RefCell<Option<Box<dyn Debug + 'a>>>,
}

impl<'a> S<'a> {
    fn r(&'a self) -> &'a () {
        panic!()
    }
}

fn main() {
    let s = S::default();
    let _ = s.r();
}
Original now malfunctioning reproducer from 2015

Playpen: http://is.gd/f1SPdn

#[derive(Default)]
struct S<'a> {
    c: RefCell<Option<Box<Sized + 'a>>>,    // Doesn't work
    //c: RefCell<Option<Box<&'a Sized>>>,   // Works
    //c: Option<Box<Sized + 'a>>,           // Also works
}

impl <'a> S<'a> {
    fn r(&'a self) -> &'a () {
        panic!();
    }
}

fn main() {
    let s = S::default();
    let r = s.r(); //~ ERROR `s` does not live long enough [E0597]
}

Compiler Output

error[E0597]: `s` does not live long enough
  --> src/main.rs:16:13
   |
15 |     let s = S::default();
   |         - binding `s` declared here
16 |     let _ = s.r();
   |             ^ borrowed value does not live long enough
17 | }
   | -
   | |
   | `s` dropped here while still borrowed
   | borrow might be used here, when `s` is dropped and runs the destructor for type `S<'_>`
Original compiler output from 2015
<anon>:19:13: 19:14 error: `s` does not live long enough
<anon>:19     let r = s.r();
                      ^
<anon>:17:11: 20:2 note: reference must be valid for the block at 17:10...
<anon>:17 fn main() {
<anon>:18     let s = S::default();
<anon>:19     let r = s.r();
<anon>:20 }
<anon>:18:26: 20:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 18:25
<anon>:18     let s = S::default();
<anon>:19     let r = s.r();
<anon>:20 }

This is confusing, since the compiler seems to demand that s is valid in the line before it is declared (the only difference between the regions is that the first one includes the fn main() {). It is never mentioned that this is caused by S being invariant on 'a, which disallows rustc to enlarge the lifetime to include the whole block.

I think rustc should give a better error is this case (maybe something like note: cannot extend lifetime of `s` since its type `S` is invariant with respect to `'a`).

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-diagnosticsArea: Messages for errors, warnings, and lintsA-lifetimesArea: Lifetimes / regionsC-enhancementCategory: An issue proposing an enhancement or a PR with one.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions