diff --git a/crates/c/src/lib.rs b/crates/c/src/lib.rs index 8113dc47c..b0809caa0 100644 --- a/crates/c/src/lib.rs +++ b/crates/c/src/lib.rs @@ -1039,8 +1039,7 @@ impl C { } _ => {} } - self.public_anonymous_types.insert(*id); - self.private_anonymous_types.remove(id); + self.visit_anonymous_types(resolve, &Type::Id(*id)); dst.push_str(&ns); dst.push_str("_"); push_ty_name( @@ -1057,6 +1056,87 @@ impl C { } } } + + fn visit_anonymous_types(&mut self, resolve: &Resolve, ty: &Type) { + match ty { + Type::String => { + self.needs_string = true; + } + Type::Id(id) => { + let ty = &resolve.types[*id]; + if ty.name.is_none() { + match &ty.kind { + TypeDefKind::Type(_) => {} + TypeDefKind::Handle(Handle::Borrow(resource)) + if matches!( + self.resources + .get(&dealias(resolve, *resource)) + .map(|info| &info.direction), + Some(Direction::Export) + ) => {} + _ => { + self.public_anonymous_types.insert(*id); + self.private_anonymous_types.remove(id); + } + } + } + + match &ty.kind { + TypeDefKind::Type(t) => self.visit_anonymous_types(resolve, t), + TypeDefKind::Record(r) => { + for field in &r.fields { + self.visit_anonymous_types(resolve, &field.ty); + } + } + TypeDefKind::Resource + | TypeDefKind::Handle(_) + | TypeDefKind::Flags(_) + | TypeDefKind::Enum(_) => {} + TypeDefKind::Variant(v) => { + for case in &v.cases { + if let Some(ty) = &case.ty { + self.visit_anonymous_types(resolve, ty); + } + } + } + TypeDefKind::Tuple(t) => { + for ty in &t.types { + self.visit_anonymous_types(resolve, ty); + } + } + TypeDefKind::Option(ty) => { + self.visit_anonymous_types(resolve, ty); + } + TypeDefKind::Result(r) => { + if let Some(ty) = &r.ok { + self.visit_anonymous_types(resolve, ty); + } + if let Some(ty) = &r.err { + self.visit_anonymous_types(resolve, ty); + } + } + TypeDefKind::List(ty) => { + self.visit_anonymous_types(resolve, ty); + } + TypeDefKind::Future(ty) => { + if let Some(ty) = ty { + self.visit_anonymous_types(resolve, ty); + } + } + TypeDefKind::Stream(s) => { + if let Some(ty) = &s.element { + self.visit_anonymous_types(resolve, ty); + } + if let Some(ty) = &s.end { + self.visit_anonymous_types(resolve, ty); + } + } + TypeDefKind::Unknown => unreachable!(), + } + } + _ => {} + } + } } pub fn push_ty_name( diff --git a/crates/go/tests/codegen.rs b/crates/go/tests/codegen.rs index c9f0fe56e..27f927191 100644 --- a/crates/go/tests/codegen.rs +++ b/crates/go/tests/codegen.rs @@ -17,6 +17,7 @@ macro_rules! codegen_test { (resource_local_alias_borrow_import $name:tt $test:tt) => {}; (resource_borrow_in_record $name:tt $test:tt) => {}; (resource_borrow_in_record_export $name:tt $test:tt) => {}; + (resource_own_in_other_interface $name:tt $test:tt) => {}; (resources_in_aggregates $name:tt $test:tt) => {}; (issue668 $name:tt $test:tt) => {}; diff --git a/crates/teavm-java/tests/codegen.rs b/crates/teavm-java/tests/codegen.rs index 480683710..0362d5263 100644 --- a/crates/teavm-java/tests/codegen.rs +++ b/crates/teavm-java/tests/codegen.rs @@ -15,6 +15,7 @@ macro_rules! codegen_test { (resource_local_alias_borrow_import $name:tt $test:tt) => {}; (resource_borrow_in_record $name:tt $test:tt) => {}; (resource_borrow_in_record_export $name:tt $test:tt) => {}; + (resource_own_in_other_interface $name:tt $test:tt) => {}; (same_names5 $name:tt $test:tt) => {}; (resources_in_aggregates $name:tt $test:tt) => {}; (issue668 $name:tt $test:tt) => {};