mirror of
https://github.com/topjohnwu/cxx.git
synced 2025-02-19 07:38:02 +00:00
Add ExternType derive for opaque Rust types
This commit is contained in:
parent
ecce017e14
commit
16e2620fe5
@ -52,7 +52,7 @@ fn sort_by_inner_namespace(apis: Vec<&Api>, depth: usize) -> NamespaceEntries {
|
||||
mod tests {
|
||||
use super::NamespaceEntries;
|
||||
use crate::syntax::namespace::Namespace;
|
||||
use crate::syntax::{Api, Doc, ExternType, Pair};
|
||||
use crate::syntax::{Api, Doc, ExternType, Lang, Pair};
|
||||
use proc_macro2::{Ident, Span};
|
||||
use std::iter::FromIterator;
|
||||
use syn::Token;
|
||||
@ -126,7 +126,9 @@ mod tests {
|
||||
fn make_api(ns: Option<&str>, ident: &str) -> Api {
|
||||
let ns = ns.map_or(Namespace::ROOT, |ns| syn::parse_str(ns).unwrap());
|
||||
Api::CxxType(ExternType {
|
||||
lang: Lang::Rust,
|
||||
doc: Doc::new(),
|
||||
derives: Vec::new(),
|
||||
type_token: Token![type](Span::call_site()),
|
||||
name: Pair::new(ns, Ident::new(ident, Span::call_site())),
|
||||
semi_token: Token![;](Span::call_site()),
|
||||
|
@ -16,6 +16,7 @@ pub fn expand_struct(strct: &Struct, actual_derives: &mut Option<TokenStream>) -
|
||||
Trait::Debug => expanded.extend(struct_debug(strct, span)),
|
||||
Trait::Default => expanded.extend(struct_default(strct, span)),
|
||||
Trait::Eq => traits.push(quote_spanned!(span=> ::std::cmp::Eq)),
|
||||
Trait::ExternType => unreachable!(),
|
||||
Trait::Hash => traits.push(quote_spanned!(span=> ::std::hash::Hash)),
|
||||
Trait::Ord => expanded.extend(struct_ord(strct, span)),
|
||||
Trait::PartialEq => traits.push(quote_spanned!(span=> ::std::cmp::PartialEq)),
|
||||
@ -57,6 +58,7 @@ pub fn expand_enum(enm: &Enum, actual_derives: &mut Option<TokenStream>) -> Toke
|
||||
traits.push(quote_spanned!(span=> ::std::cmp::Eq));
|
||||
has_eq = true;
|
||||
}
|
||||
Trait::ExternType => unreachable!(),
|
||||
Trait::Hash => traits.push(quote_spanned!(span=> ::std::hash::Hash)),
|
||||
Trait::Ord => expanded.extend(enum_ord(enm, span)),
|
||||
Trait::PartialEq => {
|
||||
|
@ -617,9 +617,24 @@ fn expand_rust_type_impl(ety: &ExternType) -> TokenStream {
|
||||
let span = ident.span();
|
||||
let unsafe_impl = quote_spanned!(ety.type_token.span=> unsafe impl);
|
||||
|
||||
quote_spanned! {span=>
|
||||
let mut impls = quote_spanned! {span=>
|
||||
#unsafe_impl ::cxx::private::RustType for #ident {}
|
||||
};
|
||||
|
||||
for derive in &ety.derives {
|
||||
if derive.what == Trait::ExternType {
|
||||
let type_id = type_id(&ety.name);
|
||||
let span = derive.span;
|
||||
impls.extend(quote_spanned! {span=>
|
||||
unsafe impl ::cxx::ExternType for #ident {
|
||||
type Id = #type_id;
|
||||
type Kind = ::cxx::kind::Opaque;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impls
|
||||
}
|
||||
|
||||
fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
|
||||
|
@ -232,6 +232,13 @@ fn check_api_struct(cx: &mut Check, strct: &Struct) {
|
||||
}
|
||||
}
|
||||
|
||||
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 @@ fn check_api_enum(cx: &mut Check, enm: &Enum) {
|
||||
}
|
||||
|
||||
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_enum(cx: &mut Check, enm: &Enum) {
|
||||
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),
|
||||
|
@ -1,4 +1,5 @@
|
||||
use proc_macro2::{Ident, Span};
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub struct Derive {
|
||||
@ -13,6 +14,7 @@ pub enum Trait {
|
||||
Debug,
|
||||
Default,
|
||||
Eq,
|
||||
ExternType,
|
||||
Hash,
|
||||
Ord,
|
||||
PartialEq,
|
||||
@ -27,6 +29,7 @@ impl Derive {
|
||||
"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 @@ impl AsRef<str> for Trait {
|
||||
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 AsRef<str> for Trait {
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -67,7 +67,9 @@ pub enum IncludeKind {
|
||||
}
|
||||
|
||||
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![;],
|
||||
|
@ -327,12 +327,14 @@ fn parse_extern_type(
|
||||
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 @@ fn parse_extern_type(
|
||||
Lang::Rust => Api::RustType,
|
||||
};
|
||||
api_type(ExternType {
|
||||
lang,
|
||||
doc,
|
||||
derives,
|
||||
type_token,
|
||||
name: Pair::new(namespace, ident),
|
||||
semi_token,
|
||||
|
Loading…
x
Reference in New Issue
Block a user