Rules for shortening trait object lifetime bounds

I found that the following function compiles:

trait TestTrait {}

fn shorten_lifetime<'a, 'b: 'a>(x: &'a mut (dyn TestTrait + 'b)) -> &'a mut (dyn TestTrait + 'a) {
    x
}

However, I don't understand what justifies this "shortening" of the lifetime bound. I searched the Rust Reference for an applicable coercion rule, but I'm unable to find any. In particular:

  • It's not the unsized coercion: the unsized coercion coerces &mut T to &mut U only when T is a sized type.
  • It's not the subtyping rule: the mutable reference type &'a mut T is invariant in T so that part cannot change.

What are the rules behind this?

It is the unsizing coercion. That's also how dropping auto-traits and (eventually) trait upcasting work.

Perhaps you read these docs which say

  • The type is sized.

But you can demonstrate that what I said above is true.

1 Like

I didn't actually address this part. You can search for "Interaction with object coercion" in this RFC for the justification, and Ralf talks a bit about it in other terms here.[1]


  1. you might have to read a little more to get the full context ↩ī¸Ž

Thanks. I think I now understand that there is a specific rule for this kind of coercion (dyn upcasting) and why it's sound. Perhaps the reference should be updated to include the upcast case?

I haven't reviewed it, but there's a pending PR.

1 Like