Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jun 23, 2025

The host_bindgen macro was generating clippy unused_unit warnings when creating bindings for WIT functions with no return value (void functions). This occurred because the macro generated explicit () return statements that clippy correctly identified as redundant.

Problem

When using WIT like:

interface adder {
  do-something: func(number: u32);  // No return value
}

The macro generated code like:

fn do_something(&mut self, number: u32) -> () {
    let ret = ::hyperlight_host::sandbox::Callable::call::<::std::vec::Vec<u8>>(&mut self.sb, /*...*/);
    let ::std::result::Result::Ok(ret) = ret else { panic!("bad return from guest {:?}", ret) };
    ()  // ← This explicit () triggers clippy::unused_unit
}

Solution

1. Modified emit_hl_unmarshal_result in src/hyperlight_component_util/src/hl.rs:

  • Changed from quote! { () } to TokenStream::new() for empty result types
  • Functions with void return now generate no explicit return statement

2. Updated guest code generation in src/hyperlight_component_util/src/guest.rs:

  • Made the #[allow(clippy::unused_unit)] attribute conditional
  • Only emit the attribute when there's actually an unmarshal expression to suppress

Result

Now generates clean code that doesn't trigger clippy warnings:

fn do_something(&mut self, number: u32) -> () {
    let ret = ::hyperlight_host::sandbox::Callable::call::<::std::vec::Vec<u8>>(&mut self.sb, /*...*/);
    let ::std::result::Result::Ok(ret) = ret else { panic!("bad return from guest {:?}", ret) };
    // No explicit () - function implicitly returns ()
}

Testing

  • ✅ Builds successfully
  • ✅ Clippy passes (including with -D clippy::unused-unit)
  • ✅ Existing functionality unchanged
  • ✅ Guest bindings still compile correctly
  • ✅ Tested with the exact WIT example from the issue

Fixes #653.


💬 Share your feedback on Copilot coding agent for the chance to win a $200 gift card! Click here to start the survey.

Copilot AI changed the title [WIP] Marcro fails clippy checks with specific wit that doesn't have a return value Fix clippy unused_unit warnings in host_bindgen macro for void return functions Jun 23, 2025
Copilot AI requested a review from jsturtevant June 23, 2025 16:28
Copilot finished work on behalf of jsturtevant June 23, 2025 16:28
@jsturtevant jsturtevant added the kind/bugfix For PRs that fix bugs label Jun 23, 2025
Copy link
Contributor

@jsturtevant jsturtevant left a comment

Choose a reason for hiding this comment

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

It would be nice to see a test case added to the wit file that has a function that has no returns

quote! {}
} else {
quote! {
#[allow(clippy::unused_unit)]
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think this will be needed since this use case is handled by return an empty quote

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right! Since emit_hl_unmarshal_result returns TokenStream::new() for void functions, the conditional logic wasn't needed. Simplified the code to use unmarshal directly. (412ab9f)

cc 9e697e3320100630afae15901d82d23237f04e3d8090ec2c9ecb211fbf322909 # shrinks to x = 0.0
cc 033b8487116d6b64d1c321ca2475618b943551b670ed562648c12f3a7586243a # shrinks to x = EnumA
cc 37f8b1a347c5a2a096a8904b918c0f049b729c80e329ed63dc1b501258a2973b # shrinks to x = false
cc f401ff3b24d9e0b6a5332fbaecbb5cde12d13d932d33d27a5d15ce2ea73a1125 # shrinks to x = 'A'
Copy link
Contributor

Choose a reason for hiding this comment

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

Where did this come from? Don't include thes right now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Removed the proptest-regressions file that was accidentally included. (412ab9f)

Copy link
Contributor

Choose a reason for hiding this comment

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

let's not do dependency updates in this PR and leave that for independent PRs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Reverted the Cargo.lock dependency updates to keep this PR focused only on the clippy fix. (412ab9f)

Copy link
Contributor Author

Copilot AI commented Jun 23, 2025

It would be nice to see a test case added to the wit file that has a function that has no returns

Added a test case for void return function to guest.wit: do-something: func(number: u32); with corresponding implementation. Verified the fix works correctly with this test case and passes clippy with -D clippy::unused_unit. (412ab9f)

Copilot AI requested a review from jsturtevant June 23, 2025 18:38
Copilot finished work on behalf of jsturtevant June 23, 2025 18:38
pub fn emit_hl_unmarshal_result(s: &mut State, id: Ident, rt: &etypes::Result) -> TokenStream {
match rt {
etypes::Result::Named(rs) if rs.is_empty() => quote! { () },
etypes::Result::Named(rs) if rs.is_empty() => TokenStream::new(),
Copy link
Member

Choose a reason for hiding this comment

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

I don't like this as a solution, because it changes the contract for this helper to something a lot less intuitive:

The resultant token stream will be an expression which typechecks at the Rust type ...

becomes

The resultant token stream will typecheck at the Rust type of the unnamed type of the result, or the empty stream if named results are used

which means that it can't generally be used to uniformly generate a return value. Right now, this expression is only used in the tail position of a function definition, so it works "by coincidence"---but this change makes the interface more brittle (e.g. if you wanted to refactor the macro to trace the return value, you would need special cases to not accidentally generate an empty let statement).

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.

Marcro fails clippy checks with specific wit that doesn't have a return value

3 participants