Skip to content

Commit dc415cc

Browse files
authored
Merge pull request #635 from dtolnay/lifetimes
Parameterize shim trait impl blocks over lifetimes
2 parents eb472ad + dc79f24 commit dc415cc

File tree

4 files changed

+91
-32
lines changed

4 files changed

+91
-32
lines changed

macro/src/expand.rs

+59-23
Original file line numberDiff line numberDiff line change
@@ -1048,27 +1048,33 @@ fn expand_rust_box(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>) -
10481048
let local_dealloc = format_ident!("{}dealloc", local_prefix);
10491049
let local_drop = format_ident!("{}drop", local_prefix);
10501050

1051+
let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
1052+
(&imp.impl_generics, &imp.ty_generics)
1053+
} else {
1054+
(resolve.generics, resolve.generics)
1055+
};
1056+
10511057
let begin_span =
10521058
explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
10531059
let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
10541060
let unsafe_token = format_ident!("unsafe", span = begin_span);
10551061

10561062
quote_spanned! {end_span=>
10571063
#[doc(hidden)]
1058-
#unsafe_token impl ::cxx::private::ImplBox for #ident {}
1064+
#unsafe_token impl #impl_generics ::cxx::private::ImplBox for #ident #ty_generics {}
10591065
#[doc(hidden)]
10601066
#[export_name = #link_alloc]
1061-
unsafe extern "C" fn #local_alloc() -> *mut ::std::mem::MaybeUninit<#ident> {
1067+
unsafe extern "C" fn #local_alloc #impl_generics() -> *mut ::std::mem::MaybeUninit<#ident #ty_generics> {
10621068
::std::boxed::Box::into_raw(::std::boxed::Box::new(::std::mem::MaybeUninit::uninit()))
10631069
}
10641070
#[doc(hidden)]
10651071
#[export_name = #link_dealloc]
1066-
unsafe extern "C" fn #local_dealloc(ptr: *mut ::std::mem::MaybeUninit<#ident>) {
1072+
unsafe extern "C" fn #local_dealloc #impl_generics(ptr: *mut ::std::mem::MaybeUninit<#ident #ty_generics>) {
10671073
::std::boxed::Box::from_raw(ptr);
10681074
}
10691075
#[doc(hidden)]
10701076
#[export_name = #link_drop]
1071-
unsafe extern "C" fn #local_drop(this: *mut ::std::boxed::Box<#ident>) {
1077+
unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::std::boxed::Box<#ident #ty_generics>) {
10721078
::std::ptr::drop_in_place(this);
10731079
}
10741080
}
@@ -1094,47 +1100,53 @@ fn expand_rust_vec(elem: &Ident, types: &Types, explicit_impl: Option<&Impl>) ->
10941100
let local_reserve_total = format_ident!("{}reserve_total", local_prefix);
10951101
let local_set_len = format_ident!("{}set_len", local_prefix);
10961102

1103+
let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
1104+
(&imp.impl_generics, &imp.ty_generics)
1105+
} else {
1106+
(resolve.generics, resolve.generics)
1107+
};
1108+
10971109
let begin_span =
10981110
explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
10991111
let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
11001112
let unsafe_token = format_ident!("unsafe", span = begin_span);
11011113

11021114
quote_spanned! {end_span=>
11031115
#[doc(hidden)]
1104-
#unsafe_token impl ::cxx::private::ImplVec for #elem {}
1116+
#unsafe_token impl #impl_generics ::cxx::private::ImplVec for #elem #ty_generics {}
11051117
#[doc(hidden)]
11061118
#[export_name = #link_new]
1107-
unsafe extern "C" fn #local_new(this: *mut ::cxx::private::RustVec<#elem>) {
1119+
unsafe extern "C" fn #local_new #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
11081120
::std::ptr::write(this, ::cxx::private::RustVec::new());
11091121
}
11101122
#[doc(hidden)]
11111123
#[export_name = #link_drop]
1112-
unsafe extern "C" fn #local_drop(this: *mut ::cxx::private::RustVec<#elem>) {
1124+
unsafe extern "C" fn #local_drop #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>) {
11131125
::std::ptr::drop_in_place(this);
11141126
}
11151127
#[doc(hidden)]
11161128
#[export_name = #link_len]
1117-
unsafe extern "C" fn #local_len(this: *const ::cxx::private::RustVec<#elem>) -> usize {
1129+
unsafe extern "C" fn #local_len #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
11181130
(*this).len()
11191131
}
11201132
#[doc(hidden)]
11211133
#[export_name = #link_capacity]
1122-
unsafe extern "C" fn #local_capacity(this: *const ::cxx::private::RustVec<#elem>) -> usize {
1134+
unsafe extern "C" fn #local_capacity #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> usize {
11231135
(*this).capacity()
11241136
}
11251137
#[doc(hidden)]
11261138
#[export_name = #link_data]
1127-
unsafe extern "C" fn #local_data(this: *const ::cxx::private::RustVec<#elem>) -> *const #elem {
1139+
unsafe extern "C" fn #local_data #impl_generics(this: *const ::cxx::private::RustVec<#elem #ty_generics>) -> *const #elem #ty_generics {
11281140
(*this).as_ptr()
11291141
}
11301142
#[doc(hidden)]
11311143
#[export_name = #link_reserve_total]
1132-
unsafe extern "C" fn #local_reserve_total(this: *mut ::cxx::private::RustVec<#elem>, cap: usize) {
1144+
unsafe extern "C" fn #local_reserve_total #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, cap: usize) {
11331145
(*this).reserve_total(cap);
11341146
}
11351147
#[doc(hidden)]
11361148
#[export_name = #link_set_len]
1137-
unsafe extern "C" fn #local_set_len(this: *mut ::cxx::private::RustVec<#elem>, len: usize) {
1149+
unsafe extern "C" fn #local_set_len #impl_generics(this: *mut ::cxx::private::RustVec<#elem #ty_generics>, len: usize) {
11381150
(*this).set_len(len);
11391151
}
11401152
}
@@ -1151,6 +1163,12 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
11511163
let link_release = format!("{}release", prefix);
11521164
let link_drop = format!("{}drop", prefix);
11531165

1166+
let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
1167+
(&imp.impl_generics, &imp.ty_generics)
1168+
} else {
1169+
(resolve.generics, resolve.generics)
1170+
};
1171+
11541172
let can_construct_from_value = types.structs.contains_key(ident)
11551173
|| types.enums.contains_key(ident)
11561174
|| types.aliases.contains_key(ident);
@@ -1162,7 +1180,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
11621180
fn __uninit(this: *mut *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;
11631181
}
11641182
let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
1165-
unsafe { __uninit(&mut repr).cast::<#ident>().write(value) }
1183+
unsafe { __uninit(&mut repr).cast::<#ident #ty_generics>().write(value) }
11661184
repr
11671185
}
11681186
})
@@ -1176,7 +1194,7 @@ fn expand_unique_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
11761194
let unsafe_token = format_ident!("unsafe", span = begin_span);
11771195

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

1253+
let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
1254+
(&imp.impl_generics, &imp.ty_generics)
1255+
} else {
1256+
(resolve.generics, resolve.generics)
1257+
};
1258+
12351259
let can_construct_from_value = types.structs.contains_key(ident)
12361260
|| types.enums.contains_key(ident)
12371261
|| types.aliases.contains_key(ident);
@@ -1242,7 +1266,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
12421266
#[link_name = #link_uninit]
12431267
fn __uninit(new: *mut ::std::ffi::c_void) -> *mut ::std::ffi::c_void;
12441268
}
1245-
__uninit(new).cast::<#ident>().write(value);
1269+
__uninit(new).cast::<#ident #ty_generics>().write(value);
12461270
}
12471271
})
12481272
} else {
@@ -1255,7 +1279,7 @@ fn expand_shared_ptr(ident: &Ident, types: &Types, explicit_impl: Option<&Impl>)
12551279
let unsafe_token = format_ident!("unsafe", span = begin_span);
12561280

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

1327+
let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
1328+
(&imp.impl_generics, &imp.ty_generics)
1329+
} else {
1330+
(resolve.generics, resolve.generics)
1331+
};
1332+
13031333
let begin_span =
13041334
explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
13051335
let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
13061336
let unsafe_token = format_ident!("unsafe", span = begin_span);
13071337

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

1396+
let (impl_generics, ty_generics) = if let Some(imp) = explicit_impl {
1397+
(&imp.impl_generics, &imp.ty_generics)
1398+
} else {
1399+
(resolve.generics, resolve.generics)
1400+
};
1401+
13661402
let begin_span =
13671403
explicit_impl.map_or_else(Span::call_site, |explicit| explicit.impl_token.span);
13681404
let end_span = explicit_impl.map_or_else(Span::call_site, |explicit| explicit.brace_token.span);
13691405
let unsafe_token = format_ident!("unsafe", span = begin_span);
13701406

13711407
quote_spanned! {end_span=>
1372-
#unsafe_token impl ::cxx::private::VectorElement for #elem {
1408+
#unsafe_token impl #impl_generics ::cxx::private::VectorElement for #elem #ty_generics {
13731409
const __NAME: &'static dyn ::std::fmt::Display = &#name;
13741410
fn __vector_size(v: &::cxx::CxxVector<Self>) -> usize {
13751411
extern "C" {
13761412
#[link_name = #link_size]
1377-
fn __vector_size(_: &::cxx::CxxVector<#elem>) -> usize;
1413+
fn __vector_size #impl_generics(_: &::cxx::CxxVector<#elem #ty_generics>) -> usize;
13781414
}
13791415
unsafe { __vector_size(v) }
13801416
}
13811417
unsafe fn __get_unchecked(v: *mut ::cxx::CxxVector<Self>, pos: usize) -> *mut Self {
13821418
extern "C" {
13831419
#[link_name = #link_get_unchecked]
1384-
fn __get_unchecked(_: *mut ::cxx::CxxVector<#elem>, _: usize) -> *mut #elem;
1420+
fn __get_unchecked #impl_generics(_: *mut ::cxx::CxxVector<#elem #ty_generics>, _: usize) -> *mut #elem #ty_generics;
13851421
}
13861422
__get_unchecked(v, pos)
13871423
}
@@ -1397,7 +1433,7 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types)
13971433
unsafe fn __unique_ptr_raw(raw: *mut ::cxx::CxxVector<Self>) -> *mut ::std::ffi::c_void {
13981434
extern "C" {
13991435
#[link_name = #link_unique_ptr_raw]
1400-
fn __unique_ptr_raw(this: *mut *mut ::std::ffi::c_void, raw: *mut ::cxx::CxxVector<#elem>);
1436+
fn __unique_ptr_raw #impl_generics(this: *mut *mut ::std::ffi::c_void, raw: *mut ::cxx::CxxVector<#elem #ty_generics>);
14011437
}
14021438
let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
14031439
__unique_ptr_raw(&mut repr, raw);
@@ -1406,14 +1442,14 @@ fn expand_cxx_vector(elem: &Ident, explicit_impl: Option<&Impl>, types: &Types)
14061442
unsafe fn __unique_ptr_get(repr: *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<Self> {
14071443
extern "C" {
14081444
#[link_name = #link_unique_ptr_get]
1409-
fn __unique_ptr_get(this: *const *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<#elem>;
1445+
fn __unique_ptr_get #impl_generics(this: *const *mut ::std::ffi::c_void) -> *const ::cxx::CxxVector<#elem #ty_generics>;
14101446
}
14111447
__unique_ptr_get(&repr)
14121448
}
14131449
unsafe fn __unique_ptr_release(mut repr: *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<Self> {
14141450
extern "C" {
14151451
#[link_name = #link_unique_ptr_release]
1416-
fn __unique_ptr_release(this: *mut *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<#elem>;
1452+
fn __unique_ptr_release #impl_generics(this: *mut *mut ::std::ffi::c_void) -> *mut ::cxx::CxxVector<#elem #ty_generics>;
14171453
}
14181454
__unique_ptr_release(&mut repr)
14191455
}

syntax/mod.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -141,13 +141,15 @@ pub struct TypeAlias {
141141

142142
pub struct Impl {
143143
pub impl_token: Token![impl],
144-
pub generics: Lifetimes,
144+
pub impl_generics: Lifetimes,
145145
pub negative: bool,
146146
pub ty: Type,
147+
pub ty_generics: Lifetimes,
147148
pub brace_token: Brace,
148149
pub negative_token: Option<Token![!]>,
149150
}
150151

152+
#[derive(Clone, Default)]
151153
pub struct Lifetimes {
152154
pub lt_token: Option<Token![<]>,
153155
pub lifetimes: Punctuated<Lifetime, Token![,]>,

syntax/parse.rs

+26-6
Original file line numberDiff line numberDiff line change
@@ -868,7 +868,7 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
868868
"where-clause on an impl is not supported yet",
869869
));
870870
}
871-
let mut generics = Lifetimes {
871+
let mut impl_generics = Lifetimes {
872872
lt_token: imp.generics.lt_token,
873873
lifetimes: Punctuated::new(),
874874
gt_token: imp.generics.gt_token,
@@ -877,13 +877,13 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
877877
let (param, punct) = pair.into_tuple();
878878
match param {
879879
GenericParam::Lifetime(def) if def.bounds.is_empty() => {
880-
generics.lifetimes.push_value(def.lifetime);
880+
impl_generics.lifetimes.push_value(def.lifetime);
881881
if let Some(punct) = punct {
882-
generics.lifetimes.push_punct(punct);
882+
impl_generics.lifetimes.push_punct(punct);
883883
}
884884
}
885885
_ => {
886-
let span = quote!(#impl_token #generics);
886+
let span = quote!(#impl_token #impl_generics);
887887
return Err(Error::new_spanned(
888888
span,
889889
"generic parameter on an impl is not supported yet",
@@ -907,15 +907,35 @@ fn parse_impl(imp: ItemImpl) -> Result<Api> {
907907
}
908908
}
909909

910-
let negative = negative_token.is_some();
911910
let ty = parse_type(&self_ty)?;
911+
let ty_generics = match &ty {
912+
Type::RustBox(ty)
913+
| Type::RustVec(ty)
914+
| Type::UniquePtr(ty)
915+
| Type::SharedPtr(ty)
916+
| Type::WeakPtr(ty)
917+
| Type::CxxVector(ty) => match &ty.inner {
918+
Type::Ident(ident) => ident.generics.clone(),
919+
_ => Lifetimes::default(),
920+
},
921+
Type::Ident(_)
922+
| Type::Ref(_)
923+
| Type::Str(_)
924+
| Type::Fn(_)
925+
| Type::Void(_)
926+
| Type::SliceRef(_)
927+
| Type::Array(_) => Lifetimes::default(),
928+
};
929+
930+
let negative = negative_token.is_some();
912931
let brace_token = imp.brace_token;
913932

914933
Ok(Api::Impl(Impl {
915934
impl_token,
916-
generics,
935+
impl_generics,
917936
negative,
918937
ty,
938+
ty_generics,
919939
brace_token,
920940
negative_token,
921941
}))

syntax/tokens.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -192,14 +192,15 @@ impl ToTokens for Impl {
192192
fn to_tokens(&self, tokens: &mut TokenStream) {
193193
let Impl {
194194
impl_token,
195-
generics,
195+
impl_generics,
196196
negative: _,
197197
ty,
198+
ty_generics: _,
198199
brace_token,
199200
negative_token,
200201
} = self;
201202
impl_token.to_tokens(tokens);
202-
generics.to_tokens(tokens);
203+
impl_generics.to_tokens(tokens);
203204
negative_token.to_tokens(tokens);
204205
ty.to_tokens(tokens);
205206
brace_token.surround(tokens, |_tokens| {});

0 commit comments

Comments
 (0)