Skip to content

feat: host_bindgen! returns Result from guest-implemented functions - #1709

Open
jsturtevant wants to merge 1 commit into
mainfrom
rally/1316-positivity-param
Open

feat: host_bindgen! returns Result from guest-implemented functions#1709
jsturtevant wants to merge 1 commit into
mainfrom
rally/1316-positivity-param

Conversation

@jsturtevant

@jsturtevant jsturtevant commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

fixes: #1316

host_bindgen! export wrappers no longer panic when Callable::call() returns Err (guest abort/trap/timeout). Host callers now receive the HyperlightError.

Breaking change

Calls to guest exports return hyperlight_host::Result. Implementations of host imports are unchanged.

Example WIT:

world test {
  import roundtrip;
  export roundtrip;
}

interface roundtrip {
  echo: func(x: string) -> string;
}
// Implementing an import: unchanged.
impl test::wit::Roundtrip for Host {
    fn echo(&mut self, x: String) -> String { x }
}

// Calling an export: now fallible.
let value: Result<String, HyperlightError> = sandbox.roundtrip().echo("hi".into());

Interface direction

The trait and its two markers live in hyperlight_host::component, so nothing is emitted into the wit namespaces where a package name could collide:

pub trait InterfaceDirection: Sealed {
    type CallResult<T>;      // Imported: T      Exported: hyperlight_host::Result<T>
    type Borrow<'a, T: 'a>;  // Imported: guard  Exported: &'a T
}
pub struct Imported;  // host implements it, calls run guest to host
pub struct Exported;  // guest implements it, calls run host to guest

Generated traits are written against that parameter:

pub trait Roundtrip<D: InterfaceDirection = Imported> {
    fn echo(&mut self, x: String) -> <D as InterfaceDirection>::CallResult<String>;
}

A guest that traps, or a sandbox call that fails, surfaces as
hyperlight_host::Result instead of a panic inside generated code.

Instance and resource traits take a trailing InterfaceDirection parameter
that decides how a function result and a borrowed handle are represented.
Exported is the direction that runs host to guest, so a call returns a
Result and a handle is a plain borrow. Imported runs guest to host, where
a call returns the bare value and a handle arrives through the resource
tables. The parameter defaults to Imported, so implementations of
imported interfaces are written exactly as before.

hyperlight_host::component holds the trait and its two markers. Keeping
them there rather than emitting them alongside every set of bindings
keeps them clear of the wit namespaces, where a package name could
collide. The trait is sealed, since those two directions are the only
ones.

Deciding this per position rather than per occurrence is what makes one
trait able to serve an interface that a world both imports and exports,
which the test wit does with `roundtrip`. Generating two differently
shaped traits instead would need the two occurrences to be told apart
everywhere they are named, and would leave a resource shared between an
import and an export carrying whichever signature was emitted first.

State::is_export is gone. It recorded the direction at generation time,
which is only correct while no item occurs on both sides.

Signed-off-by: James Sturtevant <jsturtevant@gmail.com>
Copilot AI lite review requested due to automatic review settings August 7, 2026 22:27
@jsturtevant jsturtevant added the kind/bugfix For PRs that fix bugs label Aug 7, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates host_bindgen!-generated host bindings so that calls into guest-implemented exports return hyperlight_host::Result<T> instead of panicking when the guest traps/aborts/timeouts. It also introduces a direction-marker mechanism so a single generated Rust trait can represent both imported and exported occurrences of the same WIT interface while selecting the appropriate return/borrow shapes at each use site.

Changes:

  • Make host-side export wrappers propagate Callable::call() failures as HyperlightError instead of panicking.
  • Add hyperlight_host::component::{InterfaceDirection, Imported, Exported} and update codegen to parameterize instance/resource traits over direction.
  • Extend tests and WIT fixtures with a deliberately trapping guest export to assert the new non-panicking behavior, and document the breaking change in CHANGELOG.md.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/tests/rust_guests/witguest/src/main.rs Adds a guest failable.will_trap() implementation that panics to simulate guest abort/trap.
src/tests/rust_guests/witguest/guest.wit Declares the new exported failable interface with will-trap.
src/hyperlight_host/tests/wit_test.rs Updates callers to unwrap fallible export calls and adds a test asserting guest traps return Err(HyperlightError::GuestAborted(..)).
src/hyperlight_host/src/lib.rs Exposes the new public component module for bindgen support types.
src/hyperlight_host/src/component.rs Adds the sealed InterfaceDirection trait plus Imported/Exported markers defining call/borrow shapes.
src/hyperlight_component_util/src/rtypes.rs Updates type emission to use direction markers for borrow and call-result shapes, and ensures resource direction is chosen correctly.
src/hyperlight_component_util/src/host.rs Updates generated host export wrappers to use ? (no panic) and return Ok(unmarshal(..)).
src/hyperlight_component_util/src/guest.rs Removes now-obsolete is_export manipulation in guest emission.
src/hyperlight_component_util/src/emit.rs Replaces is_export with direction tracking and adds helpers for emitting direction markers/params.
CHANGELOG.md Records the breaking API change for host_bindgen! export call sites.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@jsturtevant

jsturtevant commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

@syntactically, please feel free to push any changes you would perfer directly here. I did my best with how I understand components but it isn't at the same level as you 😃

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

kind/bugfix For PRs that fix bugs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

host_bindgen! generated code panics on guest errors instead of returning Result

2 participants