error[E0759]: `event` has lifetime `'a` but it needs to satisfy a `'static` lifetime requirement
--> src/lib.rs:17:23
|
16 | fn show_event<'a>(event: &'a Event) {
| --------- this data with lifetime `'a`...
17 | show_fields(event.span().fields());
| ----- ^^^^
| |
| ...is captured here...
|
note: ...and is required to live as long as `'static` here
--> src/lib.rs:17:5
|
17 | show_fields(event.span().fields());
as the argument to show_fields seems to gain a 'static obligation. Is there any way to remove the 'static (owned) requirement from the argument here? All of the variations I've attempted retain the 'static obligation.
I think your problem is that fields() says it returns an iterator of (&'static str, &'_ str) while the show_fields() function says the iterator must be (&'data str, &'data str).
In theory the compiler should be able to shorten the first element's 'static lifetime to satisfy 'data because you've got immutable references, but instead it seems to be requiring that 'static == 'data.
Variance has always confused me a bit, but maybe when you are working with associated types it flips covariance for contravariance? Similar to what can happen with higher-order functions.
It couldn't do that, because Iterator<Item = (&'a str, &'a str)> to Iterator<Item = (&'static str, &'static str)> would be unsound. What you're seeing here is invariance. It works if you change the return type of fields to a concrete, covariant type (in this example std::option::IntoIter<(&'static str, &'_ str)>), because rustc is able to shorten the lifetimes of the generic parameters and therefore shorten the lifetime of the Item associated type.
Because return position impl Trait is invariant (because it could potentially be fulfilled by a type which is invariant over the lifetime(s)), we fail to unify the two types, because we can't have 'd = 'static and 'd = 'a at the same time.
rustc then chooses to explain the mismatch as "has lifetime 'a but needs to satisfy 'static, which is... not all that illuminating to where the 'static came from, thus the diagnostic issue.
Traits are always invariant in their input lifetimes (although this is underdocumented IMO), and associated types are also invariant as well.
Note also that tuple.1 is bound to &self in Span::fields(&self). If you force (&'static str, &'static str), you force &'static self. You can adjust to the signature of Span::fields to avoid equality (express covariance), but so long as 'self: 'tuple_1, it doesn't matter (if 'tuple_1 is 'static, 'self must be 'static too.)
(If 'tuple_1: 'self, it also compiles even when the tuple lifetimes are forced to be equal, but I doubt this is the contract you want on the method.)
FWIW, these hard-to-diagnose issues, are often due to a mismatch between the lifetimes we expected Rust to pick and the ones it actually picked (e.g., we were expecting something like a show_fields::<'a, 'a> call).
In that case, it can be quite helpful to explicitly turbofish the lifetimes as we'd expect them to be provided, so as to get a better error message:
Finally, to go even further, we can also turbofish all the lifetimes there. This way we manage to get a expected tuple `(&'static str, &'a str)` error message: Playground