I have the following program (playground). I can get it to work, but I don't get the intuition behind the working versions.
Note that all the ...X
types are simplified version from the graphql-parser library.
pub trait TextX<'a> {
type Value; // Originally specified as `type Value: 'a`, but doesn't seem to matter
}
impl<'a> TextX<'a> for String {
type Value = String;
}
pub struct ValueX<'a, T: TextX<'a>> {
var: T::Value
}
pub struct AppContext<'ac> {
data: &'ac str
}
struct LocalContext<'lc> {
app_context: &'lc AppContext<'lc>
}
pub fn outer<'a>(value: &'a ValueX<'a, String>, app_context: &'a AppContext<'a>) {
let local_context = LocalContext { app_context };
inner(value, &local_context);
}
fn inner<'a>(_value: &'a ValueX<'a, String>, _local_context: &'a LocalContext<'a>) {
todo!()
}
// Works: Different lifetimes for each parameter
// fn inner<'a, 'lc>(_value: &'a ValueX<'a, String>, _local_context: &'lc LocalContext<'lc>) {
// todo!()
// }
// Works: The same as above, I think, but with inferred lifetimes
// fn inner(_value: &ValueX<String>, _local_context: &LocalContext) {
// todo!()
// }
// Works: Separate lifetimes for the LocalContext reference and content
// 'a: 'lc isn't really needed (i.e. just `'a` suffices)
// fn inner<'a: 'lc, 'lc>(_value: &'a ValueX<'a, String>, _local_context: &'lc LocalContext<'a>) {
// todo!()
// }
The way I am thinking:
- In the
outer
function, the lifetime ofvalue
is longer than that oflocal_context
(content oflocal_context
live longer, but not sure if that matters). - The (non-working)
inner
function expects both parameters (as well as the structure content) to have the same lifetime. - Using the shorter lifetime (that of
local_context
) would have satisfied the lifetimes constraint of theinner
function.
However, to get inner
to compile I need one of the variations shown.
Also, I need the structure of TextX
(specifically, it needs a lifetime parameter--here unused, but the original library code needs it) to illustrate the issue. If I remove the lifetime on TextX
and propagate that change to other types, the code works as well.
What may be going on here and where is my thinking going wrong?
Thanks.