From 05528e552752b6857a8ca7d1ea2fdb17fba8e98d Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 27 May 2026 14:05:12 -0600 Subject: [PATCH 1/2] C++: fix compile errors when lowering `result`, etc. Previously, the code generator got confused about when to use `wit::string` vs. `std::string_view` when lowering variants with string payloads, tuple-with-string payloads, etc. I'll admit my C++ skills are pretty out-of-date, so I'm not 100% confident I've got everything lined up correctly here, but it fixes the scenarios I've run into so far. Feedback from experts in modern C++ would be very welcome. --- crates/cpp/src/lib.rs | 23 ++++++---- tests/codegen/more-variants.wit | 75 +++++++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 9 deletions(-) create mode 100644 tests/codegen/more-variants.wit diff --git a/crates/cpp/src/lib.rs b/crates/cpp/src/lib.rs index 0348ff7f9..9edcdd1e5 100644 --- a/crates/cpp/src/lib.rs +++ b/crates/cpp/src/lib.rs @@ -3161,23 +3161,28 @@ impl<'a, 'b> Bindgen for FunctionBindgen<'a, 'b> { } let op0 = &operands[0]; - let flavor = if matches!(self.variant, AbiVariant::GuestImport) { - Flavor::BorrowedArgument - } else { - Flavor::InStruct - }; - let ty = self.r#gen.type_name(payload, &self.namespace, flavor); let is_function_param = self.params.iter().any(|p| p == op0); - let value_extract = if matches!(payload, Type::String) + let (flavor, value_extract) = if matches!(payload, Type::String) && matches!(self.variant, AbiVariant::GuestImport) && !is_function_param { // Import from struct/variant field: optional needs .get_view() - format!("(std::move({op0})).value().get_view()") + ( + Flavor::BorrowedArgument, + format!("(std::move({op0})).value().get_view()"), + ) } else { // Direct parameter, export, or non-string: just .value() - format!("(std::move({op0})).value()") + ( + if let (Type::String, AbiVariant::GuestImport) = (payload, self.variant) { + Flavor::BorrowedArgument + } else { + Flavor::InStruct + }, + format!("(std::move({op0})).value()"), + ) }; + let ty = self.r#gen.type_name(payload, &self.namespace, flavor); let bind_some = format!("{ty} {some_payload} = {value_extract};"); uwrite!( diff --git a/tests/codegen/more-variants.wit b/tests/codegen/more-variants.wit new file mode 100644 index 000000000..c3adf43de --- /dev/null +++ b/tests/codegen/more-variants.wit @@ -0,0 +1,75 @@ +package test:test; + +interface more-variants { + variant error { + connection-failed(string), + bad-parameter(string), + query-failed(query-error), + value-conversion-failed(string), + other(string) + } + + variant query-error { + text(string), + db-error(db-error), + } + + record db-error { + as-text: string, + severity: string, + code: string, + message: string, + detail: option, + extras: list>, + } + + variant db-value { + boolean(bool), + int8(s8), + int16(s16), + int32(s32), + int64(s64), + floating32(f32), + floating64(f64), + str(string), + binary(list), + date(tuple), + time(tuple), + datetime(tuple), + timestamp(s64), + uuid(string), + jsonb(list), + decimal(string), + range-int32(tuple>, option>>), + range-int64(tuple>, option>>), + range-decimal(tuple>, option>>), + array-int32(list>), + array-int64(list>), + array-decimal(list>), + array-str(list>), + interval(interval), + db-null, + } + + record interval { + micros: s64, + days: s32, + months: s32, + } + + type row = list; + + enum range-bound-kind { + inclusive, + exclusive, + } + + resource connection { + query: func(statement: string, params: list) -> result, error>; + } +} + +world test { + import more-variants; + export foo: func(); +} From 239b02ff4644d60b8a560a7966df313fcebd987e Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Wed, 27 May 2026 14:45:12 -0600 Subject: [PATCH 2/2] add `more-variants.wit-borrowed-duplicate` to `should_fail_verify` for Rust --- crates/test/src/rust.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/test/src/rust.rs b/crates/test/src/rust.rs index 5f016d841..fe492d60e 100644 --- a/crates/test/src/rust.rs +++ b/crates/test/src/rust.rs @@ -62,7 +62,8 @@ impl LanguageMethods for Rust { ) -> bool { // Currently there's a bug with this borrowing mode which means that // this variant does not pass. - if name == "wasi-http-borrowed-duplicate" { + if name == "wasi-http-borrowed-duplicate" || name == "more-variants.wit-borrowed-duplicate" + { return true; }