WebAssembly / component-model

Repository for design and specification of the Component Model
Other
914 stars 78 forks source link

CABI: Add a `resource.consume` method for owned handles #238

Open juntyr opened 11 months ago

juntyr commented 11 months ago

Motivation

At the moment, there is no way to convert an owned resource handle inside the resource-exporting component back into an owned value of the type that implements the resource. While the specifics of performing this conversion can be left to wit-bindgen (see, e.g., https://github.com/bytecodealliance/wit-bindgen/issues/641#issuecomment-1686866481), it requires a canonical ABI primitive to consume an owned resource handle.

Detail

The canonical ABI defines a new method, resource.consume, which might be implemented as follows:

### `canon resource.consume`

def canon_resource_consume(inst, rt, i):
  # similar to resource.drop, but only for owned handles
  h = inst.handles.remove(rt, i)
  trap_if(!h.own)
  assert(h.scope is None)
  trap_if(h.lend_count != 0)
  trap_if(inst is not rt.impl and not rt.impl.may_enter)

  # note: do *not* call h's destructor

  # similar to resource.rep
  return h.rep

In particular, resource.consume, which has a (handwavy) signature of fn(owned_handle: i32) -> isize:

Closing Notes

Thank you for considering this extension to the canonical ABI :)

lukewagner commented 11 months ago

Good idea, and thanks for the super-clear write-up! I suppose this is technically possible to achieve today by adding a branch to the destructor to make it a no-op in the cases where you'd use resource.consume, but that has some overhead and could be a real pain, possibly requiring changing the linear-memory representation or adding an indirection, all of which is avoided by resource.consume. Does that sound right?

juntyr commented 11 months ago

Thanks! You’re absolutely right that the intended outcome can be achieved already, though with some tricks. In Rust, for instance,

Even though the last two options presents reasonable workarounds that still present a safe interface to users, I still think that an explicit CABI function for invalidating an owned handle without dropping the inner value is a better approach. It avoids both the potential memory overhead and additional unsafety.

Overall, I fully agree with your assessment.