rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
96.61k stars 12.48k forks source link

overly conserative region edges invoking higher-ranked closure #37666

Closed nikomatsakis closed 1 year ago

nikomatsakis commented 7 years ago

This snippet fails to compile:

struct MyType<'a, 'tcx: 'a> {
    x: &'a &'tcx ()
}

impl<'a, 'tcx> MyType<'a, 'tcx> {
    fn with<F>(&mut self, f: F)
        where F: for<'b> FnOnce(&mut MyType<'b, 'tcx>)
    {
        f(self);
    }
    fn with2<F>(&mut self, f: F)
        where F: for<'b> FnOnce(&mut MyType<'b, 'tcx>)
    {
        self.with(|this| f(this))
        // self.with(|this| this.with(f)) <-- this works, if you uncomment it, see below
    }
}

fn main() { }

with the error:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
  --> <anon>:14:26
   |
14 |         self.with(|this| f(this))
   |                          ^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime 'tcx as defined on the block at 13:4...
  --> <anon>:13:5
   |
13 |     {
   |     ^
note: ...so that the declared lifetime parameter bounds are satisfied
  --> <anon>:14:26
   |
14 |         self.with(|this| f(this))
   |                          ^^^^^^^
note: but, the lifetime must be valid for the lifetime 'b as defined on the block at 14:25...
  --> <anon>:14:26
   |
14 |         self.with(|this| f(this))
   |                          ^^^^^^^
note: ...so that expression is assignable (expected &mut MyType<'_, 'tcx>, found &mut MyType<'b, '_>)
  --> <anon>:14:28
   |
14 |         self.with(|this| f(this))
   |                            ^^^^

error: aborting due to previous error

I believe it should succeed, but somehow the implied bound that 'tcx: 'b is failing to get added in the closure. I haven't investigated much to see why this is the case.

There is a workaround. If you change self.with(|this| f(this)) to self.with(|this| this.with(f)), it works, because the implied bounds work out for you then.

Spoonbender commented 2 years ago

Triage: no change

Dylan-DPC commented 1 year ago

Closing this as the code now compiles.