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

Implementation of Debug and Hash is not general enough #1

Closed
nlinker opened this issue Apr 11, 2021 · 2 comments
Closed

Implementation of Debug and Hash is not general enough #1

nlinker opened this issue Apr 11, 2021 · 2 comments
Labels
bug Something isn't working

Comments

@nlinker
Copy link

nlinker commented Apr 11, 2021

Hi.
The crate looks promising, however I bumped with a pretty cryptic error. MRE:

use thin_trait_object::*;

#[derive(Debug, Clone)]
struct Bar(String);

#[thin_trait_object]
trait Foo {
    fn fooify(&self, bar: &Bar);
}
impl Foo for String {
    fn fooify(&self, bar: &Bar) {
        println!("Fooified a string: {} {:?}", self, bar);
    }
}

fn main() {
    let bar = Bar("suffix".to_string());
    BoxedFoo::new("Hello World!".to_string()).fooify(&bar);
}

The error:

➜  thin_trait_object git:(main) ✗ cargo run --example basic
   Compiling thin_trait_object v1.1.1 (/Users/nick/rust/scai/utils/cxx-all/thin_trait_object)
error: implementation of `Hash` is not general enough
 --> examples/basic.rs:6:1
  |
6 | #[thin_trait_object]
  | ^^^^^^^^^^^^^^^^^^^^ implementation of `Hash` is not general enough
  |
  = note: `Hash` would have to be implemented for the type `for<'r> unsafe fn(*mut c_void, &'r Bar)`
  = note: ...but `Hash` is actually implemented for the type `unsafe fn(*mut c_void, &'0 Bar)`, for some specific lifetime `'0`
  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: implementation of `Debug` is not general enough
 --> examples/basic.rs:6:1
  |
6 | #[thin_trait_object]
  | ^^^^^^^^^^^^^^^^^^^^ implementation of `Debug` is not general enough
  |
  = note: `Debug` would have to be implemented for the type `for<'r> unsafe fn(*mut c_void, &'r Bar)`
  = note: ...but `Debug` is actually implemented for the type `unsafe fn(*mut c_void, &'0 Bar)`, for some specific lifetime `'0`
  = note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 2 previous errors

I also put the MRE into the fork https://github.com/nlinker/thin_trait_object/blob/main/examples/basic.rs

@nlinker nlinker added the bug Something isn't working label Apr 11, 2021
@kotauskas
Copy link
Owner

This is indeed so cryptic that I suspect it may be a compiler bug. What's happening here is that it's trying to compile FooVtable's definition which looks like this:

#[derive(Copy, Clone, Debug, Hash)]
struct FooVtable {
    pub fooify: unsafe fn(*mut ::core::ffi::c_void, &Bar),
    pub drop: unsafe fn(*mut ::core::ffi::c_void),
}

where the unsafe fn(*mut ::core::ffi::c_void, &Bar) desugars into for<'r> unsafe fn(*mut ::core::ffi::c_void, &'r Bar). The #[derive(Debug, Hash)] derives then try to use the implementation of Debug on that type, for<'r> unsafe fn(*mut ::core::ffi::c_void, &'r Bar), which is the type of the field, but that fails for... some reason. It really shouldn't: Debug should be implemented for all fn types and the implicit HRTB, for<'r>, has nothing to do with the function pointer's ability to be printed.

I'm currently writing a band-aid fix to this (implementing Debug and Hash manually by casting the function pointer to a *mut ::core::ffi::c_void), and will explore the compiler bug further if I can.

@kotauskas
Copy link
Owner

This indeed turned out to be a known compiler bug. I've just released a fix in 1.1.2 which is functionally identical to how the derives would behave once the compiler bug is fixed.

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

2 participants