region-outlives obligations lead to uninformative/undecipherable region inference failures

c242c05
Opened by Felix S Klock II at 2022-06-08 21:35:25

Consider this program:

use std::cell::Cell;
trait Foo { fn foo(&mut self); }
struct Pair<'a,'b> { x: &'a Cell<u8>, y: &'b Cell<u8> }

// This impl says it callers of `foo` on `Pair<'a,'b>` must ensure
// that 'b outlives 'a.
impl<'a, 'b:'a> Foo for Pair<'a, 'b> {
    fn foo(&mut self) {
        println!("pre  x: {} y: {}", self.x.get(), self.y.get());
        // 'b outlives 'a, so `&'b Cell<u8> <: &'a Cell<u8>`
        self.x = self.y;
        println!("post x: {} y: {}", self.x.get(), self.y.get());
    }
}

impl<'a,'b> Pair<'a,'b> {
    fn bar(&mut self) {
        self.foo();
    }
}

fn baz<'a,'b>(pa: &'a Cell<u8>, pb: &'b Cell<u8>) {
    let mut p = Pair { x: pa, y: pb };
    p.bar();
}

fn main() {
    let a = Cell::new(1);
    let b = Cell::new(2);
    let pa = &a;
    let pb = &b;
    baz(pa, pb);
}

This yields the following error (playpen):

<anon>:18:14: 18:19 error: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
<anon>:18         self.foo();
                       ^~~~~
<anon>:17:5: 19:6 help: consider using an explicit lifetime parameter as shown: fn bar(&mut self)
<anon>:17     fn bar(&mut self) {
<anon>:18         self.foo();
<anon>:19     }
error: aborting due to previous error
playpen: application terminated with error code 101

There is no mention of the region constraint on the impl providing foo that is causing calling foo from bar to fail.

cc @nikomatsakis

  1. Also, the test case above is the result of my trying to determine whether we need to special-case the handling of region-outlives constraints in my code to address #8142 , because the current trait + obligation machinery does not seem to currently have a way to produce a hard-error in such cases. Instead it seems like it always generates a subregion constraint and lets the downstream region inference code determine that the resulting constraint set is unsatisfiable

    (Update: moved the rest of my comment into a comment on #8142, once I determined that one can indeed observe unsoundness in Drop due to ... well, due to a potentially-related problem.)

    Felix S Klock II at 2015-03-21 17:08:17

  2. Triage: no changes here.

    Steve Klabnik at 2016-06-06 20:59:34

  3. Triage: no change

    Steve Klabnik at 2019-12-25 16:16:34

  4. Current output:

    error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
      --> src/main.rs:18:14
       |
    18 |         self.foo();
       |              ^^^
       |
    note: first, the lifetime cannot outlive the lifetime `'b` as defined here...
      --> src/main.rs:16:9
       |
    16 | impl<'a,'b> Pair<'a,'b> {
       |         ^^
    note: ...but the lifetime must also be valid for the lifetime `'a` as defined here...
      --> src/main.rs:16:6
       |
    16 | impl<'a,'b> Pair<'a,'b> {
       |      ^^
    note: ...so that the types are compatible
      --> src/main.rs:18:14
       |
    18 |         self.foo();
       |              ^^^
       = note: expected `<Pair<'a, 'b> as Foo>`
                  found `<Pair<'_, '_> as Foo>`
    

    Esteban Kuber at 2022-06-08 21:35:25