Skip to content

Commit a5d03a8

Browse files
authored
C#: Compilation failure if variant has same name as one of the cases. (#1535)
* If the variant case and variant name have the same c# names, then add an underscore to the case name * Add test for variant case with same name as variant * exclude known c++ failure
1 parent 1c6a7a5 commit a5d03a8

File tree

4 files changed

+32
-5
lines changed

4 files changed

+32
-5
lines changed

crates/csharp/src/function.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::csharp_ident::ToCSharpIdent;
2-
use crate::interface::{InterfaceGenerator, ParameterType};
2+
use crate::interface::{InterfaceGenerator, ParameterType, variant_new_func_name};
33
use crate::world_generator::CSharp;
44
use heck::ToUpperCamelCase;
55
use std::fmt::Write;
@@ -167,6 +167,7 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
167167
.blocks
168168
.drain(self.blocks.len() - cases.len()..)
169169
.collect::<Vec<_>>();
170+
let variant_name = self.interface_gen.type_name_with_qualifier(ty, false);
170171
let ty = self.interface_gen.type_name_with_qualifier(ty, true);
171172
let generics_position = ty.find('<');
172173
let lifted = self.locals.tmp("lifted");
@@ -198,7 +199,8 @@ impl<'a, 'b> FunctionBindgen<'a, 'b> {
198199
String::new()
199200
};
200201

201-
let method = case_name.to_csharp_ident_upper();
202+
let method =
203+
variant_new_func_name(&variant_name, &case_name.to_csharp_ident_upper());
202204

203205
let call = if let Some(position) = generics_position {
204206
let (ty, generics) = ty.split_at(position);

crates/csharp/src/interface.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1409,6 +1409,7 @@ impl<'a> CoreInterfaceGenerator<'a> for InterfaceGenerator<'a> {
14091409
.map(|case| {
14101410
let case_name = case.name.to_csharp_ident();
14111411
let tag = case.name.to_csharp_ident_upper();
1412+
let method_name = variant_new_func_name(&name, &tag);
14121413
let (parameter, argument) = if let Some(ty) = self.non_empty_type(case.ty.as_ref())
14131414
{
14141415
(
@@ -1420,7 +1421,7 @@ impl<'a> CoreInterfaceGenerator<'a> for InterfaceGenerator<'a> {
14201421
};
14211422

14221423
format!(
1423-
"{access} static {name} {tag}({parameter}) {{
1424+
"{access} static {name} {method_name}({parameter}) {{
14241425
return new {name}(Tags.{tag}, {argument});
14251426
}}
14261427
"
@@ -1571,6 +1572,15 @@ impl<'a> CoreInterfaceGenerator<'a> for InterfaceGenerator<'a> {
15711572
}
15721573
}
15731574

1575+
// Handles the tag being the same name as the variant, which would cause a method with the same name as the type in C# which is not valid.
1576+
pub fn variant_new_func_name(variant_name: &String, tag: &String) -> String {
1577+
if *tag == *variant_name {
1578+
format!("{tag}_") // Underscores are not valid in wit identifiers so this should be safe.
1579+
} else {
1580+
tag.clone()
1581+
}
1582+
}
1583+
15741584
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
15751585
pub(crate) enum ParameterType {
15761586
ABI,

crates/test/src/cpp.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,14 @@ impl LanguageMethods for Cpp {
4141

4242
fn should_fail_verify(
4343
&self,
44-
_name: &str,
44+
name: &str,
4545
config: &crate::config::WitConfig,
4646
_args: &[String],
4747
) -> bool {
48-
config.async_
48+
return match name {
49+
"issue1514-6.wit" => true,
50+
_ => false,
51+
} || config.async_;
4952
}
5053

5154
fn prepare(&self, runner: &mut Runner) -> anyhow::Result<()> {

tests/codegen/issue1514-6.wit

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package demo:poc;
2+
3+
interface i {
4+
variant v {
5+
v,
6+
}
7+
f: func(x: v);
8+
}
9+
10+
world w {
11+
export i;
12+
}

0 commit comments

Comments
 (0)