diff options
Diffstat (limited to 'compiler/rustc_macros/src')
| -rw-r--r-- | compiler/rustc_macros/src/hash_stable.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_macros/src/query.rs | 20 | ||||
| -rw-r--r-- | compiler/rustc_macros/src/serialize.rs | 67 | ||||
| -rw-r--r-- | compiler/rustc_macros/src/type_foldable.rs | 13 |
4 files changed, 69 insertions, 39 deletions
diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs index dba885a27fe..63bdcea87f8 100644 --- a/compiler/rustc_macros/src/hash_stable.rs +++ b/compiler/rustc_macros/src/hash_stable.rs @@ -24,11 +24,9 @@ fn parse_attributes(field: &syn::Field) -> Attributes { } if meta.path().is_ident("project") { if let Meta::List(list) = meta { - if let Some(nested) = list.nested.iter().next() { - if let NestedMeta::Meta(meta) = nested { - attrs.project = meta.path().get_ident().cloned(); - any_attr = true; - } + if let Some(NestedMeta::Meta(meta)) = list.nested.iter().next() { + attrs.project = meta.path().get_ident().cloned(); + any_attr = true; } } } diff --git a/compiler/rustc_macros/src/query.rs b/compiler/rustc_macros/src/query.rs index 6dbba274360..478159147ac 100644 --- a/compiler/rustc_macros/src/query.rs +++ b/compiler/rustc_macros/src/query.rs @@ -58,6 +58,9 @@ enum QueryModifier { /// Use a separate query provider for local and extern crates SeparateProvideExtern(Ident), + + /// Always remap the ParamEnv's constness before hashing and passing to the query provider + RemapEnvConstness(Ident), } impl Parse for QueryModifier { @@ -123,6 +126,8 @@ impl Parse for QueryModifier { Ok(QueryModifier::EvalAlways(modifier)) } else if modifier == "separate_provide_extern" { Ok(QueryModifier::SeparateProvideExtern(modifier)) + } else if modifier == "remap_env_constness" { + Ok(QueryModifier::RemapEnvConstness(modifier)) } else { Err(Error::new(modifier.span(), "unknown query modifier")) } @@ -222,6 +227,9 @@ struct QueryModifiers { /// Use a separate query provider for local and extern crates separate_provide_extern: Option<Ident>, + + /// Always remap the ParamEnv's constness before hashing. + remap_env_constness: Option<Ident>, } /// Process query modifiers into a struct, erroring on duplicates @@ -236,6 +244,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { let mut anon = None; let mut eval_always = None; let mut separate_provide_extern = None; + let mut remap_env_constness = None; for modifier in query.modifiers.0.drain(..) { match modifier { QueryModifier::LoadCached(tcx, id, block) => { @@ -335,6 +344,12 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { } separate_provide_extern = Some(ident); } + QueryModifier::RemapEnvConstness(ident) => { + if remap_env_constness.is_some() { + panic!("duplicate modifier `remap_env_constness` for query `{}`", query.name); + } + remap_env_constness = Some(ident) + } } } let desc = desc.unwrap_or_else(|| { @@ -351,6 +366,7 @@ fn process_modifiers(query: &mut Query) -> QueryModifiers { anon, eval_always, separate_provide_extern, + remap_env_constness, } } @@ -485,6 +501,10 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream { if let Some(separate_provide_extern) = &modifiers.separate_provide_extern { attributes.push(quote! { (#separate_provide_extern) }); } + // Pass on the remap_env_constness modifier + if let Some(remap_env_constness) = &modifiers.remap_env_constness { + attributes.push(quote! { (#remap_env_constness) }); + } // This uses the span of the query definition for the commas, // which can be important if we later encounter any ambiguity diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs index 7bc669f2b00..6c5461505fa 100644 --- a/compiler/rustc_macros/src/serialize.rs +++ b/compiler/rustc_macros/src/serialize.rs @@ -1,6 +1,7 @@ use proc_macro2::TokenStream; -use quote::quote; +use quote::{quote, quote_spanned}; use syn::parse_quote; +use syn::spanned::Spanned; pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { let decoder_ty = quote! { __D }; @@ -46,7 +47,7 @@ fn decodable_body( quote! { ::rustc_serialize::Decoder::read_struct( __decoder, - |__decoder| { ::std::result::Result::Ok(#construct) }, + |__decoder| { #construct }, ) } } @@ -56,7 +57,7 @@ fn decodable_body( .enumerate() .map(|(idx, vi)| { let construct = vi.construct(|field, index| decode_field(field, index, false)); - quote! { #idx => { ::std::result::Result::Ok(#construct) } } + quote! { #idx => { #construct } } }) .collect(); let names: TokenStream = variants @@ -81,8 +82,7 @@ fn decodable_body( |__decoder, __variant_idx| { match __variant_idx { #match_inner - _ => return ::std::result::Result::Err( - ::rustc_serialize::Decoder::error(__decoder, #message)), + _ => panic!(#message), } }) } @@ -94,9 +94,7 @@ fn decodable_body( s.bound_impl( quote!(::rustc_serialize::Decodable<#decoder_ty>), quote! { - fn decode( - __decoder: &mut #decoder_ty, - ) -> ::std::result::Result<Self, <#decoder_ty as ::rustc_serialize::Decoder>::Error> { + fn decode(__decoder: &mut #decoder_ty) -> Self { #decode_body } }, @@ -104,6 +102,8 @@ fn decodable_body( } fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro2::TokenStream { + let field_span = field.ident.as_ref().map_or(field.ty.span(), |ident| ident.span()); + let decode_inner_method = if let syn::Type::Reference(_) = field.ty { quote! { ::rustc_middle::ty::codec::RefDecodable::decode } } else { @@ -111,24 +111,20 @@ fn decode_field(field: &syn::Field, index: usize, is_struct: bool) -> proc_macro }; let (decode_method, opt_field_name) = if is_struct { let field_name = field.ident.as_ref().map_or_else(|| index.to_string(), |i| i.to_string()); - ( - proc_macro2::Ident::new("read_struct_field", proc_macro2::Span::call_site()), - quote! { #field_name, }, - ) + (proc_macro2::Ident::new("read_struct_field", field_span), quote! { #field_name, }) } else { - ( - proc_macro2::Ident::new("read_enum_variant_arg", proc_macro2::Span::call_site()), - quote! {}, - ) + (proc_macro2::Ident::new("read_enum_variant_arg", field_span), quote! {}) }; - quote! { - match ::rustc_serialize::Decoder::#decode_method( - __decoder, #opt_field_name #decode_inner_method) { - ::std::result::Result::Ok(__res) => __res, - ::std::result::Result::Err(__err) => return ::std::result::Result::Err(__err), - } - } + let __decoder = quote! { __decoder }; + // Use the span of the field for the method call, so + // that backtraces will point to the field. + let decode_call = quote_spanned! {field_span=> + ::rustc_serialize::Decoder::#decode_method( + #__decoder, #opt_field_name #decode_inner_method) + }; + + quote! { #decode_call } } pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { @@ -247,13 +243,24 @@ fn encodable_body( }) .collect(); - let result = quote! { ::rustc_serialize::Encoder::emit_enum_variant( - __encoder, - #variant_name, - #variant_idx, - #field_idx, - |__encoder| { ::std::result::Result::Ok({ #encode_fields }) } - ) }; + let result = if field_idx != 0 { + quote! { + ::rustc_serialize::Encoder::emit_enum_variant( + __encoder, + #variant_name, + #variant_idx, + #field_idx, + |__encoder| { ::std::result::Result::Ok({ #encode_fields }) } + ) + } + } else { + quote! { + ::rustc_serialize::Encoder::emit_fieldless_enum_variant::<#variant_idx>( + __encoder, + #variant_name, + ) + } + }; variant_idx += 1; result }); diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs index 082af087bf4..bc8213a18ea 100644 --- a/compiler/rustc_macros/src/type_foldable.rs +++ b/compiler/rustc_macros/src/type_foldable.rs @@ -1,10 +1,15 @@ use quote::quote; +use syn::parse_quote; pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { if let syn::Data::Union(_) = s.ast().data { panic!("cannot derive on union") } + if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + s.add_impl_generic(parse_quote! { 'tcx }); + } + s.add_bounds(synstructure::AddBounds::Generics); let body_visit = s.each(|bind| { quote! { @@ -17,7 +22,7 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:: vi.construct(|_, index| { let bind = &bindings[index]; quote! { - ::rustc_middle::ty::fold::TypeFoldable::fold_with(#bind, __folder) + ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)? } }) }); @@ -25,11 +30,11 @@ pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2:: s.bound_impl( quote!(::rustc_middle::ty::fold::TypeFoldable<'tcx>), quote! { - fn super_fold_with<__F: ::rustc_middle::ty::fold::TypeFolder<'tcx>>( + fn try_super_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<'tcx>>( self, __folder: &mut __F - ) -> Self { - match self { #body_fold } + ) -> Result<Self, __F::Error> { + Ok(match self { #body_fold }) } fn super_visit_with<__F: ::rustc_middle::ty::fold::TypeVisitor<'tcx>>( |
