Skip to content

Commit 2add207

Browse files
committed
Create derive proc-macro for Lift trait.
1 parent d801458 commit 2add207

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

src/librustc_macros/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use proc_macro::TokenStream;
1010

1111
mod hash_stable;
1212
mod type_foldable;
13+
mod lift;
1314
mod query;
1415
mod symbols;
1516

@@ -25,3 +26,4 @@ pub fn symbols(input: TokenStream) -> TokenStream {
2526

2627
decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
2728
decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);
29+
decl_derive!([Lift, attributes(lift)] => lift::lift_derive);

src/librustc_macros/src/lift.rs

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use synstructure;
2+
use syn::{self, parse_quote};
3+
use proc_macro2;
4+
use quote::quote;
5+
6+
pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
7+
s.add_bounds(synstructure::AddBounds::Generics);
8+
9+
let tcx: syn::Lifetime = parse_quote!('tcx);
10+
let newtcx: syn::GenericParam = parse_quote!('__newtcx);
11+
12+
let lifted = {
13+
let ast = s.ast();
14+
let ident = &ast.ident;
15+
16+
// Replace `'tcx` lifetime by the `'__newtcx` lifetime
17+
let (_, generics, _) = ast.generics.split_for_impl();
18+
let mut generics : syn::AngleBracketedGenericArguments = syn::parse_quote!{ #generics };
19+
for arg in generics.args.iter_mut() {
20+
match arg {
21+
syn::GenericArgument::Lifetime(l) if *l == tcx => {
22+
*arg = parse_quote!('__newtcx);
23+
},
24+
syn::GenericArgument::Type(t) => {
25+
*arg = syn::parse_quote!{ #t::Lifted };
26+
},
27+
_ => {},
28+
}
29+
}
30+
31+
quote!{ #ident #generics }
32+
};
33+
34+
let body = s.each_variant(|vi| {
35+
let bindings = &vi.bindings();
36+
vi.construct(|_, index| {
37+
let bi = &bindings[index];
38+
quote!{ __tcx.lift(#bi)? }
39+
})
40+
});
41+
42+
s.add_impl_generic(newtcx);
43+
s.bound_impl(quote!(::rustc::ty::Lift<'__newtcx>), quote!{
44+
type Lifted = #lifted;
45+
46+
fn lift_to_tcx(&self, __tcx: ::rustc::ty::TyCtxt<'__newtcx>) -> Option<#lifted> {
47+
Some(match *self { #body })
48+
}
49+
})
50+
}

0 commit comments

Comments
 (0)