Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 14 additions & 9 deletions crates/cpp/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<wit::string> 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!(
Expand Down
3 changes: 2 additions & 1 deletion crates/test/src/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
75 changes: 75 additions & 0 deletions tests/codegen/more-variants.wit
Original file line number Diff line number Diff line change
@@ -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<string>,
extras: list<tuple<string, string>>,
}

variant db-value {
boolean(bool),
int8(s8),
int16(s16),
int32(s32),
int64(s64),
floating32(f32),
floating64(f64),
str(string),
binary(list<u8>),
date(tuple<s32, u8, u8>),
time(tuple<u8, u8, u8, u32>),
datetime(tuple<s32, u8, u8, u8, u8, u8, u32>),
timestamp(s64),
uuid(string),
jsonb(list<u8>),
decimal(string),
range-int32(tuple<option<tuple<s32, range-bound-kind>>, option<tuple<s32, range-bound-kind>>>),
range-int64(tuple<option<tuple<s64, range-bound-kind>>, option<tuple<s64, range-bound-kind>>>),
range-decimal(tuple<option<tuple<string, range-bound-kind>>, option<tuple<string, range-bound-kind>>>),
array-int32(list<option<s32>>),
array-int64(list<option<s64>>),
array-decimal(list<option<string>>),
array-str(list<option<string>>),
interval(interval),
db-null,
}

record interval {
micros: s64,
days: s32,
months: s32,
}

type row = list<db-value>;

enum range-bound-kind {
inclusive,
exclusive,
}

resource connection {
query: func(statement: string, params: list<db-value>) -> result<list<row>, error>;
}
}

world test {
import more-variants;
export foo: func();
}
Loading