Create derive proc-macro for Lift trait.
This commit is contained in:
parent
d8014582b8
commit
2add2075de
@ -10,6 +10,7 @@ use proc_macro::TokenStream;
|
||||
|
||||
mod hash_stable;
|
||||
mod type_foldable;
|
||||
mod lift;
|
||||
mod query;
|
||||
mod symbols;
|
||||
|
||||
@ -25,3 +26,4 @@ pub fn symbols(input: TokenStream) -> TokenStream {
|
||||
|
||||
decl_derive!([HashStable, attributes(stable_hasher)] => hash_stable::hash_stable_derive);
|
||||
decl_derive!([TypeFoldable, attributes(type_foldable)] => type_foldable::type_foldable_derive);
|
||||
decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
|
||||
|
50
src/librustc_macros/src/lift.rs
Normal file
50
src/librustc_macros/src/lift.rs
Normal file
@ -0,0 +1,50 @@
|
||||
use synstructure;
|
||||
use syn::{self, parse_quote};
|
||||
use proc_macro2;
|
||||
use quote::quote;
|
||||
|
||||
pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
||||
s.add_bounds(synstructure::AddBounds::Generics);
|
||||
|
||||
let tcx: syn::Lifetime = parse_quote!('tcx);
|
||||
let newtcx: syn::GenericParam = parse_quote!('__newtcx);
|
||||
|
||||
let lifted = {
|
||||
let ast = s.ast();
|
||||
let ident = &ast.ident;
|
||||
|
||||
// Replace `'tcx` lifetime by the `'__newtcx` lifetime
|
||||
let (_, generics, _) = ast.generics.split_for_impl();
|
||||
let mut generics : syn::AngleBracketedGenericArguments = syn::parse_quote!{ #generics };
|
||||
for arg in generics.args.iter_mut() {
|
||||
match arg {
|
||||
syn::GenericArgument::Lifetime(l) if *l == tcx => {
|
||||
*arg = parse_quote!('__newtcx);
|
||||
},
|
||||
syn::GenericArgument::Type(t) => {
|
||||
*arg = syn::parse_quote!{ #t::Lifted };
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
quote!{ #ident #generics }
|
||||
};
|
||||
|
||||
let body = s.each_variant(|vi| {
|
||||
let bindings = &vi.bindings();
|
||||
vi.construct(|_, index| {
|
||||
let bi = &bindings[index];
|
||||
quote!{ __tcx.lift(#bi)? }
|
||||
})
|
||||
});
|
||||
|
||||
s.add_impl_generic(newtcx);
|
||||
s.bound_impl(quote!(::rustc::ty::Lift<'__newtcx>), quote!{
|
||||
type Lifted = #lifted;
|
||||
|
||||
fn lift_to_tcx(&self, __tcx: ::rustc::ty::TyCtxt<'__newtcx>) -> Option<#lifted> {
|
||||
Some(match *self { #body })
|
||||
}
|
||||
})
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user