Allow aliases and C++ opaque types to be trivial.
This change allows aliases:
type Foo = bindgen::Bar;
and C++ opaque types:
type Foo;
to declare that they're 'trivial' in the sense that:
* They have trivial move constructors
* They have no destructors
and therefore may be passed and owned by value in Rust.
A subsequent commit will add C++ static assertions.
This commit is a BREAKING CHANGE as it requires existing
ExternTypes to gain a new associated type
diff --git a/syntax/check.rs b/syntax/check.rs
index 147984e..cfac236 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -338,6 +338,7 @@
|| cx.types.cxx.contains(ident)
&& !cx.types.structs.contains_key(ident)
&& !cx.types.enums.contains_key(ident)
+ && !cx.types.required_trivial_aliases.contains(ident)
|| cx.types.rust.contains(ident)
}
@@ -376,7 +377,11 @@
} else if cx.types.enums.contains_key(ident) {
"enum".to_owned()
} else if cx.types.cxx.contains(ident) {
- "C++ type".to_owned()
+ if cx.types.required_trivial_aliases.contains(ident) {
+ "trivial C++ type".to_owned()
+ } else {
+ "non-trivial C++ type".to_owned()
+ }
} else if cx.types.rust.contains(ident) {
"opaque Rust type".to_owned()
} else if Atom::from(ident) == Some(CxxString) {
diff --git a/syntax/types.rs b/syntax/types.rs
index 8a86a46..ff78268 100644
--- a/syntax/types.rs
+++ b/syntax/types.rs
@@ -14,6 +14,7 @@
pub rust: Set<&'a Ident>,
pub aliases: Map<&'a Ident, &'a TypeAlias>,
pub untrusted: Map<&'a Ident, &'a ExternType>,
+ pub required_trivial_aliases: Set<&'a Ident>,
}
impl<'a> Types<'a> {
@@ -135,6 +136,55 @@
}
}
+ // All these APIs may contain types passed by value. We need to ensure
+ // we check that this is permissible. We do this _after_ scanning all
+ // the APIs above, in case some function or struct references a type
+ // which is declared subsequently.
+ let mut required_trivial_aliases = Set::new();
+
+ fn insist_alias_types_are_trivial<'c>(
+ required_trivial_aliases: &mut Set<&'c Ident>,
+ aliases: &Map<&'c Ident, &'c TypeAlias>,
+ ty: &'c Type,
+ ) {
+ if let Type::Ident(ident) = ty {
+ if aliases.contains_key(ident) {
+ required_trivial_aliases.insert(ident);
+ }
+ }
+ }
+
+ for api in apis {
+ match api {
+ Api::Struct(strct) => {
+ for field in &strct.fields {
+ insist_alias_types_are_trivial(
+ &mut required_trivial_aliases,
+ &aliases,
+ &field.ty,
+ );
+ }
+ }
+ Api::CxxFunction(efn) | Api::RustFunction(efn) => {
+ for arg in &efn.args {
+ insist_alias_types_are_trivial(
+ &mut required_trivial_aliases,
+ &aliases,
+ &arg.ty,
+ );
+ }
+ if let Some(ret) = &efn.ret {
+ insist_alias_types_are_trivial(
+ &mut required_trivial_aliases,
+ &aliases,
+ &ret,
+ );
+ }
+ }
+ _ => {}
+ }
+ }
+
Types {
all,
structs,
@@ -143,6 +193,7 @@
rust,
aliases,
untrusted,
+ required_trivial_aliases,
}
}