diff --git a/src/generator.rs b/src/generator.rs index 2ee5ef65..bcb77581 100644 --- a/src/generator.rs +++ b/src/generator.rs @@ -376,11 +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)?; + source.push_str(", "); } source.push(')'); } 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(()) +}