From aff7b30a5c7a38ba609eaf2a8c6567b7193c0074 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Wed, 22 Jun 2022 02:36:09 +0000 Subject: [PATCH] Use new `Type`-based resolution to decide if a container is transparent We also assert that we were able to resolve paths inside containers as we shouldn't be deciding if a container is transparent without all the context. --- c-bindings-gen/src/types.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/c-bindings-gen/src/types.rs b/c-bindings-gen/src/types.rs index 8b9606d..497556d 100644 --- a/c-bindings-gen/src/types.rs +++ b/c-bindings-gen/src/types.rs @@ -1339,14 +1339,27 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { "crate::c_types" } + /// This should just be a closure, but doing so gets an error like + /// error: reached the recursion limit while instantiating `types::TypeResolver::is_transpar...c/types.rs:1358:104: 1358:110]>>` + /// which implies the concrete function instantiation of `is_transparent_container` ends up + /// being recursive. + fn deref_type<'one, 'b: 'one> (obj: &'one &'b syn::Type) -> &'b syn::Type { *obj } + /// Returns true if the path containing the given args is a "transparent" container, ie an /// Option or a container which does not require a generated continer class. fn is_transparent_container<'i, I: Iterator>(&self, full_path: &str, _is_ref: bool, mut args: I, generics: Option<&GenericTypes>) -> bool { if full_path == "Option" { let inner = args.next().unwrap(); assert!(args.next().is_none()); - match inner { - syn::Type::Reference(_) => true, + match generics.resolve_type(inner) { + syn::Type::Reference(r) => { + let elem = &*r.elem; + match elem { + syn::Type::Path(_) => + self.is_transparent_container(full_path, true, [elem].iter().map(Self::deref_type), generics), + _ => true, + } + }, syn::Type::Array(a) => { if let syn::Expr::Lit(l) = &a.len { if let syn::Lit::Int(i) = &l.lit { @@ -1368,7 +1381,7 @@ impl<'a, 'c: 'a> TypeResolver<'a, 'c> { if self.c_type_has_inner_from_path(&resolved) { return true; } if self.is_primitive(&resolved) { return false; } if self.c_type_from_path(&resolved, false, false).is_some() { true } else { false } - } else { true } + } else { unimplemented!(); } }, syn::Type::Tuple(_) => false, _ => unimplemented!(), -- 2.30.2