From 7f97c3f863331c071736ecbec287710e07af3b6c Mon Sep 17 00:00:00 2001 From: Joel Dice Date: Thu, 5 Oct 2023 12:04:03 -0600 Subject: [PATCH] fix resource-own-in-other-interface test for C Signed-off-by: Joel Dice --- crates/c/src/lib.rs | 114 +++++++++++++++++++++++++---- crates/go/tests/codegen.rs | 1 + crates/teavm-java/tests/codegen.rs | 1 + 3 files changed, 102 insertions(+), 14 deletions(-) diff --git a/crates/c/src/lib.rs b/crates/c/src/lib.rs index 8113dc47c..24b2c7259 100644 --- a/crates/c/src/lib.rs +++ b/crates/c/src/lib.rs @@ -11,14 +11,14 @@ use wit_bindgen_core::{ }; use wit_component::StringEncoding; -#[derive(Default, Copy, Clone, PartialEq, Eq)] +#[derive(Default, Copy, Clone, PartialEq, Eq, Debug)] enum Direction { #[default] Import, Export, } -#[derive(Default)] +#[derive(Default, Debug)] struct ResourceInfo { direction: Direction, borrow: Option, @@ -650,22 +650,21 @@ impl C { resolve: &Resolve, handle: &Handle, handles: &HashMap<&Handle, TypeId>, + owner: TypeOwner, ) -> Option { - let mut target = match handle { - Handle::Borrow(target) => target, - Handle::Own(target) => target, - }; + let (Handle::Borrow(mut target) | Handle::Own(mut target)) = handle; loop { - if let TypeDefKind::Type(Type::Id(id)) = &resolve.types[*target].kind { + let def = &resolve.types[target]; + if let TypeDefKind::Type(Type::Id(id)) = &def.kind { let target_handle = match handle { Handle::Borrow(_) => Handle::Borrow(*id), Handle::Own(_) => Handle::Own(*id), }; - if let Some(ty) = handles.get(&target_handle) { + if let (true, Some(ty)) = (def.owner == owner, handles.get(&target_handle)) { break Some(*ty); } else { - target = id; + target = *id; } } else { break None; @@ -698,8 +697,8 @@ impl C { let prev = mem::take(&mut self.src.h_defs); self.src.h_defs("\ntypedef "); - let kind = &resolve.types[ty].kind; - match kind { + let def = &resolve.types[ty]; + match &def.kind { TypeDefKind::Type(_) | TypeDefKind::Flags(_) | TypeDefKind::Record(_) @@ -709,9 +708,16 @@ impl C { unreachable!() } TypeDefKind::Handle(handle) => { + let (Handle::Borrow(target) | Handle::Own(target)) = handle; + // If this is an alias to a handle _and_ a corresponding handle type exists for the target of the // alias, generate a typedef alias. Otherwise, generate an independent type. - if let Some(ty) = self.find_handle_alias_target(resolve, handle, handles) { + if let Some(ty) = self.find_handle_alias_target( + resolve, + handle, + handles, + resolve.types[*target].owner, + ) { let mut name = self.owner_namespace(resolve, ty); name.push_str("_"); push_ty_name( @@ -1039,8 +1045,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 +1062,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) => {};