Cause
Deviation is the cause of the problem.
- In
struct Header<R: Reader>(R, usize); , Header<R> covariant wrt R - However, in
struct Header<R: Reader>(R, R::Offset); , Header<R> is an invariant wrt R
Subtyping is a safe conversion of life spans. For example, &'static [u8] can be converted to &'a [u8] .
The difference describes how subtyping rises to complex types. For example, if Header<_> is covariant and R is a subtype of S , Header<R> is a subtype of Header<S> . This does not apply to invariant structures.
In the current Rust, attributes are always invariant , since the variance of the attribute cannot be inferred or not specified in the current syntax. The same restrictions apply to projected types, such as R::Offset .
In your code, since Header is invariant, Header<&'a [u8]> cannot be expanded to Header<&'b [u8]> , even if 'a: 'b . Since fn test requires the same type for both arguments, the compiler needs the same lifetime for slice1 and slice2 .
Decision
One possible ad-hoc solution is to generalize the signature for fn test , if possible.
fn test<R: Reader, S: Reader>(_: Header<R>, _: Header<S>) {}
Another solution is to make Header covariance somehow.
Perhaps it is safe to assume that the Header is covariant if type Offset has 'static , but the current compiler does not make such smart output.
Perhaps you can split the lifetime as a parameter for the Header . This restores covariance.
trait Offset: Default {} trait Reader { type Offset: Offset; } impl Offset for usize {} impl Reader for [u8] { type Offset = usize; } struct Header<'a, R: Reader + ?Sized + 'a>(&'a R, R::Offset); impl <'a, R: Reader<Offset=usize> + ?Sized> Header<'a, R> { fn new(r: &'a R) -> Self { Header(r, 0) } } fn test<R: Reader + ?Sized>(_: Header<R>, _: Header<R>) {} fn main() { let buf1 = [0u8]; let slice1 = &buf1[..]; let header1 = Header::new(slice1); let buf2 = [0u8]; let slice2 = &buf2[..]; let header2 = Header::new(slice2); test(header1, header2); }