Improve POD detection for structs with POD fields
diff --git a/syntax/mod.rs b/syntax/mod.rs
index 3b5b4d7..31c88c9 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -15,6 +15,7 @@
mod names;
pub mod namespace;
mod parse;
+mod pod;
pub mod qualified;
pub mod report;
pub mod set;
diff --git a/syntax/pod.rs b/syntax/pod.rs
new file mode 100644
index 0000000..d808a99
--- /dev/null
+++ b/syntax/pod.rs
@@ -0,0 +1,35 @@
+use crate::syntax::atom::Atom::{self, *};
+use crate::syntax::{derive, Trait, Type, Types};
+
+impl<'a> Types<'a> {
+ pub fn is_guaranteed_pod(&self, ty: &Type) -> bool {
+ match ty {
+ Type::Ident(ident) => {
+ let ident = &ident.rust;
+ if let Some(atom) = Atom::from(ident) {
+ match atom {
+ Bool | Char | U8 | U16 | U32 | U64 | Usize | I8 | I16 | I32 | I64
+ | Isize | F32 | F64 => true,
+ CxxString | RustString => false,
+ }
+ } else if let Some(strct) = self.structs.get(ident) {
+ derive::contains(&strct.derives, Trait::Copy)
+ || strct
+ .fields
+ .iter()
+ .all(|field| self.is_guaranteed_pod(&field.ty))
+ } else {
+ self.enums.contains_key(ident)
+ }
+ }
+ Type::RustBox(_)
+ | Type::RustVec(_)
+ | Type::UniquePtr(_)
+ | Type::SharedPtr(_)
+ | Type::CxxVector(_)
+ | Type::Void(_) => false,
+ Type::Ref(_) | Type::Str(_) | Type::Fn(_) | Type::SliceRef(_) => true,
+ Type::Array(array) => self.is_guaranteed_pod(&array.inner),
+ }
+ }
+}
diff --git a/syntax/types.rs b/syntax/types.rs
index 72216b3..9652eb3 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -1,10 +1,8 @@
-use crate::syntax::atom::Atom::{self, *};
use crate::syntax::improper::ImproperCtype;
use crate::syntax::report::Errors;
use crate::syntax::set::{OrderedSet as Set, UnorderedSet};
use crate::syntax::{
- derive, toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, RustName, Struct, Trait, Type,
- TypeAlias,
+ toposort, Api, Enum, ExternFn, ExternType, Impl, Pair, RustName, Struct, Type, TypeAlias,
};
use proc_macro2::Ident;
use quote::ToTokens;
@@ -261,22 +259,12 @@
pub fn needs_indirect_abi(&self, ty: &Type) -> bool {
match ty {
- Type::Ident(ident) => {
- if let Some(strct) = self.structs.get(&ident.rust) {
- !self.is_pod(strct)
- } else {
- Atom::from(&ident.rust) == Some(RustString)
- }
- }
- Type::SharedPtr(_) | Type::RustVec(_) | Type::Array(_) => true,
- _ => false,
+ Type::RustBox(_) | Type::UniquePtr(_) => false,
+ Type::Array(_) => true,
+ _ => !self.is_guaranteed_pod(ty),
}
}
- pub fn is_pod(&self, strct: &Struct) -> bool {
- derive::contains(&strct.derives, Trait::Copy)
- }
-
// Types that trigger rustc's default #[warn(improper_ctypes)] lint, even if
// they may be otherwise unproblematic to mention in an extern signature.
// For example in a signature like `extern "C" fn(*const String)`, rustc