about summary refs log tree commit diff
path: root/compiler/rustc_macros/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_macros/src')
-rw-r--r--compiler/rustc_macros/src/hash_stable.rs8
-rw-r--r--compiler/rustc_macros/src/query.rs20
-rw-r--r--compiler/rustc_macros/src/serialize.rs67
-rw-r--r--compiler/rustc_macros/src/type_foldable.rs13
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>>(