Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
ZhennanWu opened this issue Feb 4, 2022 · 0 comments
Labels
bug Something isn't working

Comments

@ZhennanWu
Copy link

ZhennanWu commented Feb 4, 2022

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 ZhennanWu added the bug Something isn't working label Feb 4, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant