Skip to content

impl UniquePtrTarget for T; #329

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions gen/src/write.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,9 @@ fn write_includes(out: &mut OutFile, types: &Types) {
_ => {}
}
}
if !types.unique_ptr_impls.is_empty() {
out.include.memory = true;
}
}

fn write_include_cxxbridge(out: &mut OutFile, apis: &[Api], types: &Types) {
Expand Down Expand Up @@ -1054,13 +1057,6 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
write_rust_vec_extern(out, inner);
}
}
} else if let Type::UniquePtr(ptr) = ty {
if let Type::Ident(inner) = &ptr.inner {
if Atom::from(inner).is_none() && !types.aliases.contains_key(inner) {
out.next_section();
write_unique_ptr(out, inner, types);
}
}
} else if let Type::CxxVector(ptr) = ty {
if let Type::Ident(inner) = &ptr.inner {
if Atom::from(inner).is_none() && !types.aliases.contains_key(inner) {
Expand All @@ -1070,6 +1066,12 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
}
}
}

for inner in types.unique_ptr_impls.into_iter() {
out.next_section();
write_unique_ptr(out, inner, types);
}

out.end_block("extern \"C\"");

out.begin_block("namespace rust");
Expand Down
12 changes: 5 additions & 7 deletions macro/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {

for api in apis {
match api {
Api::Include(_) | Api::RustType(_) => {}
Api::Include(_) | Api::RustType(_) | Api::Impl(_) => {}
Api::Struct(strct) => expanded.extend(expand_struct(strct)),
Api::Enum(enm) => expanded.extend(expand_enum(enm)),
Api::CxxType(ety) => {
Expand Down Expand Up @@ -74,12 +74,6 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
hidden.extend(expand_rust_vec(namespace, ident));
}
}
} else if let Type::UniquePtr(ptr) = ty {
if let Type::Ident(ident) = &ptr.inner {
if Atom::from(ident).is_none() && !types.aliases.contains_key(ident) {
expanded.extend(expand_unique_ptr(namespace, ident, types));
}
}
} else if let Type::CxxVector(ptr) = ty {
if let Type::Ident(ident) = &ptr.inner {
if Atom::from(ident).is_none() && !types.aliases.contains_key(ident) {
Expand All @@ -92,6 +86,10 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
}
}

for ident in types.unique_ptr_impls.into_iter() {
expanded.extend(expand_unique_ptr(namespace, ident, types));
}

// Work around https://github.com/rust-lang/rust/issues/67851.
if !hidden.is_empty() {
expanded.extend(quote! {
Expand Down
6 changes: 4 additions & 2 deletions syntax/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ use crate::syntax::namespace::Namespace;
use quote::quote;
use syn::parse::{Error, Parse, ParseStream, Result};
use syn::{
braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemStruct,
ItemUse, LitStr, Token, Visibility,
braced, token, Abi, Attribute, ForeignItem, Ident, Item as RustItem, ItemEnum, ItemImpl,
ItemStruct, ItemUse, LitStr, Token, Visibility,
};

pub struct Module {
Expand All @@ -22,6 +22,7 @@ pub enum Item {
Enum(ItemEnum),
ForeignMod(ItemForeignMod),
Use(ItemUse),
Impl(ItemImpl),
Other(RustItem),
}

Expand Down Expand Up @@ -99,6 +100,7 @@ impl Parse for Item {
brace_token: item.brace_token,
items: item.items,
})),
RustItem::Impl(item) => Ok(Item::Impl(ItemImpl { attrs, ..item })),
RustItem::Use(item) => Ok(Item::Use(ItemUse { attrs, ..item })),
other => Ok(Item::Other(other)),
}
Expand Down
2 changes: 1 addition & 1 deletion syntax/ident.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ pub(crate) fn check_all(cx: &mut Check, namespace: &Namespace, apis: &[Api]) {

for api in apis {
match api {
Api::Include(_) => {}
Api::Include(_) | Api::Impl(_) => {}
Api::Struct(strct) => {
check(cx, &strct.ident);
for field in &strct.fields {
Expand Down
8 changes: 8 additions & 0 deletions syntax/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub enum Api {
RustType(ExternType),
RustFunction(ExternFn),
TypeAlias(TypeAlias),
Impl(Impl),
}

pub struct ExternType {
Expand Down Expand Up @@ -87,6 +88,13 @@ pub struct TypeAlias {
pub semi_token: Token![;],
}

pub struct Impl {
pub impl_token: Token![impl],
pub trait_ident: Ident,
pub for_token: Token![for],
pub ident: Ident,
}

pub struct Signature {
pub unsafety: Option<Token![unsafe]>,
pub fn_token: Token![fn],
Expand Down
54 changes: 50 additions & 4 deletions syntax/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,17 @@ use crate::syntax::file::{Item, ItemForeignMod};
use crate::syntax::report::Errors;
use crate::syntax::Atom::*;
use crate::syntax::{
attrs, error, Api, Doc, Enum, ExternFn, ExternType, Lang, Receiver, Ref, Signature, Slice,
Struct, Ty1, Type, TypeAlias, Var, Variant,
attrs, error, Api, Doc, Enum, ExternFn, ExternType, Impl, Lang, Receiver, Ref, Signature,
Slice, Struct, Ty1, Type, TypeAlias, Var, Variant,
};
use proc_macro2::{TokenStream, TokenTree};
use quote::{format_ident, quote, quote_spanned};
use syn::parse::{ParseStream, Parser};
use syn::punctuated::Punctuated;
use syn::{
Abi, Attribute, Error, Fields, FnArg, ForeignItem, ForeignItemFn, ForeignItemType,
GenericArgument, Ident, ItemEnum, ItemStruct, LitStr, Pat, PathArguments, Result, ReturnType,
Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
GenericArgument, Ident, ItemEnum, ItemImpl, ItemStruct, LitStr, Pat, PathArguments, Result,
ReturnType, Token, Type as RustType, TypeBareFn, TypePath, TypeReference, TypeSlice,
};

pub mod kw {
Expand All @@ -34,6 +34,7 @@ pub fn parse_items(cx: &mut Errors, items: Vec<Item>, trusted: bool) -> Vec<Api>
},
Item::ForeignMod(foreign_mod) => parse_foreign_mod(cx, foreign_mod, &mut apis, trusted),
Item::Use(item) => cx.error(item, error::USE_NOT_ALLOWED),
Item::Impl(item) => parse_impl(cx, item, &mut apis),
Item::Other(item) => cx.error(item, "unsupported item"),
}
}
Expand Down Expand Up @@ -621,3 +622,48 @@ fn parse_return_type(
ty => Ok(Some(ty)),
}
}

fn parse_impl(cx: &mut Errors, imp: ItemImpl, api: &mut Vec<Api>) {
// At present we only support impl UniquePtrTarget for <ty>;
if !imp.items.is_empty() {
cx.error(imp, "impl must be empty");
return;
}
match &imp.trait_ {
None => cx.error(imp, "impl must be for a trait"),
Some((_, ty_path, for_token)) => {
let ident = ty_path.get_ident();
match ident {
None => {
cx.error(imp, "path incomplete");
return;
}
Some(trait_ident) if trait_ident.to_string() == "UniquePtrTarget" => {
let ty = parse_type(&imp.self_ty);
match ty {
Err(_) => {
cx.error(imp, "unable to parse type");
return;
}
Ok(ty) => match ty {
Type::Ident(ty) => {
api.push(Api::Impl(Impl {
for_token: for_token.clone(),
trait_ident: trait_ident.clone(),
impl_token: imp.impl_token,
ident: ty,
}));
}
_ => cx
.error(imp, "can only impl UniquePtrTarget for a plain identifier"),
},
}
}
Some(_) => cx.error(
imp,
"only supported trait which can be implemented is UniquePtrTarget",
),
}
}
}
}
4 changes: 4 additions & 0 deletions syntax/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ where
pub fn contains(&self, value: &T) -> bool {
self.set.contains(value)
}

pub fn is_empty(&self) -> bool {
self.set.is_empty()
}
}

impl<'s, 'a, T> IntoIterator for &'s OrderedSet<&'a T> {
Expand Down
16 changes: 16 additions & 0 deletions syntax/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct Types<'a> {
pub aliases: Map<&'a Ident, &'a TypeAlias>,
pub untrusted: Map<&'a Ident, &'a ExternType>,
pub required_trivial: Map<&'a Ident, TrivialReason<'a>>,
pub unique_ptr_impls: Set<&'a Ident>,
}

impl<'a> Types<'a> {
Expand All @@ -26,6 +27,7 @@ impl<'a> Types<'a> {
let mut rust = Set::new();
let mut aliases = Map::new();
let mut untrusted = Map::new();
let mut unique_ptr_impls = Set::new();

fn visit<'a>(all: &mut Set<&'a Type>, ty: &'a Type) {
all.insert(ty);
Expand Down Expand Up @@ -133,6 +135,9 @@ impl<'a> Types<'a> {
cxx.insert(ident);
aliases.insert(ident, alias);
}
Api::Impl(imp) => {
unique_ptr_impls.insert(&imp.ident);
}
}
}

Expand Down Expand Up @@ -170,6 +175,16 @@ impl<'a> Types<'a> {
}
}

for ty in &all {
if let Type::UniquePtr(ptr) = ty {
if let Type::Ident(ident) = &ptr.inner {
if Atom::from(ident).is_none() && !aliases.contains_key(ident) {
unique_ptr_impls.insert(ident);
}
}
}
}

Types {
all,
structs,
Expand All @@ -179,6 +194,7 @@ impl<'a> Types<'a> {
aliases,
untrusted,
required_trivial,
unique_ptr_impls,
}
}

Expand Down