From 3c58c0ed9d535882298568b8de0128634b5c3e72 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sun, 26 Feb 2023 13:19:30 +0000 Subject: [PATCH 01/22] Improve docs of traversable derivation macros --- compiler/rustc_macros/src/lib.rs | 49 ++++++++++++++++++++++++++------ 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 737500cc257eb..d91d83ae81736 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -124,21 +124,52 @@ decl_derive!( [TypeFoldable, attributes(type_foldable)] => /// Derives `TypeFoldable` for the annotated `struct` or `enum` (`union` is not supported). /// - /// The fold will produce a value of the same struct or enum variant as the input, with - /// each field respectively folded using the `TypeFoldable` implementation for its type. - /// However, if a field of a struct or an enum variant is annotated with - /// `#[type_foldable(identity)]` then that field will retain its incumbent value (and its - /// type is not required to implement `TypeFoldable`). + /// Folds will produce a value of the same struct or enum variant as the input, with each field + /// respectively folded (in definition order) using the `TypeFoldable` implementation for its + /// type. However, if a field of a struct or of an enum variant is annotated with + /// `#[type_foldable(identity)]` then that field will retain its incumbent value (and its type + /// is not required to implement `TypeFoldable`). However use of this attribute is dangerous + /// and should be used with extreme caution: should the type of the annotated field contain + /// (now or in the future) a type that is of interest to a folder, it will not get folded (which + /// may result in unexpected, hard-to-track bugs that could result in unsoundness). + /// + /// If the annotated type has a `'tcx` lifetime parameter, then that will be used as the + /// lifetime for the type context/interner; otherwise the lifetime of the type context/interner + /// will be unrelated to the annotated type. It therefore matters how any lifetime parameters of + /// the annotated type are named. For example, deriving `TypeFoldable` for both `Foo<'a>` and + /// `Bar<'tcx>` will respectively produce: + /// + /// `impl<'a, 'tcx> TypeFoldable> for Foo<'a>` + /// + /// and + /// + /// `impl<'tcx> TypeFoldable> for Bar<'tcx>` type_foldable::type_foldable_derive ); decl_derive!( [TypeVisitable, attributes(type_visitable)] => /// Derives `TypeVisitable` for the annotated `struct` or `enum` (`union` is not supported). /// - /// Each field of the struct or enum variant will be visited in definition order, using the - /// `TypeVisitable` implementation for its type. However, if a field of a struct or an enum - /// variant is annotated with `#[type_visitable(ignore)]` then that field will not be - /// visited (and its type is not required to implement `TypeVisitable`). + /// Each field of the struct or enum variant will be visited (in definition order) using the + /// `TypeVisitable` implementation for its type. However, if a field of a struct or of an enum + /// variant is annotated with `#[type_visitable(ignore)]` then that field will not be visited + /// (and its type is not required to implement `TypeVisitable`). However use of this attribute + /// is dangerous and should be used with extreme caution: should the type of the annotated + /// field (now or in the future) a type that is of interest to a visitor, it will not get + /// visited (which may result in unexpected, hard-to-track bugs that could result in + /// unsoundness). + /// + /// If the annotated type has a `'tcx` lifetime parameter, then that will be used as the + /// lifetime for the type context/interner; otherwise the lifetime of the type context/interner + /// will be unrelated to the annotated type. It therefore matters how any lifetime parameters of + /// the annotated type are named. For example, deriving `TypeVisitable` for both `Foo<'a>` and + /// `Bar<'tcx>` will respectively produce: + /// + /// `impl<'a, 'tcx> TypeVisitable> for Foo<'a>` + /// + /// and + /// + /// `impl<'tcx> TypeVisitable> for Bar<'tcx>` type_visitable::type_visitable_derive ); decl_derive!([Lift, attributes(lift)] => lift::lift_derive); From 1a9c3e56409f72ec917eee056dc6e9567f6688b6 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sun, 26 Feb 2023 13:21:01 +0000 Subject: [PATCH 02/22] Generify traversable derivation macros --- compiler/rustc_macros/src/lib.rs | 7 +- compiler/rustc_macros/src/traversable.rs | 125 ++++++++++++++++++++ compiler/rustc_macros/src/type_foldable.rs | 57 --------- compiler/rustc_macros/src/type_visitable.rs | 50 -------- 4 files changed, 128 insertions(+), 111 deletions(-) create mode 100644 compiler/rustc_macros/src/traversable.rs delete mode 100644 compiler/rustc_macros/src/type_foldable.rs delete mode 100644 compiler/rustc_macros/src/type_visitable.rs diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index d91d83ae81736..425891f1596c4 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -20,8 +20,7 @@ mod newtype; mod query; mod serialize; mod symbols; -mod type_foldable; -mod type_visitable; +mod traversable; #[proc_macro] pub fn rustc_queries(input: TokenStream) -> TokenStream { @@ -144,7 +143,7 @@ decl_derive!( /// and /// /// `impl<'tcx> TypeFoldable> for Bar<'tcx>` - type_foldable::type_foldable_derive + traversable::traversable_derive:: ); decl_derive!( [TypeVisitable, attributes(type_visitable)] => @@ -170,7 +169,7 @@ decl_derive!( /// and /// /// `impl<'tcx> TypeVisitable> for Bar<'tcx>` - type_visitable::type_visitable_derive + traversable::traversable_derive:: ); decl_derive!([Lift, attributes(lift)] => lift::lift_derive); decl_derive!( diff --git a/compiler/rustc_macros/src/traversable.rs b/compiler/rustc_macros/src/traversable.rs new file mode 100644 index 0000000000000..7a3c5623f16f8 --- /dev/null +++ b/compiler/rustc_macros/src/traversable.rs @@ -0,0 +1,125 @@ +use proc_macro2::TokenStream; +use quote::{quote, ToTokens}; +use syn::{parse_quote, Attribute, Meta, NestedMeta}; + +pub struct Foldable; +pub struct Visitable; + +/// An abstraction over traversable traits. +pub trait Traversable { + /// The trait that this `Traversable` represents. + fn traversable() -> TokenStream; + + /// The `match` arms for a traversal of this type. + fn arms(structure: &mut synstructure::Structure<'_>) -> TokenStream; + + /// The body of an implementation given the match `arms`. + fn impl_body(arms: impl ToTokens) -> TokenStream; +} + +impl Traversable for Foldable { + fn traversable() -> TokenStream { + quote! { ::rustc_middle::ty::fold::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>> } + } + fn arms(structure: &mut synstructure::Structure<'_>) -> TokenStream { + structure.each_variant(|vi| { + let bindings = vi.bindings(); + vi.construct(|_, index| { + let bind = &bindings[index]; + + // retain value of fields with #[type_foldable(identity)] + let fixed = bind + .ast() + .attrs + .iter() + .map(Attribute::parse_meta) + .filter_map(Result::ok) + .flat_map(|attr| match attr { + Meta::List(list) if list.path.is_ident("type_foldable") => list.nested, + _ => Default::default(), + }) + .any(|nested| match nested { + NestedMeta::Meta(Meta::Path(path)) => path.is_ident("identity"), + _ => false, + }); + + if fixed { + bind.to_token_stream() + } else { + quote! { + ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)? + } + } + }) + }) + } + fn impl_body(arms: impl ToTokens) -> TokenStream { + quote! { + fn try_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>( + self, + __folder: &mut __F + ) -> ::core::result::Result { + ::core::result::Result::Ok(match self { #arms }) + } + } + } +} + +impl Traversable for Visitable { + fn traversable() -> TokenStream { + quote! { ::rustc_middle::ty::visit::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>> } + } + fn arms(structure: &mut synstructure::Structure<'_>) -> TokenStream { + // ignore fields with #[type_visitable(ignore)] + structure.filter(|bi| { + !bi.ast() + .attrs + .iter() + .map(Attribute::parse_meta) + .filter_map(Result::ok) + .flat_map(|attr| match attr { + Meta::List(list) if list.path.is_ident("type_visitable") => list.nested, + _ => Default::default(), + }) + .any(|nested| match nested { + NestedMeta::Meta(Meta::Path(path)) => path.is_ident("ignore"), + _ => false, + }) + }); + + structure.each(|bind| { + quote! { + ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)?; + } + }) + } + fn impl_body(arms: impl ToTokens) -> TokenStream { + quote! { + fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>( + &self, + __visitor: &mut __V + ) -> ::std::ops::ControlFlow<__V::BreakTy> { + match self { #arms } + ::std::ops::ControlFlow::Continue(()) + } + } + } +} + +pub fn traversable_derive( + mut structure: synstructure::Structure<'_>, +) -> TokenStream { + if let syn::Data::Union(_) = structure.ast().data { + panic!("cannot derive on union") + } + + structure.add_bounds(synstructure::AddBounds::Generics); + structure.bind_with(|_| synstructure::BindStyle::Move); + + if !structure.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { + structure.add_impl_generic(parse_quote! { 'tcx }); + } + + let arms = T::arms(&mut structure); + structure.bound_impl(T::traversable(), T::impl_body(arms)) +} diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs deleted file mode 100644 index 388e254cd6453..0000000000000 --- a/compiler/rustc_macros/src/type_foldable.rs +++ /dev/null @@ -1,57 +0,0 @@ -use quote::{quote, ToTokens}; -use syn::{parse_quote, Attribute, Meta, NestedMeta}; - -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); - s.bind_with(|_| synstructure::BindStyle::Move); - let body_fold = s.each_variant(|vi| { - let bindings = vi.bindings(); - vi.construct(|_, index| { - let bind = &bindings[index]; - - // retain value of fields with #[type_foldable(identity)] - let fixed = bind - .ast() - .attrs - .iter() - .map(Attribute::parse_meta) - .filter_map(Result::ok) - .flat_map(|attr| match attr { - Meta::List(list) if list.path.is_ident("type_foldable") => list.nested, - _ => Default::default(), - }) - .any(|nested| match nested { - NestedMeta::Meta(Meta::Path(path)) => path.is_ident("identity"), - _ => false, - }); - - if fixed { - bind.to_token_stream() - } else { - quote! { - ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)? - } - } - }) - }); - - s.bound_impl( - quote!(::rustc_middle::ty::fold::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>>), - quote! { - fn try_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>( - self, - __folder: &mut __F - ) -> Result { - Ok(match self { #body_fold }) - } - }, - ) -} diff --git a/compiler/rustc_macros/src/type_visitable.rs b/compiler/rustc_macros/src/type_visitable.rs deleted file mode 100644 index f6f4c4779c302..0000000000000 --- a/compiler/rustc_macros/src/type_visitable.rs +++ /dev/null @@ -1,50 +0,0 @@ -use quote::quote; -use syn::{parse_quote, Attribute, Meta, NestedMeta}; - -pub fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { - if let syn::Data::Union(_) = s.ast().data { - panic!("cannot derive on union") - } - - // ignore fields with #[type_visitable(ignore)] - s.filter(|bi| { - !bi.ast() - .attrs - .iter() - .map(Attribute::parse_meta) - .filter_map(Result::ok) - .flat_map(|attr| match attr { - Meta::List(list) if list.path.is_ident("type_visitable") => list.nested, - _ => Default::default(), - }) - .any(|nested| match nested { - NestedMeta::Meta(Meta::Path(path)) => path.is_ident("ignore"), - _ => false, - }) - }); - - 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! { - ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)?; - } - }); - s.bind_with(|_| synstructure::BindStyle::Move); - - s.bound_impl( - quote!(::rustc_middle::ty::visit::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>), - quote! { - fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>( - &self, - __visitor: &mut __V - ) -> ::std::ops::ControlFlow<__V::BreakTy> { - match *self { #body_visit } - ::std::ops::ControlFlow::Continue(()) - } - }, - ) -} From 09239c25fb7c21c1912bcbc80c200ba36fbd9529 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sat, 25 Feb 2023 13:44:15 +0000 Subject: [PATCH 03/22] Automatically skip traversal of boring fields A trait, `rustc_type_ir::SkipTraversalAutoImplOnly`, is auto-implemented for types that do not contain anything that may be of interest to traversers (folders and visitors). "Auto-deref specialisation" is then used in the derive macros to avoid traversing fields of such types without requiring them to implement the traversable traits. --- compiler/rustc_macros/src/lib.rs | 48 ++-- compiler/rustc_macros/src/traversable.rs | 268 +++++++++++++++-------- compiler/rustc_middle/src/mir/query.rs | 2 - compiler/rustc_middle/src/ty/context.rs | 8 +- compiler/rustc_middle/src/ty/fold.rs | 4 +- compiler/rustc_middle/src/ty/visit.rs | 2 +- compiler/rustc_type_ir/src/fold.rs | 38 +++- compiler/rustc_type_ir/src/lib.rs | 20 +- compiler/rustc_type_ir/src/macros.rs | 28 +++ compiler/rustc_type_ir/src/visit.rs | 34 ++- 10 files changed, 343 insertions(+), 109 deletions(-) diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 425891f1596c4..f2729fe421fc2 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -120,17 +120,26 @@ decl_derive!([TyEncodable] => serialize::type_encodable_derive); decl_derive!([MetadataDecodable] => serialize::meta_decodable_derive); decl_derive!([MetadataEncodable] => serialize::meta_encodable_derive); decl_derive!( - [TypeFoldable, attributes(type_foldable)] => + [TypeFoldable, attributes(skip_traversal)] => /// Derives `TypeFoldable` for the annotated `struct` or `enum` (`union` is not supported). /// /// Folds will produce a value of the same struct or enum variant as the input, with each field /// respectively folded (in definition order) using the `TypeFoldable` implementation for its - /// type. However, if a field of a struct or of an enum variant is annotated with - /// `#[type_foldable(identity)]` then that field will retain its incumbent value (and its type - /// is not required to implement `TypeFoldable`). However use of this attribute is dangerous - /// and should be used with extreme caution: should the type of the annotated field contain - /// (now or in the future) a type that is of interest to a folder, it will not get folded (which - /// may result in unexpected, hard-to-track bugs that could result in unsoundness). + /// type if it has one. Fields of non-generic types that do not contain anything that may be of + /// interest to folders will automatically be left unchanged whether the type implements + /// `TypeFoldable` or not; the same behaviour can be achieved for fields of generic types by + /// applying `#[skip_traversal]` to the field definition (or even to a variant definition if it + /// should apply to all fields therein), but the derived implementation will only be applicable + /// to concrete types where such annotated fields do not contain anything that may be of + /// interest to folders (thus preventing fields from being left unchanged erroneously). + /// + /// In some rare situations, it may be necessary for `TypeFoldable` to be implemented for types + /// that do not contain anything of interest to folders. Whilst the macro expansion in such + /// cases would (as described above) result in folds that merely reconstruct `self`, this is + /// accomplished via method calls that might not get optimised away. One can therefore annotate + /// the type itself with `#[skip_traversal]` to immediately return `self` instead; as above, + /// such derived implementations are only applicable if the annotated type does not contain + /// anything that may be of interest to a folder. /// /// If the annotated type has a `'tcx` lifetime parameter, then that will be used as the /// lifetime for the type context/interner; otherwise the lifetime of the type context/interner @@ -146,17 +155,26 @@ decl_derive!( traversable::traversable_derive:: ); decl_derive!( - [TypeVisitable, attributes(type_visitable)] => + [TypeVisitable, attributes(skip_traversal)] => /// Derives `TypeVisitable` for the annotated `struct` or `enum` (`union` is not supported). /// /// Each field of the struct or enum variant will be visited (in definition order) using the - /// `TypeVisitable` implementation for its type. However, if a field of a struct or of an enum - /// variant is annotated with `#[type_visitable(ignore)]` then that field will not be visited - /// (and its type is not required to implement `TypeVisitable`). However use of this attribute - /// is dangerous and should be used with extreme caution: should the type of the annotated - /// field (now or in the future) a type that is of interest to a visitor, it will not get - /// visited (which may result in unexpected, hard-to-track bugs that could result in - /// unsoundness). + /// `TypeVisitable` implementation for its type if it has one. Fields of non-generic types that + /// do not contain anything that may be of interest to visitors will automatically be skipped + /// whether the type implements `TypeVisitable` or not; the same behaviour can be achieved for + /// fields of generic types by applying `#[skip_traversal]` to the field definition (or even to + /// a variant definition if it should apply to all fields therein), but the derived + /// implementation will only be applicable to concrete types where such annotated fields do not + /// contain anything that may be of interest to visitors (thus preventing fields from being so + /// skipped erroneously). + /// + /// In some rare situations, it may be necessary for `TypeVisitable` to be implemented for + /// types that do not contain anything of interest to visitors. Whilst the macro expansion in + /// such cases would (as described above) result in visits that skip all fields, this is + /// accomplished via method calls that might not get optimised away. One can therefore annotate + /// the type itself with `#[skip_traversal]` to immediately return `Continue(())` instead; as + /// above, such derived implementations are only applicable if the annotated type does not + /// contain anything that may be of interest to visitors. /// /// If the annotated type has a `'tcx` lifetime parameter, then that will be used as the /// lifetime for the type context/interner; otherwise the lifetime of the type context/interner diff --git a/compiler/rustc_macros/src/traversable.rs b/compiler/rustc_macros/src/traversable.rs index 7a3c5623f16f8..57d1eeab6f028 100644 --- a/compiler/rustc_macros/src/traversable.rs +++ b/compiler/rustc_macros/src/traversable.rs @@ -1,106 +1,141 @@ -use proc_macro2::TokenStream; -use quote::{quote, ToTokens}; -use syn::{parse_quote, Attribute, Meta, NestedMeta}; +use proc_macro2::{Span, TokenStream}; +use quote::{quote, quote_spanned, ToTokens}; +use std::collections::HashMap; +use syn::{parse_quote, spanned::Spanned, Attribute, Generics, Ident, Lifetime, LifetimeDef}; + +/// Generate a type parameter with the given `suffix` that does not conflict with +/// any of the `existing` generics. +fn gen_param(suffix: impl ToString, existing: &Generics) -> Ident { + let mut suffix = suffix.to_string(); + while existing.type_params().any(|t| t.ident == suffix) { + suffix.insert(0, '_'); + } + Ident::new(&suffix, Span::call_site()) +} + +/// Return the `TyCtxt` interner for the given `structure`. +/// +/// If the input represented by `structure` has a `'tcx` lifetime parameter, then that will be used +/// used as the lifetime of the `TyCtxt`. Otherwise a `'tcx` lifetime parameter that is unrelated +/// to the input will be used. +fn gen_interner(structure: &mut synstructure::Structure<'_>) -> TokenStream { + let lt = structure + .ast() + .generics + .lifetimes() + .find_map(|def| (def.lifetime.ident == "tcx").then_some(&def.lifetime)) + .cloned() + .unwrap_or_else(|| { + let tcx: Lifetime = parse_quote! { 'tcx }; + structure.add_impl_generic(LifetimeDef::new(tcx.clone()).into()); + tcx + }); + + quote! { ::rustc_middle::ty::TyCtxt<#lt> } +} + +/// Returns the `Span` of the first `#[skip_traversal]` attribute in `attrs`. +fn find_skip_traversal_attribute(attrs: &[Attribute]) -> Option { + attrs.iter().find(|&attr| *attr == parse_quote! { #[skip_traversal] }).map(Spanned::span) +} pub struct Foldable; pub struct Visitable; /// An abstraction over traversable traits. pub trait Traversable { - /// The trait that this `Traversable` represents. - fn traversable() -> TokenStream; + /// The trait that this `Traversable` represents, parameterised by `interner`. + fn traversable(interner: &impl ToTokens) -> TokenStream; + + /// Any supertraits that this trait is required to implement. + fn supertraits(interner: &impl ToTokens) -> TokenStream; - /// The `match` arms for a traversal of this type. - fn arms(structure: &mut synstructure::Structure<'_>) -> TokenStream; + /// A (`noop`) traversal of this trait upon the `bind` expression. + fn traverse(bind: TokenStream, noop: bool) -> TokenStream; - /// The body of an implementation given the match `arms`. - fn impl_body(arms: impl ToTokens) -> TokenStream; + /// A `match` arm for `variant`, where `f` generates the tokens for each binding. + fn arm( + variant: &synstructure::VariantInfo<'_>, + f: impl FnMut(&synstructure::BindingInfo<'_>) -> TokenStream, + ) -> TokenStream; + + /// The body of an implementation given the `interner`, `traverser` and match expression `body`. + fn impl_body( + interner: impl ToTokens, + traverser: impl ToTokens, + body: impl ToTokens, + ) -> TokenStream; } impl Traversable for Foldable { - fn traversable() -> TokenStream { - quote! { ::rustc_middle::ty::fold::TypeFoldable<::rustc_middle::ty::TyCtxt<'tcx>> } + fn traversable(interner: &impl ToTokens) -> TokenStream { + quote! { ::rustc_middle::ty::fold::TypeFoldable<#interner> } } - fn arms(structure: &mut synstructure::Structure<'_>) -> TokenStream { - structure.each_variant(|vi| { - let bindings = vi.bindings(); - vi.construct(|_, index| { - let bind = &bindings[index]; - - // retain value of fields with #[type_foldable(identity)] - let fixed = bind - .ast() - .attrs - .iter() - .map(Attribute::parse_meta) - .filter_map(Result::ok) - .flat_map(|attr| match attr { - Meta::List(list) if list.path.is_ident("type_foldable") => list.nested, - _ => Default::default(), - }) - .any(|nested| match nested { - NestedMeta::Meta(Meta::Path(path)) => path.is_ident("identity"), - _ => false, - }); - - if fixed { - bind.to_token_stream() - } else { - quote! { - ::rustc_middle::ty::fold::TypeFoldable::try_fold_with(#bind, __folder)? - } - } - }) - }) + fn supertraits(interner: &impl ToTokens) -> TokenStream { + Visitable::traversable(interner) + } + fn traverse(bind: TokenStream, noop: bool) -> TokenStream { + if noop { + bind + } else { + quote! { ::rustc_middle::ty::prefer_noop_traversal_if_applicable!(#bind.try_fold_with(folder))? } + } + } + fn arm( + variant: &synstructure::VariantInfo<'_>, + mut f: impl FnMut(&synstructure::BindingInfo<'_>) -> TokenStream, + ) -> TokenStream { + let bindings = variant.bindings(); + variant.construct(|_, index| f(&bindings[index])) } - fn impl_body(arms: impl ToTokens) -> TokenStream { + fn impl_body( + interner: impl ToTokens, + traverser: impl ToTokens, + body: impl ToTokens, + ) -> TokenStream { quote! { - fn try_fold_with<__F: ::rustc_middle::ty::fold::FallibleTypeFolder<::rustc_middle::ty::TyCtxt<'tcx>>>( + fn try_fold_with<#traverser: ::rustc_middle::ty::fold::FallibleTypeFolder<#interner>>( self, - __folder: &mut __F - ) -> ::core::result::Result { - ::core::result::Result::Ok(match self { #arms }) + folder: &mut #traverser + ) -> ::core::result::Result { + ::core::result::Result::Ok(#body) } } } } impl Traversable for Visitable { - fn traversable() -> TokenStream { - quote! { ::rustc_middle::ty::visit::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>> } + fn traversable(interner: &impl ToTokens) -> TokenStream { + quote! { ::rustc_middle::ty::visit::TypeVisitable<#interner> } } - fn arms(structure: &mut synstructure::Structure<'_>) -> TokenStream { - // ignore fields with #[type_visitable(ignore)] - structure.filter(|bi| { - !bi.ast() - .attrs - .iter() - .map(Attribute::parse_meta) - .filter_map(Result::ok) - .flat_map(|attr| match attr { - Meta::List(list) if list.path.is_ident("type_visitable") => list.nested, - _ => Default::default(), - }) - .any(|nested| match nested { - NestedMeta::Meta(Meta::Path(path)) => path.is_ident("ignore"), - _ => false, - }) - }); - - structure.each(|bind| { - quote! { - ::rustc_middle::ty::visit::TypeVisitable::visit_with(#bind, __visitor)?; - } - }) + fn supertraits(_: &impl ToTokens) -> TokenStream { + quote! { ::core::clone::Clone + ::core::fmt::Debug } + } + fn traverse(bind: TokenStream, noop: bool) -> TokenStream { + if noop { + quote! {} + } else { + quote! { ::rustc_middle::ty::prefer_noop_traversal_if_applicable!(#bind.visit_with(visitor))?; } + } } - fn impl_body(arms: impl ToTokens) -> TokenStream { + fn arm( + variant: &synstructure::VariantInfo<'_>, + f: impl FnMut(&synstructure::BindingInfo<'_>) -> TokenStream, + ) -> TokenStream { + variant.bindings().iter().map(f).collect() + } + fn impl_body( + interner: impl ToTokens, + traverser: impl ToTokens, + body: impl ToTokens, + ) -> TokenStream { quote! { - fn visit_with<__V: ::rustc_middle::ty::visit::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>( + fn visit_with<#traverser: ::rustc_middle::ty::visit::TypeVisitor<#interner>>( &self, - __visitor: &mut __V - ) -> ::std::ops::ControlFlow<__V::BreakTy> { - match self { #arms } - ::std::ops::ControlFlow::Continue(()) + visitor: &mut #traverser + ) -> ::core::ops::ControlFlow<#traverser::BreakTy> { + #body + ::core::ops::ControlFlow::Continue(()) } } } @@ -109,17 +144,78 @@ impl Traversable for Visitable { pub fn traversable_derive( mut structure: synstructure::Structure<'_>, ) -> TokenStream { - if let syn::Data::Union(_) = structure.ast().data { - panic!("cannot derive on union") - } + let skip_traversal = quote! { ::rustc_middle::ty::SkipTraversalAutoImplOnly }; + + let interner = gen_interner(&mut structure); + let traverser = gen_param("T", &structure.ast().generics); + let traversable = T::traversable(&interner); + let ast = structure.ast(); - structure.add_bounds(synstructure::AddBounds::Generics); + structure.add_bounds(synstructure::AddBounds::None); structure.bind_with(|_| synstructure::BindStyle::Move); - if !structure.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { - structure.add_impl_generic(parse_quote! { 'tcx }); + // If our derived implementation will be generic over the traversable type, then we must + // constrain it to only those generic combinations that satisfy the traversable trait's + // supertraits. + let is_generic = !ast.generics.params.is_empty(); + if is_generic { + let supertraits = T::supertraits(&interner); + structure.add_where_predicate(parse_quote! { Self: #supertraits }); } - let arms = T::arms(&mut structure); - structure.bound_impl(T::traversable(), T::impl_body(arms)) + let body = if let Some(_span) = find_skip_traversal_attribute(&ast.attrs) { + if !is_generic { + // FIXME: spanned error causes ICE: "suggestion must not have overlapping parts" + return quote!({ + ::core::compile_error!("non-generic types are automatically skipped where possible"); + }); + } + structure.add_where_predicate(parse_quote! { Self: #skip_traversal }); + T::traverse(quote! { self }, true) + } else { + // We add predicates to each generic field type, rather than to our generic type parameters. + // This results in a "perfect derive" that avoids having to propagate `#[skip_traversal]` annotations + // into wrapping types, but it can result in trait solver cycles if any type parameters are involved + // in recursive type definitions; fortunately that is not the case (yet). + let mut predicates = HashMap::new(); + let arms = structure.each_variant(|variant| { + let skipped_variant_span = find_skip_traversal_attribute(&variant.ast().attrs); + if variant.referenced_ty_params().is_empty() { + if let Some(span) = skipped_variant_span { + return quote_spanned!(span => { + ::core::compile_error!("non-generic variants are automatically skipped where possible"); + }); + } + } + T::arm(variant, |bind| { + let ast = bind.ast(); + let skipped_span = skipped_variant_span.or_else(|| find_skip_traversal_attribute(&ast.attrs)); + if bind.referenced_ty_params().is_empty() { + if skipped_variant_span.is_none() && let Some(span) = skipped_span { + return quote_spanned!(span => { + ::core::compile_error!("non-generic fields are automatically skipped where possible"); + }); + } + } else if let Some(prev) = predicates.insert(ast.ty.clone(), skipped_span) && let Some(span) = prev.xor(skipped_span) { + // It makes no sense to allow this. Skipping the field requires that its type impls the `SkipTraversalAutoImplOnly` + // auto-trait, which means that it does not contain anything interesting to traversers; not also skipping all other + // fields of identical type is indicative of a likely erroneous assumption on the author's part--especially since + // such other (unannotated) fields will be skipped anyway, as the noop traversal takes precedence. + return quote_spanned!(span => { + ::core::compile_error!("generic field skipped here, but another field of the same type is not skipped"); + }); + } + T::traverse(bind.into_token_stream(), skipped_span.is_some()) + }) + }); + // the order in which `where` predicates appear in rust source is irrelevant + #[allow(rustc::potential_query_instability)] + for (ty, skip) in predicates { + let bound = if skip.is_some() { &skip_traversal } else { &traversable }; + structure.add_where_predicate(parse_quote! { #ty: #bound }); + } + quote! { match self { #arms } } + }; + + structure.bound_impl(traversable, T::impl_body(interner, traverser, body)) } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index d85d68870d7d8..8173374f806d4 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -161,8 +161,6 @@ pub struct GeneratorLayout<'tcx> { /// Which saved locals are storage-live at the same time. Locals that do not /// have conflicts with each other are allowed to overlap in the computed /// layout. - #[type_foldable(identity)] - #[type_visitable(ignore)] pub storage_conflicts: BitMatrix, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index e4694809cd1a2..eca4b5bcccb38 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -68,7 +68,7 @@ use rustc_target::abi::{Layout, LayoutS, TargetDataLayout, VariantIdx}; use rustc_target::spec::abi; use rustc_type_ir::sty::TyKind::*; use rustc_type_ir::WithCachedTypeInfo; -use rustc_type_ir::{CollectAndApply, DynKind, Interner, TypeFlags}; +use rustc_type_ir::{CollectAndApply, DynKind, Interner, SkipTraversalAutoImplOnly, TypeFlags}; use std::any::Any; use std::assert_matches::debug_assert_matches; @@ -130,6 +130,12 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type PlaceholderRegion = ty::PlaceholderRegion; } +impl !SkipTraversalAutoImplOnly for Binder<'_, T> {} +impl !SkipTraversalAutoImplOnly for Ty<'_> {} +impl !SkipTraversalAutoImplOnly for ty::Const<'_> {} +impl !SkipTraversalAutoImplOnly for Region<'_> {} +impl !SkipTraversalAutoImplOnly for Predicate<'_> {} + type InternedSet<'tcx, T> = ShardedHashMap, ()>; pub struct CtxtInterners<'tcx> { diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index d66f436f947a3..976b5369fb1e3 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -4,7 +4,9 @@ use rustc_hir::def_id::DefId; use std::collections::BTreeMap; -pub use rustc_type_ir::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; +pub use rustc_type_ir::fold::{ + FallibleTypeFolder, SpecTypeFoldable, TypeFoldable, TypeFolder, TypeSuperFoldable, +}; /////////////////////////////////////////////////////////////////////////// // Some sample folders diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 6814cadb9a8e4..c9d4dfdaede78 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sso::SsoHashSet; use std::ops::ControlFlow; -pub use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; +pub use rustc_type_ir::visit::{SpecTypeVisitable, TypeSuperVisitable, TypeVisitable, TypeVisitor}; pub trait TypeVisitableExt<'tcx>: TypeVisitable> { /// Returns `true` if `self` has any late-bound regions that are either diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 3a053d4c6a997..00b6da627f1ec 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -42,7 +42,8 @@ //! - ty.super_fold_with(folder) //! - u.fold_with(folder) //! ``` -use crate::{visit::TypeVisitable, Interner}; +use crate::{visit::TypeVisitable, Interner, SkipTraversalAutoImplOnly}; +use std::marker::PhantomData; /// This trait is implemented for every type that can be folded, /// providing the skeleton of the traversal. @@ -237,3 +238,38 @@ where Ok(self.fold_predicate(p)) } } + +pub trait SpecTypeFoldable { + type Item; + fn spec_try_fold_with>( + self, + value: Self::Item, + folder: &mut F, + ) -> Result; +} + +impl> SpecTypeFoldable for PhantomData { + type Item = T; + + #[inline(always)] + fn spec_try_fold_with>( + self, + value: T, + folder: &mut F, + ) -> Result { + value.try_fold_with(folder) + } +} + +impl SpecTypeFoldable for &PhantomData { + type Item = T; + + #[inline(always)] + fn spec_try_fold_with>( + self, + value: T, + _: &mut F, + ) -> Result { + Ok(value) + } +} diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 5a991e03dee52..83354d71f2b11 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -1,4 +1,5 @@ #![feature(associated_type_defaults)] +#![feature(auto_traits)] #![feature(fmt_helpers_for_derive)] #![feature(min_specialization)] #![feature(never_type)] @@ -27,7 +28,7 @@ pub mod ty_info; pub mod visit; #[macro_use] -mod macros; +pub mod macros; mod structural_impls; pub use codec::*; @@ -69,6 +70,23 @@ pub trait Interner: Sized { type PlaceholderRegion: Clone + Debug + Hash + Ord; } +/// Marker trait for types that do not need to be traversed by folders or visitors, +/// because they do not contain anything that could be of interest. +/// +/// Negative implementations of this trait should be provided by types that *are* +/// of interest for folders and visitors, namely for any given `I: Interner`: +/// * `I::Binder` +/// * `I::Ty` +/// * `I::Const` +/// * `I::Region` +/// * `I::Predicate` +/// +/// Manually implementing this trait is DANGEROUS and should NEVER be done, as it +/// can lead to miscompilation. Even if the type for which you wish to implement +/// this trait does not today contain anything of interest to folders or visitors, +/// a field added or changed in future may cause breakage. +pub auto trait SkipTraversalAutoImplOnly {} + /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` /// that produces `T` items. You could combine them with /// `f(&iter.collect::>())`, but this requires allocating memory for the diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index 6c181039730b7..320053a2ab805 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -174,3 +174,31 @@ macro_rules! EnumTypeTraversalImpl { ) }; } + +#[inline(always)] +pub fn unreachable_phantom_constraint(_: T) -> std::marker::PhantomData { + unreachable!() +} + +#[macro_export] +macro_rules! prefer_noop_traversal_if_applicable { + ($val:tt.try_fold_with($folder:expr)) => {{ + use $crate::fold::SpecTypeFoldable as _; + $crate::prefer_noop_traversal_if_applicable!($val.spec_try_fold_with($folder)) + }}; + ($val:tt.visit_with($visitor:expr)) => {{ + use $crate::visit::SpecTypeVisitable as _; + $crate::prefer_noop_traversal_if_applicable!($val.spec_visit_with($visitor)) + }}; + ($val:tt.$method:ident($traverser:expr)) => {{ + let val = $val; + + #[allow(unreachable_code)] + let p = 'p: { + break 'p ::core::marker::PhantomData; + break 'p $crate::macros::unreachable_phantom_constraint(val); + }; + + (&&p).$method(val, $traverser) + }}; +} diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 62239fd20066a..98f58a9645146 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -38,9 +38,10 @@ //! - ty.super_visit_with(visitor) //! - u.visit_with(visitor) //! ``` -use crate::Interner; +use crate::{Interner, SkipTraversalAutoImplOnly}; use std::fmt; +use std::marker::PhantomData; use std::ops::ControlFlow; /// This trait is implemented for every type that can be visited, @@ -113,3 +114,34 @@ pub trait TypeVisitor: Sized { p.super_visit_with(self) } } + +pub trait SpecTypeVisitable { + type Item: ?Sized; + fn spec_visit_with>( + self, + value: &Self::Item, + visitor: &mut V, + ) -> ControlFlow; +} + +impl> SpecTypeVisitable for PhantomData<&T> { + type Item = T; + + #[inline(always)] + fn spec_visit_with>( + self, + value: &T, + visitor: &mut V, + ) -> ControlFlow { + value.visit_with(visitor) + } +} + +impl SpecTypeVisitable for &PhantomData<&T> { + type Item = T; + + #[inline(always)] + fn spec_visit_with>(self, _: &T, _: &mut V) -> ControlFlow { + ControlFlow::Continue(()) + } +} From d2ec961a675addb47b3307bdd2a5267e00d8cc3e Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sun, 26 Feb 2023 00:40:02 +0000 Subject: [PATCH 04/22] Use specialisation in ParamEnv traversable impls --- compiler/rustc_middle/src/ty/mod.rs | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 298b2c3073cd3..9f5e9dc395252 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1627,17 +1627,31 @@ impl<'tcx> TypeFoldable> for ParamEnv<'tcx> { folder: &mut F, ) -> Result { Ok(ParamEnv::new( - self.caller_bounds().try_fold_with(folder)?, - self.reveal().try_fold_with(folder)?, - self.constness(), + rustc_type_ir::prefer_noop_traversal_if_applicable!( + { self.caller_bounds() }.try_fold_with(folder) + )?, + rustc_type_ir::prefer_noop_traversal_if_applicable!( + { self.reveal() }.try_fold_with(folder) + )?, + rustc_type_ir::prefer_noop_traversal_if_applicable!( + { self.constness() }.try_fold_with(folder) + )?, )) } } impl<'tcx> TypeVisitable> for ParamEnv<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.caller_bounds().visit_with(visitor)?; - self.reveal().visit_with(visitor) + rustc_type_ir::prefer_noop_traversal_if_applicable!( + { &self.caller_bounds() }.visit_with(visitor) + )?; + rustc_type_ir::prefer_noop_traversal_if_applicable!( + { &self.reveal() }.visit_with(visitor) + )?; + rustc_type_ir::prefer_noop_traversal_if_applicable!( + { &self.constness() }.visit_with(visitor) + )?; + ControlFlow::Continue(()) } } From 99e070ff44c608b8c8a64d5a0422089986792b16 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sat, 25 Feb 2023 23:16:22 +0000 Subject: [PATCH 05/22] Derive traversable impls for UserTypeProjection UserTypeProjection had explicit traversable implementations, but which were in effect no-ops. There is no good reason for these impls not be derived instead. --- compiler/rustc_middle/src/mir/mod.rs | 27 +++------------------------ 1 file changed, 3 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 42c0354d03af5..d5d2907566cf8 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -9,7 +9,7 @@ use crate::mir::visit::MirVisitable; use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; use crate::ty::print::{FmtPrinter, Printer}; -use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; +use crate::ty::visit::TypeVisitableExt; use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex}; use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; @@ -36,7 +36,7 @@ use either::Either; use std::borrow::Cow; use std::fmt::{self, Debug, Display, Formatter, Write}; -use std::ops::{ControlFlow, Index, IndexMut}; +use std::ops::{Index, IndexMut}; use std::{iter, mem}; pub use self::query::*; @@ -2709,6 +2709,7 @@ impl<'tcx> UserTypeProjections { /// `field[0]` (aka `.0`), indicating that the type of `s` is /// determined by finding the type of the `.0` field from `T`. #[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] +#[derive(TypeFoldable, TypeVisitable)] pub struct UserTypeProjection { pub base: UserTypeAnnotationIndex, pub projs: Vec, @@ -2752,28 +2753,6 @@ impl UserTypeProjection { } } -impl<'tcx> TypeFoldable> for UserTypeProjection { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - Ok(UserTypeProjection { - base: self.base.try_fold_with(folder)?, - projs: self.projs.try_fold_with(folder)?, - }) - } -} - -impl<'tcx> TypeVisitable> for UserTypeProjection { - fn visit_with>>( - &self, - visitor: &mut Vs, - ) -> ControlFlow { - self.base.visit_with(visitor) - // Note: there's nothing in `self.proj` to visit. - } -} - rustc_index::newtype_index! { #[derive(HashStable)] #[debug_format = "promoted[{}]"] From 408ba98e3dbf52115c2869ffbc8333d311b42879 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sat, 25 Feb 2023 23:07:41 +0000 Subject: [PATCH 06/22] Derive traversable impls for BindingForm BindingForm has been a no-op traversable ever since it was first added in cac6126, but it was modified in 0193d1f to (optionally) contain a Place without its implementations being updated to fold/visit such. By using the derive macro to implement the visitable traits, we ensure that all contained types of interest are folded/visited. --- compiler/rustc_middle/src/mir/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index d5d2907566cf8..574a8b364e3c2 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -674,7 +674,7 @@ pub enum LocalKind { ReturnPointer, } -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] pub struct VarBindingForm<'tcx> { /// Is variable bound via `x`, `mut x`, `ref x`, or `ref mut x`? pub binding_mode: ty::BindingMode, @@ -696,7 +696,7 @@ pub struct VarBindingForm<'tcx> { pub pat_span: Span, } -#[derive(Clone, Debug, TyEncodable, TyDecodable)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] pub enum BindingForm<'tcx> { /// This is a binding for a non-`self` binding, or a `self` that has an explicit type. Var(VarBindingForm<'tcx>), @@ -706,7 +706,7 @@ pub enum BindingForm<'tcx> { RefForGuard, } -TrivialTypeTraversalAndLiftImpls! { +CloneLiftImpls! { for<'tcx> { BindingForm<'tcx>, } From ef977767916c473662e593407a059f8d89de6314 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sun, 26 Feb 2023 00:31:37 +0000 Subject: [PATCH 07/22] Derive traversable impls for Obligation Ever since folding was first added in c5754f397, obligations have not folded or visited their causes the ObligationCauseCode potentially containing types that may be of interest to a folder or visitor. By using the derive macro to implement the visitable traits, we ensure that all contained types of interest are folded/visited. --- compiler/rustc_infer/src/traits/mod.rs | 2 +- .../src/traits/structural_impls.rs | 33 +------------------ 2 files changed, 2 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 77c67c14ecc55..e4fe32bb181ca 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -34,7 +34,7 @@ pub use rustc_middle::traits::*; /// either identifying an `impl` (e.g., `impl Eq for i32`) that /// satisfies the obligation, or else finding a bound that is in /// scope. The eventual result is usually a `Selection` (defined below). -#[derive(Clone, PartialEq, Eq, Hash)] +#[derive(Clone, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] pub struct Obligation<'tcx, T> { /// The reason we have to prove this thing. pub cause: ObligationCause<'tcx>, diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index 3a5273b0359e4..d823e8b78cb31 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -1,11 +1,8 @@ use crate::traits; use crate::traits::project::Normalized; -use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable}; -use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor}; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty; use std::fmt; -use std::ops::ControlFlow; // Structural impls for the structs in `traits`. @@ -57,31 +54,3 @@ impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> { write!(f, "MismatchedProjectionTypes({:?})", self.err) } } - -/////////////////////////////////////////////////////////////////////////// -// TypeFoldable implementations. - -impl<'tcx, O: TypeFoldable>> TypeFoldable> - for traits::Obligation<'tcx, O> -{ - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - Ok(traits::Obligation { - cause: self.cause, - recursion_depth: self.recursion_depth, - predicate: self.predicate.try_fold_with(folder)?, - param_env: self.param_env.try_fold_with(folder)?, - }) - } -} - -impl<'tcx, O: TypeVisitable>> TypeVisitable> - for traits::Obligation<'tcx, O> -{ - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - self.predicate.visit_with(visitor)?; - self.param_env.visit_with(visitor) - } -} From 5d4dd4b532498eb0c993f151ca09b11b4f8b0d35 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sat, 25 Feb 2023 23:20:07 +0000 Subject: [PATCH 08/22] Simplify traversable impls for ExternalConstraints Rather than being concerned with internals of ExternalConstraintsData, we derive traversable impls for that type to which we then delegate. --- compiler/rustc_middle/src/traits/solve.rs | 25 +++-------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 92d3e73e683cd..3d0b9bf3a25d4 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -1,5 +1,3 @@ -use std::ops::ControlFlow; - use rustc_data_structures::intern::Interned; use rustc_query_system::cache::Cache; @@ -7,8 +5,7 @@ use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints}; use crate::traits::query::NoSolution; use crate::traits::Canonical; use crate::ty::{ - self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, - TypeVisitor, + self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitor, }; pub type EvaluationCache<'tcx> = Cache, QueryResult<'tcx>>; @@ -128,21 +125,7 @@ impl<'tcx> TypeFoldable> for ExternalConstraints<'tcx> { self, folder: &mut F, ) -> Result { - Ok(FallibleTypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData { - region_constraints: self.region_constraints.clone().try_fold_with(folder)?, - opaque_types: self - .opaque_types - .iter() - .map(|opaque| opaque.try_fold_with(folder)) - .collect::>()?, - })) - } - - fn fold_with>>(self, folder: &mut F) -> Self { - TypeFolder::interner(folder).mk_external_constraints(ExternalConstraintsData { - region_constraints: self.region_constraints.clone().fold_with(folder), - opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(), - }) + Ok(folder.interner().mk_external_constraints((*self).clone().try_fold_with(folder)?)) } } @@ -151,8 +134,6 @@ impl<'tcx> TypeVisitable> for ExternalConstraints<'tcx> { &self, visitor: &mut V, ) -> std::ops::ControlFlow { - self.region_constraints.visit_with(visitor)?; - self.opaque_types.visit_with(visitor)?; - ControlFlow::Continue(()) + (**self).visit_with(visitor) } } From b75b00d913bf0abe137dcfc6d9fe2e618c94c009 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sat, 25 Feb 2023 15:19:51 +0000 Subject: [PATCH 09/22] Remove superfluous traversable impls --- compiler/rustc_middle/src/hir/place.rs | 2 - compiler/rustc_middle/src/infer/canonical.rs | 8 +-- compiler/rustc_middle/src/mir/basic_blocks.rs | 2 +- compiler/rustc_middle/src/mir/coverage.rs | 4 +- .../rustc_middle/src/mir/interpret/error.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 2 +- compiler/rustc_middle/src/mir/query.rs | 2 +- compiler/rustc_middle/src/mir/syntax.rs | 6 +- .../rustc_middle/src/mir/type_foldable.rs | 31 ++------- compiler/rustc_middle/src/thir.rs | 1 - compiler/rustc_middle/src/traits/mod.rs | 1 - compiler/rustc_middle/src/traits/select.rs | 2 +- compiler/rustc_middle/src/traits/solve.rs | 4 +- .../rustc_middle/src/ty/abstract_const.rs | 4 +- compiler/rustc_middle/src/ty/binding.rs | 2 +- compiler/rustc_middle/src/ty/closure.rs | 5 -- .../rustc_middle/src/ty/structural_impls.rs | 68 ++++--------------- .../rustc_type_ir/src/structural_impls.rs | 51 ++++++++------ 18 files changed, 67 insertions(+), 130 deletions(-) diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index 83d3b0100b844..dd91577a78a66 100644 --- a/compiler/rustc_middle/src/hir/place.rs +++ b/compiler/rustc_middle/src/hir/place.rs @@ -5,7 +5,6 @@ use rustc_hir::HirId; use rustc_target::abi::VariantIdx; #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub enum PlaceBase { /// A temporary variable. Rvalue, @@ -18,7 +17,6 @@ pub enum PlaceBase { } #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub enum ProjectionKind { /// A dereference of a pointer, reference or `Box` of the given type. Deref, diff --git a/compiler/rustc_middle/src/infer/canonical.rs b/compiler/rustc_middle/src/infer/canonical.rs index 7f8fc17744dc9..6b7a9188f27b1 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -387,11 +387,9 @@ impl<'tcx, V> Canonical<'tcx, V> { pub type QueryOutlivesConstraint<'tcx> = (ty::OutlivesPredicate, Region<'tcx>>, ConstraintCategory<'tcx>); -TrivialTypeTraversalAndLiftImpls! { - for <'tcx> { - crate::infer::canonical::Certainty, - crate::infer::canonical::CanonicalTyVarKind, - } +CloneLiftImpls! { + crate::infer::canonical::Certainty, + crate::infer::canonical::CanonicalTyVarKind, } impl<'tcx> CanonicalVarValues<'tcx> { diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index b93871769b791..97e7d5d011d08 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -174,7 +174,7 @@ impl<'tcx> graph::WithPredecessors for BasicBlocks<'tcx> { } } -TrivialTypeTraversalAndLiftImpls! { +CloneLiftImpls! { Cache, } diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index db24dae11304f..7d235aa662296 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -95,7 +95,7 @@ impl From for ExpressionOperandId { } } -#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] pub enum CoverageKind { Counter { function_source_hash: u64, @@ -147,7 +147,6 @@ impl Debug for CoverageKind { } #[derive(Clone, TyEncodable, TyDecodable, Hash, HashStable, PartialEq, Eq, PartialOrd, Ord)] -#[derive(TypeFoldable, TypeVisitable)] pub struct CodeRegion { pub file_name: Symbol, pub start_line: u32, @@ -167,7 +166,6 @@ impl Debug for CodeRegion { } #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub enum Op { Subtract, Add, diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index c5137cf0666ea..18920e56ba85f 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -27,7 +27,7 @@ impl From for ErrorHandled { } } -TrivialTypeTraversalAndLiftImpls! { +CloneLiftImpls! { ErrorHandled, } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 574a8b364e3c2..226be9c51e167 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2635,7 +2635,7 @@ impl<'tcx> UnevaluatedConst<'tcx> { /// The first will lead to the constraint `w: &'1 str` (for some /// inferred region `'1`). The second will lead to the constraint `w: /// &'static str`. -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub struct UserTypeProjections { pub contents: Vec<(UserTypeProjection, Span)>, } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 8173374f806d4..053131256ea46 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -370,7 +370,7 @@ pub enum ConstraintCategory<'tcx> { } #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] -#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] +#[derive(TyEncodable, TyDecodable, HashStable)] pub enum ReturnConstraint { Normal, ClosureUpvar(Field), diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index b16b6616415aa..fe24e11d8f2e8 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -491,7 +491,6 @@ pub enum FakeReadCause { } #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub struct Coverage { pub kind: CoverageKind, pub code_region: Option, @@ -901,6 +900,7 @@ pub enum ProjectionElem { /// /// The `x[i]` is turned into a `Deref` followed by an `Index`, not just an `Index`. The same /// thing is true of the `ConstantIndex` and `Subslice` projections below. + #[skip_traversal] Index(V), /// These indices are generated by slice patterns. Easiest to explain @@ -1184,7 +1184,7 @@ pub enum NullOp { } #[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] -#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] +#[derive(HashStable, TyEncodable, TyDecodable)] pub enum UnOp { /// The `!` operator for logical inversion Not, @@ -1193,7 +1193,7 @@ pub enum UnOp { } #[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Ord, Eq, Hash)] -#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, HashStable)] pub enum BinOp { /// The `+` operator (addition) Add, diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 9881583214eb4..1719398125e52 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -1,15 +1,16 @@ //! `TypeFoldable` implementations for MIR types -use rustc_ast::InlineAsmTemplatePiece; - use super::*; use crate::ty; TrivialTypeTraversalAndLiftImpls! { + FakeReadCause, +} + +CloneLiftImpls! { BlockTailInfo, MirPhase, SourceInfo, - FakeReadCause, RetagKind, SourceScope, SourceScopeLocalData, @@ -24,30 +25,6 @@ TrivialTypeTraversalAndLiftImpls! { GeneratorSavedLocal, } -TrivialTypeTraversalImpls! { - for <'tcx> { - ConstValue<'tcx>, - } -} - -impl<'tcx> TypeFoldable> for &'tcx [InlineAsmTemplatePiece] { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) - } -} - -impl<'tcx> TypeFoldable> for &'tcx [Span] { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) - } -} - impl<'tcx> TypeFoldable> for &'tcx ty::List> { fn try_fold_with>>( self, diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 3b11fab8cdf57..a9b3ccf55bddc 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -231,7 +231,6 @@ pub enum StmtKind<'tcx> { } #[derive(Clone, Debug, Copy, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] -#[derive(TypeFoldable, TypeVisitable)] pub struct LocalVarId(pub hir::HirId); /// A THIR expression. diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index fb3e9cb126317..c375163e9d37e 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -451,7 +451,6 @@ pub enum ObligationCauseCode<'tcx> { /// we can walk in order to obtain precise spans for any /// 'nested' types (e.g. `Foo` in `Option`). #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, Encodable, Decodable)] -#[derive(TypeVisitable, TypeFoldable)] pub enum WellFormedLoc { /// Use the type of the provided definition. Ty(LocalDefId), diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index 1cc9fd526b44f..9179f26fae490 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -304,7 +304,7 @@ impl From for OverflowError { } } -TrivialTypeTraversalAndLiftImpls! { +CloneLiftImpls! { OverflowError, } diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 3d0b9bf3a25d4..794a2089d444f 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -44,7 +44,7 @@ pub struct Response<'tcx> { pub certainty: Certainty, } -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum Certainty { Yes, Maybe(MaybeCause), @@ -74,7 +74,7 @@ impl Certainty { } /// Why we failed to evaluate a goal. -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub enum MaybeCause { /// We failed due to ambiguity. This ambiguity can either /// be a true ambiguity, i.e. there are multiple different answers, diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index f889ce82706b3..34933f0c568b1 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -7,7 +7,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::DefId; #[derive(Hash, Debug, Clone, Copy, Ord, PartialOrd, PartialEq, Eq)] -#[derive(TyDecodable, TyEncodable, HashStable, TypeVisitable, TypeFoldable)] +#[derive(TyDecodable, TyEncodable, HashStable)] pub enum CastKind { /// thir::ExprKind::As As, @@ -28,7 +28,7 @@ impl From for NotConstEvaluatable { } } -TrivialTypeTraversalAndLiftImpls! { +CloneLiftImpls! { NotConstEvaluatable, } diff --git a/compiler/rustc_middle/src/ty/binding.rs b/compiler/rustc_middle/src/ty/binding.rs index a5b05a4f9b526..5a88a2649a785 100644 --- a/compiler/rustc_middle/src/ty/binding.rs +++ b/compiler/rustc_middle/src/ty/binding.rs @@ -6,7 +6,7 @@ pub enum BindingMode { BindByValue(Mutability), } -TrivialTypeTraversalAndLiftImpls! { BindingMode, } +CloneLiftImpls! { BindingMode, } impl BindingMode { pub fn convert(BindingAnnotation(by_ref, mutbl): BindingAnnotation) -> BindingMode { diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index dc2bd54b7fe48..1547810e713aa 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -20,7 +20,6 @@ use self::BorrowKind::*; pub const CAPTURE_STRUCT_LOCAL: mir::Local = mir::Local::from_u32(1); #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub struct UpvarPath { pub hir_id: hir::HirId, } @@ -29,7 +28,6 @@ pub struct UpvarPath { /// the original var ID (that is, the root variable that is referenced /// by the upvar) and the ID of the closure expression. #[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub struct UpvarId { pub var_path: UpvarPath, pub closure_expr_id: LocalDefId, @@ -44,7 +42,6 @@ impl UpvarId { /// Information describing the capture of an upvar. This is computed /// during `typeck`, specifically by `regionck`. #[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub enum UpvarCapture { /// Upvar is captured by value. This is always true when the /// closure is labeled `move`, but can also be true in other cases @@ -298,7 +295,6 @@ pub fn is_ancestor_or_same_capture( /// for a particular capture as well as identifying the part of the source code /// that triggered this capture to occur. #[derive(PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub struct CaptureInfo { /// Expr Id pointing to use that resulted in selecting the current capture kind /// @@ -377,7 +373,6 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc } #[derive(Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub enum BorrowKind { /// Data must be immutable and is aliasable. ImmBorrow, diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index ef643531bb288..74a7e680240ef 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -8,7 +8,7 @@ use crate::mir::{Field, ProjectionKind}; use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; use crate::ty::print::{with_no_trimmed_paths, FmtPrinter, Printer}; use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; -use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt}; +use crate::ty::{self, AliasTy, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_hir::def::Namespace; use rustc_index::vec::{Idx, IndexVec}; use rustc_target::abi::TyAndLayout; @@ -208,13 +208,7 @@ CloneLiftImpls! { u64, String, rustc_type_ir::DebruijnIndex, -} -// For things about which the type library does not know, or does not -// provide any traversal implementations, we need to provide both a Lift -// implementation and traversal implementations (the latter only for -// TyCtxt<'_> interners). -TrivialTypeTraversalAndLiftImpls! { ::rustc_target::abi::VariantIdx, crate::middle::region::Scope, crate::ty::FloatTy, @@ -223,14 +217,10 @@ TrivialTypeTraversalAndLiftImpls! { ::rustc_ast::NodeId, ::rustc_span::symbol::Symbol, ::rustc_hir::def::Res, - ::rustc_hir::def_id::DefId, - ::rustc_hir::def_id::LocalDefId, ::rustc_hir::HirId, ::rustc_hir::MatchSource, ::rustc_hir::Mutability, - ::rustc_hir::Unsafety, ::rustc_target::asm::InlineAsmRegOrRegClass, - ::rustc_target::spec::abi::Abi, crate::mir::coverage::ExpressionOperandId, crate::mir::coverage::CounterValueReference, crate::mir::coverage::InjectedExpressionId, @@ -241,11 +231,6 @@ TrivialTypeTraversalAndLiftImpls! { crate::traits::Reveal, crate::ty::adjustment::AutoBorrowMutability, crate::ty::AdtKind, - crate::ty::BoundConstness, - // Including `BoundRegionKind` is a *bit* dubious, but direct - // references to bound region appear in `ty::Error`, and aren't - // really meant to be folded. In general, we can only fold a fully - // general `Region`. crate::ty::BoundRegionKind, crate::ty::AssocItem, crate::ty::AssocKind, @@ -262,7 +247,6 @@ TrivialTypeTraversalAndLiftImpls! { crate::ty::RegionVid, crate::ty::UniverseIndex, crate::ty::Variance, - ::rustc_span::Span, ::rustc_span::symbol::Ident, ::rustc_errors::ErrorGuaranteed, Field, @@ -272,7 +256,20 @@ TrivialTypeTraversalAndLiftImpls! { ty::Placeholder, } +// For things about which the type library does not know, or does not +// provide any traversal implementations, we need to provide both a Lift +// implementation and traversal implementations (the latter only for +// TyCtxt<'_> interners). TrivialTypeTraversalAndLiftImpls! { + ::rustc_hir::def_id::DefId, + ::rustc_hir::def_id::LocalDefId, + ::rustc_hir::Unsafety, + ::rustc_target::spec::abi::Abi, + crate::ty::BoundConstness, + ::rustc_span::Span, +} + +CloneLiftImpls! { for<'tcx> { ty::ValTree<'tcx>, } @@ -372,25 +369,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> { /////////////////////////////////////////////////////////////////////////// // Traversal implementations. -/// AdtDefs are basically the same as a DefId. -impl<'tcx> TypeFoldable> for ty::AdtDef<'tcx> { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) - } -} - -impl<'tcx> TypeVisitable> for ty::AdtDef<'tcx> { - fn visit_with>>( - &self, - _visitor: &mut V, - ) -> ControlFlow { - ControlFlow::Continue(()) - } -} - impl<'tcx, T: TypeFoldable>> TypeFoldable> for ty::Binder<'tcx, T> { fn try_fold_with>>( self, @@ -681,24 +659,6 @@ impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { } } -impl<'tcx> TypeFoldable> for InferConst<'tcx> { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) - } -} - -impl<'tcx> TypeVisitable> for InferConst<'tcx> { - fn visit_with>>( - &self, - _visitor: &mut V, - ) -> ControlFlow { - ControlFlow::Continue(()) - } -} - impl<'tcx> TypeSuperVisitable> for ty::UnevaluatedConst<'tcx> { fn super_visit_with>>( &self, diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index 3ebe241042f25..45f7dcfec5abe 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -22,16 +22,20 @@ TrivialTypeTraversalImpls! { (), bool, usize, - u16, - u32, - u64, - String, - crate::DebruijnIndex, } /////////////////////////////////////////////////////////////////////////// -// Traversal implementations. +// Traversable implementations for upstream types. +// We provide implementations for 2- and 3-element tuples, however (absent specialisation) +// we can only provide for one case: we choose our implementations to be where all elements +// themselves implement the respective traits; thus if an element is a no-op traversal, it +// must provide explicit implementations even though the auto-deref specialisation normally +// would normally negate any need. The derive macros can be used for this purpose however. +// +// Note that if all elements are no-op traversals then the tuple itself will auto-implement +// the `SkipTraversalAutoImplOnly` trait and these implementations will be bypassed; +// consequently explicit implementations on the element types would not then be required. impl, U: TypeFoldable> TypeFoldable for (T, U) { fn try_fold_with>(self, folder: &mut F) -> Result<(T, U), F::Error> { Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?)) @@ -70,19 +74,15 @@ impl, B: TypeVisitable, C: TypeVisitable> } } -EnumTypeTraversalImpl! { - impl TypeFoldable for Option { - (Some)(a), - (None), - } where I: Interner, T: TypeFoldable -} -EnumTypeTraversalImpl! { - impl TypeVisitable for Option { - (Some)(a), - (None), - } where I: Interner, T: TypeVisitable -} - +// As noted above for tuples, (absent specialisation) we can only provide implementations for +// `Result` in one case: we choose our implementations to be where both the `Ok` and `Err` +// types themselves implement the respective traits; thus if one of those types is a no-op +// traversal, it must provide explicit implementations even though the aute-deref specialisation +// normally would negate any need. The derive macros can be used for this purpose however. +// +// Note that if both elements are no-op traversals then the `Result` itself will auto-implement +// the `SkipTraversalAutoImplOnly` trait and these implementations will be bypassed; +// consequently explicit implementations on the element types would not then be required. EnumTypeTraversalImpl! { impl TypeFoldable for Result { (Ok)(a), @@ -96,6 +96,19 @@ EnumTypeTraversalImpl! { } where I: Interner, T: TypeVisitable, E: TypeVisitable, } +EnumTypeTraversalImpl! { + impl TypeFoldable for Option { + (Some)(a), + (None), + } where I: Interner, T: TypeFoldable +} +EnumTypeTraversalImpl! { + impl TypeVisitable for Option { + (Some)(a), + (None), + } where I: Interner, T: TypeVisitable +} + impl> TypeFoldable for Rc { fn try_fold_with>(self, folder: &mut F) -> Result { self.try_map_id(|value| value.try_fold_with(folder)) From 8f8a9207c7d7e3b7a635f608a67171c066bcb5d8 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sat, 25 Feb 2023 17:40:25 +0000 Subject: [PATCH 10/22] Remove superfluous traversable impl for usize --- compiler/rustc_mir_transform/src/function_item_references.rs | 2 +- compiler/rustc_type_ir/src/structural_impls.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index 66d32b954e473..ca68e30813e7e 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -175,7 +175,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { let ty_params = fn_substs.types().map(|ty| format!("{}", ty)); let const_params = fn_substs.consts().map(|c| format!("{}", c)); let params = ty_params.chain(const_params).join(", "); - let num_args = fn_sig.inputs().map_bound(|inputs| inputs.len()).skip_binder(); + let num_args = fn_sig.inputs().skip_binder().len(); let variadic = if fn_sig.c_variadic() { ", ..." } else { "" }; let ret = if fn_sig.output().skip_binder().is_unit() { "" } else { " -> _" }; self.tcx.struct_span_lint_hir( diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index 45f7dcfec5abe..3abc53686df84 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -21,7 +21,6 @@ use std::sync::Arc; TrivialTypeTraversalImpls! { (), bool, - usize, } /////////////////////////////////////////////////////////////////////////// From 4e4b9365359a960ea90c84282a367d7831b0afbf Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sat, 25 Feb 2023 17:41:02 +0000 Subject: [PATCH 11/22] Remove superfluous traversable impl for bool --- compiler/rustc_hir_typeck/src/pat.rs | 2 +- compiler/rustc_type_ir/src/structural_impls.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index c36c75e444368..a53c81c1f13d3 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -561,7 +561,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (lhs, Some((true, rhs_ty, rhs_sp))) => one_side_err(rhs_sp, rhs_ty, lhs), _ => span_bug!(span, "Impossible, verified above."), } - if (lhs, rhs).references_error() { + if (lhs.map(|(_, ty, _)| ty), rhs.map(|(_, ty, _)| ty)).references_error() { err.downgrade_to_delayed_bug(); } if self.tcx.sess.teach(&err.get_code().unwrap()) { diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index 3abc53686df84..f7f70e534557b 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -20,7 +20,6 @@ use std::sync::Arc; TrivialTypeTraversalImpls! { (), - bool, } /////////////////////////////////////////////////////////////////////////// From e3f58d053ff9eca98f1b9610992a45372d73c783 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Mon, 20 Mar 2023 10:12:52 +0000 Subject: [PATCH 12/22] Newtype for FakeRead semi-traversable tuple --- .../src/diagnostics/conflict_errors.rs | 12 +++++++----- .../rustc_borrowck/src/diagnostics/explain_borrow.rs | 10 +++++++--- compiler/rustc_borrowck/src/diagnostics/mod.rs | 7 ++++--- compiler/rustc_borrowck/src/invalidation.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 6 +++--- compiler/rustc_middle/src/mir/mod.rs | 2 +- compiler/rustc_middle/src/mir/syntax.rs | 6 +++++- compiler/rustc_middle/src/mir/type_foldable.rs | 5 +---- compiler/rustc_middle/src/mir/visit.rs | 2 +- compiler/rustc_mir_build/src/build/cfg.rs | 2 +- .../rustc_mir_dataflow/src/move_paths/builder.rs | 2 +- compiler/rustc_mir_transform/src/coverage/spans.rs | 8 ++++---- compiler/rustc_mir_transform/src/remove_zsts.rs | 2 +- .../clippy/clippy_utils/src/qualify_min_const_fn.rs | 4 ++-- 14 files changed, 39 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 7c88205da3b9a..4adda364183b3 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -14,8 +14,9 @@ use rustc_infer::traits::ObligationCause; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ self, AggregateKind, BindingForm, BorrowKind, ClearCrossCrate, ConstraintCategory, - FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, - ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm, + FakeReadCause, FakeReadCauseAndPlace, LocalDecl, LocalInfo, LocalKind, Location, Operand, + Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, + VarBindingForm, }; use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty}; use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex}; @@ -2578,9 +2579,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { impl<'tcx> Visitor<'tcx> for FakeReadCauseFinder<'tcx> { fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) { match statement { - Statement { kind: StatementKind::FakeRead(box (cause, place)), .. } - if *place == self.place => - { + Statement { + kind: StatementKind::FakeRead(box FakeReadCauseAndPlace(cause, place)), + .. + } if *place == self.place => { self.cause = Some(*cause); } _ => (), diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 62b3f3ecfc32f..f25bd3042176d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -6,8 +6,8 @@ use rustc_hir::intravisit::Visitor; use rustc_index::vec::IndexVec; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::{ - Body, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, Operand, Place, - Rvalue, Statement, StatementKind, TerminatorKind, + Body, CastKind, ConstraintCategory, FakeReadCause, FakeReadCauseAndPlace, Local, LocalInfo, + Location, Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind, }; use rustc_middle::ty::adjustment::PointerCast; use rustc_middle::ty::{self, RegionVid, TyCtxt}; @@ -482,7 +482,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let block = &self.body.basic_blocks[location.block]; let kind = if let Some(&Statement { - kind: StatementKind::FakeRead(box (FakeReadCause::ForLet(_), place)), + kind: + StatementKind::FakeRead(box FakeReadCauseAndPlace( + FakeReadCause::ForLet(_), + place, + )), .. }) = block.statements.get(location.statement_index) { diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 611abb01238b8..d09781ce1b026 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -9,8 +9,9 @@ use rustc_hir::GeneratorKind; use rustc_infer::infer::{LateBoundRegionConversionTime, TyCtxtInferExt}; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ - AggregateKind, Constant, FakeReadCause, Field, Local, LocalInfo, LocalKind, Location, Operand, - Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, + AggregateKind, Constant, FakeReadCause, FakeReadCauseAndPlace, Field, Local, LocalInfo, + LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, + StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::print::Print; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; @@ -818,7 +819,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // StatementKind::FakeRead only contains a def_id if they are introduced as a result // of pattern matching within a closure. - if let StatementKind::FakeRead(box (cause, place)) = stmt.kind { + if let StatementKind::FakeRead(box FakeReadCauseAndPlace(cause, place)) = stmt.kind { match cause { FakeReadCause::ForMatchedPlace(Some(closure_def_id)) | FakeReadCause::ForLet(Some(closure_def_id)) => { diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index a71c416328611..378dd1e5dab43 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -62,7 +62,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { self.mutate_place(location, *lhs, Shallow(None)); } - StatementKind::FakeRead(box (_, _)) => { + StatementKind::FakeRead(_) => { // Only relevant for initialized/liveness/safety checks. } StatementKind::Intrinsic(box NonDivergingIntrinsic::Assume(op)) => { diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 5e77f6b190a69..4fe9a48e2b03e 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -30,8 +30,8 @@ use rustc_infer::infer::{ }; use rustc_macros::fluent_messages; use rustc_middle::mir::{ - traversal, Body, ClearCrossCrate, Local, Location, Mutability, NonDivergingIntrinsic, Operand, - Place, PlaceElem, PlaceRef, VarDebugInfoContents, + traversal, Body, ClearCrossCrate, FakeReadCauseAndPlace, Local, Location, Mutability, + NonDivergingIntrinsic, Operand, Place, PlaceElem, PlaceRef, VarDebugInfoContents, }; use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind}; use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; @@ -663,7 +663,7 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx self.mutate_place(location, (*lhs, span), Shallow(None), flow_state); } - StatementKind::FakeRead(box (_, place)) => { + StatementKind::FakeRead(box FakeReadCauseAndPlace(_, place)) => { // Read for match doesn't access any memory and is used to // assert that a place is safe and live. So we don't have to // do any checks here. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 226be9c51e167..e0fe573b80389 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1434,7 +1434,7 @@ impl Debug for Statement<'_> { use self::StatementKind::*; match self.kind { Assign(box (ref place, ref rv)) => write!(fmt, "{:?} = {:?}", place, rv), - FakeRead(box (ref cause, ref place)) => { + FakeRead(box FakeReadCauseAndPlace(ref cause, ref place)) => { write!(fmt, "FakeRead({:?}, {:?})", cause, place) } Retag(ref kind, ref place) => write!( diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index fe24e11d8f2e8..daad160f2ee58 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -278,7 +278,7 @@ pub enum StatementKind<'tcx> { /// When executed at runtime this is a nop. /// /// Disallowed after drop elaboration. - FakeRead(Box<(FakeReadCause, Place<'tcx>)>), + FakeRead(Box>), /// Write the discriminant for a variant to the enum Place. /// @@ -434,6 +434,10 @@ pub enum RetagKind { Default, } +#[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, Hash, HashStable, PartialEq)] +#[derive(TypeFoldable, TypeVisitable)] +pub struct FakeReadCauseAndPlace<'tcx>(pub FakeReadCause, pub Place<'tcx>); + /// The `FakeReadCause` describes the type of pattern why a FakeRead statement exists. #[derive(Copy, Clone, TyEncodable, TyDecodable, Debug, Hash, HashStable, PartialEq)] pub enum FakeReadCause { diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 1719398125e52..e32632b6bee38 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -3,14 +3,11 @@ use super::*; use crate::ty; -TrivialTypeTraversalAndLiftImpls! { - FakeReadCause, -} - CloneLiftImpls! { BlockTailInfo, MirPhase, SourceInfo, + FakeReadCause, RetagKind, SourceScope, SourceScopeLocalData, diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index cffdd7ff37f22..8ae5aa2a5d788 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -367,7 +367,7 @@ macro_rules! make_mir_visitor { ) => { self.visit_assign(place, rvalue, location); } - StatementKind::FakeRead(box (_, place)) => { + StatementKind::FakeRead(box FakeReadCauseAndPlace(_, place)) => { self.visit_place( place, PlaceContext::NonMutatingUse(NonMutatingUseContext::Inspect), diff --git a/compiler/rustc_mir_build/src/build/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs index 4f1623b4c6a7c..254f1d5d776fc 100644 --- a/compiler/rustc_mir_build/src/build/cfg.rs +++ b/compiler/rustc_mir_build/src/build/cfg.rs @@ -85,7 +85,7 @@ impl<'tcx> CFG<'tcx> { cause: FakeReadCause, place: Place<'tcx>, ) { - let kind = StatementKind::FakeRead(Box::new((cause, place))); + let kind = StatementKind::FakeRead(Box::new(FakeReadCauseAndPlace(cause, place))); let stmt = Statement { source_info, kind }; self.push(block, stmt); } diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index d9ceac1154f4a..b6e636ba747c2 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -311,7 +311,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { } self.gather_rvalue(rval); } - StatementKind::FakeRead(box (_, place)) => { + StatementKind::FakeRead(box FakeReadCauseAndPlace(_, place)) => { self.create_move_path(*place); } StatementKind::StorageLive(_) => {} diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 2f1202586594a..8e6030ec804e1 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -5,8 +5,8 @@ use itertools::Itertools; use rustc_data_structures::graph::WithNumNodes; use rustc_middle::mir::spanview::source_range_no_file; use rustc_middle::mir::{ - self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, - TerminatorKind, + self, AggregateKind, BasicBlock, FakeReadCause, FakeReadCauseAndPlace, Rvalue, Statement, + StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::TyCtxt; use rustc_span::source_map::original_sp; @@ -823,10 +823,10 @@ pub(super) fn filtered_statement_span(statement: &Statement<'_>) -> Option // and `_1` is the `Place` for `somenum`. // // If and when the Issue is resolved, remove this special case match pattern: - StatementKind::FakeRead(box (cause, _)) if cause == FakeReadCause::ForGuardBinding => None, + StatementKind::FakeRead(box FakeReadCauseAndPlace(cause, _)) if cause == FakeReadCause::ForGuardBinding => None, // Retain spans from all other statements - StatementKind::FakeRead(box (_, _)) // Not including `ForGuardBinding` + StatementKind::FakeRead(_) // Not including `ForGuardBinding` | StatementKind::Intrinsic(..) | StatementKind::Assign(_) | StatementKind::SetDiscriminant { .. } diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 1f37f03cff1ca..19692a0a10223 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -119,7 +119,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { | StatementKind::AscribeUserType(box (place, _), _) | StatementKind::Retag(_, box place) | StatementKind::PlaceMention(box place) - | StatementKind::FakeRead(box (_, place)) => Some(place), + | StatementKind::FakeRead(box FakeReadCauseAndPlace(_, place)) => Some(place), StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { Some(local.into()) } diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 24403e8b6f347..1f5dea3f099cb 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -7,7 +7,7 @@ use crate::msrvs::Msrv; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_middle::mir::{ - Body, CastKind, NonDivergingIntrinsic, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, + Body, CastKind, FakeReadCauseAndPlace, NonDivergingIntrinsic, NullOp, Operand, Place, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::subst::GenericArgKind; @@ -221,7 +221,7 @@ fn check_statement<'tcx>( check_rvalue(tcx, body, def_id, rval, span) }, - StatementKind::FakeRead(box (_, place)) => check_place(tcx, *place, span, body), + StatementKind::FakeRead(box FakeReadCauseAndPlace(_, place)) => check_place(tcx, *place, span, body), // just an assignment StatementKind::SetDiscriminant { place, .. } | StatementKind::Deinit(place) => { check_place(tcx, **place, span, body) From feaeef5cb902fcf7349fcf83dde5aedee4490311 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Mon, 20 Mar 2023 10:14:57 +0000 Subject: [PATCH 13/22] Newtype for AscribeUserType semi-traversable tuple --- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 7 +++++-- compiler/rustc_middle/src/mir/syntax.rs | 4 ++-- compiler/rustc_middle/src/mir/visit.rs | 2 +- compiler/rustc_mir_build/src/build/expr/as_place.rs | 4 ++-- compiler/rustc_mir_build/src/build/matches/mod.rs | 7 +++++-- compiler/rustc_mir_transform/src/remove_zsts.rs | 2 +- 7 files changed, 17 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 53fef4d75bf67..ce5c51c450ef8 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1247,7 +1247,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); } } - StatementKind::AscribeUserType(box (place, projection), variance) => { + StatementKind::AscribeUserType(box AscribeUserType(place, projection), variance) => { let place_ty = place.ty(body, tcx).ty; if let Err(terr) = self.relate_type_and_user_type( place_ty, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index e0fe573b80389..88a21b612eb60 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -1457,7 +1457,7 @@ impl Debug for Statement<'_> { PlaceMention(ref place) => { write!(fmt, "PlaceMention({:?})", place) } - AscribeUserType(box (ref place, ref c_ty), ref variance) => { + AscribeUserType(box self::AscribeUserType(ref place, ref c_ty), ref variance) => { write!(fmt, "AscribeUserType({:?}, {:?}, {:?})", place, variance, c_ty) } Coverage(box self::Coverage { ref kind, code_region: Some(ref rgn) }) => { @@ -2693,6 +2693,10 @@ impl<'tcx> UserTypeProjections { } } +#[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] +#[derive(TypeFoldable, TypeVisitable)] +pub struct AscribeUserType<'tcx>(pub Place<'tcx>, pub UserTypeProjection); + /// Encodes the effect of a user-supplied type annotation on the /// subcomponents of a pattern. The effect is determined by applying the /// given list of projections to some underlying base type. Often, @@ -2709,7 +2713,6 @@ impl<'tcx> UserTypeProjections { /// `field[0]` (aka `.0`), indicating that the type of `s` is /// determined by finding the type of the `.0` field from `T`. #[derive(Clone, Debug, TyEncodable, TyDecodable, Hash, HashStable, PartialEq)] -#[derive(TypeFoldable, TypeVisitable)] pub struct UserTypeProjection { pub base: UserTypeAnnotationIndex, pub projs: Vec, diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index daad160f2ee58..e1ea1dc7c117c 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -3,7 +3,7 @@ //! This is in a dedicated file so that changes to this file can be reviewed more carefully. //! The intention is that this file only contains datatype declarations, no code. -use super::{BasicBlock, Constant, Field, Local, SwitchTargets, UserTypeProjection}; +use super::{AscribeUserType, BasicBlock, Constant, Field, Local, SwitchTargets}; use crate::mir::coverage::{CodeRegion, CoverageKind}; use crate::traits::Reveal; @@ -350,7 +350,7 @@ pub enum StatementKind<'tcx> { /// When executed at runtime this is a nop. /// /// Disallowed after drop elaboration. - AscribeUserType(Box<(Place<'tcx>, UserTypeProjection)>, ty::Variance), + AscribeUserType(Box>, ty::Variance), /// Marks the start of a "coverage region", injected with '-Cinstrument-coverage'. A /// `Coverage` statement carries metadata about the coverage region, used to inject a coverage diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 8ae5aa2a5d788..671e76b28956c 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -413,7 +413,7 @@ macro_rules! make_mir_visitor { ); } StatementKind::AscribeUserType( - box (place, user_ty), + box AscribeUserType(place, user_ty), variance ) => { self.visit_ascribe_user_ty(place, $(& $mutability)? *variance, user_ty, location); diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 33200b80a572d..7af5130273328 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -487,7 +487,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Statement { source_info, kind: StatementKind::AscribeUserType( - Box::new(( + Box::new(AscribeUserType( place, UserTypeProjection { base: annotation_index, projs: vec![] }, )), @@ -514,7 +514,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Statement { source_info, kind: StatementKind::AscribeUserType( - Box::new(( + Box::new(AscribeUserType( Place::from(temp), UserTypeProjection { base: annotation_index, projs: vec![] }, )), diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 2d52102db2cc6..aa58bdfb2cad7 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -530,7 +530,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Statement { source_info: ty_source_info, kind: StatementKind::AscribeUserType( - Box::new((place, UserTypeProjection { base, projs: Vec::new() })), + Box::new(AscribeUserType( + place, + UserTypeProjection { base, projs: Vec::new() }, + )), // We always use invariant as the variance here. This is because the // variance field from the ascription refers to the variance to use // when applying the type to the value being matched, but this @@ -2087,7 +2090,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Statement { source_info, kind: StatementKind::AscribeUserType( - Box::new(( + Box::new(AscribeUserType( ascription.source, UserTypeProjection { base, projs: Vec::new() }, )), diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 19692a0a10223..621d267990ea4 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -116,7 +116,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> { } StatementKind::Deinit(box place) | StatementKind::SetDiscriminant { box place, variant_index: _ } - | StatementKind::AscribeUserType(box (place, _), _) + | StatementKind::AscribeUserType(box AscribeUserType(place, _), _) | StatementKind::Retag(_, box place) | StatementKind::PlaceMention(box place) | StatementKind::FakeRead(box FakeReadCauseAndPlace(_, place)) => Some(place), From c79f135c340661c7d4eccadd4d17051cf97158fd Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Mon, 20 Mar 2023 10:15:53 +0000 Subject: [PATCH 14/22] Newtypes not DefId and LocalDefId traversable impl --- compiler/rustc_middle/src/query/keys.rs | 14 ++++++++++- compiler/rustc_middle/src/query/mod.rs | 4 +-- compiler/rustc_middle/src/ty/instance.rs | 10 ++++++-- compiler/rustc_middle/src/ty/mod.rs | 14 +++++++++-- .../rustc_middle/src/ty/structural_impls.rs | 4 +-- compiler/rustc_ty_utils/src/instance.rs | 25 +++++++++++-------- 6 files changed, 52 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 6e961a775c1ff..d14917325de1f 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -353,6 +353,18 @@ impl<'tcx> Key for (DefId, SubstsRef<'tcx>) { } } +impl<'tcx> Key for ty::InstanceOfArg<'tcx> { + type CacheSelector = DefaultCacheSelector; + + #[inline(always)] + fn query_crate_is_local(&self) -> bool { + self.0.krate == LOCAL_CRATE + } + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.0.default_span(tcx) + } +} + impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) { type CacheSelector = DefaultCacheSelector; @@ -365,7 +377,7 @@ impl<'tcx> Key for (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>) { } } -impl<'tcx> Key for (LocalDefId, DefId, SubstsRef<'tcx>) { +impl<'tcx> Key for ty::InstanceOfConstArg<'tcx> { type CacheSelector = DefaultCacheSelector; #[inline(always)] diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 4bf81c97d06ad..5271fc0cdb02e 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2133,14 +2133,14 @@ rustc_queries! { /// from `Ok(None)` to avoid misleading diagnostics when an error /// has already been/will be emitted, for the original cause query resolve_instance( - key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)> + key: ty::ParamEnvAnd<'tcx, ty::InstanceOfArg<'tcx>> ) -> Result>, ErrorGuaranteed> { desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } remap_env_constness } query resolve_instance_of_const_arg( - key: ty::ParamEnvAnd<'tcx, (LocalDefId, DefId, SubstsRef<'tcx>)> + key: ty::ParamEnvAnd<'tcx, ty::InstanceOfConstArg<'tcx>> ) -> Result>, ErrorGuaranteed> { desc { "resolving instance of the const argument `{}`", diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 5fc98f01a5470..4bf012dc57e51 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -319,6 +319,12 @@ impl<'tcx> fmt::Display for Instance<'tcx> { } } +#[derive(Clone, Copy, Debug, Eq, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)] +pub struct InstanceOfConstArg<'tcx>(pub ty::LocalDefId, pub DefId, pub SubstsRef<'tcx>); + +#[derive(Clone, Copy, Debug, Eq, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)] +pub struct InstanceOfArg<'tcx>(pub DefId, pub SubstsRef<'tcx>); + impl<'tcx> Instance<'tcx> { pub fn new(def_id: DefId, substs: SubstsRef<'tcx>) -> Instance<'tcx> { assert!( @@ -419,10 +425,10 @@ impl<'tcx> Instance<'tcx> { // FIXME(eddyb) should this always use `param_env.with_reveal_all()`? if let Some((did, param_did)) = def.as_const_arg() { tcx.resolve_instance_of_const_arg( - tcx.erase_regions(param_env.and((did, param_did, substs))), + tcx.erase_regions(param_env.and(InstanceOfConstArg(did, param_did, substs))), ) } else { - tcx.resolve_instance(tcx.erase_regions(param_env.and((def.did, substs)))) + tcx.resolve_instance(tcx.erase_regions(param_env.and(InstanceOfArg(def.did, substs)))) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 9f5e9dc395252..22176fd357511 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -87,7 +87,9 @@ pub use self::context::{ tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, OnDiskCache, TyCtxt, TyCtxtFeed, }; -pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; +pub use self::instance::{ + Instance, InstanceDef, InstanceOfArg, InstanceOfConstArg, ShortInstance, UnusedGenericParams, +}; pub use self::list::List; pub use self::parameterized::ParameterizedOverTcx; pub use self::rvalue_scopes::RvalueScopes; @@ -1425,6 +1427,14 @@ pub struct BoundConst<'tcx> { pub type PlaceholderConst<'tcx> = Placeholder; +#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)] +#[derive(PartialEq, Eq, PartialOrd, Ord)] +#[derive(Hash, HashStable)] +pub struct SubstsWithOptConstParam<'tcx, T>( + #[skip_traversal] pub WithOptConstParam, + pub SubstsRef<'tcx>, +); + /// A `DefId` which, in case it is a const argument, is potentially bundled with /// the `DefId` of the generic parameter it instantiates. /// @@ -1476,7 +1486,7 @@ pub type PlaceholderConst<'tcx> = Placeholder; /// except that instead of a `Ty` we bundle the `DefId` of the const parameter. /// Meaning that we need to use `type_of(const_param_did)` if `const_param_did` is `Some` /// to get the type of `did`. -#[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable, Lift, TyEncodable, TyDecodable)] +#[derive(Copy, Clone, Debug, Lift, TyEncodable, TyDecodable)] #[derive(PartialEq, Eq, PartialOrd, Ord)] #[derive(Hash, HashStable)] pub struct WithOptConstParam { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 74a7e680240ef..895cac90580e5 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -217,6 +217,8 @@ CloneLiftImpls! { ::rustc_ast::NodeId, ::rustc_span::symbol::Symbol, ::rustc_hir::def::Res, + ::rustc_hir::def_id::DefId, + ::rustc_hir::def_id::LocalDefId, ::rustc_hir::HirId, ::rustc_hir::MatchSource, ::rustc_hir::Mutability, @@ -261,8 +263,6 @@ CloneLiftImpls! { // implementation and traversal implementations (the latter only for // TyCtxt<'_> interners). TrivialTypeTraversalAndLiftImpls! { - ::rustc_hir::def_id::DefId, - ::rustc_hir::def_id::LocalDefId, ::rustc_hir::Unsafety, ::rustc_target::spec::abi::Abi, crate::ty::BoundConstness, diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 2eaeca73da75f..c363a466f6be4 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -1,5 +1,5 @@ use rustc_errors::ErrorGuaranteed; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::traits::CodegenObligationError; use rustc_middle::ty::subst::SubstsRef; @@ -10,26 +10,31 @@ use traits::{translate_substs, Reveal}; fn resolve_instance<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, (DefId, SubstsRef<'tcx>)>, + key: ty::ParamEnvAnd<'tcx, ty::InstanceOfArg<'tcx>>, ) -> Result>, ErrorGuaranteed> { - let (param_env, (did, substs)) = key.into_parts(); + let (param_env, ty::InstanceOfArg(did, substs)) = key.into_parts(); if let Some(did) = did.as_local() { if let Some(param_did) = tcx.opt_const_param_of(did) { - return tcx.resolve_instance_of_const_arg(param_env.and((did, param_did, substs))); + return tcx.resolve_instance_of_const_arg( + param_env.and(ty::InstanceOfConstArg(did, param_did, substs)), + ); } } - inner_resolve_instance(tcx, param_env.and((ty::WithOptConstParam::unknown(did), substs))) + inner_resolve_instance( + tcx, + param_env.and(ty::SubstsWithOptConstParam(ty::WithOptConstParam::unknown(did), substs)), + ) } fn resolve_instance_of_const_arg<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, (LocalDefId, DefId, SubstsRef<'tcx>)>, + key: ty::ParamEnvAnd<'tcx, ty::InstanceOfConstArg<'tcx>>, ) -> Result>, ErrorGuaranteed> { - let (param_env, (did, const_param_did, substs)) = key.into_parts(); + let (param_env, ty::InstanceOfConstArg(did, const_param_did, substs)) = key.into_parts(); inner_resolve_instance( tcx, - param_env.and(( + param_env.and(ty::SubstsWithOptConstParam( ty::WithOptConstParam { did: did.to_def_id(), const_param_did: Some(const_param_did) }, substs, )), @@ -38,9 +43,9 @@ fn resolve_instance_of_const_arg<'tcx>( fn inner_resolve_instance<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, (ty::WithOptConstParam, SubstsRef<'tcx>)>, + key: ty::ParamEnvAnd<'tcx, ty::SubstsWithOptConstParam<'tcx, DefId>>, ) -> Result>, ErrorGuaranteed> { - let (param_env, (def, substs)) = key.into_parts(); + let (param_env, ty::SubstsWithOptConstParam(def, substs)) = key.into_parts(); let result = if let Some(trait_def_id) = tcx.trait_of_item(def.did) { debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env); From 6833eea383b1a31b32c8a97e84728f0a83649a27 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sat, 25 Feb 2023 19:51:28 +0000 Subject: [PATCH 15/22] Use rustc_type_ir directly in derived traversables --- Cargo.lock | 3 +++ compiler/rustc_infer/Cargo.toml | 1 + compiler/rustc_macros/src/traversable.rs | 14 +++++++------- compiler/rustc_trait_selection/Cargo.toml | 1 + compiler/rustc_transmute/Cargo.toml | 2 ++ 5 files changed, 14 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 61f2cfb9e22c4..36b56a47b073d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4803,6 +4803,7 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", + "rustc_type_ir", "smallvec", "tracing", ] @@ -5369,6 +5370,7 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_transmute", + "rustc_type_ir", "smallvec", "tracing", ] @@ -5405,6 +5407,7 @@ dependencies = [ "rustc_middle", "rustc_span", "rustc_target", + "rustc_type_ir", "tracing", ] diff --git a/compiler/rustc_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 02ac83a5e8b25..89d83a45e916f 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -17,4 +17,5 @@ rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } +rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } diff --git a/compiler/rustc_macros/src/traversable.rs b/compiler/rustc_macros/src/traversable.rs index 57d1eeab6f028..3af7ff596de0a 100644 --- a/compiler/rustc_macros/src/traversable.rs +++ b/compiler/rustc_macros/src/traversable.rs @@ -69,7 +69,7 @@ pub trait Traversable { impl Traversable for Foldable { fn traversable(interner: &impl ToTokens) -> TokenStream { - quote! { ::rustc_middle::ty::fold::TypeFoldable<#interner> } + quote! { ::rustc_type_ir::fold::TypeFoldable<#interner> } } fn supertraits(interner: &impl ToTokens) -> TokenStream { Visitable::traversable(interner) @@ -78,7 +78,7 @@ impl Traversable for Foldable { if noop { bind } else { - quote! { ::rustc_middle::ty::prefer_noop_traversal_if_applicable!(#bind.try_fold_with(folder))? } + quote! { ::rustc_type_ir::prefer_noop_traversal_if_applicable!(#bind.try_fold_with(folder))? } } } fn arm( @@ -94,7 +94,7 @@ impl Traversable for Foldable { body: impl ToTokens, ) -> TokenStream { quote! { - fn try_fold_with<#traverser: ::rustc_middle::ty::fold::FallibleTypeFolder<#interner>>( + fn try_fold_with<#traverser: ::rustc_type_ir::fold::FallibleTypeFolder<#interner>>( self, folder: &mut #traverser ) -> ::core::result::Result { @@ -106,7 +106,7 @@ impl Traversable for Foldable { impl Traversable for Visitable { fn traversable(interner: &impl ToTokens) -> TokenStream { - quote! { ::rustc_middle::ty::visit::TypeVisitable<#interner> } + quote! { ::rustc_type_ir::visit::TypeVisitable<#interner> } } fn supertraits(_: &impl ToTokens) -> TokenStream { quote! { ::core::clone::Clone + ::core::fmt::Debug } @@ -115,7 +115,7 @@ impl Traversable for Visitable { if noop { quote! {} } else { - quote! { ::rustc_middle::ty::prefer_noop_traversal_if_applicable!(#bind.visit_with(visitor))?; } + quote! { ::rustc_type_ir::prefer_noop_traversal_if_applicable!(#bind.visit_with(visitor))?; } } } fn arm( @@ -130,7 +130,7 @@ impl Traversable for Visitable { body: impl ToTokens, ) -> TokenStream { quote! { - fn visit_with<#traverser: ::rustc_middle::ty::visit::TypeVisitor<#interner>>( + fn visit_with<#traverser: ::rustc_type_ir::visit::TypeVisitor<#interner>>( &self, visitor: &mut #traverser ) -> ::core::ops::ControlFlow<#traverser::BreakTy> { @@ -144,7 +144,7 @@ impl Traversable for Visitable { pub fn traversable_derive( mut structure: synstructure::Structure<'_>, ) -> TokenStream { - let skip_traversal = quote! { ::rustc_middle::ty::SkipTraversalAutoImplOnly }; + let skip_traversal = quote! { ::rustc_type_ir::SkipTraversalAutoImplOnly }; let interner = gen_interner(&mut structure); let traverser = gen_param("T", &structure.ast().generics); diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index d3eba43b47e95..7724dc9b6c3ee 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -23,5 +23,6 @@ rustc_session = { path = "../rustc_session" } rustc_span = { path = "../rustc_span" } rustc_target = { path = "../rustc_target" } rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] } +rustc_type_ir = { path = "../rustc_type_ir" } smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } itertools = "0.10.1" diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml index aa6fe7d241968..403890ac3169e 100644 --- a/compiler/rustc_transmute/Cargo.toml +++ b/compiler/rustc_transmute/Cargo.toml @@ -14,6 +14,7 @@ rustc_macros = { path = "../rustc_macros", optional = true} rustc_middle = { path = "../rustc_middle", optional = true} rustc_span = { path = "../rustc_span", optional = true} rustc_target = { path = "../rustc_target", optional = true} +rustc_type_ir = { path = "../rustc_type_ir", optional = true} [features] rustc = [ @@ -23,6 +24,7 @@ rustc = [ "rustc_macros", "rustc_span", "rustc_target", + "rustc_type_ir", ] [dev-dependencies] From 8da36bd4ede3090b001ad10b429ec11da178f64e Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Tue, 21 Mar 2023 08:49:31 +0000 Subject: [PATCH 16/22] Derive traversables over generic interners --- compiler/rustc_macros/src/lib.rs | 22 ++++++++++------------ compiler/rustc_macros/src/traversable.rs | 23 ++++++++++------------- 2 files changed, 20 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index f2729fe421fc2..170c6404a9d9e 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -141,13 +141,12 @@ decl_derive!( /// such derived implementations are only applicable if the annotated type does not contain /// anything that may be of interest to a folder. /// - /// If the annotated type has a `'tcx` lifetime parameter, then that will be used as the - /// lifetime for the type context/interner; otherwise the lifetime of the type context/interner - /// will be unrelated to the annotated type. It therefore matters how any lifetime parameters of - /// the annotated type are named. For example, deriving `TypeFoldable` for both `Foo<'a>` and - /// `Bar<'tcx>` will respectively produce: + /// The derived implementation will use `TyCtxt<'tcx>` as the interner iff the annotated type + /// has a `'tcx` lifetime parameter; otherwise it will be generic over all interners. It + /// therefore matters how any lifetime parameters of the annotated type are named. For example, + /// deriving `TypeFoldable` for both `Foo<'a>` and `Bar<'tcx>` will respectively produce: /// - /// `impl<'a, 'tcx> TypeFoldable> for Foo<'a>` + /// `impl<'a, I: Interner> TypeFoldable for Foo<'a>` /// /// and /// @@ -176,13 +175,12 @@ decl_derive!( /// above, such derived implementations are only applicable if the annotated type does not /// contain anything that may be of interest to visitors. /// - /// If the annotated type has a `'tcx` lifetime parameter, then that will be used as the - /// lifetime for the type context/interner; otherwise the lifetime of the type context/interner - /// will be unrelated to the annotated type. It therefore matters how any lifetime parameters of - /// the annotated type are named. For example, deriving `TypeVisitable` for both `Foo<'a>` and - /// `Bar<'tcx>` will respectively produce: + /// The derived implementation will use `TyCtxt<'tcx>` as the interner iff the annotated type + /// has a `'tcx` lifetime parameter; otherwise it will be generic over all interners. It + /// therefore matters how any lifetime parameters of the annotated type are named. For example, + /// deriving `TypeVisitable` for both `Foo<'a>` and `Bar<'tcx>` will respectively produce: /// - /// `impl<'a, 'tcx> TypeVisitable> for Foo<'a>` + /// `impl<'a, I: Interner> TypeVisitable for Foo<'a>` /// /// and /// diff --git a/compiler/rustc_macros/src/traversable.rs b/compiler/rustc_macros/src/traversable.rs index 3af7ff596de0a..927ca0788eb0f 100644 --- a/compiler/rustc_macros/src/traversable.rs +++ b/compiler/rustc_macros/src/traversable.rs @@ -1,7 +1,7 @@ use proc_macro2::{Span, TokenStream}; use quote::{quote, quote_spanned, ToTokens}; use std::collections::HashMap; -use syn::{parse_quote, spanned::Spanned, Attribute, Generics, Ident, Lifetime, LifetimeDef}; +use syn::{parse_quote, spanned::Spanned, Attribute, Generics, Ident}; /// Generate a type parameter with the given `suffix` that does not conflict with /// any of the `existing` generics. @@ -13,25 +13,22 @@ fn gen_param(suffix: impl ToString, existing: &Generics) -> Ident { Ident::new(&suffix, Span::call_site()) } -/// Return the `TyCtxt` interner for the given `structure`. +/// Return the interner for the given `structure`. /// -/// If the input represented by `structure` has a `'tcx` lifetime parameter, then that will be used -/// used as the lifetime of the `TyCtxt`. Otherwise a `'tcx` lifetime parameter that is unrelated -/// to the input will be used. +/// If the input represented by `structure` has a `'tcx` lifetime parameter, then we `TyCtxt<'tcx>` +/// will be returned; otherwise our derived implementation will be generic over the interner. fn gen_interner(structure: &mut synstructure::Structure<'_>) -> TokenStream { - let lt = structure + structure .ast() .generics .lifetimes() .find_map(|def| (def.lifetime.ident == "tcx").then_some(&def.lifetime)) - .cloned() + .map(|lt| quote! { ::rustc_middle::ty::TyCtxt<#lt> }) .unwrap_or_else(|| { - let tcx: Lifetime = parse_quote! { 'tcx }; - structure.add_impl_generic(LifetimeDef::new(tcx.clone()).into()); - tcx - }); - - quote! { ::rustc_middle::ty::TyCtxt<#lt> } + let ident = gen_param("I", &structure.ast().generics); + structure.add_impl_generic(parse_quote! { #ident: ::rustc_type_ir::Interner }); + ident.into_token_stream() + }) } /// Returns the `Span` of the first `#[skip_traversal]` attribute in `attrs`. From d1cc6e5036a74953c63026225ff8a0ee0a89e91a Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Mon, 20 Mar 2023 09:57:05 +0000 Subject: [PATCH 17/22] Use Spanned not semi-traversable Span tuples --- Cargo.lock | 1 + .../src/diagnostics/conflict_errors.rs | 4 +- .../src/diagnostics/move_errors.rs | 3 +- .../src/type_check/canonical.rs | 8 +- .../rustc_codegen_cranelift/src/common.rs | 6 +- .../src/debuginfo/create_scope_map.rs | 10 +-- compiler/rustc_codegen_ssa/src/mir/block.rs | 6 +- .../interpret/intrinsics/caller_location.rs | 6 +- .../rustc_hir_analysis/src/astconv/mod.rs | 12 +-- compiler/rustc_hir_analysis/src/bounds.rs | 16 ++-- .../rustc_hir_analysis/src/check/check.rs | 2 +- .../src/check/compare_impl_item.rs | 21 +++-- .../rustc_hir_analysis/src/check/dropck.rs | 2 +- compiler/rustc_hir_analysis/src/check/mod.rs | 6 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 24 +++--- compiler/rustc_hir_analysis/src/collect.rs | 5 +- .../src/collect/item_bounds.rs | 26 ++++--- .../src/collect/predicates_of.rs | 77 ++++++++++--------- .../src/collect/resolve_bound_vars.rs | 4 +- .../src/constrained_generic_params.rs | 5 +- .../src/impl_wf_check/min_specialization.rs | 22 +++--- .../src/outlives/explicit.rs | 8 +- .../rustc_hir_analysis/src/variance/mod.rs | 2 +- compiler/rustc_hir_typeck/src/_match.rs | 4 +- compiler/rustc_hir_typeck/src/callee.rs | 8 +- compiler/rustc_hir_typeck/src/closure.rs | 9 ++- compiler/rustc_hir_typeck/src/expr.rs | 5 +- .../src/fn_ctxt/adjust_fulfillment_errors.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 6 +- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 2 +- .../src/generator_interior/mod.rs | 4 +- .../rustc_hir_typeck/src/method/confirm.rs | 6 +- .../src/infer/error_reporting/mod.rs | 3 +- .../src/infer/error_reporting/note.rs | 6 +- .../rustc_infer/src/infer/opaque_types.rs | 4 +- compiler/rustc_infer/src/traits/util.rs | 18 ++--- compiler/rustc_lint/src/builtin.rs | 10 +-- .../src/multiple_supertrait_upcastable.rs | 2 +- .../src/opaque_hidden_inferred_bound.rs | 12 +-- compiler/rustc_lint/src/traits.rs | 8 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 2 +- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/mir/mod.rs | 12 +-- compiler/rustc_middle/src/mir/pretty.rs | 12 ++- compiler/rustc_middle/src/mir/visit.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/traits/mod.rs | 4 +- compiler/rustc_middle/src/traits/util.rs | 4 +- compiler/rustc_middle/src/ty/codec.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 8 +- compiler/rustc_middle/src/ty/generics.rs | 16 ++-- compiler/rustc_middle/src/ty/mod.rs | 24 ++++-- compiler/rustc_middle/src/ty/parameterized.rs | 4 + compiler/rustc_middle/src/ty/print/pretty.rs | 4 +- .../rustc_middle/src/ty/structural_impls.rs | 10 ++- compiler/rustc_middle/src/ty/util.rs | 2 +- compiler/rustc_mir_build/src/build/block.rs | 10 ++- .../rustc_mir_build/src/build/matches/mod.rs | 16 ++-- compiler/rustc_mir_build/src/build/mod.rs | 4 +- .../rustc_mir_transform/src/const_prop.rs | 2 +- .../src/const_prop_lint.rs | 2 +- compiler/rustc_mir_transform/src/generator.rs | 4 +- compiler/rustc_mir_transform/src/inline.rs | 5 +- compiler/rustc_privacy/src/lib.rs | 6 +- .../rustc_query_impl/src/on_disk_cache.rs | 2 +- compiler/rustc_span/Cargo.toml | 1 + compiler/rustc_span/src/source_map.rs | 1 + .../src/traits/error_reporting/suggestions.rs | 16 ++-- .../rustc_trait_selection/src/traits/mod.rs | 14 ++-- .../src/traits/object_safety.rs | 17 ++-- .../src/traits/project.rs | 16 ++-- .../src/traits/select/confirmation.rs | 4 +- .../src/traits/select/mod.rs | 6 +- .../src/traits/specialize/mod.rs | 2 +- .../rustc_trait_selection/src/traits/util.rs | 10 +-- .../src/traits/vtable.rs | 8 +- .../rustc_trait_selection/src/traits/wf.rs | 2 +- compiler/rustc_traits/src/chalk/db.rs | 8 +- compiler/rustc_traits/src/type_op.rs | 8 +- compiler/rustc_ty_utils/src/ty.rs | 2 +- src/librustdoc/clean/mod.rs | 12 +-- src/librustdoc/clean/simplify.rs | 6 +- src/tools/clippy/clippy_lints/src/derive.rs | 6 +- .../clippy_lints/src/future_not_send.rs | 4 +- .../src/unit_return_expecting_ord.rs | 12 +-- .../clippy/clippy_utils/src/eager_or_lazy.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- .../clippy_utils/src/qualify_min_const_fn.rs | 2 +- src/tools/clippy/clippy_utils/src/ty.rs | 20 ++--- src/tools/miri/src/helpers.rs | 2 +- 90 files changed, 400 insertions(+), 329 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 36b56a47b073d..ae3159e30fff9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5301,6 +5301,7 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_serialize", + "rustc_type_ir", "scoped-tls", "sha1", "sha2", diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 4adda364183b3..7d6389c7bb323 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -671,8 +671,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let tcx = self.infcx.tcx; // Find out if the predicates show that the type is a Fn or FnMut - let find_fn_kind_from_did = |(pred, _): (ty::Predicate<'tcx>, _)| { - if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = pred.kind().skip_binder() + let find_fn_kind_from_did = |pred: ty::Spanned>| { + if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = pred.node.kind().skip_binder() && pred.self_ty() == ty { if Some(pred.def_id()) == tcx.lang_items().fn_trait() { diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 3662bec0c7636..dd465ad5bd748 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -103,7 +103,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // opt_match_place is None for let [mut] x = ... statements, // whether or not the right-hand side is a place expression if let LocalInfo::User(BindingForm::Var(VarBindingForm { - opt_match_place: Some((opt_match_place, match_span)), + opt_match_place: + Some(ty::Spanned { node: opt_match_place, span: match_span }), binding_mode: _, opt_ty_info: _, pat_span: _, diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index b27d5d2053213..07c25e0f02822 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -107,10 +107,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { instantiated_predicates: ty::InstantiatedPredicates<'tcx>, locations: Locations, ) { - for (predicate, span) in instantiated_predicates { - debug!(?predicate); - let category = ConstraintCategory::Predicate(span); - let predicate = self.normalize_with_category(predicate, locations, category); + for predicate in instantiated_predicates { + debug!(?predicate.node); + let category = ConstraintCategory::Predicate(predicate.span); + let predicate = self.normalize_with_category(predicate.node, locations, category); self.prove_predicate(predicate, locations, category); } } diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index d39bf700035f9..cc771e80d9ffe 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -451,13 +451,13 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { loop { let scope_data = &self.mir.source_scopes[source_info.scope]; - if let Some((callee, callsite_span)) = scope_data.inlined { + if let Some(callee) = scope_data.inlined { // Stop inside the most nested non-`#[track_caller]` function, // before ever reaching its caller (which is irrelevant). - if !callee.def.requires_caller_location(self.tcx) { + if !callee.node.def.requires_caller_location(self.tcx) { return span_to_caller_location(self, source_info.span); } - source_info.span = callsite_span; + source_info.span = callee.span; } // Skip past all of the parents with `inlined: None`. diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 99e4ded62f1a7..cbd747ffcb315 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -87,13 +87,13 @@ fn make_mir_scope<'ll, 'tcx>( let file_metadata = file_metadata(cx, &loc.file); let dbg_scope = match scope_data.inlined { - Some((callee, _)) => { + Some(callee) => { // FIXME(eddyb) this would be `self.monomorphize(&callee)` // if this is moved to `rustc_codegen_ssa::mir::debuginfo`. let callee = cx.tcx.subst_and_normalize_erasing_regions( instance.substs, ty::ParamEnv::reveal_all(), - callee, + callee.node, ); let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty()); cx.dbg_scope_fn(callee, callee_fn_abi, None) @@ -109,11 +109,11 @@ fn make_mir_scope<'ll, 'tcx>( }, }; - let inlined_at = scope_data.inlined.map(|(_, callsite_span)| { + let inlined_at = scope_data.inlined.map(|callee| { // FIXME(eddyb) this doesn't account for the macro-related // `Span` fixups that `rustc_codegen_ssa::mir::debuginfo` does. - let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callsite_span); - cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callsite_span) + let callsite_scope = parent_scope.adjust_dbg_scope_for_span(cx, callee.span); + cx.dbg_loc(callsite_scope, parent_scope.inlined_at, callee.span) }); debug_context.scopes[scope] = DebugScope { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index bdfc0aa1c30c7..196619c8f7b4f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1497,13 +1497,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { loop { let scope_data = &self.mir.source_scopes[source_info.scope]; - if let Some((callee, callsite_span)) = scope_data.inlined { + if let Some(callee) = scope_data.inlined { // Stop inside the most nested non-`#[track_caller]` function, // before ever reaching its caller (which is irrelevant). - if !callee.def.requires_caller_location(tcx) { + if !callee.node.def.requires_caller_location(tcx) { return span_to_caller_location(source_info.span); } - source_info.span = callsite_span; + source_info.span = callee.span; } // Skip past all of the parents with `inlined: None`. diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs index 76c8d0a975ac0..7fd2000a718c2 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/caller_location.rs @@ -44,13 +44,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { loop { let scope_data = &frame.body.source_scopes[source_info.scope]; - if let Some((callee, callsite_span)) = scope_data.inlined { + if let Some(callee) = scope_data.inlined { // Stop inside the most nested non-`#[track_caller]` function, // before ever reaching its caller (which is irrelevant). - if !callee.def.requires_caller_location(*self.tcx) { + if !callee.node.def.requires_caller_location(*self.tcx) { return source_info.span; } - source_info.span = callsite_span; + source_info.span = callee.span; } // Skip past all of the parents with `inlined: None`. diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6a27383121d2d..d1f30429da153 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1314,20 +1314,20 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut trait_bounds = vec![]; let mut projection_bounds = vec![]; - for (pred, span) in bounds.predicates() { - let bound_pred = pred.kind(); + for pred in bounds.predicates() { + let bound_pred = pred.node.kind(); match bound_pred.skip_binder() { ty::PredicateKind::Clause(clause) => match clause { ty::Clause::Trait(trait_pred) => { assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive); trait_bounds.push(( bound_pred.rebind(trait_pred.trait_ref), - span, + pred.span, trait_pred.constness, )); } ty::Clause::Projection(proj) => { - projection_bounds.push((bound_pred.rebind(proj), span)); + projection_bounds.push((bound_pred.rebind(proj), pred.span)); } ty::Clause::TypeOutlives(_) => { // Do nothing, we deal with regions separately @@ -1784,8 +1784,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { || { traits::transitive_bounds_that_define_assoc_type( tcx, - predicates.iter().filter_map(|(p, _)| { - Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref)) + predicates.iter().filter_map(|p| { + Some(p.node.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref)) }), assoc_name, ) diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index 0880c8c15f2e0..bdae0ca8d293b 100644 --- a/compiler/rustc_hir_analysis/src/bounds.rs +++ b/compiler/rustc_hir_analysis/src/bounds.rs @@ -23,7 +23,7 @@ use rustc_span::Span; /// include the self type (e.g., `trait_bounds`) but in others we do not #[derive(Default, PartialEq, Eq, Clone, Debug)] pub struct Bounds<'tcx> { - pub predicates: Vec<(ty::Predicate<'tcx>, Span)>, + pub predicates: Vec>>, } impl<'tcx> Bounds<'tcx> { @@ -33,7 +33,7 @@ impl<'tcx> Bounds<'tcx> { region: ty::PolyTypeOutlivesPredicate<'tcx>, span: Span, ) { - self.predicates.push((region.to_predicate(tcx), span)); + self.predicates.push(ty::Spanned { node: region.to_predicate(tcx), span }); } pub fn push_trait_bound( @@ -43,7 +43,10 @@ impl<'tcx> Bounds<'tcx> { span: Span, constness: ty::BoundConstness, ) { - self.predicates.push((trait_ref.with_constness(constness).to_predicate(tcx), span)); + self.predicates.push(ty::Spanned { + node: trait_ref.with_constness(constness).to_predicate(tcx), + span, + }); } pub fn push_projection_bound( @@ -52,17 +55,18 @@ impl<'tcx> Bounds<'tcx> { projection: ty::PolyProjectionPredicate<'tcx>, span: Span, ) { - self.predicates.push((projection.to_predicate(tcx), span)); + self.predicates.push(ty::Spanned { node: projection.to_predicate(tcx), span }); } pub fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) { let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span)); let trait_ref = ty::Binder::dummy(tcx.mk_trait_ref(sized_def_id, [ty])); // Preferrable to put this obligation first, since we report better errors for sized ambiguity. - self.predicates.insert(0, (trait_ref.without_const().to_predicate(tcx), span)); + self.predicates + .insert(0, ty::Spanned { node: trait_ref.without_const().to_predicate(tcx), span }); } - pub fn predicates(&self) -> impl Iterator, Span)> + '_ { + pub fn predicates(&self) -> impl Iterator>> + '_ { self.predicates.iter().cloned() } } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 872fec3954b29..976c6f6d8b4e4 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -320,7 +320,7 @@ pub(super) fn check_opaque_for_inheriting_lifetimes( let prohibit_opaque = tcx .explicit_item_bounds(def_id) .iter() - .try_for_each(|(predicate, _)| predicate.visit_with(&mut visitor)); + .try_for_each(|predicate| predicate.node.visit_with(&mut visitor)); if let Some(ty) = prohibit_opaque.break_value() { visitor.visit_item(&item); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 32b6aeed5f8cc..5a2129af18f56 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -187,7 +187,7 @@ fn compare_method_predicate_entailment<'tcx>( hybrid_preds.predicates.extend( trait_m_predicates .instantiate_own(tcx, trait_to_placeholder_substs) - .map(|(predicate, _)| predicate), + .map(|predicate| predicate.node), ); // Construct trait parameter environment and then shift it into the placeholder viewpoint. @@ -207,7 +207,7 @@ fn compare_method_predicate_entailment<'tcx>( debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds()); let impl_m_own_bounds = impl_m_predicates.instantiate_own(tcx, impl_to_placeholder_substs); - for (predicate, span) in impl_m_own_bounds { + for ty::Spanned { node: predicate, span } in impl_m_own_bounds { let normalize_cause = traits::ObligationCause::misc(span, impl_m_def_id); let predicate = ocx.normalize(&normalize_cause, param_env, predicate); @@ -846,7 +846,7 @@ impl<'tcx> TypeFolder> for ImplTraitInTraitCollector<'_, 'tcx> { }); self.types.insert(proj.def_id, (infer_ty, proj.substs)); // Recurse into bounds - for (pred, pred_span) in self.interner().bound_explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) { + for ty::Spanned { node: pred, span: pred_span } in self.interner().bound_explicit_item_bounds(proj.def_id).subst_iter_copied(self.interner(), proj.substs) { let pred = pred.fold_with(self); let pred = self.ocx.normalize( &ObligationCause::misc(self.span, self.body_id), @@ -1804,7 +1804,7 @@ fn compare_type_predicate_entailment<'tcx>( hybrid_preds.predicates.extend( trait_ty_predicates .instantiate_own(tcx, trait_to_impl_substs) - .map(|(predicate, _)| predicate), + .map(|predicate| predicate.node), ); debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds); @@ -1822,7 +1822,7 @@ fn compare_type_predicate_entailment<'tcx>( debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds()); - for (predicate, span) in impl_ty_own_bounds { + for ty::Spanned { node: predicate, span } in impl_ty_own_bounds { let cause = ObligationCause::misc(span, impl_ty_def_id); let predicate = ocx.normalize(&cause, param_env, predicate); @@ -2043,9 +2043,14 @@ pub(super) fn check_type_bounds<'tcx>( let obligations = tcx .bound_explicit_item_bounds(trait_ty.def_id) .subst_iter_copied(tcx, rebased_substs) - .map(|(concrete_ty_bound, span)| { - debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound); - traits::Obligation::new(tcx, mk_cause(span), param_env, concrete_ty_bound) + .map(|concrete_ty_bound| { + debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound.node); + traits::Obligation::new( + tcx, + mk_cause(concrete_ty_bound.span), + param_env, + concrete_ty_bound.node, + ) }) .collect(); debug!("check_type_bounds: item_bounds={:?}", obligations); diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index 2bb724138f584..8d30c3f7826a5 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -155,7 +155,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( // just to look for all the predicates directly. assert_eq!(dtor_predicates.parent, None); - for &(predicate, predicate_sp) in dtor_predicates.predicates { + for &ty::Spanned { node: predicate, span: predicate_sp } in dtor_predicates.predicates { // (We do not need to worry about deep analysis of type // expressions etc because the Drop impls are already forced // to take on a structure that is roughly an alpha-renaming of diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 9acfc1b3d2924..267be0430249a 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -302,9 +302,9 @@ fn bounds_from_generic_predicates<'tcx>( ) -> (String, String) { let mut types: FxHashMap, Vec> = FxHashMap::default(); let mut projections = vec![]; - for (predicate, _) in predicates.predicates { - debug!("predicate {:?}", predicate); - let bound_predicate = predicate.kind(); + for predicate in predicates.predicates { + debug!("predicate {:?}", predicate.node); + let bound_predicate = predicate.node.kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => { let entry = types.entry(trait_predicate.self_ty()).or_default(); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 4120ad45f6a6b..837378762f875 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1134,14 +1134,14 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt let bounds = wfcx.tcx().explicit_item_bounds(item.def_id); debug!("check_associated_type_bounds: bounds={:?}", bounds); - let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| { - let normalized_bound = wfcx.normalize(span, None, bound); + let wf_obligations = bounds.iter().flat_map(|&bound| { + let normalized_bound = wfcx.normalize(span, None, bound.node); traits::wf::predicate_obligations( wfcx.infcx, wfcx.param_env, wfcx.body_def_id, normalized_bound, - bound_span, + bound.span, ) }); @@ -1377,7 +1377,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id let default_obligations = predicates .predicates .iter() - .flat_map(|&(pred, sp)| { + .flat_map(|&pred| { #[derive(Default)] struct CountParams { params: FxHashSet, @@ -1404,18 +1404,18 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id } } let mut param_count = CountParams::default(); - let has_region = pred.visit_with(&mut param_count).is_break(); - let substituted_pred = ty::EarlyBinder(pred).subst(tcx, substs); + let has_region = pred.node.visit_with(&mut param_count).is_break(); + let substituted_pred = ty::EarlyBinder(pred.node).subst(tcx, substs); // Don't check non-defaulted params, dependent defaults (including lifetimes) // or preds with multiple params. if substituted_pred.has_non_region_param() || param_count.params.len() > 1 || has_region { None - } else if predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) { + } else if predicates.predicates.iter().any(|&p| p.node == substituted_pred) { // Avoid duplication of predicates that contain no parameters, for example. None } else { - Some((substituted_pred, sp)) + Some((substituted_pred, pred.span)) } }) .map(|(pred, sp)| { @@ -1443,13 +1443,13 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id debug!(?predicates.predicates); assert_eq!(predicates.predicates.len(), predicates.spans.len()); - let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| { + let wf_obligations = predicates.into_iter().flat_map(|p| { traits::wf::predicate_obligations( infcx, wfcx.param_env.without_const(), wfcx.body_def_id, - p, - sp, + p.node, + p.span, ) }); let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect(); @@ -1566,7 +1566,7 @@ fn check_return_position_impl_trait_in_trait_bounds<'tcx>( { let span = tcx.def_span(opaque_ty.def_id); let bounds = wfcx.tcx().explicit_item_bounds(opaque_ty.def_id); - let wf_obligations = bounds.iter().flat_map(|&(bound, bound_span)| { + let wf_obligations = bounds.iter().flat_map(|&ty::Spanned { node: bound, span: bound_span }| { let bound = ty::EarlyBinder(bound).subst(tcx, opaque_ty.substs); let normalized_bound = wfcx.normalize(span, None, bound); traits::wf::predicate_obligations( diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 604d54cafb532..6c9db1c18bc5d 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1448,8 +1448,9 @@ fn predicates_defined_on(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicate "predicates_defined_on: inferred_outlives_of({:?}) = {:?}", def_id, inferred_outlives, ); - let inferred_outlives_iter = - inferred_outlives.iter().map(|(clause, span)| ((*clause).to_predicate(tcx), *span)); + let inferred_outlives_iter = inferred_outlives + .iter() + .map(|(clause, span)| ty::Spanned { node: (*clause).to_predicate(tcx), span: *span }); if result.predicates.is_empty() { result.predicates = tcx.arena.alloc_from_iter(inferred_outlives_iter); } else { diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index df0258ff7a36c..620d88582a067 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -19,7 +19,7 @@ fn associated_type_bounds<'tcx>( assoc_item_def_id: DefId, ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, -) -> &'tcx [(ty::Predicate<'tcx>, Span)] { +) -> &'tcx [ty::Spanned>] { let item_ty = tcx.mk_projection( assoc_item_def_id, InternalSubsts::identity_for_item(tcx, assoc_item_def_id), @@ -33,15 +33,17 @@ fn associated_type_bounds<'tcx>( let trait_def_id = tcx.parent(assoc_item_def_id); let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id.expect_local()); - let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|(pred, _)| { - match pred.kind().skip_binder() { - ty::PredicateKind::Clause(ty::Clause::Trait(tr)) => tr.self_ty() == item_ty, - ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => { - proj.projection_ty.self_ty() == item_ty - } - ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => outlives.0 == item_ty, - _ => false, + let bounds_from_parent = trait_predicates.predicates.iter().copied().filter(|pred| match pred + .node + .kind() + .skip_binder() + { + ty::PredicateKind::Clause(ty::Clause::Trait(tr)) => tr.self_ty() == item_ty, + ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => { + proj.projection_ty.self_ty() == item_ty } + ty::PredicateKind::Clause(ty::Clause::TypeOutlives(outlives)) => outlives.0 == item_ty, + _ => false, }); let all_bounds = tcx.arena.alloc_from_iter(bounds.predicates().chain(bounds_from_parent)); @@ -60,7 +62,7 @@ fn opaque_type_bounds<'tcx>( ast_bounds: &'tcx [hir::GenericBound<'tcx>], item_ty: Ty<'tcx>, span: Span, -) -> &'tcx [(ty::Predicate<'tcx>, Span)] { +) -> &'tcx [ty::Spanned>] { ty::print::with_no_queries!({ let icx = ItemCtxt::new(tcx, opaque_def_id); let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds); @@ -75,7 +77,7 @@ fn opaque_type_bounds<'tcx>( pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, def_id: DefId, -) -> &'_ [(ty::Predicate<'_>, Span)] { +) -> &'_ [ty::Spanned>] { match tcx.opt_rpitit_info(def_id) { // RPITIT's bounds are the same as opaque type bounds, but with // a projection self type. @@ -126,7 +128,7 @@ pub(super) fn item_bounds( let bounds = tcx.mk_predicates_from_iter( util::elaborate_predicates( tcx, - tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound), + tcx.explicit_item_bounds(def_id).iter().map(|&bound| bound.node), ) .map(|obligation| obligation.predicate), ); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 2badd66e346f1..c079896396674 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{GenericPredicates, ToPredicate}; use rustc_span::symbol::{sym, Ident}; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::DUMMY_SP; #[derive(Debug)] struct OnlySelfBounds(bool); @@ -49,11 +49,13 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic }; let span = rustc_span::DUMMY_SP; - result.predicates = - tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain(std::iter::once(( - ty::TraitRef::identity(tcx, def_id).with_constness(constness).to_predicate(tcx), + result.predicates = tcx.arena.alloc_from_iter(result.predicates.iter().copied().chain( + std::iter::once(ty::Spanned { + node: + ty::TraitRef::identity(tcx, def_id).with_constness(constness).to_predicate(tcx), span, - )))); + }), + )); } debug!("predicates_of(def_id={:?}) = {:?}", def_id, result); result @@ -77,7 +79,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP // We use an `IndexSet` to preserve order of insertion. // Preserving the order of insertion is important here so as not to break UI tests. - let mut predicates: FxIndexSet<(ty::Predicate<'_>, Span)> = FxIndexSet::default(); + let mut predicates: FxIndexSet>> = FxIndexSet::default(); let ast_generics = match node { Node::TraitItem(item) => item.generics, @@ -136,7 +138,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP // (see below). Recall that a default impl is not itself an impl, but rather a // set of defaults that can be incorporated into another impl. if let Some(trait_ref) = is_default_impl_trait { - predicates.insert((trait_ref.without_const().to_predicate(tcx), tcx.def_span(def_id))); + predicates.insert(ty::Spanned { + node: trait_ref.without_const().to_predicate(tcx), + span: tcx.def_span(def_id), + }); } // Collect the region predicates that were declared inline as @@ -187,7 +192,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP ty::Clause::ConstArgHasType(ct, ct_ty), )) .to_predicate(tcx); - predicates.insert((predicate, param.span)); + predicates.insert(ty::Spanned { node: predicate, span: param.span }); index += 1; } @@ -219,7 +224,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP ty::PredicateKind::WellFormed(ty.into()), bound_vars, ); - predicates.insert((predicate.to_predicate(tcx), span)); + predicates.insert(ty::Spanned { node: predicate.to_predicate(tcx), span }); } } @@ -242,7 +247,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP )) .to_predicate(icx.tcx); - (pred, span) + ty::Spanned { node: pred, span } })) } @@ -302,20 +307,20 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP index: dup_index, name: duplicate.name.ident().name, }); - predicates.push(( - ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives( + predicates.push(ty::Spanned { + node: ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives( ty::OutlivesPredicate(orig_region, dup_region), ))) .to_predicate(icx.tcx), - duplicate.span, - )); - predicates.push(( - ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives( + span: duplicate.span, + }); + predicates.push(ty::Spanned { + node: ty::Binder::dummy(ty::PredicateKind::Clause(ty::Clause::RegionOutlives( ty::OutlivesPredicate(dup_region, orig_region), ))) .to_predicate(icx.tcx), - duplicate.span, - )); + span: duplicate.span, + }); } debug!(?predicates); } @@ -329,10 +334,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP fn const_evaluatable_predicates_of( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> FxIndexSet<(ty::Predicate<'_>, Span)> { +) -> FxIndexSet>> { struct ConstCollector<'tcx> { tcx: TyCtxt<'tcx>, - preds: FxIndexSet<(ty::Predicate<'tcx>, Span)>, + preds: FxIndexSet>>, } impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> { @@ -340,11 +345,11 @@ fn const_evaluatable_predicates_of( let ct = ty::Const::from_anon_const(self.tcx, c.def_id); if let ty::ConstKind::Unevaluated(_) = ct.kind() { let span = self.tcx.def_span(c.def_id); - self.preds.insert(( - ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)) + self.preds.insert(ty::Spanned { + node: ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(ct)) .to_predicate(self.tcx), span, - )); + }); } } @@ -428,7 +433,7 @@ pub(super) fn explicit_predicates_of<'tcx>( .predicates .iter() .copied() - .filter(|(pred, _)| match pred.kind().skip_binder() { + .filter(|pred| match pred.node.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(tr)) => !is_assoc_item_ty(tr.self_ty()), ty::PredicateKind::Clause(ty::Clause::Projection(proj)) => { !is_assoc_item_ty(proj.projection_ty.self_ty()) @@ -475,9 +480,9 @@ pub(super) fn explicit_predicates_of<'tcx>( let filtered_predicates = parent_preds .predicates .into_iter() - .filter(|(pred, _)| { + .filter(|pred| { if let ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(ct, _)) = - pred.kind().skip_binder() + pred.node.kind().skip_binder() { match ct.kind() { ty::ConstKind::Param(param_const) => { @@ -598,12 +603,12 @@ pub(super) fn super_predicates_that_define_assoc_type( if assoc_name.is_none() { // Now require that immediate supertraits are converted, // which will, in turn, reach indirect supertraits. - for &(pred, span) in superbounds { - debug!("superbound: {:?}", pred); + for &pred in superbounds { + debug!("superbound: {:?}", pred.node); if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = - pred.kind().skip_binder() + pred.node.kind().skip_binder() { - tcx.at(span).super_predicates_of(bound.def_id()); + tcx.at(pred.span).super_predicates_of(bound.def_id()); } } } @@ -674,8 +679,10 @@ pub(super) fn type_param_predicates( // Implied `Self: Trait` and supertrait bounds. if param_id == item_hir_id { let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); - extend = - Some((identity_trait_ref.without_const().to_predicate(tcx), item.span)); + extend = Some(ty::Spanned { + node: identity_trait_ref.without_const().to_predicate(tcx), + span: item.span, + }); } generics } @@ -701,7 +708,7 @@ pub(super) fn type_param_predicates( Some(assoc_name), ) .into_iter() - .filter(|(predicate, _)| match predicate.kind().skip_binder() { + .filter(|predicate| match predicate.node.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(data)) => data.self_ty().is_param(index), _ => false, }), @@ -724,7 +731,7 @@ impl<'tcx> ItemCtxt<'tcx> { ty: Ty<'tcx>, only_self_bounds: OnlySelfBounds, assoc_name: Option, - ) -> Vec<(ty::Predicate<'tcx>, Span)> { + ) -> Vec>> { ast_generics .predicates .iter() @@ -779,7 +786,7 @@ fn predicates_from_bound<'tcx>( param_ty: Ty<'tcx>, bound: &'tcx hir::GenericBound<'tcx>, bound_vars: &'tcx ty::List, -) -> Vec<(ty::Predicate<'tcx>, Span)> { +) -> Vec>> { let mut bounds = Bounds::default(); astconv.add_bounds(param_ty, [bound].into_iter(), &mut bounds, bound_vars); bounds.predicates().collect() diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 465ae047de373..6468f1bedb326 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1700,8 +1700,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { } let predicates = tcx.super_predicates_that_define_assoc_type((def_id, Some(assoc_name))); - let obligations = predicates.predicates.iter().filter_map(|&(pred, _)| { - let bound_predicate = pred.kind(); + let obligations = predicates.predicates.iter().filter_map(|&pred| { + let bound_predicate = pred.node.kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(data)) => { // The order here needs to match what we would get from `subst_supertrait` diff --git a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs index e18b0f082798b..5f4432c80dd7f 100644 --- a/compiler/rustc_hir_analysis/src/constrained_generic_params.rs +++ b/compiler/rustc_hir_analysis/src/constrained_generic_params.rs @@ -1,7 +1,6 @@ use rustc_data_structures::fx::FxHashSet; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::source_map::Span; use std::ops::ControlFlow; #[derive(Clone, PartialEq, Eq, Hash, Debug)] @@ -151,7 +150,7 @@ pub fn identify_constrained_generic_params<'tcx>( /// think of any. pub fn setup_constraining_predicates<'tcx>( tcx: TyCtxt<'tcx>, - predicates: &mut [(ty::Predicate<'tcx>, Span)], + predicates: &mut [ty::Spanned>], impl_trait_ref: Option>, input_parameters: &mut FxHashSet, ) { @@ -188,7 +187,7 @@ pub fn setup_constraining_predicates<'tcx>( // Note that we don't have to care about binders here, // as the impl trait ref never contains any late-bound regions. if let ty::PredicateKind::Clause(ty::Clause::Projection(projection)) = - predicates[j].0.kind().skip_binder() + predicates[j].node.kind().skip_binder() { // Special case: watch out for some kind of sneaky attempt // to project out an associated type defined by this very diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index 58dd03811f78c..f82dfc68f4008 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -212,9 +212,9 @@ fn unconstrained_parent_impl_substs<'tcx>( // what we want here. We want only a list of constrained parameters while // the functions in `cgp` add the constrained parameters to a list of // unconstrained parameters. - for (predicate, _) in impl_generic_predicates.predicates.iter() { + for predicate in impl_generic_predicates.predicates.iter() { if let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = - predicate.kind().skip_binder() + predicate.node.kind().skip_binder() { let projection_ty = proj.projection_ty; let projected_ty = proj.term; @@ -324,9 +324,10 @@ fn check_predicates<'tcx>( instantiated.predicates, // Don't drop predicates (unsound!) because `spans` is too short instantiated.spans.into_iter().chain(std::iter::repeat(span)), - ), + ) + .map(|(node, span)| ty::Spanned { node, span }), ) - .map(|obligation| (obligation.predicate, obligation.cause.span)) + .map(|obligation| ty::Spanned { node: obligation.predicate, span: obligation.cause.span }) .collect(); let mut impl2_predicates = if impl2_node.is_from_trait() { @@ -361,9 +362,9 @@ fn check_predicates<'tcx>( // which is sound because we forbid impls like the following // // impl AlwaysApplicable for D { } - let always_applicable_traits = impl1_predicates.iter().copied().filter(|&(predicate, _)| { + let always_applicable_traits = impl1_predicates.iter().copied().filter(|&predicate| { matches!( - trait_predicate_kind(tcx, predicate), + trait_predicate_kind(tcx, predicate.node), Some(TraitSpecializationKind::AlwaysApplicable) ) }); @@ -385,9 +386,12 @@ fn check_predicates<'tcx>( .map(|obligation| obligation.predicate), ); - for (predicate, span) in impl1_predicates { - if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(tcx, predicate, *pred2, span)) { - check_specialization_on(tcx, predicate, span) + for predicate in impl1_predicates { + if !impl2_predicates + .iter() + .any(|pred2| trait_predicates_eq(tcx, predicate.node, *pred2, predicate.span)) + { + check_specialization_on(tcx, predicate.node, predicate.span) } } } diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index 9ee6785970c46..47c571b9b9168 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -28,8 +28,8 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { let mut required_predicates = RequiredPredicates::default(); // process predicates and convert to `RequiredPredicates` entry, see below - for &(predicate, span) in predicates.predicates { - match predicate.kind().skip_binder() { + for predicate in predicates.predicates { + match predicate.node.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::TypeOutlives(OutlivesPredicate( ty, reg, @@ -37,7 +37,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { tcx, ty.into(), reg, - span, + predicate.span, &mut required_predicates, ), @@ -48,7 +48,7 @@ impl<'tcx> ExplicitPredicatesMap<'tcx> { tcx, reg1.into(), reg2, - span, + predicate.span, &mut required_predicates, ), diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index 361e8948e851a..96512bca4ee20 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -154,7 +154,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances }; let id_substs = ty::InternalSubsts::identity_for_item(tcx, item_def_id.to_def_id()); for pred in tcx.bound_explicit_item_bounds(item_def_id.to_def_id()).transpose_iter() { - let pred = pred.map_bound(|(pred, _)| *pred).subst(tcx, id_substs); + let pred = pred.map_bound(|pred| pred.node).subst(tcx, id_substs); debug!(?pred); // We only ignore opaque type substs if the opaque type is the outermost type. diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 035ccf30b2462..2a22fdd39d97a 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -528,12 +528,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } for ty in [first_ty, second_ty] { - for (pred, _) in self + for pred in self .tcx .bound_explicit_item_bounds(rpit_def_id) .subst_iter_copied(self.tcx, substs) { - let pred = pred.kind().rebind(match pred.kind().skip_binder() { + let pred = pred.node.kind().rebind(match pred.node.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) => { // FIXME(rpitit): This will need to be fixed when we move to associated types assert!(matches!( diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index ecbe4a97dd967..5ab7cc2c2e239 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -385,21 +385,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.tcx.has_attr(def_id, sym::rustc_evaluate_where_clauses) { let predicates = self.tcx.predicates_of(def_id); let predicates = predicates.instantiate(self.tcx, subst); - for (predicate, predicate_span) in predicates { + for predicate in predicates { let obligation = Obligation::new( self.tcx, ObligationCause::dummy_with_span(callee_expr.span), self.param_env, - predicate, + predicate.node, ); let result = self.evaluate_obligation(&obligation); self.tcx .sess .struct_span_err( callee_expr.span, - &format!("evaluate({:?}) = {:?}", predicate, result), + &format!("evaluate({:?}) = {:?}", predicate.node, result), ) - .span_label(predicate_span, "predicate") + .span_label(predicate.span, "predicate") .emit(); } } diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index ec391ea80f48b..3cbe4e5cc9c1c 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -186,7 +186,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates( self.tcx.mk_ty_var(self.root_var(vid)), - self.obligations_for_self_ty(vid).map(|obl| (obl.predicate, obl.cause.span)), + self.obligations_for_self_ty(vid) + .map(|obl| ty::Spanned { node: obl.predicate, span: obl.cause.span }), ), ty::FnPtr(sig) => { let expected_sig = ExpectedSig { cause_span: None, sig }; @@ -199,7 +200,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn deduce_closure_signature_from_predicates( &self, expected_ty: Ty<'tcx>, - predicates: impl DoubleEndedIterator, Span)>, + predicates: impl DoubleEndedIterator>>, ) -> (Option>, Option) { let mut expected_sig = None; let mut expected_kind = None; @@ -712,13 +713,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .bound_explicit_item_bounds(def_id) .subst_iter_copied(self.tcx, substs) - .find_map(|(p, s)| get_future_output(p, s))?, + .find_map(|p| get_future_output(p.node, p.span))?, ty::Error(_) => return None, ty::Alias(ty::Projection, proj) if self.tcx.is_impl_trait_in_trait(proj.def_id) => self .tcx .bound_explicit_item_bounds(proj.def_id) .subst_iter_copied(self.tcx, proj.substs) - .find_map(|(p, s)| get_future_output(p, s))?, + .find_map(|p| get_future_output(p.node, p.span))?, _ => span_bug!( self.tcx.def_span(expr_def_id), "async fn generator return type not an inference variable: {ret_ty}" diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 29db16849dd5b..4370eb4fc7162 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -866,7 +866,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let new_cause = ObligationCause::new( cause.span, cause.body_id, - ObligationCauseCode::OpaqueReturnType(Some((return_expr_ty, span))), + ObligationCauseCode::OpaqueReturnType(Some(ty::Spanned { + node: return_expr_ty, + span, + })), ); *cause = new_cause; } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs index ec14bd3c6f43e..c220cde8c09e0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs @@ -503,7 +503,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Err(expr); } let relevant_broken_predicate: ty::PredicateKind<'tcx> = - impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder(); + impl_predicates.predicates[impl_predicate_index].node.kind().skip_binder(); match relevant_broken_predicate { ty::PredicateKind::Clause(ty::Clause::Trait(broken_trait)) => { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 61338ac613aea..8f07eeca4881b 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1866,13 +1866,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // FIXME(compiler-errors): This could be problematic if something has two // fn-like predicates with different args, but callable types really never // do that, so it's OK. - for (predicate, span) in instantiated + for predicate in instantiated { - if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = predicate.kind().skip_binder() + if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = predicate.node.kind().skip_binder() && pred.self_ty().peel_refs() == callee_ty && self.tcx.is_fn_trait(pred.def_id()) { - err.span_note(span, "callable defined here"); + err.span_note(predicate.span, "callable defined here"); return; } } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 1dea3e6f900d4..e1af9eef138b8 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -228,7 +228,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { { // HACK(eddyb) should get the original `Span`. let span = tcx.def_span(def_id); - Some((predicate, span)) + Some(ty::Spanned { node: predicate, span }) } _ => None, } diff --git a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs index 9ecc870a70dbd..a2af1aef1a281 100644 --- a/compiler/rustc_hir_typeck/src/generator_interior/mod.rs +++ b/compiler/rustc_hir_typeck/src/generator_interior/mod.rs @@ -577,10 +577,10 @@ fn check_must_not_suspend_ty<'tcx>( // FIXME: support adding the attribute to TAITs ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { let mut has_emitted = false; - for &(predicate, _) in fcx.tcx.explicit_item_bounds(def) { + for &predicate in fcx.tcx.explicit_item_bounds(def) { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = - predicate.kind().skip_binder() + predicate.node.kind().skip_binder() { let def_id = poly_trait_predicate.trait_ref.def_id; let descr_pre = &format!("{}implementer{} of ", data.descr_pre, plural_suffix); diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index a0aa43deadcfd..fae75a3e80c5f 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -582,11 +582,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { { let span = predicates .iter() - .find_map( - |(p, span)| { - if p == obligation.predicate { Some(span) } else { None } - }, - ) + .find_map(|p| (p.node == obligation.predicate).then_some(p.span)) .unwrap_or(rustc_span::DUMMY_SP); Some((trait_pred, span)) } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index fd16363a1db01..acff07d90de70 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -375,8 +375,9 @@ impl<'tcx> InferCtxt<'tcx> { let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; self.tcx.bound_explicit_item_bounds(def_id).subst_iter_copied(self.tcx, substs).find_map( - |(predicate, _)| { + |predicate| { predicate + .node .kind() .map_bound(|kind| match kind { ty::PredicateKind::Clause(ty::Clause::Projection(projection_predicate)) diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs index 7ffe1fd20b49a..26e88603bac73 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -314,9 +314,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { .tcx .explicit_predicates_of(trait_item_def_id) .instantiate_own(self.tcx, trait_item_substs) - .map(|(pred, _)| { - if pred.is_suggestable(self.tcx, false) { - Ok(pred.to_string()) + .map(|pred| { + if pred.node.is_suggestable(self.tcx, false) { + Ok(pred.node.to_string()) } else { Err(()) } diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 49f823a47b83d..d1501fd2b2342 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -547,8 +547,8 @@ impl<'tcx> InferCtxt<'tcx> { let item_bounds = tcx.bound_explicit_item_bounds(def_id.to_def_id()); - for (predicate, _) in item_bounds.subst_iter_copied(tcx, substs) { - let predicate = predicate.fold_with(&mut BottomUpFolder { + for predicate in item_bounds.subst_iter_copied(tcx, substs) { + let predicate = predicate.node.fold_with(&mut BottomUpFolder { tcx, ty_op: |ty| match *ty.kind() { // We can't normalize associated types from `rustc_infer`, diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index c07ff51657994..5754170d05a29 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -3,9 +3,8 @@ use smallvec::smallvec; use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::traits::{self, Obligation, ObligationCause, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_middle::ty::{self, ToPredicate, TyCtxt}; +use rustc_middle::ty::{self, Spanned, ToPredicate, TyCtxt}; use rustc_span::symbol::Ident; -use rustc_span::Span; pub fn anonymize_predicate<'tcx>( tcx: TyCtxt<'tcx>, @@ -100,10 +99,10 @@ pub fn elaborate_predicates<'tcx>( pub fn elaborate_predicates_with_span<'tcx>( tcx: TyCtxt<'tcx>, - predicates: impl Iterator, Span)>, + predicates: impl Iterator>>, ) -> Elaborator<'tcx> { let obligations = predicates - .map(|(predicate, span)| { + .map(|ty::Spanned { node: predicate, span }| { predicate_obligation( predicate, ty::ParamEnv::empty(), @@ -154,8 +153,8 @@ impl<'tcx> Elaborator<'tcx> { // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let obligations = - predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| { + let obligations = predicates.predicates.iter().enumerate().map( + |(index, &Spanned { node: mut pred, span })| { // when parent predicate is non-const, elaborate it to non-const predicates. if data.constness == ty::BoundConstness::NotConst { pred = pred.without_const(tcx); @@ -179,7 +178,8 @@ impl<'tcx> Elaborator<'tcx> { obligation.param_env, cause, ) - }); + }, + ); debug!(?data, ?obligations, "super_predicates"); self.extend_deduped(obligations); } @@ -362,8 +362,8 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>( trait_ref.def_id(), Some(assoc_name), )); - for (super_predicate, _) in super_predicates.predicates { - let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref); + for super_predicate in super_predicates.predicates { + let subst_predicate = super_predicate.node.subst_supertrait(tcx, &trait_ref); if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() { stack.push(binder.map_bound(|t| t.trait_ref)); } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index b1ff76865abda..3f5f046950856 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1590,8 +1590,8 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { if cx.tcx.features().trivial_bounds { let predicates = cx.tcx.predicates_of(item.owner_id); - for &(predicate, span) in predicates.predicates { - let predicate_kind_name = match predicate.kind().skip_binder() { + for &predicate in predicates.predicates { + let predicate_kind_name = match predicate.node.kind().skip_binder() { Clause(Clause::Trait(..)) => "trait", Clause(Clause::TypeOutlives(..)) | Clause(Clause::RegionOutlives(..)) => "lifetime", @@ -1614,11 +1614,11 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { Ambiguous | TypeWellFormedFromEnv(..) => continue, }; - if predicate.is_global() { + if predicate.node.is_global() { cx.emit_spanned_lint( TRIVIAL_BOUNDS, - span, - BuiltinTrivialBounds { predicate_kind_name, predicate }, + predicate.span, + BuiltinTrivialBounds { predicate_kind_name, predicate: predicate.node }, ); } } diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index c2ed0e19f4011..6d871e1b5a569 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -45,7 +45,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { .super_predicates_of(def_id) .predicates .into_iter() - .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred()); + .filter_map(|pred| pred.node.to_opt_poly_trait_pred()); if direct_super_traits_iter.count() > 1 { cx.emit_spanned_lint( MULTIPLE_SUPERTRAIT_UPCASTABLE, diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 883a56cb3ce6b..e31f73cb23fe5 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -70,10 +70,10 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // For every projection predicate in the opaque type's explicit bounds, // check that the type that we're assigning actually satisfies the bounds // of the associated type. - for &(pred, pred_span) in cx.tcx.explicit_item_bounds(def_id) { + for &pred in cx.tcx.explicit_item_bounds(def_id) { // Liberate bound regions in the predicate since we // don't actually care about lifetimes in this check. - let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.kind()); + let predicate = cx.tcx.liberate_late_bound_regions(def_id, pred.node.kind()); let ty::PredicateKind::Clause(ty::Clause::Projection(proj)) = predicate else { continue; }; @@ -95,12 +95,12 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { // For example, in `impl Trait`, for all of the bounds on `Assoc`, // e.g. `type Assoc: OtherTrait`, replace `::Assoc: OtherTrait` // with `impl Send: OtherTrait`. - for (assoc_pred, assoc_pred_span) in cx + for assoc_pred_spanned in cx .tcx .bound_explicit_item_bounds(proj.projection_ty.def_id) .subst_iter_copied(cx.tcx, &proj.projection_ty.substs) { - let assoc_pred = assoc_pred.fold_with(proj_replacer); + let assoc_pred = assoc_pred_spanned.node.fold_with(proj_replacer); let Ok(assoc_pred) = traits::fully_normalize(infcx, traits::ObligationCause::dummy(), cx.param_env, assoc_pred) else { continue; }; @@ -127,14 +127,14 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { }; cx.emit_spanned_lint( OPAQUE_HIDDEN_INFERRED_BOUND, - pred_span, + pred.span, OpaqueHiddenInferredBoundLint { ty: cx.tcx.mk_opaque( def_id, ty::InternalSubsts::identity_for_item(cx.tcx, def_id), ), proj_ty: proj_term, - assoc_pred_span, + assoc_pred_span: assoc_pred_spanned.span, add_bound, }, ); diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 7ea1a138b7e60..0f99c445d10ac 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -91,8 +91,8 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { use rustc_middle::ty::PredicateKind::*; let predicates = cx.tcx.explicit_predicates_of(item.owner_id); - for &(predicate, span) in predicates.predicates { - let Clause(Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else { + for &predicate in predicates.predicates { + let Clause(Clause::Trait(trait_predicate)) = predicate.node.kind().skip_binder() else { continue }; let def_id = trait_predicate.trait_ref.def_id; @@ -106,8 +106,8 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { }; cx.emit_spanned_lint( DROP_BOUNDS, - span, - DropTraitConstraintsDiag { predicate, tcx: cx.tcx, def_id }, + predicate.span, + DropTraitConstraintsDiag { predicate: predicate.node, tcx: cx.tcx, def_id }, ); } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 0070e46ffdf02..68e0cbcb49aed 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -651,7 +651,7 @@ impl<'a, 'tcx> Decodable> for Symbol { } } -impl<'a, 'tcx> Decodable> for &'tcx [(ty::Predicate<'tcx>, Span)] { +impl<'a, 'tcx> Decodable> for &'tcx [ty::Spanned>] { fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { ty::codec::RefDecodable::decode(d) } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 6dc6041b284ea..1abc247f4cb7d 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -351,7 +351,7 @@ define_tables! { is_type_alias_impl_trait: Table, attr_flags: Table, def_path_hashes: Table, - explicit_item_bounds: Table, Span)>>, + explicit_item_bounds: Table>>>, inferred_outlives_of: Table, Span)>>, inherent_impls: Table>, associated_types_for_impl_traits_in_associated_fn: Table>, diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 88a21b612eb60..535a09529f9b7 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -12,7 +12,7 @@ use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex}; -use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; +use crate::ty::{GenericArg, InternalSubsts, Spanned, SubstsRef}; use rustc_data_structures::captures::Captures; use rustc_errors::ErrorGuaranteed; @@ -691,7 +691,7 @@ pub struct VarBindingForm<'tcx> { /// (a) the right-hand side isn't evaluated as a place expression. /// (b) it gives a way to separate this case from the remaining cases /// for diagnostics. - pub opt_match_place: Option<(Option>, Span)>, + pub opt_match_place: Option>>>, /// The span of the pattern in which this variable was bound. pub pat_span: Span, } @@ -1802,10 +1802,10 @@ impl SourceScope { source_scopes: &IndexVec>, ) -> Option> { let scope_data = &source_scopes[self]; - if let Some((inlined_instance, _)) = scope_data.inlined { - Some(inlined_instance) + if let Some(inlined_instance) = scope_data.inlined { + Some(inlined_instance.node) } else if let Some(inlined_scope) = scope_data.inlined_parent_scope { - Some(source_scopes[inlined_scope].inlined.unwrap().0) + Some(source_scopes[inlined_scope].inlined.unwrap().node) } else { None } @@ -1820,7 +1820,7 @@ pub struct SourceScopeData<'tcx> { /// Whether this scope is the root of a scope tree of another body, /// inlined into this body by the MIR inliner. /// `ty::Instance` is the callee, and the `Span` is the call site. - pub inlined: Option<(ty::Instance<'tcx>, Span)>, + pub inlined: Option>>, /// Nearest (transitive) parent scope (if any) which is inlined. /// This is an optimization over walking up `parent_scope` diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 7e51953599d5a..1b970d9891c83 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -612,14 +612,18 @@ fn write_scope_tree( let child_data = &body.source_scopes[child]; assert_eq!(child_data.parent_scope, Some(parent)); - let (special, span) = if let Some((callee, callsite_span)) = child_data.inlined { + let (special, span) = if let Some(callee) = child_data.inlined { ( format!( " (inlined {}{})", - if callee.def.requires_caller_location(tcx) { "#[track_caller] " } else { "" }, - callee + if callee.node.def.requires_caller_location(tcx) { + "#[track_caller] " + } else { + "" + }, + callee.node ), - Some(callsite_span), + Some(callee.span), ) } else { (String::new(), None) diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 671e76b28956c..8c98e573b2d47 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -322,7 +322,7 @@ macro_rules! make_mir_visitor { if let Some(parent_scope) = parent_scope { self.visit_source_scope($(& $mutability)? *parent_scope); } - if let Some((callee, callsite_span)) = inlined { + if let Some(Spanned { node: callee, span: callsite_span }) = inlined { let location = Location::START; self.visit_span($(& $mutability)? *callsite_span); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 5271fc0cdb02e..2b9c5709d625c 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -273,7 +273,7 @@ rustc_queries! { /// `key` is the `DefId` of the associated type or opaque type. /// /// Bounds from the parent (e.g. with nested impl trait) are not included. - query explicit_item_bounds(key: DefId) -> &'tcx [(ty::Predicate<'tcx>, Span)] { + query explicit_item_bounds(key: DefId) -> &'tcx [ty::Spanned>] { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index c375163e9d37e..0940de147ab68 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -14,7 +14,7 @@ use crate::infer::canonical::Canonical; use crate::mir::ConstraintCategory; use crate::ty::abstract_const::NotConstEvaluatable; use crate::ty::subst::SubstsRef; -use crate::ty::{self, AdtKind, Ty, TyCtxt}; +use crate::ty::{self, AdtKind, Spanned, Ty, TyCtxt}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diagnostic}; @@ -407,7 +407,7 @@ pub enum ObligationCauseCode<'tcx> { ReturnType, /// Opaque return type of this function - OpaqueReturnType(Option<(Ty<'tcx>, Span)>), + OpaqueReturnType(Option>>), /// Block implicit return BlockTailExpression(hir::HirId), diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index d54b8c599d954..e2cd2cedf9b3e 100644 --- a/compiler/rustc_middle/src/traits/util.rs +++ b/compiler/rustc_middle/src/traits/util.rs @@ -25,8 +25,8 @@ impl<'tcx> Elaborator<'tcx> { .super_predicates_of(trait_ref.def_id()) .predicates .into_iter() - .flat_map(|(pred, _)| { - pred.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_pred() + .flat_map(|pred| { + pred.node.subst_supertrait(self.tcx, &trait_ref).to_opt_poly_trait_pred() }) .map(|t| t.map_bound(|pred| pred.trait_ref)) .filter(|supertrait_ref| self.visited.insert(*supertrait_ref)); diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 3ce80e06ad9ef..c3f6e9d9a36dc 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -355,7 +355,7 @@ impl<'tcx, D: TyDecoder>> Decodable for AdtDef<'tcx> { } impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> - for [(ty::Predicate<'tcx>, Span)] + for [ty::Spanned>] { fn decode(decoder: &mut D) -> &'tcx Self { decoder.interner().arena.alloc_from_iter( diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index eca4b5bcccb38..622fd12bd0f6a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1632,8 +1632,8 @@ impl<'tcx> TyCtxt<'tcx> { let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = ty.kind() else { return false }; let future_trait = self.require_lang_item(LangItem::Future, None); - self.explicit_item_bounds(def_id).iter().any(|(predicate, _)| { - let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() else { + self.explicit_item_bounds(def_id).iter().any(|predicate| { + let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.node.kind().skip_binder() else { return false; }; trait_predicate.trait_ref.def_id == future_trait @@ -1655,9 +1655,9 @@ impl<'tcx> TyCtxt<'tcx> { let trait_did = stack.pop()?; let generic_predicates = self.super_predicates_of(trait_did); - for (predicate, _) in generic_predicates.predicates { + for predicate in generic_predicates.predicates { if let ty::PredicateKind::Clause(ty::Clause::Trait(data)) = - predicate.kind().skip_binder() + predicate.node.kind().skip_binder() { if set.insert(data.def_id()) { stack.push(data.def_id()); diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index baef4ffeda732..1f9a06f7f9198 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -6,7 +6,9 @@ use rustc_hir::def_id::DefId; use rustc_span::symbol::{kw, Symbol}; use rustc_span::Span; -use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt}; +use super::{ + EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, Spanned, TyCtxt, +}; #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub enum GenericParamDefKind { @@ -323,7 +325,7 @@ impl<'tcx> Generics { #[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)] pub struct GenericPredicates<'tcx> { pub parent: Option, - pub predicates: &'tcx [(Predicate<'tcx>, Span)], + pub predicates: &'tcx [Spanned>], } impl<'tcx> GenericPredicates<'tcx> { @@ -341,7 +343,7 @@ impl<'tcx> GenericPredicates<'tcx> { &self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, - ) -> impl Iterator, Span)> + DoubleEndedIterator + ExactSizeIterator + ) -> impl Iterator>> + DoubleEndedIterator + ExactSizeIterator { EarlyBinder(self.predicates).subst_iter_copied(tcx, substs) } @@ -358,8 +360,8 @@ impl<'tcx> GenericPredicates<'tcx> { } instantiated .predicates - .extend(self.predicates.iter().map(|(p, _)| EarlyBinder(*p).subst(tcx, substs))); - instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp)); + .extend(self.predicates.iter().map(|p| EarlyBinder(p.node).subst(tcx, substs))); + instantiated.spans.extend(self.predicates.iter().map(|p| p.span)); } pub fn instantiate_identity(&self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx> { @@ -376,7 +378,7 @@ impl<'tcx> GenericPredicates<'tcx> { if let Some(def_id) = self.parent { tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated); } - instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p)); - instantiated.spans.extend(self.predicates.iter().map(|(_, s)| s)); + instantiated.predicates.extend(self.predicates.iter().map(|p| p.node)); + instantiated.spans.extend(self.predicates.iter().map(|p| p.span)); } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 22176fd357511..03b1def7e76be 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -48,6 +48,7 @@ use rustc_serialize::{Decodable, Encodable}; use rustc_session::lint::LintBuffer; pub use rustc_session::lint::RegisteredTools; use rustc_span::hygiene::MacroKind; +pub use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{ExpnId, ExpnKind, Span}; use rustc_target::abi::{Align, Integer, IntegerType, VariantIdx}; @@ -1292,27 +1293,34 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> { - type Item = (Predicate<'tcx>, Span); + type Item = Spanned>; - type IntoIter = std::iter::Zip>, std::vec::IntoIter>; + type IntoIter = std::iter::Map< + std::iter::Zip>, std::vec::IntoIter>, + fn((Predicate<'tcx>, Span)) -> Spanned>, + >; fn into_iter(self) -> Self::IntoIter { debug_assert_eq!(self.predicates.len(), self.spans.len()); - std::iter::zip(self.predicates, self.spans) + std::iter::zip(self.predicates, self.spans).map(|(node, span)| Spanned { node, span }) } } impl<'a, 'tcx> IntoIterator for &'a InstantiatedPredicates<'tcx> { - type Item = (Predicate<'tcx>, Span); - - type IntoIter = std::iter::Zip< - std::iter::Copied>>, - std::iter::Copied>, + type Item = Spanned>; + + type IntoIter = std::iter::Map< + std::iter::Zip< + std::iter::Copied>>, + std::iter::Copied>, + >, + fn((Predicate<'tcx>, Span)) -> Spanned>, >; fn into_iter(self) -> Self::IntoIter { debug_assert_eq!(self.predicates.len(), self.spans.len()); std::iter::zip(self.predicates.iter().copied(), self.spans.iter().copied()) + .map(|(node, span)| Spanned { node, span }) } } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 7534d06ae91f1..ed45bf960b8d5 100644 --- a/compiler/rustc_middle/src/ty/parameterized.rs +++ b/compiler/rustc_middle/src/ty/parameterized.rs @@ -36,6 +36,10 @@ impl ParameterizedOverTcx for ty::EarlyBinder { type Value<'tcx> = ty::EarlyBinder>; } +impl ParameterizedOverTcx for ty::Spanned { + type Value<'tcx> = ty::Spanned>; +} + #[macro_export] macro_rules! trivially_parameterized_over_tcx { ($($ty:ty),+ $(,)?) => { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index fffdbfc9660bb..8dd0100363b28 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -916,8 +916,8 @@ pub trait PrettyPrinter<'tcx>: let mut is_sized = false; let mut lifetimes = SmallVec::<[ty::Region<'tcx>; 1]>::new(); - for (predicate, _) in bounds.subst_iter_copied(tcx, substs) { - let bound_predicate = predicate.kind(); + for predicate in bounds.subst_iter_copied(tcx, substs) { + let bound_predicate = predicate.node.kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 895cac90580e5..07bd7971de999 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -11,6 +11,7 @@ use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; use crate::ty::{self, AliasTy, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_hir::def::Namespace; use rustc_index::vec::{Idx, IndexVec}; +use rustc_span::source_map::Spanned; use rustc_target::abi::TyAndLayout; use std::fmt; @@ -249,6 +250,7 @@ CloneLiftImpls! { crate::ty::RegionVid, crate::ty::UniverseIndex, crate::ty::Variance, + ::rustc_span::Span, ::rustc_span::symbol::Ident, ::rustc_errors::ErrorGuaranteed, Field, @@ -266,7 +268,6 @@ TrivialTypeTraversalAndLiftImpls! { ::rustc_hir::Unsafety, ::rustc_target::spec::abi::Abi, crate::ty::BoundConstness, - ::rustc_span::Span, } CloneLiftImpls! { @@ -366,6 +367,13 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> { } } +impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Spanned { + type Lifted = Spanned; + fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option { + Some(Spanned { node: tcx.lift(self.node)?, span: self.span }) + } +} + /////////////////////////////////////////////////////////////////////////// // Traversal implementations. diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index dc585f438f4cd..456a639b5fc11 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -678,7 +678,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn bound_explicit_item_bounds( self, def_id: DefId, - ) -> ty::EarlyBinder<&'tcx [(ty::Predicate<'tcx>, rustc_span::Span)]> { + ) -> ty::EarlyBinder<&'tcx [ty::Spanned>]> { ty::EarlyBinder(self.explicit_item_bounds(def_id)) } diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 2643d33cee00a..0156150e3c217 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -231,7 +231,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { remainder_span, pattern, None, - Some((Some(&destination), initializer_span)), + Some(ty::Spanned { + node: Some(&destination), + span: initializer_span, + }), ); this.visit_primary_bindings( pattern, @@ -308,7 +311,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { remainder_span, pattern, None, - Some((None, initializer_span)), + Some(ty::Spanned { + node: None, + span: initializer_span, + }), ); this.expr_into_pattern(block, &pattern, init) // irrefutable pattern diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index aa58bdfb2cad7..cfef8c449322b 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -345,8 +345,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // }; // ``` let scrutinee_place = scrutinee_place_builder.try_to_place(this); - let opt_scrutinee_place = - scrutinee_place.as_ref().map(|place| (Some(place), scrutinee_span)); + let opt_scrutinee_place = scrutinee_place + .as_ref() + .map(|place| ty::Spanned { node: Some(place), span: scrutinee_span }); let scope = this.declare_bindings( None, arm.span, @@ -611,7 +612,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // ``` if let Some(place) = initializer.try_to_place(self) { let LocalInfo::User(BindingForm::Var( - VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. }, + VarBindingForm { opt_match_place: Some(ty::Spanned { node: ref mut match_place, .. }), .. }, )) = **self.local_decls[local].local_info.as_mut().assert_crate_local() else { bug!("Let binding to non-user variable.") }; @@ -646,7 +647,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { scope_span: Span, pattern: &Pat<'tcx>, guard: Option<&Guard<'tcx>>, - opt_match_place: Option<(Option<&Place<'tcx>>, Span)>, + opt_match_place: Option>>>, ) -> Option { self.visit_primary_bindings( &pattern, @@ -668,7 +669,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ty, user_ty, ArmHasGuard(guard.is_some()), - opt_match_place.map(|(x, y)| (x.cloned(), y)), + opt_match_place.map(|x| ty::Spanned { node: x.node.cloned(), span: x.span }), pattern.span, ); }, @@ -1796,7 +1797,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut [&mut guard_candidate, &mut otherwise_candidate], ); let expr_place = expr_place_builder.try_to_place(self); - let opt_expr_place = expr_place.as_ref().map(|place| (Some(place), expr_span)); + let opt_expr_place = + expr_place.as_ref().map(|place| ty::Spanned { node: Some(place), span: expr_span }); let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap(); self.break_for_else(otherwise_post_guard_block, else_target, self.source_info(expr_span)); @@ -2212,7 +2214,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { var_ty: Ty<'tcx>, user_ty: UserTypeProjections, has_guard: ArmHasGuard, - opt_match_place: Option<(Option>, Span)>, + opt_match_place: Option>>>, pat_span: Span, ) { let tcx = self.tcx; diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 80d8b27336c54..25db800e9cb5a 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -884,7 +884,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { LocalInfo::User(BindingForm::Var(VarBindingForm { binding_mode, opt_ty_info: param.ty_span, - opt_match_place: Some((None, span)), + opt_match_place: Some(ty::Spanned { node: None, span }), pat_span: span, })) }; @@ -896,7 +896,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr.span, &pat, None, - Some((Some(&place), span)), + Some(ty::Spanned { node: Some(&place), span }), ); let place_builder = PlaceBuilder::from(local); unpack!(block = self.place_into_pattern(block, &pat, place_builder, false)); diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index de7b8c63fc87a..761362f1d373b 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -113,7 +113,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { .predicates_of(def_id.to_def_id()) .predicates .iter() - .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); + .filter_map(|p| p.node.is_global().then_some(p.node)); if traits::impossible_predicates( tcx, traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(), diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 68e50070e56e1..2b7f007ff0dcb 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -90,7 +90,7 @@ impl<'tcx> MirLint<'tcx> for ConstProp { .predicates_of(def_id.to_def_id()) .predicates .iter() - .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); + .filter_map(|p| p.node.is_global().then_some(p.node)); if traits::impossible_predicates( tcx, traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(), diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index e6875fad3068d..bd97655f00fcc 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1785,10 +1785,10 @@ fn check_must_not_suspend_ty<'tcx>( // FIXME: support adding the attribute to TAITs ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { let mut has_emitted = false; - for &(predicate, _) in tcx.explicit_item_bounds(def) { + for &predicate in tcx.explicit_item_bounds(def) { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::PredicateKind::Clause(ty::Clause::Trait(ref poly_trait_predicate)) = - predicate.kind().skip_binder() + predicate.node.kind().skip_binder() { let def_id = poly_trait_predicate.trait_ref.def_id; let descr_pre = &format!("{}implementer{} of ", data.descr_pre, plural_suffix); diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 9cba8870f2377..727490c3d0483 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1059,7 +1059,10 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { // Mark the outermost callee scope as an inlined one. assert_eq!(scope_data.inlined, None); - scope_data.inlined = Some((self.callsite.callee, self.callsite.source_info.span)); + scope_data.inlined = Some(ty::Spanned { + node: self.callsite.callee, + span: self.callsite.source_info.span, + }); } else if scope_data.inlined_parent_scope.is_none() { // Make it easy to find the scope with `inlined` set above. scope_data.inlined_parent_scope = Some(self.map_scope(OUTERMOST_SOURCE_SCOPE)); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index cd67644589846..5b6b324579367 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -189,7 +189,7 @@ where predicates: ty::GenericPredicates<'tcx>, ) -> ControlFlow { let ty::GenericPredicates { parent: _, predicates } = predicates; - predicates.iter().try_for_each(|&(predicate, _span)| self.visit_predicate(predicate)) + predicates.iter().try_for_each(|&predicate| self.visit_predicate(predicate.node)) } } @@ -1248,8 +1248,8 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { self.tcx.types.never, ); - for (pred, _) in bounds.predicates() { - match pred.kind().skip_binder() { + for pred in bounds.predicates() { + match pred.node.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => { if self.visit_trait(trait_predicate.trait_ref).is_break() { return; diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs index 35b7e5919e42a..44c7ffa9283d7 100644 --- a/compiler/rustc_query_impl/src/on_disk_cache.rs +++ b/compiler/rustc_query_impl/src/on_disk_cache.rs @@ -820,7 +820,7 @@ impl<'a, 'tcx> Decodable> } } -impl<'a, 'tcx> Decodable> for &'tcx [(ty::Predicate<'tcx>, Span)] { +impl<'a, 'tcx> Decodable> for &'tcx [ty::Spanned>] { fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { RefDecodable::decode(d) } diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index ae81d95e27967..3ed5cc2d9bff7 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -11,6 +11,7 @@ rustc_macros = { path = "../rustc_macros" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } rustc_arena = { path = "../rustc_arena" } +rustc_type_ir = { path = "../rustc_type_ir" } scoped-tls = "1.0" unicode-width = "0.1.4" cfg-if = "1.0" diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index ee895f53eba9b..265910bdf33d1 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -76,6 +76,7 @@ pub mod monotonic { } #[derive(Clone, Encodable, Decodable, Debug, Copy, HashStable_Generic)] +#[derive(Eq, PartialEq, Hash, TypeFoldable, TypeVisitable)] pub struct Spanned { pub node: T, pub span: Span, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 186bfc701bc4c..ecac860dc84cf 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2108,7 +2108,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // but whose substs don't match. let other_pred = predicates.into_iter() .enumerate() - .find(|(other_idx, (pred, _))| match pred.kind().skip_binder() { + .find(|(other_idx, pred)| match pred.node.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) if self.tcx.is_fn_trait(trait_pred.def_id()) && other_idx != idx @@ -2116,12 +2116,12 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // (i.e. constraining this closure) && expected_self == self.tcx.anonymize_bound_vars( - pred.kind().rebind(trait_pred.self_ty()), + pred.node.kind().rebind(trait_pred.self_ty()), ) // But the substs don't match (i.e. incompatible args) && expected_substs != self.tcx.anonymize_bound_vars( - pred.kind().rebind(trait_pred.trait_ref.substs), + pred.node.kind().rebind(trait_pred.trait_ref.substs), ) => { true @@ -2129,9 +2129,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { _ => false, }); // If we found one, then it's very likely the cause of the error. - if let Some((_, (_, other_pred_span))) = other_pred { + if let Some((_, other_pred)) = other_pred { err.span_note( - other_pred_span, + other_pred.span, "closure inferred to have a different signature due to this bound", ); } @@ -3339,10 +3339,10 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } } ObligationCauseCode::OpaqueReturnType(expr_info) => { - if let Some((expr_ty, expr_span)) = expr_info { - let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr_ty)); + if let Some(expr) = expr_info { + let expr_ty = with_forced_trimmed_paths!(self.ty_to_string(expr.node)); err.span_label( - expr_span, + expr.span, with_forced_trimmed_paths!(format!( "return type was inferred to be `{expr_ty}` here", )), diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index bfeda88a6d40c..d56e0f52e178c 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -113,11 +113,11 @@ pub fn predicates_for_generics<'tcx>( param_env: ty::ParamEnv<'tcx>, generic_bounds: ty::InstantiatedPredicates<'tcx>, ) -> impl Iterator> { - generic_bounds.into_iter().enumerate().map(move |(idx, (predicate, span))| Obligation { - cause: cause(idx, span), + generic_bounds.into_iter().enumerate().map(move |(idx, predicate)| Obligation { + cause: cause(idx, predicate.span), recursion_depth: 0, param_env, - predicate, + predicate: predicate.node, }) } @@ -523,13 +523,13 @@ fn is_impossible_method(tcx: TyCtxt<'_>, (impl_def_id, trait_item_def_id): (DefI let param_env = tcx.param_env(impl_def_id); let mut visitor = ReferencesOnlyParentGenerics { tcx, generics, trait_item_def_id }; - let predicates_for_trait = predicates.predicates.iter().filter_map(|(pred, span)| { - pred.visit_with(&mut visitor).is_continue().then(|| { + let predicates_for_trait = predicates.predicates.iter().filter_map(|pred| { + pred.node.visit_with(&mut visitor).is_continue().then(|| { Obligation::new( tcx, - ObligationCause::dummy_with_span(*span), + ObligationCause::dummy_with_span(pred.span), param_env, - ty::EarlyBinder(*pred).subst(tcx, impl_trait_ref.substs), + ty::EarlyBinder(pred.node).subst(tcx, impl_trait_ref.substs), ) }) }); diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index a5def4151bfda..917e0b40ed737 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -284,7 +284,10 @@ fn predicates_reference_self( predicates .predicates .iter() - .map(|&(predicate, sp)| (predicate.subst_supertrait(tcx, &trait_ref), sp)) + .map(|&predicate| ty::Spanned { + node: predicate.node.subst_supertrait(tcx, &trait_ref), + span: predicate.span, + }) .filter_map(|predicate| predicate_references_self(tcx, predicate)) .collect() } @@ -300,7 +303,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span fn predicate_references_self<'tcx>( tcx: TyCtxt<'tcx>, - (predicate, sp): (ty::Predicate<'tcx>, Span), + ty::Spanned { node: predicate, span: sp }: ty::Spanned>, ) -> Option { let self_ty = tcx.types.self_param; let has_self_ty = |arg: &GenericArg<'tcx>| arg.walk().any(|arg| arg == self_ty.into()); @@ -555,7 +558,7 @@ fn virtual_call_violation_for_method<'tcx>( // NOTE: This check happens last, because it results in a lint, and not a // hard error. - if tcx.predicates_of(method.def_id).predicates.iter().any(|&(pred, span)| { + if tcx.predicates_of(method.def_id).predicates.iter().any(|&pred| { // dyn Trait is okay: // // trait Trait { @@ -565,7 +568,7 @@ fn virtual_call_violation_for_method<'tcx>( // because a trait object can't claim to live longer than the concrete // type. If the lifetime bound holds on dyn Trait then it's guaranteed // to hold as well on the concrete type. - if pred.to_opt_type_outlives().is_some() { + if pred.node.to_opt_type_outlives().is_some() { return false; } @@ -586,7 +589,7 @@ fn virtual_call_violation_for_method<'tcx>( trait_ref: pred_trait_ref, constness: ty::BoundConstness::NotConst, polarity: ty::ImplPolarity::Positive, - })) = pred.kind().skip_binder() + })) = pred.node.kind().skip_binder() && pred_trait_ref.self_ty() == tcx.types.self_param && tcx.trait_is_auto(pred_trait_ref.def_id) { @@ -596,14 +599,14 @@ fn virtual_call_violation_for_method<'tcx>( // auto trait. if pred_trait_ref.substs.len() != 1 { tcx.sess.diagnostic().delay_span_bug( - span, + pred.span, "auto traits cannot have generic parameters", ); } return false; } - contains_illegal_self_type_reference(tcx, trait_def_id, pred) + contains_illegal_self_type_reference(tcx, trait_def_id, pred.node) }) { return Some(MethodViolationCode::WhereClauseReferencesSelf); } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index b8d9cff9c489b..7b384b7660304 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2254,21 +2254,21 @@ fn confirm_impl_trait_in_trait_candidate<'tcx>( tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs), &mut obligations, ); - obligations.extend(predicates.into_iter().map(|(pred, span)| { + obligations.extend(predicates.into_iter().map(|pred| { Obligation::with_depth( tcx, ObligationCause::new( obligation.cause.span, obligation.cause.body_id, - if span.is_dummy() { + if pred.span.is_dummy() { super::ItemObligation(impl_fn_def_id) } else { - super::BindingObligation(impl_fn_def_id, span) + super::BindingObligation(impl_fn_def_id, pred.span) }, ), obligation.recursion_depth + 1, obligation.param_env, - pred, + pred.node, ) })); @@ -2299,13 +2299,13 @@ fn assoc_ty_own_obligations<'cx, 'tcx>( let predicates = tcx .predicates_of(obligation.predicate.def_id) .instantiate_own(tcx, obligation.predicate.substs); - for (predicate, span) in predicates { + for predicate in predicates { let normalized = normalize_with_depth_to( selcx, obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - predicate, + predicate.node, nested, ); @@ -2316,7 +2316,7 @@ fn assoc_ty_own_obligations<'cx, 'tcx>( | super::AscribeUserTypeProvePredicate(..) ) { obligation.cause.clone() - } else if span.is_dummy() { + } else if predicate.span.is_dummy() { ObligationCause::new( obligation.cause.span, obligation.cause.body_id, @@ -2326,7 +2326,7 @@ fn assoc_ty_own_obligations<'cx, 'tcx>( ObligationCause::new( obligation.cause.span, obligation.cause.body_id, - super::BindingObligation(obligation.predicate.def_id, span), + super::BindingObligation(obligation.predicate.def_id, predicate.span), ) }; nested.push(Obligation::with_depth( diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 3d5dd18f4c1d7..2f3a185de9e36 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -184,13 +184,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() { let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs); - for (predicate, _) in predicates { + for predicate in predicates { let normalized = normalize_with_depth_to( self, obligation.param_env, obligation.cause.clone(), obligation.recursion_depth + 1, - predicate, + predicate.node, &mut obligations, ); obligations.push(Obligation::with_depth( diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index bc1c72da1e175..31d31f054dc10 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2692,13 +2692,13 @@ impl<'tcx> SelectionContext<'_, 'tcx> { assert_eq!(predicates.parent, None); let predicates = predicates.instantiate_own(tcx, substs); let mut obligations = Vec::with_capacity(predicates.len()); - for (index, (predicate, span)) in predicates.into_iter().enumerate() { + for (index, predicate) in predicates.into_iter().enumerate() { let cause = cause.clone().derived_cause(parent_trait_pred, |derived| { ImplDerivedObligation(Box::new(ImplDerivedObligationCause { derived, impl_or_alias_def_id: def_id, impl_def_predicate_index: Some(index), - span, + span: predicate.span, })) }); let predicate = normalize_with_depth_to( @@ -2706,7 +2706,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { param_env, cause.clone(), recursion_depth, - predicate, + predicate.node, &mut obligations, ); obligations.push(Obligation { cause, recursion_depth, param_env, predicate }); diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 8e229dd8d6b98..f599af4e627e1 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -470,7 +470,7 @@ pub(crate) fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Opti let mut pretty_predicates = Vec::with_capacity(predicates.len() + types_without_default_bounds.len()); - for (mut p, _) in predicates { + for ty::Spanned { node: mut p, .. } in predicates { if let Some(poly_trait_ref) = p.to_opt_poly_trait_pred() { if Some(poly_trait_ref.def_id()) == sized_trait { types_without_default_bounds.remove(&poly_trait_ref.self_ty().skip_binder()); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index ab4c36975a0ec..c1f583f7b9237 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -118,10 +118,10 @@ impl<'tcx> TraitAliasExpander<'tcx> { let predicates = tcx.super_predicates_of(trait_ref.def_id()); debug!(?predicates); - let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { - pred.subst_supertrait(tcx, &trait_ref) - .to_opt_poly_trait_pred() - .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span)) + let items = predicates.predicates.iter().rev().filter_map(|pred| { + pred.node.subst_supertrait(tcx, &trait_ref).to_opt_poly_trait_pred().map(|trait_ref| { + item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), pred.span) + }) }); debug!("expand_trait_aliases: items={:?}", items.clone().collect::>()); @@ -177,7 +177,7 @@ impl Iterator for SupertraitDefIds<'_> { predicates .predicates .iter() - .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred()) + .filter_map(|pred| pred.node.to_opt_poly_trait_pred()) .map(|trait_ref| trait_ref.def_id()) .filter(|&super_def_id| visited.insert(super_def_id)), ); diff --git a/compiler/rustc_trait_selection/src/traits/vtable.rs b/compiler/rustc_trait_selection/src/traits/vtable.rs index a4e9928f8b2cf..ff711d6f9df40 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -113,8 +113,10 @@ pub(super) fn prepare_vtable_segments<'tcx, T>( .super_predicates_of(inner_most_trait_ref.def_id()) .predicates .into_iter() - .filter_map(move |(pred, _)| { - pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred() + .filter_map(move |pred| { + pred.node + .subst_supertrait(tcx, &inner_most_trait_ref) + .to_opt_poly_trait_pred() }); 'diving_in_skip_visited_traits: loop { @@ -263,7 +265,7 @@ fn vtable_entries<'tcx>( let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs); if impossible_predicates( tcx, - predicates.map(|(predicate, _)| predicate).collect(), + predicates.map(|predicate| predicate.node).collect(), ) { debug!("vtable_entries: predicates do not hold"); return VtblEntry::Vacant; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index d498af359c584..7245d49455ab5 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -773,7 +773,7 @@ impl<'tcx> WfPredicates<'tcx> { debug_assert_eq!(predicates.predicates.len(), origins.len()); iter::zip(predicates, origins.into_iter().rev()) - .map(|((mut pred, span), origin_def_id)| { + .map(|(ty::Spanned { node: mut pred, span }, origin_def_id)| { let code = if span.is_dummy() { traits::ItemObligation(origin_def_id) } else { diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index f8c8f744e6d53..1b8f60c7fa340 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -42,7 +42,7 @@ impl<'tcx> RustIrDatabase<'tcx> { .tcx .predicates_defined_on(def_id) .instantiate_own(self.interner.tcx, bound_vars) - .filter_map(|(wc, _)| LowerInto::lower_into(wc, self.interner)) + .filter_map(|wc| LowerInto::lower_into(wc.node, self.interner)) .collect() } @@ -54,7 +54,7 @@ impl<'tcx> RustIrDatabase<'tcx> { bounds .0 .iter() - .map(|(bound, _)| bounds.rebind(*bound).subst(self.interner.tcx, &bound_vars)) + .map(|bound| bounds.rebind(bound.node).subst(self.interner.tcx, &bound_vars)) .filter_map(|bound| LowerInto::>::lower_into(bound, self.interner)) .collect() } @@ -511,8 +511,8 @@ impl<'tcx> chalk_solve::RustIrDatabase> for RustIrDatabase<'t explicit_item_bounds .0 .iter() - .map(|(bound, _)| { - explicit_item_bounds.rebind(*bound).subst(self.interner.tcx, &bound_vars) + .map(|bound| { + explicit_item_bounds.rebind(bound.node).subst(self.interner.tcx, &bound_vars) }) .map(|bound| { bound.fold_with(&mut ReplaceOpaqueTyFolder { diff --git a/compiler/rustc_traits/src/type_op.rs b/compiler/rustc_traits/src/type_op.rs index e0fd487b3d37f..75c7fd592f1e9 100644 --- a/compiler/rustc_traits/src/type_op.rs +++ b/compiler/rustc_traits/src/type_op.rs @@ -107,15 +107,15 @@ fn relate_mir_and_user_substs<'tcx>( let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); debug!(?instantiated_predicates); - for (instantiated_predicate, predicate_span) in instantiated_predicates { - let span = if span == DUMMY_SP { predicate_span } else { span }; + for instantiated_predicate in instantiated_predicates { + let span = if span == DUMMY_SP { instantiated_predicate.span } else { span }; let cause = ObligationCause::new( span, CRATE_DEF_ID, - ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span), + ObligationCauseCode::AscribeUserTypeProvePredicate(instantiated_predicate.span), ); let instantiated_predicate = - ocx.normalize(&cause.clone(), param_env, instantiated_predicate); + ocx.normalize(&cause.clone(), param_env, instantiated_predicate.node); ocx.register_obligation(Obligation::new(tcx, cause, param_env, instantiated_predicate)); } diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 9fed1e57c9213..d3b76867c55da 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -65,7 +65,7 @@ fn sized_constraint_for_ty<'tcx>( .without_const() .to_predicate(tcx); let predicates = tcx.predicates_of(adtdef.did()).predicates; - if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] } + if predicates.iter().any(|p| p.node == sized_predicate) { vec![] } else { vec![ty] } } Placeholder(..) | Bound(..) | Infer(..) => { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e3e5454ef5443..eb49c8948d193 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -432,7 +432,7 @@ fn clean_projection<'tcx>( .tcx .explicit_item_bounds(ty.skip_binder().def_id) .iter() - .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.skip_binder().substs)) + .map(|bound| EarlyBinder(bound.node).subst(cx.tcx, ty.skip_binder().substs)) .collect::>(); return clean_middle_opaque_bounds(cx, bounds); } @@ -770,10 +770,10 @@ fn clean_ty_generics<'tcx>( let where_predicates = preds .predicates .iter() - .flat_map(|(p, _)| { + .flat_map(|p| { let mut projection = None; let param_idx = (|| { - let bound_p = p.kind(); + let bound_p = p.node.kind(); match bound_p.skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(pred)) => { if let ty::Param(param) = pred.self_ty().kind() { @@ -803,7 +803,7 @@ fn clean_ty_generics<'tcx>( if let Some(param_idx) = param_idx && let Some(b) = impl_trait.get_mut(¶m_idx.into()) { - let p: WherePredicate = clean_predicate(*p, cx)?; + let p: WherePredicate = clean_predicate(p.node, cx)?; b.extend( p.get_bounds() @@ -839,7 +839,7 @@ fn clean_ty_generics<'tcx>( return None; } - Some(p) + Some(&p.node) }) .collect::>(); @@ -1849,7 +1849,7 @@ pub(crate) fn clean_middle_ty<'tcx>( .tcx .explicit_item_bounds(def_id) .iter() - .map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, substs)) + .map(|bound| EarlyBinder(bound.node).subst(cx.tcx, substs)) .collect::>(); clean_middle_opaque_bounds(cx, bounds) } diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index dbbc25739aa07..7ee01db0915cb 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -131,8 +131,10 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) predicates .predicates .iter() - .filter_map(|(pred, _)| { - if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = pred.kind().skip_binder() { + .filter_map(|pred| { + if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = + pred.node.kind().skip_binder() + { if pred.trait_ref.self_ty() == self_ty { Some(pred.def_id()) } else { None } } else { None diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs index b8428d66a5dc8..3f350e6807093 100644 --- a/src/tools/clippy/clippy_lints/src/derive.rs +++ b/src/tools/clippy/clippy_lints/src/derive.rs @@ -502,8 +502,8 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> .collect::>(); let ty_predicates = tcx.predicates_of(did).predicates; - for (p, _) in ty_predicates { - if let PredicateKind::Clause(Clause::Trait(p)) = p.kind().skip_binder() + for p in ty_predicates { + if let PredicateKind::Clause(Clause::Trait(p)) = p.node.kind().skip_binder() && p.trait_ref.def_id == eq_trait_id && let ty::Param(self_ty) = p.trait_ref.self_ty().kind() && p.constness == BoundConstness::NotConst @@ -514,7 +514,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> } ParamEnv::new( - tcx.mk_predicates_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( + tcx.mk_predicates_from_iter(ty_predicates.iter().map(|p| p.node).chain( params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| { tcx.mk_predicate(Binder::dummy(PredicateKind::Clause(Clause::Trait(TraitPredicate { trait_ref: tcx.mk_trait_ref(eq_trait_id, [tcx.mk_param_from_def(param)]), diff --git a/src/tools/clippy/clippy_lints/src/future_not_send.rs b/src/tools/clippy/clippy_lints/src/future_not_send.rs index 9fb73a371b8f4..75baddf620d45 100644 --- a/src/tools/clippy/clippy_lints/src/future_not_send.rs +++ b/src/tools/clippy/clippy_lints/src/future_not_send.rs @@ -66,8 +66,8 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend { if let ty::Alias(ty::Opaque, AliasTy { def_id, substs, .. }) = *ret_ty.kind() { let preds = cx.tcx.explicit_item_bounds(def_id); let mut is_future = false; - for &(p, _span) in preds { - let p = EarlyBinder(p).subst(cx.tcx, substs); + for p in preds { + let p = EarlyBinder(p.node).subst(cx.tcx, substs); if let Some(trait_pred) = p.to_opt_poly_trait_pred() { if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() { is_future = true; diff --git a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs index 289ca4e9bed3c..e8693e469ce12 100644 --- a/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs +++ b/src/tools/clippy/clippy_lints/src/unit_return_expecting_ord.rs @@ -43,10 +43,10 @@ fn get_trait_predicates_for_trait_id<'tcx>( trait_id: Option, ) -> Vec> { let mut preds = Vec::new(); - for (pred, _) in generics.predicates { + for pred in generics.predicates { if_chain! { - if let PredicateKind::Clause(Clause::Trait(poly_trait_pred)) = pred.kind().skip_binder(); - let trait_pred = cx.tcx.erase_late_bound_regions(pred.kind().rebind(poly_trait_pred)); + if let PredicateKind::Clause(Clause::Trait(poly_trait_pred)) = pred.node.kind().skip_binder(); + let trait_pred = cx.tcx.erase_late_bound_regions(pred.node.kind().rebind(poly_trait_pred)); if let Some(trait_def_id) = trait_id; if trait_def_id == trait_pred.trait_ref.def_id; then { @@ -62,9 +62,9 @@ fn get_projection_pred<'tcx>( generics: GenericPredicates<'tcx>, trait_pred: TraitPredicate<'tcx>, ) -> Option> { - generics.predicates.iter().find_map(|(proj_pred, _)| { - if let ty::PredicateKind::Clause(Clause::Projection(pred)) = proj_pred.kind().skip_binder() { - let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.kind().rebind(pred)); + generics.predicates.iter().find_map(|proj_pred| { + if let ty::PredicateKind::Clause(Clause::Projection(pred)) = proj_pred.node.kind().skip_binder() { + let projection_pred = cx.tcx.erase_late_bound_regions(proj_pred.node.kind().rebind(pred)); if projection_pred.projection_ty.substs == trait_pred.trait_ref.substs { return Some(projection_pred); } diff --git a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs index babbc7294a173..d164d442d0c5c 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -72,7 +72,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg: .iter() .flat_map(|v| v.fields.iter()) .any(|x| matches!(cx.tcx.type_of(x.did).subst_identity().peel_refs().kind(), ty::Param(_))) - && all_predicates_of(cx.tcx, fn_id).all(|(pred, _)| match pred.kind().skip_binder() { + && all_predicates_of(cx.tcx, fn_id).all(|pred| match pred.node.kind().skip_binder() { PredicateKind::Clause(ty::Clause::Trait(pred)) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker, _ => true, }) diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 29830557a4454..6a2cae0189346 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2102,7 +2102,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool { .predicates_of(did) .predicates .iter() - .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); + .filter_map(|p| p.is_global().then_some(p.node)); traits::impossible_predicates( cx.tcx, traits::elaborate_predicates(cx.tcx, predicates) diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 1f5dea3f099cb..95607947d9e0f 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -24,7 +24,7 @@ pub fn is_min_const_fn<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, msrv: &Msrv) let mut current = def_id; loop { let predicates = tcx.predicates_of(current); - for (predicate, _) in predicates.predicates { + for ty::Spanned { node: predicate, .. } in predicates.predicates { match predicate.kind().skip_binder() { ty::PredicateKind::Clause( ty::Clause::RegionOutlives(_) diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index e0ea3952785bb..676050ae1af60 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::{ }; use rustc_middle::ty::{GenericArg, GenericArgKind}; use rustc_span::symbol::Ident; -use rustc_span::{sym, Span, Symbol, DUMMY_SP}; +use rustc_span::{sym, Symbol, DUMMY_SP}; use rustc_target::abi::{Size, VariantIdx}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; @@ -90,8 +90,8 @@ pub fn contains_ty_adt_constructor_opaque<'tcx>(cx: &LateContext<'tcx>, ty: Ty<' return false; } - for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) { - match predicate.kind().skip_binder() { + for predicate in cx.tcx.explicit_item_bounds(def_id) { + match predicate.node.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through // and check substituions to find `U`. ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) => { @@ -267,8 +267,8 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { }, ty::Tuple(substs) => substs.iter().any(|ty| is_must_use_ty(cx, ty)), ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => { - for (predicate, _) in cx.tcx.explicit_item_bounds(*def_id) { - if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.kind().skip_binder() { + for predicate in cx.tcx.explicit_item_bounds(*def_id) { + if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_predicate)) = predicate.node.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; } @@ -548,7 +548,7 @@ pub fn is_uninit_value_valid_for_ty(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { } /// Gets an iterator over all predicates which apply to the given item. -pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator, Span)> { +pub fn all_predicates_of(tcx: TyCtxt<'_>, id: DefId) -> impl Iterator>> { let mut next_id = Some(id); iter::from_fn(move || { next_id.take().map(|id| { @@ -726,18 +726,18 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option let mut output = None; let lang_items = cx.tcx.lang_items(); - for (pred, _) in cx + for pred in cx .tcx .bound_explicit_item_bounds(ty.def_id) .subst_iter_copied(cx.tcx, ty.substs) { - match pred.kind().skip_binder() { + match pred.node.kind().skip_binder() { PredicateKind::Clause(ty::Clause::Trait(p)) if (lang_items.fn_trait() == Some(p.def_id()) || lang_items.fn_mut_trait() == Some(p.def_id()) || lang_items.fn_once_trait() == Some(p.def_id())) => { - let i = pred.kind().rebind(p.trait_ref.substs.type_at(1)); + let i = pred.node.kind().rebind(p.trait_ref.substs.type_at(1)); if inputs.map_or(false, |inputs| inputs != i) { // Multiple different fn trait impls. Is this even allowed? @@ -752,7 +752,7 @@ fn sig_for_projection<'tcx>(cx: &LateContext<'tcx>, ty: AliasTy<'tcx>) -> Option // Multiple different fn trait impls. Is this even allowed? return None; } - output = pred.kind().rebind(p.term.ty()).transpose(); + output = pred.node.kind().rebind(p.term.ty()).transpose(); }, _ => (), } diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 21a413002d06e..d96fef7ce2a76 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -928,7 +928,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> { let scope = frame.current_source_info()?.scope; let inlined_parent = frame.body.source_scopes[scope].inlined_parent_scope?; let source = &frame.body.source_scopes[inlined_parent]; - source.inlined.expect("inlined_parent_scope points to scope without inline info").0 + source.inlined.expect("inlined_parent_scope points to scope without inline info").node }; // Fall back to the instance of the function itself. let instance = instance.unwrap_or(frame.instance); From 9b8fcc5d204f6ab82e6b38db77e3ef30ae9854f1 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Tue, 21 Mar 2023 08:49:51 +0000 Subject: [PATCH 18/22] Make no-op traversables generic over the interner --- Cargo.lock | 2 ++ compiler/rustc_hir/Cargo.toml | 1 + compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_middle/src/macros.rs | 22 +++++++++++-------- .../rustc_middle/src/ty/structural_impls.rs | 11 ++-------- compiler/rustc_target/Cargo.toml | 1 + compiler/rustc_target/src/abi/mod.rs | 2 +- compiler/rustc_target/src/spec/abi.rs | 2 +- 8 files changed, 22 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ae3159e30fff9..5797cd6fa3b84 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4693,6 +4693,7 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", + "rustc_type_ir", "smallvec", "tracing", ] @@ -5340,6 +5341,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", + "rustc_type_ir", "serde_json", "tracing", ] diff --git a/compiler/rustc_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index 129f8d235adbc..e15a84329325c 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -15,6 +15,7 @@ rustc_index = { path = "../rustc_index" } rustc_span = { path = "../rustc_span" } rustc_serialize = { path = "../rustc_serialize" } rustc_ast = { path = "../rustc_ast" } +rustc_type_ir = { path = "../rustc_type_ir" } tracing = "0.1" smallvec = { version = "1.8.1", features = ["union", "may_dangle"] } odht = { version = "0.3.1", features = ["nightly"] } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f4b46b9a131fb..acd34e36bafb4 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3190,7 +3190,7 @@ impl<'hir> Item<'hir> { } #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] -#[derive(Encodable, Decodable, HashStable_Generic)] +#[derive(Encodable, Decodable, HashStable_Generic, TypeFoldable, TypeVisitable)] pub enum Unsafety { Unsafe, Normal, diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index a8d71ce030c2a..a436159642ac7 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -67,10 +67,10 @@ macro_rules! CloneLiftImpls { /// allocated data** (i.e., don't need to be folded). #[macro_export] macro_rules! TrivialTypeTraversalImpls { - (for <$tcx:lifetime> { $($ty:ty,)+ }) => { + ($(for { $($generic:tt)+ } { $interner:ty } { $ty:ty })+) => { $( - impl<$tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<$tcx>> for $ty { - fn try_fold_with>>( + impl<$($generic)+> $crate::ty::fold::TypeFoldable<$interner> for $ty { + fn try_fold_with>( self, _: &mut F, ) -> ::std::result::Result { @@ -78,7 +78,7 @@ macro_rules! TrivialTypeTraversalImpls { } #[inline] - fn fold_with>>( + fn fold_with>( self, _: &mut F, ) -> Self { @@ -86,9 +86,9 @@ macro_rules! TrivialTypeTraversalImpls { } } - impl<$tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<$tcx>> for $ty { + impl<$($generic)+> $crate::ty::visit::TypeVisitable<$interner> for $ty { #[inline] - fn visit_with>>( + fn visit_with>( &self, _: &mut F) -> ::std::ops::ControlFlow @@ -99,11 +99,15 @@ macro_rules! TrivialTypeTraversalImpls { )+ }; + (for <$tcx:lifetime> { $($ty:ty,)+ }) => { + TrivialTypeTraversalImpls! { + $(for { $tcx } { $crate::ty::TyCtxt<$tcx> } { $ty })+ + } + }; + ($($ty:ty,)+) => { TrivialTypeTraversalImpls! { - for<'tcx> { - $($ty,)+ - } + $(for { I: $crate::ty::Interner } { I } { $ty })+ } }; } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 07bd7971de999..fae6bf9f921b8 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -12,7 +12,6 @@ use crate::ty::{self, AliasTy, Lift, Term, TermKind, Ty, TyCtxt}; use rustc_hir::def::Namespace; use rustc_index::vec::{Idx, IndexVec}; use rustc_span::source_map::Spanned; -use rustc_target::abi::TyAndLayout; use std::fmt; use std::ops::ControlFlow; @@ -223,7 +222,9 @@ CloneLiftImpls! { ::rustc_hir::HirId, ::rustc_hir::MatchSource, ::rustc_hir::Mutability, + ::rustc_hir::Unsafety, ::rustc_target::asm::InlineAsmRegOrRegClass, + ::rustc_target::spec::abi::Abi, crate::mir::coverage::ExpressionOperandId, crate::mir::coverage::CounterValueReference, crate::mir::coverage::InjectedExpressionId, @@ -265,8 +266,6 @@ CloneLiftImpls! { // implementation and traversal implementations (the latter only for // TyCtxt<'_> interners). TrivialTypeTraversalAndLiftImpls! { - ::rustc_hir::Unsafety, - ::rustc_target::spec::abi::Abi, crate::ty::BoundConstness, } @@ -675,9 +674,3 @@ impl<'tcx> TypeSuperVisitable> for ty::UnevaluatedConst<'tcx> { self.substs.visit_with(visitor) } } - -impl<'tcx> TypeVisitable> for TyAndLayout<'tcx, Ty<'tcx>> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - visitor.visit_ty(self.ty) - } -} diff --git a/compiler/rustc_target/Cargo.toml b/compiler/rustc_target/Cargo.toml index 568c916a16328..027388c7b2fca 100644 --- a/compiler/rustc_target/Cargo.toml +++ b/compiler/rustc_target/Cargo.toml @@ -14,3 +14,4 @@ rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } rustc_span = { path = "../rustc_span" } +rustc_type_ir = { path = "../rustc_type_ir" } diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index 8d2e92cc76c6f..8f10334889cc8 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -24,7 +24,7 @@ impl ToJson for Endian { /// to that obtained from `layout_of(ty)`, as we need to produce /// layouts for which Rust types do not exist, such as enum variants /// or synthetic fields of enums (i.e., discriminants) and fat pointers. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic, TypeVisitable)] pub struct TyAndLayout<'a, Ty> { pub ty: Ty, pub layout: Layout<'a>, diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs index d4f7ed31b895c..90025bd2ad037 100644 --- a/compiler/rustc_target/src/spec/abi.rs +++ b/compiler/rustc_target/src/spec/abi.rs @@ -8,7 +8,7 @@ use rustc_span::{Span, Symbol}; mod tests; #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)] -#[derive(HashStable_Generic, Encodable, Decodable)] +#[derive(HashStable_Generic, Encodable, Decodable, TypeFoldable, TypeVisitable)] pub enum Abi { // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the // hashing tests. These are used in many places, so giving them stable values reduces test From 85f0500d94f56a257c1f6c1204c98a873fb404d8 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sat, 25 Feb 2023 23:21:49 +0000 Subject: [PATCH 19/22] Replace TrivialTypeTraversal macros with derives --- compiler/rustc_middle/src/macros.rs | 57 ------------------- compiler/rustc_middle/src/ty/mod.rs | 1 + .../rustc_middle/src/ty/structural_impls.rs | 9 +-- compiler/rustc_type_ir/src/macros.rs | 36 ------------ .../rustc_type_ir/src/structural_impls.rs | 23 +++++--- 5 files changed, 16 insertions(+), 110 deletions(-) diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index a436159642ac7..0b392d79a7a55 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -62,60 +62,3 @@ macro_rules! CloneLiftImpls { } }; } - -/// Used for types that are `Copy` and which **do not care arena -/// allocated data** (i.e., don't need to be folded). -#[macro_export] -macro_rules! TrivialTypeTraversalImpls { - ($(for { $($generic:tt)+ } { $interner:ty } { $ty:ty })+) => { - $( - impl<$($generic)+> $crate::ty::fold::TypeFoldable<$interner> for $ty { - fn try_fold_with>( - self, - _: &mut F, - ) -> ::std::result::Result { - Ok(self) - } - - #[inline] - fn fold_with>( - self, - _: &mut F, - ) -> Self { - self - } - } - - impl<$($generic)+> $crate::ty::visit::TypeVisitable<$interner> for $ty { - #[inline] - fn visit_with>( - &self, - _: &mut F) - -> ::std::ops::ControlFlow - { - ::std::ops::ControlFlow::Continue(()) - } - } - )+ - }; - - (for <$tcx:lifetime> { $($ty:ty,)+ }) => { - TrivialTypeTraversalImpls! { - $(for { $tcx } { $crate::ty::TyCtxt<$tcx> } { $ty })+ - } - }; - - ($($ty:ty,)+) => { - TrivialTypeTraversalImpls! { - $(for { I: $crate::ty::Interner } { I } { $ty })+ - } - }; -} - -#[macro_export] -macro_rules! TrivialTypeTraversalAndLiftImpls { - ($($t:tt)*) => { - TrivialTypeTraversalImpls! { $($t)* } - CloneLiftImpls! { $($t)* } - } -} diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 03b1def7e76be..f99e16605f30c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -291,6 +291,7 @@ pub enum Visibility { } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] +#[derive(TypeFoldable, TypeVisitable)] pub enum BoundConstness { /// `T: Trait` NotConst, diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index fae6bf9f921b8..4e068d9599e65 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -235,6 +235,7 @@ CloneLiftImpls! { crate::traits::Reveal, crate::ty::adjustment::AutoBorrowMutability, crate::ty::AdtKind, + crate::ty::BoundConstness, crate::ty::BoundRegionKind, crate::ty::AssocItem, crate::ty::AssocKind, @@ -261,14 +262,6 @@ CloneLiftImpls! { ty::Placeholder, } -// For things about which the type library does not know, or does not -// provide any traversal implementations, we need to provide both a Lift -// implementation and traversal implementations (the latter only for -// TyCtxt<'_> interners). -TrivialTypeTraversalAndLiftImpls! { - crate::ty::BoundConstness, -} - CloneLiftImpls! { for<'tcx> { ty::ValTree<'tcx>, diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index 320053a2ab805..0f7a50b1fa19a 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -1,39 +1,3 @@ -/// Used for types that are `Copy` and which **do not care arena -/// allocated data** (i.e., don't need to be folded). -macro_rules! TrivialTypeTraversalImpls { - ($($ty:ty,)+) => { - $( - impl $crate::fold::TypeFoldable for $ty { - fn try_fold_with>( - self, - _: &mut F, - ) -> ::std::result::Result { - Ok(self) - } - - #[inline] - fn fold_with>( - self, - _: &mut F, - ) -> Self { - self - } - } - - impl $crate::visit::TypeVisitable for $ty { - #[inline] - fn visit_with>( - &self, - _: &mut F) - -> ::std::ops::ControlFlow - { - ::std::ops::ControlFlow::Continue(()) - } - } - )+ - }; -} - macro_rules! EnumTypeTraversalImpl { (impl<$($p:tt),*> TypeFoldable<$tcx:tt> for $s:path { $($variants:tt)* diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index f7f70e534557b..d0288ee85e2fa 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -13,17 +13,22 @@ use std::rc::Rc; use std::sync::Arc; /////////////////////////////////////////////////////////////////////////// -// Atomic structs -// -// For things that don't carry any arena-allocated data (and are -// copy...), just add them to this list. +// Traversable implementations for upstream types. -TrivialTypeTraversalImpls! { - (), +// `()` is (obviously) a no-op traversal and therefore the auto-deref specialisation normally +// negates any need for explicit implementation, however `ProjectionElem`'s implementation +// requires its second type parameter to implement these traits and (annoyingly) +// `ProjectionKind` (currently) uses unit type for that parameter. +impl TypeFoldable for () { + fn try_fold_with>(self, _: &mut F) -> Result<(), F::Error> { + Ok(()) + } +} +impl TypeVisitable for () { + fn visit_with>(&self, _: &mut V) -> ControlFlow { + ControlFlow::Continue(()) + } } - -/////////////////////////////////////////////////////////////////////////// -// Traversable implementations for upstream types. // We provide implementations for 2- and 3-element tuples, however (absent specialisation) // we can only provide for one case: we choose our implementations to be where all elements From b0ccdace8c2ba9400ede177f280a0e5abce74f1b Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sun, 26 Feb 2023 00:36:20 +0000 Subject: [PATCH 20/22] Unimpl TypeSuperVisitable for UnevaluatedConst UnevaluatedConst is not a type of any interest to folders or visitors, and therefore should not be "super visitable" at all. --- compiler/rustc_middle/src/ty/structural_impls.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 4e068d9599e65..d5a9a1417ef83 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -658,12 +658,3 @@ impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { self.kind().visit_with(visitor) } } - -impl<'tcx> TypeSuperVisitable> for ty::UnevaluatedConst<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { - self.substs.visit_with(visitor) - } -} From 11296fac815ed4e10805bbeb7a1c92084c5eedd1 Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sun, 26 Feb 2023 11:46:52 +0000 Subject: [PATCH 21/22] Generify traversals of interned types --- compiler/rustc_data_structures/src/intern.rs | 4 +++ compiler/rustc_middle/src/traits/solve.rs | 29 ++----------------- compiler/rustc_middle/src/ty/context.rs | 14 ++++++--- .../rustc_type_ir/src/structural_impls.rs | 17 ++++++++++- 4 files changed, 32 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index ba94f3776eb90..0dee7ccefb312 100644 --- a/compiler/rustc_data_structures/src/intern.rs +++ b/compiler/rustc_data_structures/src/intern.rs @@ -24,6 +24,10 @@ mod private { #[rustc_pass_by_value] pub struct Interned<'a, T>(pub &'a T, pub private::PrivateZst); +pub trait Internable<'a, I>: Sized { + fn intern(self, interner: I) -> Interned<'a, Self>; +} + impl<'a, T> Interned<'a, T> { /// Create a new `Interned` value. The value referred to *must* be interned /// and thus be unique, and it *must* remain unique in the future. This diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 794a2089d444f..911606e9744ad 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -4,9 +4,7 @@ use rustc_query_system::cache::Cache; use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints}; use crate::traits::query::NoSolution; use crate::traits::Canonical; -use crate::ty::{ - self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitor, -}; +use crate::ty::{self, ToPredicate, Ty, TyCtxt}; pub type EvaluationCache<'tcx> = Cache, QueryResult<'tcx>>; @@ -96,7 +94,7 @@ pub type CanonicalResponse<'tcx> = Canonical<'tcx, Response<'tcx>>; /// solver, merge the two responses again. pub type QueryResult<'tcx> = Result, NoSolution>; -#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, TypeFoldable, TypeVisitable)] pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>); impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> { @@ -114,26 +112,3 @@ pub struct ExternalConstraintsData<'tcx> { pub region_constraints: QueryRegionConstraints<'tcx>, pub opaque_types: Vec<(Ty<'tcx>, Ty<'tcx>)>, } - -// FIXME: Having to clone `region_constraints` for folding feels bad and -// probably isn't great wrt performance. -// -// Not sure how to fix this, maybe we should also intern `opaque_types` and -// `region_constraints` here or something. -impl<'tcx> TypeFoldable> for ExternalConstraints<'tcx> { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - Ok(folder.interner().mk_external_constraints((*self).clone().try_fold_with(folder)?)) - } -} - -impl<'tcx> TypeVisitable> for ExternalConstraints<'tcx> { - fn visit_with>>( - &self, - visitor: &mut V, - ) -> std::ops::ControlFlow { - (**self).visit_with(visitor) - } -} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 622fd12bd0f6a..a7ccd048d8a0a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -30,7 +30,7 @@ use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; use rustc_ast as ast; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::intern::Interned; +use rustc_data_structures::intern::{Internable, Interned}; use rustc_data_structures::memmap::Mmap; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; @@ -1555,11 +1555,17 @@ macro_rules! direct_interners { } } + impl<'tcx> Internable<'tcx, TyCtxt<'tcx>> for $ty { + fn intern(self, tcx: TyCtxt<'tcx>) -> Interned<'tcx, Self> { + Interned::new_unchecked(tcx.interners.$name.intern(self, |v| { + InternedInSet(tcx.interners.arena.alloc(v)) + }).0) + } + } + impl<'tcx> TyCtxt<'tcx> { $vis fn $method(self, v: $ty) -> $ret_ty { - $ret_ctor(Interned::new_unchecked(self.interners.$name.intern(v, |v| { - InternedInSet(self.interners.arena.alloc(v)) - }).0)) + $ret_ctor(v.intern(self)) } })+ } diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs index d0288ee85e2fa..fd4732f950083 100644 --- a/compiler/rustc_type_ir/src/structural_impls.rs +++ b/compiler/rustc_type_ir/src/structural_impls.rs @@ -5,7 +5,10 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::visit::{TypeVisitable, TypeVisitor}; use crate::Interner; -use rustc_data_structures::functor::IdFunctor; +use rustc_data_structures::{ + functor::IdFunctor, + intern::{Internable, Interned}, +}; use rustc_index::vec::{Idx, IndexVec}; use std::ops::ControlFlow; @@ -189,3 +192,15 @@ impl, Ix: Idx> TypeVisitable for IndexVec + TypeFoldable> TypeFoldable for Interned<'a, T> { + fn try_fold_with>(self, folder: &mut F) -> Result { + (*self).clone().try_fold_with(folder).map(|v| v.intern(folder.interner())) + } +} + +impl> TypeVisitable for Interned<'_, T> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + (**self).visit_with(visitor) + } +} From bf618ac8f760abba4b64593242135c7e40aa160d Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Fri, 17 Mar 2023 17:02:54 +0000 Subject: [PATCH 22/22] Explain no-op traversable impls --- compiler/rustc_hir/src/hir.rs | 3 ++ compiler/rustc_macros/src/lib.rs | 12 +++++- compiler/rustc_macros/src/traversable.rs | 54 ++++++++++++++++++------ compiler/rustc_middle/src/ty/mod.rs | 6 +++ compiler/rustc_target/src/spec/abi.rs | 3 ++ 5 files changed, 64 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index acd34e36bafb4..123112a17623d 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3191,6 +3191,9 @@ impl<'hir> Item<'hir> { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable_Generic, TypeFoldable, TypeVisitable)] +#[skip_traversal(but_impl_because = " + `Unsafety` impls `Relate`, which is a subtrait of `TypeFoldable`. +")] pub enum Unsafety { Unsafe, Normal, diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 170c6404a9d9e..5d98bdc731d66 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -139,7 +139,11 @@ decl_derive!( /// accomplished via method calls that might not get optimised away. One can therefore annotate /// the type itself with `#[skip_traversal]` to immediately return `self` instead; as above, /// such derived implementations are only applicable if the annotated type does not contain - /// anything that may be of interest to a folder. + /// anything that may be of interest to a folder. Moreover, since such implementations should + /// rarely be necessary, a descriptive reason for the implementation must also be provided: + /// e.g. `#[skip_traversal(but_impl_because = "")]`. If applied to a + /// non-generic type (which cannot ever contain anything that may be of interest to folders), + /// this attribute is mandatory. /// /// The derived implementation will use `TyCtxt<'tcx>` as the interner iff the annotated type /// has a `'tcx` lifetime parameter; otherwise it will be generic over all interners. It @@ -173,7 +177,11 @@ decl_derive!( /// accomplished via method calls that might not get optimised away. One can therefore annotate /// the type itself with `#[skip_traversal]` to immediately return `Continue(())` instead; as /// above, such derived implementations are only applicable if the annotated type does not - /// contain anything that may be of interest to visitors. + /// contain anything that may be of interest to visitors. Moreover, since such implementations + /// should rarely be necessary, a descriptive reason for the implementation must also be + /// provided: e.g. `#[skip_traversal(but_impl_because = "")]`. If applied to + /// a non-generic type (which cannot ever contain anything that may be of interest to + /// visitors), this attribute is mandatory. /// /// The derived implementation will use `TyCtxt<'tcx>` as the interner iff the annotated type /// has a `'tcx` lifetime parameter; otherwise it will be generic over all interners. It diff --git a/compiler/rustc_macros/src/traversable.rs b/compiler/rustc_macros/src/traversable.rs index 927ca0788eb0f..366a31771c1ea 100644 --- a/compiler/rustc_macros/src/traversable.rs +++ b/compiler/rustc_macros/src/traversable.rs @@ -1,7 +1,30 @@ use proc_macro2::{Span, TokenStream}; use quote::{quote, quote_spanned, ToTokens}; use std::collections::HashMap; -use syn::{parse_quote, spanned::Spanned, Attribute, Generics, Ident}; +use syn::{ + parse::{Error, ParseStream}, + parse_quote, + spanned::Spanned, + Attribute, Generics, Ident, LitStr, Token, +}; + +mod kw { + syn::custom_keyword!(but_impl_because); +} + +fn parse_skip_reason(input: ParseStream<'_>) -> Result<(), Error> { + input.parse::()?; + input.parse::()?; + let reason = input.parse::()?; + if reason.value().trim().is_empty() { + Err(Error::new_spanned( + reason, + "the value of `but_impl_because` must be a non-empty string", + )) + } else { + Ok(()) + } +} /// Generate a type parameter with the given `suffix` that does not conflict with /// any of the `existing` generics. @@ -31,9 +54,9 @@ fn gen_interner(structure: &mut synstructure::Structure<'_>) -> TokenStream { }) } -/// Returns the `Span` of the first `#[skip_traversal]` attribute in `attrs`. -fn find_skip_traversal_attribute(attrs: &[Attribute]) -> Option { - attrs.iter().find(|&attr| *attr == parse_quote! { #[skip_traversal] }).map(Spanned::span) +/// Returns the first `#[skip_traversal]` attribute in `attrs`. +fn find_skip_traversal_attribute(attrs: &[Attribute]) -> Option<&Attribute> { + attrs.iter().find(|&attr| attr.path.is_ident("skip_traversal")) } pub struct Foldable; @@ -160,15 +183,22 @@ pub fn traversable_derive( structure.add_where_predicate(parse_quote! { Self: #supertraits }); } - let body = if let Some(_span) = find_skip_traversal_attribute(&ast.attrs) { - if !is_generic { - // FIXME: spanned error causes ICE: "suggestion must not have overlapping parts" - return quote!({ - ::core::compile_error!("non-generic types are automatically skipped where possible"); - }); + let body = if let Some(attr) = find_skip_traversal_attribute(&ast.attrs) { + if let Err(err) = attr.parse_args_with(parse_skip_reason) { + return err.into_compile_error(); } + // If `is_generic`, it's possible that this no-op impl may not be applicable; but that's fine as it + // will cause a compilation error forcing removal of the inappropriate `#[skip_traversal]` attribute. structure.add_where_predicate(parse_quote! { Self: #skip_traversal }); T::traverse(quote! { self }, true) + } else if !is_generic { + quote_spanned!(ast.ident.span() => { + ::core::compile_error!("\ + traversal of non-generic types are no-ops by default, so explicitly deriving the traversable traits for them is rarely necessary\n\ + if the need has arisen to due the appearance of this type in an anonymous tuple, consider replacing that tuple with a named struct\n\ + otherwise add `#[skip_traversal(but_impl_because = \"\")]` to this type\ + ") + }) } else { // We add predicates to each generic field type, rather than to our generic type parameters. // This results in a "perfect derive" that avoids having to propagate `#[skip_traversal]` annotations @@ -176,7 +206,7 @@ pub fn traversable_derive( // in recursive type definitions; fortunately that is not the case (yet). let mut predicates = HashMap::new(); let arms = structure.each_variant(|variant| { - let skipped_variant_span = find_skip_traversal_attribute(&variant.ast().attrs); + let skipped_variant_span = find_skip_traversal_attribute(&variant.ast().attrs).map(Spanned::span); if variant.referenced_ty_params().is_empty() { if let Some(span) = skipped_variant_span { return quote_spanned!(span => { @@ -186,7 +216,7 @@ pub fn traversable_derive( } T::arm(variant, |bind| { let ast = bind.ast(); - let skipped_span = skipped_variant_span.or_else(|| find_skip_traversal_attribute(&ast.attrs)); + let skipped_span = skipped_variant_span.or_else(|| find_skip_traversal_attribute(&ast.attrs).map(Spanned::span)); if bind.referenced_ty_params().is_empty() { if skipped_variant_span.is_none() && let Some(span) = skipped_span { return quote_spanned!(span => { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f99e16605f30c..290c6d339371f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -249,6 +249,9 @@ pub enum ImplSubject<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] #[derive(TypeFoldable, TypeVisitable)] +#[skip_traversal(but_impl_because = " + `ImplPolarity` impls `Relate`, which is a subtrait of `TypeFoldable`. +")] pub enum ImplPolarity { /// `impl Trait for Type` Positive, @@ -292,6 +295,9 @@ pub enum Visibility { #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] #[derive(TypeFoldable, TypeVisitable)] +#[skip_traversal(but_impl_because = " + `BoundConstness` impls `Relate`, which is a subtrait of `TypeFoldable`. +")] pub enum BoundConstness { /// `T: Trait` NotConst, diff --git a/compiler/rustc_target/src/spec/abi.rs b/compiler/rustc_target/src/spec/abi.rs index 90025bd2ad037..73e9d52285013 100644 --- a/compiler/rustc_target/src/spec/abi.rs +++ b/compiler/rustc_target/src/spec/abi.rs @@ -9,6 +9,9 @@ mod tests; #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy, Debug)] #[derive(HashStable_Generic, Encodable, Decodable, TypeFoldable, TypeVisitable)] +#[skip_traversal(but_impl_because = " + `Abi` impls `Relate`, which is a subtrait of `TypeFoldable`. +")] pub enum Abi { // Some of the ABIs come first because every time we add a new ABI, we have to re-bless all the // hashing tests. These are used in many places, so giving them stable values reduces test