Help with Vec::dedup_by_key and lifetime error

I’m working with dynamic types and need to filter a Vec<Box<Any>> to ensure that each type can only appear once. This is what I tried:

use std::any::Any;

pub fn dedup_types(mut list: Vec<Box<Any>>) -> Vec<Box<Any>> {
    list.sort_unstable_by_key(|elem| elem.type_id());
    list.dedup_by_key(|elem| elem.type_id());
    list
}

but it fails with this error:

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
 --> src/lib.rs:5:35
  |
5 |     list.dedup_by_key(|elem| elem.type_id());
  |                                   ^^^^^^^
  |
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 5:23...
 --> src/lib.rs:5:23
  |
5 |     list.dedup_by_key(|elem| elem.type_id());
  |                       ^^^^^^^^^^^^^^^^^^^^^
  = note: ...so that the types are compatible:
          expected &&mut std::boxed::Box<(dyn std::any::Any + 'static)>
             found &&mut std::boxed::Box<(dyn std::any::Any + 'static)>
  = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the type `&mut std::boxed::Box<(dyn std::any::Any + 'static)>` will meet its required lifetime bounds
 --> src/lib.rs:5:35
  |
5 |     list.dedup_by_key(|elem| elem.type_id());
  |                                   ^^^^^^^

I’m not sure what this error means (the “expected” and “found” types are exactly the same) or why dedup_by_key fails when sort_unstable_by_key succeeds with exactly the same key extraction function. Any ideas?

I think sort_unstable_by_key compiles because it takes a FnMut(&T) -> K whereas dedup_by_key takes a FnMut(&mut T) -> K. I’m not sure what is happening with the lifetimes but (*elem).type_id() works.

Thanks, that’ll do. I don’t get it but if rustc is happy then I’m happy :slight_smile:

Hmm something is still wrong here. Filtering always reduces the list to 1 element regardless of how many unique types exist.

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=a98f9621e6cb26b172f51058f1c97277

pub fn dedup_types(list: &mut Vec<Box<Any>>)  {
    list.sort_unstable_by_key(|elem| (**elem).type_id());
    list.dedup_by_key(|elem| (**elem).type_id());
}

this works

1 Like

Thanks!

I guess it was sorting/deduping by the type of Box<Any>, which is of course always the same, so it always reduced to one element. The extra level of dereferencing makes it grab the type of the inner Any instead.

Trait selection is pretty interesting here. Any is only implemented for T: 'static + ?Sized, and this is where the 'static bit in the error message emanates from.

What’s interesting is for sort_unstable_by_key, the compiler correctly applies the Any constraint to Box<dyn Any>, whereas for dedup it’s (apparently) picking &mut Box<dyn Any> as the type, and then complains that it needs &'static mut Box<dyn Any> to satisfy Any requirements. Seems strange, but maybe I’m missing something.