This is a subsequent question of Does the lifetime parameter denote any lifetime in HRTB if it is constrainted?
#![feature(fn_traits)]
#![feature(unboxed_closures)]
use std::marker::PhantomData;
struct Scope<'a, 'b>(PhantomData<*mut &'a ()>, PhantomData<*mut &'b ()>);
impl<'a, 'env> Scope<'a, 'env> {
fn spawn<F>(&'a self, mut f: F) where F: FnMut() + 'a {
f();
}
}
fn scope_spawn<'b, F>(_f: F) where F: for<'a> FnOnce(&'a Scope<'a, 'b>) {}
struct Closure<F>(F);
impl<'a, 'b, F> FnOnce<(&'a Scope<'a, 'b>,)> for Closure<F>
where
F: FnMut() + 'b, // #1
//'b: 'a,
{
type Output = ();
extern "rust-call" fn call_once(self, (scope,): (&'a Scope<'a, 'b>,)) {
scope.spawn(self.0);
}
}
fn main() {
let mut i = 0;
scope_spawn(Closure(|| { i = 1; }));
}
Notice the trait bound in the Fn
trait's implementation for type Closure<F>
, this example is Ok. The type &'a Scope<'a, 'b>
formed in the parameter implies 'b:'a
. Specifically, it implies something like for<'a where 'b:'a>
, which means that: The implicit bound adds an upper limit to the 'a
that needs to be handled (but there's still no lower limit). However, if changing #1
to F: FnMut() + 'a
, the compiler will report an error:
closure may outlive the current function, but it borrows `i`, which is owned by the current function
This is confused. Why F:FnMut() + 'b
is ok, and 'a
is any lifetime less than or equal to 'b
(implcited by the formed type), however, F:FnMut() +'a
causes the above error?
Update:
I suspect that F: FnMut() +'a
has the same reason as why explicit trait bound 'b:'a
can cause the error too. That is, in the trait's implementation for which the HRTB checks, any explicit use of the lifetime corresponding to the lifetime introduced by for
in HRTB will be considered as if it were rewritten as for<'a>
, in this example, F:FnMut() +'a
is F: for<'a> FnMut() +'a
, which requires F
outlives 'static
.