thin_trait_object icon indicating copy to clipboard operation
thin_trait_object copied to clipboard

Unbounded lifetime parameters in vtable method signature, if method return type has a lifetime bounded by Self

Open ZhennanWu opened this issue 4 years ago • 0 comments

This bug happens when the return type has a lifetime bounded by &self. Because in the vtable, &self is casted into a lifetime-less raw pointer ffi::c_void, therefore the vtable method's return type becomes unbounded.

Minimum Reproducible Example

#[thin_trait_object]
trait Foo: 'static {
    fn as_slice(&self) -> &[u32];
}

We get

error[E0106]: missing lifetime specifier
 --> src\render.rs:9:27
  |
9 |     fn as_slice(&self) -> &[u64];
  |                           ^ expected named lifetime parameter
  |
  = help: this function's return type contains a borrowed value with an elided lifetime, but the lifetime cannot be derived from the arguments
  = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the type lifetime-generic with a new `'a` lifetime
  |
7 ~ for<'a> #[thin_trait_object]
8 | trait Foo {
9 ~     fn as_slice(&self) -> &'a [u64];
  |
help: consider using the `'static` lifetime
  |
9 |     fn as_slice(&self) -> &'static [u64];

The expanded macro

    #[repr(C)]
    struct FooVtable {
        pub as_slice: unsafe fn(*mut ::core::ffi::c_void) -> &[u64], // <---- This is problematic
        pub drop: unsafe fn(*mut ::core::ffi::c_void),
    }

Some thoughts

An immediate solution is to replace the vtable method's return type with raw pointers. However, the problem is that this only works with plain references, and other lifetime-bounded types will still be affected (Iterators, some smart pointers, etc). Fully covering these cases seems too much.

I don't have much experience with unsafe hacks and didn't see a particularly good way to fix this. However, this issue is not urgent since copy-pasting cargo expand and manual-fixing always works.

ZhennanWu avatar Feb 04 '22 13:02 ZhennanWu