I am not an expert, but as I see it, in:
fn baz1<'f, 'g>(b: &'f i32, _foo: &'f Foo<'f, 'g>) {}
the &'f Foo<'f, 'g>
reference is an input, so the caller can verify (by being able to construct that reference) that 'g: 'f
, however in:
pub fn baz2<'f, 'g: 'f, F>(f: F) -> ()
where
F: FnOnce(&'f Foo<'f, 'g>) -> ()
the &'f Foo<'f, 'g>
reference is something like an output (an input to an input), the implementation of baz2
will (probably) construct such reference (so it can call f
) and to do so it will need 'g: 'f
.
As for why such bound is not implied, I do not know, but my guess would be to keep open the possibility to make references always valid but sometimes uninhabited types (e.g. &'long &'short T
would be a valid type with no values).
Then the baz2
without the 'g: 'f
bound would be valid and it would essentially say that baz2
does not call f
.
So if you look at this header:
pub fn baz2<'f, 'g, F>(f: F) -> ()
where
F: FnOnce(&'f Foo<'f, 'g>) -> ()
it might have two meanings:
- You do want to call
f
in baz2
. But then you need also 'g: 'f
,
- You do not want to call
f
in baz2
. But then the F: FnOnce(&'f Foo<'f, 'g>)
is redundant.
- You might also want to do something that does not call
f
, but still needs the F: FnOnce(&'f Foo<'f, 'g>)
bound, but that is invalid in current rust.
The Rust authors probably did not want to make any of these implicit. You can choose explicitly by adding 'g: 'f
or omitting F: FnOnce(&'f Foo<'f, 'g>)
.
There is no such ambiguity in baz1
(the latter version that takes _foo
by reference), without the 'g: 'f
it is uncallable.
But that is just my guess.