Add ExternType derive for opaque Rust types
diff --git a/syntax/check.rs b/syntax/check.rs
index 725105d..a60332d 100644
--- a/syntax/check.rs
+++ b/syntax/check.rs
@@ -232,6 +232,13 @@
}
}
+ for derive in &strct.derives {
+ if derive.what == Trait::ExternType {
+ let msg = format!("derive({}) on shared struct is not supported", derive);
+ cx.error(derive, msg);
+ }
+ }
+
for field in &strct.fields {
if let Type::Fn(_) = field.ty {
cx.error(
@@ -258,11 +265,9 @@
}
for derive in &enm.derives {
- if derive.what == Trait::Default {
- cx.error(
- derive,
- "derive(Default) on shared enums is not supported yet",
- );
+ if derive.what == Trait::Default || derive.what == Trait::ExternType {
+ let msg = format!("derive({}) on shared enum is not supported", derive);
+ cx.error(derive, msg);
}
}
}
@@ -270,6 +275,21 @@
fn check_api_type(cx: &mut Check, ety: &ExternType) {
check_reserved_name(cx, &ety.name.rust);
+ for derive in &ety.derives {
+ if derive.what == Trait::ExternType && ety.lang == Lang::Rust {
+ continue;
+ }
+ let lang = match ety.lang {
+ Lang::Rust => "Rust",
+ Lang::Cxx => "C++",
+ };
+ let msg = format!(
+ "derive({}) on opaque {} type is not supported yet",
+ derive, lang,
+ );
+ cx.error(derive, msg);
+ }
+
if let Some(reason) = cx.types.required_trivial.get(&ety.name.rust) {
let what = match reason {
TrivialReason::StructField(strct) => format!("a field of `{}`", strct.name.rust),
diff --git a/syntax/derive.rs b/syntax/derive.rs
index 1121211..96b3eea 100644
--- a/syntax/derive.rs
+++ b/syntax/derive.rs
@@ -1,4 +1,5 @@
use proc_macro2::{Ident, Span};
+use std::fmt::{self, Display};
#[derive(Copy, Clone)]
pub struct Derive {
@@ -13,6 +14,7 @@
Debug,
Default,
Eq,
+ ExternType,
Hash,
Ord,
PartialEq,
@@ -27,6 +29,7 @@
"Debug" => Trait::Debug,
"Default" => Trait::Default,
"Eq" => Trait::Eq,
+ "ExternType" => Trait::ExternType,
"Hash" => Trait::Hash,
"Ord" => Trait::Ord,
"PartialEq" => Trait::PartialEq,
@@ -52,6 +55,7 @@
Trait::Debug => "Debug",
Trait::Default => "Default",
Trait::Eq => "Eq",
+ Trait::ExternType => "ExternType",
Trait::Hash => "Hash",
Trait::Ord => "Ord",
Trait::PartialEq => "PartialEq",
@@ -60,6 +64,12 @@
}
}
+impl Display for Derive {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ formatter.write_str(self.what.as_ref())
+ }
+}
+
pub fn contains(derives: &[Derive], query: Trait) -> bool {
derives.iter().any(|derive| derive.what == query)
}
diff --git a/syntax/mod.rs b/syntax/mod.rs
index bd7efc0..e8288a9 100644
--- a/syntax/mod.rs
+++ b/syntax/mod.rs
@@ -67,7 +67,9 @@
}
pub struct ExternType {
+ pub lang: Lang,
pub doc: Doc,
+ pub derives: Vec<Derive>,
pub type_token: Token![type],
pub name: Pair,
pub semi_token: Token![;],
diff --git a/syntax/parse.rs b/syntax/parse.rs
index a009e19..e46cdb4 100644
--- a/syntax/parse.rs
+++ b/syntax/parse.rs
@@ -327,12 +327,14 @@
namespace: &Namespace,
) -> Api {
let mut doc = Doc::new();
+ let mut derives = Vec::new();
let mut namespace = namespace.clone();
attrs::parse(
cx,
&foreign_type.attrs,
attrs::Parser {
doc: Some(&mut doc),
+ derives: Some(&mut derives),
namespace: Some(&mut namespace),
..Default::default()
},
@@ -345,7 +347,9 @@
Lang::Rust => Api::RustType,
};
api_type(ExternType {
+ lang,
doc,
+ derives,
type_token,
name: Pair::new(namespace, ident),
semi_token,