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

Errors in generated code with `duplicate_if_necessary` ownership set to `true`.

Open peterhuene opened this issue 2 years ago • 5 comments

Repro steps

  1. git clone [email protected]:peterhuene/wit-bindgen-repro.git (repository link)
  2. cd wit-bindgen-repro
  3. cargo build

Expected results

A successful build.

Actual results

error[E0308]: mismatched types
 --> src/lib.rs:1:1
  |
1 | / wit_bindgen::generate!({
2 | |     path: "wit",
3 | |     world: "proxy",
4 | |     ownership: Borrowing { duplicate_if_necessary: true },
5 | | });
  | |  ^
  | |  |
  | |  expected `ErrorCodeResult`, found `ErrorCodeParam<'_>`
  | |__this expression has type `&ErrorCodeResult`
  |    unit variant defined here
  |
  = note: this error originates in the macro `wit_bindgen::generate` (in Nightly builds, run with -Z macro-backtrace for more info)

Details

wit-bindgen version: 0.21.0

peterhuene avatar Mar 05 '24 21:03 peterhuene

It looks like the bindings generation is getting tripped up for ResponseOutparam::set when lowering the result's error variant, which should use ErrorCodeResult::XYZ in the match, but the generator emits ErrorCodeParam::XYZ.

peterhuene avatar Mar 07 '24 16:03 peterhuene

Actually, given that what is being lowered is a parameter, I would expect the signature of ResponseOutparam::set to be:

pub fn set(param: ResponseOutparam, response: Result<OutgoingResponse, ErrorCodeParam<'_>>)

instead of the currently generated:

pub fn set(param: ResponseOutparam, response: Result<OutgoingResponse, ErrorCodeResult>)

peterhuene avatar Mar 07 '24 18:03 peterhuene

Test case simplified to this WIT:

package wit-bindgen:repro;

interface foo {
  variant v {
    foo,
    bar(string)
  }

  resource r {
    foo: static func(r: result<r, v>);
  }
}

world repro {
  import foo;
  export foo;
}

The presence of the resource in result<r, v> seems to be tripping it up.

Signature of foo with result<r, v>:

pub fn foo(r: Result<R, VResult>)

Signature of foo with result<_, v>:

pub fn foo(r: Result<(), VParam<'_>>)

The latter is correct.

peterhuene avatar Mar 08 '24 23:03 peterhuene

Oof now this is a tough one. The reason VResult is chosen here is because the parameter to foo contains an own resource, and we want to map that ownership in Rust as "this whole owned thing is being transferred". Specifically it's hitting this case which forces the parameter r to be rendered as owned rather than borrowed.

This then disagrees the function bindings generator which ends up using a different path to calculate a different name for this parameter.

Looks like the fixes I applied in https://github.com/bytecodealliance/wit-bindgen/pull/846 were, predictably, not enough. Alas!

alexcrichton avatar Mar 09 '24 00:03 alexcrichton

Ah I literally just discovered that the calculated has_own_handle in the condition you linked to was behind the discrepancy and was about to loop you in, but you beat me to it!

peterhuene avatar Mar 09 '24 01:03 peterhuene