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

[Error] ReprC Implementation Not General Enough #38

Closed
zicklag opened this issue Feb 28, 2021 · 5 comments
Closed

[Error] ReprC Implementation Not General Enough #38

zicklag opened this issue Feb 28, 2021 · 5 comments
Assignees
Labels
K-bug Kind: existing code isn’t behaving as expected
Milestone

Comments

@zicklag
Copy link

zicklag commented Feb 28, 2021

I'm getting an error with this example, is there anything I can do about it?

use safer_ffi::prelude::*;

pub use ty::Void;
mod ty {
    use safer_ffi::derive_ReprC;

    #[derive_ReprC]
    #[ReprC::opaque]
    /// A type used to represent an untyped pointer
    pub struct Void {
        _private: (),
    }
}

#[derive_ReprC]
#[repr(C)]
#[derive(Clone)]
pub struct CHostFunctionPointers {
    /// Get the full CBOR serialized [`ScriptApi`] including components discovered and
    /// implemented by other language adapters or the dynamite host.
    pub get_full_api: extern "C" fn(dynamite: *const Void) -> repr_c::Vec<u8>,

    /// Call a function provided by the scripting API
    call_function: extern "C" fn(
        dynamite: *const Void,
        path: str::Ref,
        args: c_slice::Ref<*const Void>,
    ) -> *const Void,
}

#[derive_ReprC]
#[repr(C)]
pub struct RemoteHostFunctions {
    pub dynamite: *const Void,
    pub pointers: CHostFunctionPointers,
}
error[E0277]: the trait bound `<CHostFunctionPointers as ReprC>::CLayout: CType` is not satisfied
  --> src/lib.rs:32:1
   |
32 | #[derive_ReprC]
   | ^^^^^^^^^^^^^^^ the trait `CType` is not implemented for `<CHostFunctionPointers as ReprC>::CLayout`
   |
   = help: see issue #48214
   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: implementation of `ReprC` is not general enough
  --> src/lib.rs:32:1
   |
32 | #[derive_ReprC]
   | ^^^^^^^^^^^^^^^ implementation of `ReprC` is not general enough
   |
   = note: `ReprC` would have to be implemented for the type `for<'r, 's> extern "C" fn(*const ty::Void, str_ref<'r>, slice_ref<'s, *const ty::Void>) -> *const ty::Void`
   = note: ...but `ReprC` is actually implemented for the type `extern "C" fn(*const ty::Void, str_ref<'0>, slice_ref<'_, *const ty::Void>) -> *const ty::Void`, for some specific lifetime `'0`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: implementation of `ReprC` is not general enough
  --> src/lib.rs:32:1
   |
32 | #[derive_ReprC]
   | ^^^^^^^^^^^^^^^ implementation of `ReprC` is not general enough
   |
   = note: `ReprC` would have to be implemented for the type `for<'r, 's> extern "C" fn(*const ty::Void, str_ref<'r>, slice_ref<'s, *const ty::Void>) -> *const ty::Void`
   = note: ...but `ReprC` is actually implemented for the type `extern "C" fn(*const ty::Void, str_ref<'_>, slice_ref<'0, *const ty::Void>) -> *const ty::Void`, for some specific lifetime `'0`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: implementation of `ReprC` is not general enough
  --> src/lib.rs:32:1
   |
32 | #[derive_ReprC]
   | ^^^^^^^^^^^^^^^ implementation of `ReprC` is not general enough
   |
   = note: `ReprC` would have to be implemented for the type `for<'r, 's> extern "C" fn(*const ty::Void, str_ref<'r>, slice_ref<'s, *const ty::Void>) -> *const ty::Void`
   = note: ...but `ReprC` is actually implemented for the type `extern "C" fn(*const ty::Void, str_ref<'0>, slice_ref<'_, *const ty::Void>) -> *const ty::Void`, for some specific lifetime `'0`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: implementation of `ReprC` is not general enough
  --> src/lib.rs:32:1
   |
32 | #[derive_ReprC]
   | ^^^^^^^^^^^^^^^ implementation of `ReprC` is not general enough
   |
   = note: `ReprC` would have to be implemented for the type `for<'r, 's> extern "C" fn(*const ty::Void, str_ref<'r>, slice_ref<'s, *const ty::Void>) -> *const ty::Void`
   = note: ...but `ReprC` is actually implemented for the type `extern "C" fn(*const ty::Void, str_ref<'_>, slice_ref<'0, *const ty::Void>) -> *const ty::Void`, for some specific lifetime `'0`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: implementation of `ReprC` is not general enough
  --> src/lib.rs:32:1
   |
32 | #[derive_ReprC]
   | ^^^^^^^^^^^^^^^ implementation of `ReprC` is not general enough
   |
   = note: `ReprC` would have to be implemented for the type `for<'r, 's> extern "C" fn(*const ty::Void, str_ref<'r>, slice_ref<'s, *const ty::Void>) -> *const ty::Void`
   = note: ...but `ReprC` is actually implemented for the type `extern "C" fn(*const ty::Void, str_ref<'0>, slice_ref<'_, *const ty::Void>) -> *const ty::Void`, for some specific lifetime `'0`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: implementation of `ReprC` is not general enough
  --> src/lib.rs:32:1
   |
32 | #[derive_ReprC]
   | ^^^^^^^^^^^^^^^ implementation of `ReprC` is not general enough
   |
   = note: `ReprC` would have to be implemented for the type `for<'r, 's> extern "C" fn(*const ty::Void, str_ref<'r>, slice_ref<'s, *const ty::Void>) -> *const ty::Void`
   = note: ...but `ReprC` is actually implemented for the type `extern "C" fn(*const ty::Void, str_ref<'_>, slice_ref<'0, *const ty::Void>) -> *const ty::Void`, for some specific lifetime `'0`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0277]: the trait bound `<CHostFunctionPointers as ReprC>::CLayout: CType` is not satisfied
  --> src/lib.rs:32:1
   |
32 | #[derive_ReprC]
   | ^^^^^^^^^^^^^^^ the trait `CType` is not implemented for `<CHostFunctionPointers as ReprC>::CLayout`
   |
   = help: see issue #48214
   = help: add `#![feature(trivial_bounds)]` to the crate attributes to enable
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: implementation of `ReprC` is not general enough
  --> src/lib.rs:32:1
   |
32 | #[derive_ReprC]
   | ^^^^^^^^^^^^^^^ implementation of `ReprC` is not general enough
   |
   = note: `ReprC` would have to be implemented for the type `for<'r, 's> extern "C" fn(*const ty::Void, str_ref<'r>, slice_ref<'s, *const ty::Void>) -> *const ty::Void`
   = note: ...but `ReprC` is actually implemented for the type `extern "C" fn(*const ty::Void, str_ref<'0>, slice_ref<'_, *const ty::Void>) -> *const ty::Void`, for some specific lifetime `'0`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: implementation of `ReprC` is not general enough
  --> src/lib.rs:32:1
   |
32 | #[derive_ReprC]
   | ^^^^^^^^^^^^^^^ implementation of `ReprC` is not general enough
   |
   = note: `ReprC` would have to be implemented for the type `for<'r, 's> extern "C" fn(*const ty::Void, str_ref<'r>, slice_ref<'s, *const ty::Void>) -> *const ty::Void`
   = note: ...but `ReprC` is actually implemented for the type `extern "C" fn(*const ty::Void, str_ref<'_>, slice_ref<'0, *const ty::Void>) -> *const ty::Void`, for some specific lifetime `'0`
   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 10 previous errors

For more information about this error, try `rustc --explain E0277`.
error: could not compile `ffi_example`

Apparently it works with feature(trivial_bounds).

Edit: I don't think the trivial_bounds feature fixes everything, actually.

@zicklag zicklag changed the title Implementation Not General Enough [Error] ReprC Implementation Not General Enough Feb 28, 2021
@zicklag
Copy link
Author

zicklag commented Mar 1, 2021

As I look around, I'm getting the feeling that it's perfectly possible to implement ReprC for the struct, but that the macro just doesn't have the proper for<'a, 'b> thing ( higher-kinded trait bound, if I remember right ). Is there an easy-enough way to manualy implement ReprC for that struct so that I don't need the macro and I can do it properly?

@zicklag
Copy link
Author

zicklag commented Mar 1, 2021

Hey, I think using cargo exand I've figured out what code the macro is trying to expand to, and it seems like this is equivalent, and works as far as my initial testing ( compiling and running it 😉 ):

#[repr(C)]
#[derive(Clone, Copy)]
pub struct CHostFunctionPointers {
    /// Get the full CBOR serialized [`ScriptApi`] including components discovered and
    /// implemented by other language adapters or the dynamite host.
    pub get_full_api: extern "C" fn(dynamite: *const Void) -> repr_c::Vec<u8>,

    /// Call a function provided by the scripting API
    call_function: extern "C" fn(
        dynamite: *const Void,
        path: str::Ref<'_>,
        args: c_slice::Ref<'_, *const Void>,
    ) -> *const Void,
}
unsafe impl safer_ffi::layout::CType for CHostFunctionPointers {
    type OPAQUE_KIND = safer_ffi::layout::OpaqueKind::Concrete;
}
unsafe impl safer_ffi::layout::ReprC for CHostFunctionPointers {
    type CLayout = Self;
    #[inline]
    fn is_valid(_: &Self::CLayout) -> bool {
        true
    }
}

I have no idea if it makes sense 😜.

@danielhenrymantilla
Copy link
Collaborator

danielhenrymantilla commented Mar 1, 2021

Yes, as you have correctly identified, this is an issue related to function pointer with different "higher-order-ness" requiring different generic signatures to be covered; see:

This is thus a known issue of safer-ffi, which you can find at #16. It has been marked as resolved, since in the main development branch (ditto), a workaround similar to that of that crate has been used. I have even written about it in the following gist: https://gist.github.com/danielhenrymantilla/be45a92cb6ad8b177cc28eda9c7f2004#why-are-higher-order-lifetimes-challenging-for-safer-ffi

I haven't release that officially since I need to untangle this kind of features with some development / experimental features present in the ditto branch. But, provided you pin-point a commit within the ditto branch, I assure you I won't rewrite the history of that branch and so you should have a "stable" / smooth experience with it anyways:

Temporary solution

  • # Cargo.toml
    [dependencies.safer-ffi] # (or use `[patch.crates-io.safer-ffi]`)
    git = "https://github.com/getditto/safer_ffi"
    branch = "ditto"
    rev = "fa26bdd4cfbdeee282ed4b420b46a5e2fecd3739"
    features = ["proc_macros"]
  • #![deny(elided_lifetimes_in_paths)] // the macro needs explicit lifetime parameters, even if elided, to work.
    
    #[derive_ReprC]
    #[repr(transparent)]
    struct call_function_t /* = */ (
        unsafe extern "C" fn(
            dynamite: *const Void,
            path: str::Ref<'_>,
            args: c_slice::Ref<'_, *const Void>,
        ) -> *const Void
    );
    
    #[repr(C)]
    #[derive(Clone)]
    pub struct CHostFunctionPointers {
        /// Get the full CBOR serialized [`ScriptApi`] including components discovered and
        /// implemented by other language adapters or the dynamite host.
        pub get_full_api: unsafe extern "C" fn(dynamite: *const Void) -> repr_c::Vec<u8>,
    
        /// Call a function provided by the scripting API
        call_function: call_function_t,
    }

An official release of safer-ffi improving most of these rough edges (naming, higher-order fns, etc.) is planned within the next 1-2 months, anyways 🙂

@danielhenrymantilla danielhenrymantilla added this to the Version 0.1.0 milestone Mar 1, 2021
@danielhenrymantilla danielhenrymantilla added K-bug Kind: existing code isn’t behaving as expected soon-ish labels Mar 1, 2021
@zicklag
Copy link
Author

zicklag commented Mar 1, 2021

Awesome! Thanks for the help!

@danielhenrymantilla
Copy link
Collaborator

Good news, the changes from that experimental branch have made it to master! On the other hand, master is not yet in a releasable-to-crates.io state, but that should be happening within the following weeks.

Closing this as completed, then 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
K-bug Kind: existing code isn’t behaving as expected
Projects
None yet
Development

No branches or pull requests

3 participants