From d970158c4bdfd36898d19ce1db9cbd44b80350b4 Mon Sep 17 00:00:00 2001 From: colin Date: Tue, 3 Jun 2025 13:37:23 -0400 Subject: [PATCH 1/2] Fix single-element tuple generation in WIT bindings Single-element tuples in Rust require a trailing comma to distinguish them from parentheses used for grouping. The generator was producing (String) instead of (String,) for single-element tuples, causing compilation errors. This fix adds logic to append a comma when generating single-element tuples in the TypeDefKind::Tuple case. --- src/generator.rs | 3 +++ tests/new.rs | 56 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/src/generator.rs b/src/generator.rs index 2ee5ef65..6f468246 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -382,6 +382,9 @@ impl<'a> UnimplementedFunction<'a> { } self.print_type(ty, trie, source)?; } + if t.types.len() == 1 { + source.push(','); + } source.push(')'); } TypeDefKind::Record(_) => { diff --git a/tests/new.rs b/tests/new.rs index 7017aeae..3d025b78 100644 --- a/tests/new.rs +++ b/tests/new.rs @@ -305,3 +305,59 @@ fn it_supports_the_proxy_option() -> Result<()> { Ok(()) } + +#[tokio::test(flavor = "multi_thread", worker_threads = 1)] +async fn test_single_element_tuple_generation() -> Result<()> { + let (server, config, _task) = spawn_server(["test"]).await?; + + publish_wit( + config, + "test:tuples", + "1.0.0", + r#"package test:tuples@1.0.0; + +world test-world { + export test-interface: interface { + test-function: func(params: tuple) -> result, string>; + another-function: func(single: tuple) -> tuple>; + } +} +"#, + ) + .await?; + + let project = server.project("test-tuple", true, ["--target", "test:tuples@1.0.0"])?; + + project + .cargo_component(["build"]) + .assert() + .stderr(contains( + "Finished `dev` profile [unoptimized + debuginfo] target(s)", + )) + .success(); + + let lib_rs = fs::read_to_string(project.root().join("src/lib.rs"))?; + + assert!( + lib_rs.contains("params: (String,)"), + "Single-element tuple parameter should have trailing comma. Generated code:\n{}", + lib_rs + ); + assert!( + lib_rs.contains("Result<(u32,), String>") || lib_rs.contains("-> (u32,)"), + "Single-element tuple return should have trailing comma. Generated code:\n{}", + lib_rs + ); + assert!( + lib_rs.contains("single: (bool,)"), + "Single-element tuple parameter should have trailing comma. Generated code:\n{}", + lib_rs + ); + assert!( + lib_rs.contains("-> (Vec,)"), + "Single-element tuple return should have trailing comma. Generated code:\n{}", + lib_rs + ); + + Ok(()) +} From d85a54705c0305d0d4d066084645cf8ee7c4e196 Mon Sep 17 00:00:00 2001 From: colin Date: Tue, 3 Jun 2025 13:56:48 -0400 Subject: [PATCH 2/2] Simplify tuple generation logic per reviewer feedback --- src/generator.rs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/generator.rs b/src/generator.rs index 6f468246..bcb77581 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -376,14 +376,9 @@ impl<'a> UnimplementedFunction<'a> { } TypeDefKind::Tuple(t) => { source.push('('); - for (i, ty) in t.types.iter().enumerate() { - if i > 0 { - source.push_str(", "); - } + for ty in t.types.iter() { self.print_type(ty, trie, source)?; - } - if t.types.len() == 1 { - source.push(','); + source.push_str(", "); } source.push(')'); }