Skip to content

Parameterize shim trait impl blocks over lifetimes #635

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

Merged
merged 2 commits into from
Jan 2, 2021
Merged
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
82 changes: 59 additions & 23 deletions macro/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1048,27 +1048,33 @@ fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
let local_dealloc = format_ident!("{}dealloc", local_prefix);
let local_drop = format_ident!("{}drop", local_prefix);

let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
(&imp.impl_generics, &imp.ty_generics)
} else {
(resolve.generics, resolve.generics)
};

let begin_span =
explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
let unsafe_token = format_ident!("unsafe", span = begin_span);

quote_spanned! {end_span=>
#[doc(hidden)]
#unsafe_token impl ::cxx::private::ImplBox for #ident {}
#unsafe_token impl #impl_generics ::cxx::private::ImplBox for #ident #ty_generics {}
#[doc(hidden)]
#[export_name = #link_alloc]
unsafe extern "C" fn #local_alloc() -> *mut ::std::mem::MaybeUninit<#ident> {
unsafe extern "C" fn #local_alloc #impl_generics() -> *mut ::std::mem::MaybeUninit<#ident #ty_generics> {
::std::boxed::Box::into_raw(::std::boxed::Box::new(::std::mem::MaybeUninit::uninit()))
}
#[doc(hidden)]
#[export_name = #link_dealloc]
unsafe extern "C" fn #local_dealloc(ptr: *mut ::std::mem::MaybeUninit<#ident>) {
unsafe extern "C" fn #local_dealloc #impl_generics(ptr: *mut ::std::mem::MaybeUninit<#ident #ty_generics>) {
::std::boxed::Box::from_raw(ptr);
}
#[doc(hidden)]
#[export_name = #link_drop]
unsafe extern "C" fn #local_drop(this: *mut ::std::boxed::Box<#ident>) {
unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::std::boxed::Box<#ident #ty_generics>) {
::std::ptr::drop_in_place(this);
}
}
Expand All @@ -1094,47 +1100,53 @@ fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) ->
let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
let local_set_len = format_ident!("{}set_len", local_prefix);

let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
(&imp.impl_generics, &imp.ty_generics)
} else {
(resolve.generics, resolve.generics)
};

let begin_span =
explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
let unsafe_token = format_ident!("unsafe", span = begin_span);

quote_spanned! {end_span=>
#[doc(hidden)]
#unsafe_token impl ::cxx::private::ImplVec for #elem {}
#unsafe_token impl #impl_generics ::cxx::private::ImplVec for #elem #ty_generics {}
#[doc(hidden)]
#[export_name = #link_new]
unsafe extern "C" fn #local_new(this: *mut ::cxx::private::RustVec<#elem>) {
unsafe extern "C" fn #local_new #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
::std::ptr::write(this, ::cxx::private::RustVec::new());
}
#[doc(hidden)]
#[export_name = #link_drop]
unsafe extern "C" fn #local_drop(this: *mut ::cxx::private::RustVec<#elem>) {
unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
::std::ptr::drop_in_place(this);
}
#[doc(hidden)]
#[export_name = #link_len]
unsafe extern "C" fn #local_len(this: *const ::cxx::private::RustVec<#elem>) -> usize {
unsafe extern "C" fn #local_len #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
(*this).len()
}
#[doc(hidden)]
#[export_name = #link_capacity]
unsafe extern "C" fn #local_capacity(this: *const ::cxx::private::RustVec<#elem>) -> usize {
unsafe extern "C" fn #local_capacity #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
(*this).capacity()
}
#[doc(hidden)]
#[export_name = #link_data]
unsafe extern "C" fn #local_data(this: *const ::cxx::private::RustVec<#elem>) -> *const #elem {
unsafe extern "C" fn #local_data #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> *const #elem #ty_generics {
(*this).as_ptr()
}
#[doc(hidden)]
#[export_name = #link_reserve_total]
unsafe extern "C" fn #local_reserve_total(this: *mut ::cxx::private::RustVec<#elem>, cap: usize) {
unsafe extern "C" fn #local_reserve_total #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, cap: usize) {
(*this).reserve_total(cap);
}
#[doc(hidden)]
#[export_name = #link_set_len]
unsafe extern "C" fn #local_set_len(this: *mut ::cxx::private::RustVec<#elem>, len: usize) {
unsafe extern "C" fn #local_set_len #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
(*this).set_len(len);
}
}
Expand All @@ -1151,6 +1163,12 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
let link_release = format!("{}release", prefix);
let link_drop = format!("{}drop", prefix);

let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
(&imp.impl_generics, &imp.ty_generics)
} else {
(resolve.generics, resolve.generics)
};

let can_construct_from_value = types.structs.contains_key(ident)
|| types.enums.contains_key(ident)
|| types.aliases.contains_key(ident);
Expand All @@ -1162,7 +1180,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
fn __uninit(this: *mut *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;
}
let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
unsafe { __uninit(&mut repr).cast::<#ident>().write(value) }
unsafe { __uninit(&mut repr).cast::<#ident #ty_generics>().write(value) }
repr
}
})
Expand All @@ -1176,7 +1194,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
let unsafe_token = format_ident!("unsafe", span = begin_span);

quote_spanned! {end_span=>
#unsafe_token impl ::cxx::private::UniquePtrTarget for #ident {
#unsafe_token impl #impl_generics ::cxx::private::UniquePtrTarget for #ident #ty_generics {
const __NAME: &'static dyn ::std::fmt::Display = &#name;
fn __null() -> *mut ::std::ffi::c_void {
extern "C" {
Expand Down Expand Up @@ -1232,6 +1250,12 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
let link_get = format!("{}get", prefix);
let link_drop = format!("{}drop", prefix);

let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
(&imp.impl_generics, &imp.ty_generics)
} else {
(resolve.generics, resolve.generics)
};

let can_construct_from_value = types.structs.contains_key(ident)
|| types.enums.contains_key(ident)
|| types.aliases.contains_key(ident);
Expand All @@ -1242,7 +1266,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
#[link_name = #link_uninit]
fn __uninit(new: *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;
}
__uninit(new).cast::<#ident>().write(value);
__uninit(new).cast::<#ident #ty_generics>().write(value);
}
})
} else {
Expand All @@ -1255,7 +1279,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
let unsafe_token = format_ident!("unsafe", span = begin_span);

quote_spanned! {end_span=>
#unsafe_token impl ::cxx::private::SharedPtrTarget for #ident {
#unsafe_token impl #impl_generics ::cxx::private::SharedPtrTarget for #ident #ty_generics {
const __NAME: &'static dyn ::std::fmt::Display = &#name;
unsafe fn __null(new: *mut ::std::ffi::c_void) {
extern "C" {
Expand Down Expand Up @@ -1300,13 +1324,19 @@ fn expand_weak_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
let link_upgrade = format!("{}upgrade", prefix);
let link_drop = format!("{}drop", prefix);

let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
(&imp.impl_generics, &imp.ty_generics)
} else {
(resolve.generics, resolve.generics)
};

let begin_span =
explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
let unsafe_token = format_ident!("unsafe", span = begin_span);

quote_spanned! {end_span=>
#unsafe_token impl ::cxx::private::WeakPtrTarget for #ident {
#unsafe_token impl #impl_generics ::cxx::private::WeakPtrTarget for #ident #ty_generics {
const __NAME: &'static dyn ::std::fmt::Display = &#name;
unsafe fn __null(new: *mut ::std::ffi::c_void) {
extern "C" {
Expand Down Expand Up @@ -1363,25 +1393,31 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types)
let link_unique_ptr_release = format!("{}release", unique_ptr_prefix);
let link_unique_ptr_drop = format!("{}drop", unique_ptr_prefix);

let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
(&imp.impl_generics, &imp.ty_generics)
} else {
(resolve.generics, resolve.generics)
};

let begin_span =
explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
let unsafe_token = format_ident!("unsafe", span = begin_span);

quote_spanned! {end_span=>
#unsafe_token impl ::cxx::private::VectorElement for #elem {
#unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics {
const __NAME: &'static dyn ::std::fmt::Display = &#name;
fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
extern "C" {
#[link_name = #link_size]
fn __vector_size(_: &::cxx::CxxVector<#elem>) -> usize;
fn __vector_size #impl_generics(_: &::cxx::CxxVector<#elem #ty_generics>) -> usize;
}
unsafe { __vector_size(v) }
}
unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
extern "C" {
#[link_name = #link_get_unchecked]
fn __get_unchecked(_: *mut ::cxx::CxxVector<#elem>, _: usize) -> *mut #elem;
fn __get_unchecked #impl_generics(_: *mut ::cxx::CxxVector<#elem #ty_generics>, _: usize) -> *mut #elem #ty_generics;
}
__get_unchecked(v, pos)
}
Expand All @@ -1397,7 +1433,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types)
unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> *mut ::std::ffi::c_void {
extern "C" {
#[link_name = #link_unique_ptr_raw]
fn __unique_ptr_raw(this: *mut *mut ::std::ffi::c_void, raw: *mut ::cxx::CxxVector<#elem>);
fn __unique_ptr_raw #impl_generics(this: *mut *mut ::std::ffi::c_void, raw: *mut ::cxx::CxxVector<#elem #ty_generics>);
}
let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
__unique_ptr_raw(&mut repr, raw);
Expand All @@ -1406,14 +1442,14 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types)
unsafe fn __unique_ptr_get(repr: *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<Self> {
extern "C" {
#[link_name = #link_unique_ptr_get]
fn __unique_ptr_get(this: *const *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<#elem>;
fn __unique_ptr_get #impl_generics(this: *const *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<#elem #ty_generics>;
}
__unique_ptr_get(&repr)
}
unsafe fn __unique_ptr_release(mut repr: *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<Self> {
extern "C" {
#[link_name = #link_unique_ptr_release]
fn __unique_ptr_release(this: *mut *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<#elem>;
fn __unique_ptr_release #impl_generics(this: *mut *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<#elem #ty_generics>;
}
__unique_ptr_release(&mut repr)
}
Expand Down
4 changes: 3 additions & 1 deletion syntax/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,13 +141,15 @@ pub struct TypeAlias {

pub struct Impl {
pub impl_token: Token![impl],
pub generics: Lifetimes,
pub impl_generics: Lifetimes,
pub negative: bool,
pub ty: Type,
pub ty_generics: Lifetimes,
pub brace_token: Brace,
pub negative_token: Option<Token![!]>,
}

#[derive(Clone, Default)]
pub struct Lifetimes {
pub lt_token: Option<Token![<]>,
pub lifetimes: Punctuated<Lifetime, Token![,]>,
Expand Down
32 changes: 26 additions & 6 deletions syntax/parse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -868,7 +868,7 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
"where-clause on an impl is not supported yet",
));
}
let mut generics = Lifetimes {
let mut impl_generics = Lifetimes {
lt_token: imp.generics.lt_token,
lifetimes: Punctuated::new(),
gt_token: imp.generics.gt_token,
Expand All @@ -877,13 +877,13 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
let (param, punct) = pair.into_tuple();
match param {
GenericParam::Lifetime(def) if def.bounds.is_empty() => {
generics.lifetimes.push_value(def.lifetime);
impl_generics.lifetimes.push_value(def.lifetime);
if let Some(punct) = punct {
generics.lifetimes.push_punct(punct);
impl_generics.lifetimes.push_punct(punct);
}
}
_ => {
let span = quote!(#impl_token #generics);
let span = quote!(#impl_token #impl_generics);
return Err(Error::new_spanned(
span,
"generic parameter on an impl is not supported yet",
Expand All @@ -907,15 +907,35 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
}
}

let negative = negative_token.is_some();
let ty = parse_type(&self_ty)?;
let ty_generics = match &ty {
Type::RustBox(ty)
| Type::RustVec(ty)
| Type::UniquePtr(ty)
| Type::SharedPtr(ty)
| Type::WeakPtr(ty)
| Type::CxxVector(ty) => match &ty.inner {
Type::Ident(ident) => ident.generics.clone(),
_ => Lifetimes::default(),
},
Type::Ident(_)
| Type::Ref(_)
| Type::Str(_)
| Type::Fn(_)
| Type::Void(_)
| Type::SliceRef(_)
| Type::Array(_) => Lifetimes::default(),
};

let negative = negative_token.is_some();
let brace_token = imp.brace_token;

Ok(Api::Impl(Impl {
impl_token,
generics,
impl_generics,
negative,
ty,
ty_generics,
brace_token,
negative_token,
}))
Expand Down
5 changes: 3 additions & 2 deletions syntax/tokens.rs
Original file line number Diff line number Diff line change
Expand Up @@ -192,14 +192,15 @@ impl ToTokens for Impl {
fn to_tokens(&self, tokens: &mut TokenStream) {
let Impl {
impl_token,
generics,
impl_generics,
negative: _,
ty,
ty_generics: _,
brace_token,
negative_token,
} = self;
impl_token.to_tokens(tokens);
generics.to_tokens(tokens);
impl_generics.to_tokens(tokens);
negative_token.to_tokens(tokens);
ty.to_tokens(tokens);
brace_token.surround(tokens, |_tokens| {});
Expand Down