Lifetime elision for trait implemented on a mutable reference

Hello,

I am trying to implement a trait for a reference to a dyn Trait object of the same trait. And somewhere a lifetime is being elided that's longer than I want.

in both the working and non_working cases, the object being passed is a &mut dyn MyTrait and it doesn't live beyond the function.

Can this pattern be made to work? (*without adding a lifetime parameter to the trait)

use std::borrow::BorrowMut;

trait MyTrait {}

impl MyTrait for &mut dyn MyTrait {}

impl MyTrait for i32 {}

fn non_working_func(_obj: impl MyTrait) {
    
}

fn working_func(_obj: &mut dyn MyTrait) {
    
}

fn main() {
    let mut boxed = Box::new(42) as Box<dyn MyTrait>;
    let borrowed: &mut dyn MyTrait = boxed.borrow_mut();
    working_func(borrowed);
    non_working_func(borrowed);
}

Thank you.

EDIT:

see comment below for correct explanation.

just use regular reborrow syntax should work:

    let borrowed: &mut dyn MyTrait = &mut *boxed;
1 Like

interesting, just tested it out, I don't know why, but the lifetime inference 1for reborrow of trait object seems odds to me:

// this works
let borrowed: &mut dyn MyTrait = &mut *boxed;
// this also works
let borrowed = &mut *boxed as &mut dyn MyTrait;
// for some reason, the following does **NOT** work:
let borrowed = &mut *boxed; //<-- error: *boxed doesn't live long enough

hope someone could explain the rule here.

1 Like

I don't have time to investigate in detail this moment, but I will note that this:

impl MyTrait for &mut dyn MyTrait {}

requires lifetime equality like so:

impl<'a> MyTrait for &'a mut (dyn MyTrait + 'a) {}

Whereas this allows the outer lifetime to be shorter than the inner lifetime:

impl MyTrait for &mut (dyn MyTrait + '_) {}

And allows the example to compile.

There's probably some situations where unsized coercion allowing a shorter trait object lifetime does or does not take place.[1]


Again I don't have time to confirm it right now, but it's probably because let statements with type annotations are coercion sites[2], but let expressions without annotations are not.[3]


  1. Recent related IRLO thread. ↩︎

  2. as are as _ expressions ↩︎

  3. There's a bit more nuance beyond "is there an annotation", like &mut _ vs. just _. ↩︎

3 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.