wit-bindgen icon indicating copy to clipboard operation
wit-bindgen copied to clipboard

Confusing error for Rust-exported items

Open alexcrichton opened this issue 3 years ago • 6 comments

When generating a rust-compiled-to-wasm module and you want to export things with the witx macro, it's possible to get a pretty confusing error. This Rust code:

witx_bindgen_rust::export!("w1.witx");

use w1::*;

struct Wasm;

impl w1::W1 for Wasm {
    fn doubles(i: i32) -> i32 {
        return i * 2;
    }
}

with this *.witx:

doubles: function(i: s32) -> s32

yields this error:

$ cargo test
   Compiling witx-bindgen-rust v0.1.0 (/home/acrichto/code/witx-bindgen/crates/rust-wasm)
error[E0038]: the trait `w1::W1` cannot be made into an object
 --> crates/rust-wasm/tests/wat.rs:1:1
  |
1 | witx_bindgen_rust::export!("w1.witx");
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `w1::W1` cannot be made into an object
  |
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
 --> crates/rust-wasm/tests/wat.rs:1:1
  |
1 | witx_bindgen_rust::export!("w1.witx");
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  | |
  | this trait cannot be made into an object...
  | ...because associated function `doubles` has no `self` parameter
  = note: this error originates in the macro `witx_bindgen_rust::export` (in Nightly builds, run with -Z macro-backtrace for more info)
help: consider turning `doubles` into a method by giving it a `&self` argument
  |
1 | witx_bindgen_rust::export!(&self, "w1.witx");
  |                            ^^^^^^
help: alternatively, consider constraining `doubles` so it does not apply to trait objects
  |
1 | witx_bindgen_rust::export!("w1.witx"); where Self: Sized
  |                                        ^^^^^^^^^^^^^^^^^

error: aborting due to previous error

For more information about this error, try `rustc --explain E0038`.
error: could not compile `witx-bindgen-rust`

To learn more, run the command again with --verbose.

The problem is that the generated code expects a W1 struct to be defined in the parent namespace but it's not. Instead W1 is defined as the trait itself (via the use-glob) which causes a bad error.

alexcrichton avatar Aug 04 '21 14:08 alexcrichton

Should we also file an issue against rustc for the erroneous "help" of modifying the proc macro invocation site?

peterhuene avatar Aug 04 '21 17:08 peterhuene

Perhaps? That's a pretty systemic problems where errors in macros just in general have pretty awful compiler diagnostics. I've always assumed it's a known issue that doesn't have a great solution, but I could be wrong!

alexcrichton avatar Aug 04 '21 20:08 alexcrichton

I ran into this problem, and fixed it by changing from struct Wasm/impl w1::W1 for Wasm to struct W1/impl w1::W1 for W1. With that said, aside from the comment that:

The problem is that the generated code expects a W1 struct to be defined in the parent namespace but it's not. Instead W1 is defined as the trait itself (via the use-glob) which causes a bad error.*

... I don't really understand why that's a problem in the first place and would love it if someone could enlighten me!

danbugs avatar Jun 20 '22 18:06 danbugs

I'm confused, do we still have a macro with witx in the name? I thought that had all been changed in favor of wit.

What if we made bindgen an attribute macro so that you could do something like this?

#[wit-bindgen]
#[export("w1.witx")]
struct Wasm;

Then the attribute macro could use whatever type name you attach it to instead of having to use a predetermined one. This could also be done for the wit-bindgen macro as well.

This would also create more consistency for where the macro goes in the file.

esoterra avatar Jun 21 '22 15:06 esoterra

This may also be related to https://github.com/bytecodealliance/wit-bindgen/issues/243 where in general I think attribute macros or derives would be a better idea than the current "pray the type exists at this place" logic.

alexcrichton avatar Jun 21 '22 15:06 alexcrichton

It'd also be great if somewhere along the way these attributes could pass more configuration to the code generators so users can do things like add more derives to generated types.

esoterra avatar Jun 21 '22 16:06 esoterra

I think that this has been fixed with the export_*!(...) macro nowadays, so closing.

alexcrichton avatar Nov 22 '22 20:11 alexcrichton