diff --git a/Cargo.lock b/Cargo.lock index adaac69af577..4c342fa13767 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3918,6 +3918,7 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", + "rustc_type_ir", "smallvec", "tracing", ] @@ -4032,6 +4033,7 @@ dependencies = [ "rustc_serialize", "rustc_span", "rustc_target", + "rustc_type_ir", "smallvec", "tracing", ] @@ -4531,6 +4533,7 @@ dependencies = [ "rustc_index", "rustc_macros", "rustc_serialize", + "rustc_type_ir", "scoped-tls", "sha1", "sha2", @@ -4570,6 +4573,7 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", + "rustc_type_ir", "serde_json", "tracing", ] @@ -4601,6 +4605,7 @@ dependencies = [ "rustc_span", "rustc_target", "rustc_transmute", + "rustc_type_ir", "smallvec", "tracing", ] @@ -4630,6 +4635,7 @@ dependencies = [ "rustc_middle", "rustc_span", "rustc_target", + "rustc_type_ir", "tracing", ] diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 247200dcd269..eba8c1428ada 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -14,9 +14,9 @@ use rustc_middle::hir::nested_filter::OnlyBodies; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ self, AggregateKind, BindingForm, BorrowKind, CallSource, ClearCrossCrate, ConstraintCategory, - FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind, Operand, Place, - PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, - VarBindingForm, + FakeReadCause, FakeReadCauseAndPlace, LocalDecl, LocalInfo, LocalKind, Location, MutBorrowKind, + Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, + TerminatorKind, VarBindingForm, }; use rustc_middle::ty::{self, suggest_constraining_type_params, PredicateKind, Ty}; use rustc_middle::util::CallKind; @@ -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::Clause<'tcx>, _)| { - if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder() + let find_fn_kind_from_did = |pred: ty::Spanned>| { + if let ty::ClauseKind::Trait(pred) = pred.node.kind().skip_binder() && pred.self_ty() == ty { if Some(pred.def_id()) == tcx.lang_items().fn_trait() { @@ -698,7 +698,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => tcx .explicit_item_bounds(def_id) .iter_instantiated_copied(tcx, args) - .find_map(|(clause, span)| find_fn_kind_from_did((clause, span))), + .find_map(find_fn_kind_from_did), ty::Closure(_, args) => match args.as_closure().kind() { ty::ClosureKind::Fn => Some(hir::Mutability::Not), ty::ClosureKind::FnMut => Some(hir::Mutability::Mut), @@ -3010,9 +3010,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 8a930ca59a33..ff0ca491115d 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::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::{ - Body, CallSource, CastKind, ConstraintCategory, FakeReadCause, Local, LocalInfo, Location, - Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind, + Body, CallSource, CastKind, ConstraintCategory, FakeReadCause, FakeReadCauseAndPlace, Local, + LocalInfo, Location, Operand, Place, Rvalue, Statement, StatementKind, TerminatorKind, }; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{self, RegionVid, TyCtxt}; @@ -477,7 +477,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 4b95b4783eb4..94c78eb67142 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -13,9 +13,9 @@ use rustc_index::IndexSlice; use rustc_infer::infer::LateBoundRegionConversionTime; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ - AggregateKind, CallSource, ConstOperand, FakeReadCause, Local, LocalInfo, LocalKind, Location, - Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, - TerminatorKind, + AggregateKind, CallSource, ConstOperand, FakeReadCause, FakeReadCauseAndPlace, 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}; @@ -797,7 +797,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/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 41d6b98d7cfa..61622eba1734 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -130,7 +130,7 @@ 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(opt_match_place), binding_mode: _, opt_ty_info: _, pat_span: _, @@ -143,8 +143,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { original_path, *move_from, local, - opt_match_place, - match_span, + opt_match_place.node, + opt_match_place.span, stmt_source_info.span, ); return; diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index 7b5b52e39b12..e7ce728c10aa 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 1a74582389d1..008be6fe3889 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -629,7 +629,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro 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_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index fc600af1b76f..9caabb4df1da 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -99,10 +99,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_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 9f30d9d8ba12..b8fb18c23e60 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1297,7 +1297,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_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 6a63eda4b993..37aaeb30bac1 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -90,13 +90,13 @@ fn make_mir_scope<'ll, 'tcx>( let file_metadata = file_metadata(cx, &loc.file); let parent_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.instantiate_and_normalize_erasing_regions( instance.args, ty::ParamEnv::reveal_all(), - ty::EarlyBinder::bind(callee), + ty::EarlyBinder::bind(callee.node), ); debug_context.inlined_function_scopes.entry(callee).or_insert_with(|| { let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty()); @@ -116,11 +116,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_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 07cab5e3400e..ee57a8295f23 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1165,9 +1165,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { // If the stacktrace passes through MIR-inlined source scopes, add them. let mir::SourceInfo { mut span, scope } = *frame.body.source_info(loc); let mut scope_data = &frame.body.source_scopes[scope]; - while let Some((instance, call_span)) = scope_data.inlined { - frames.push(FrameInfo { span, instance }); - span = call_span; + while let Some(instance) = scope_data.inlined { + frames.push(FrameInfo { span, instance: instance.node }); + span = instance.span; scope_data = &frame.body.source_scopes[scope_data.parent_scope.unwrap()]; } span diff --git a/compiler/rustc_data_structures/src/intern.rs b/compiler/rustc_data_structures/src/intern.rs index e0f8c350c2a8..7d1482a171b7 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_hir/Cargo.toml b/compiler/rustc_hir/Cargo.toml index a72c4d0f18bc..120122001110 100644 --- a/compiler/rustc_hir/Cargo.toml +++ b/compiler/rustc_hir/Cargo.toml @@ -15,6 +15,7 @@ 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"] } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c4e44a6a4e38..3ed7ae47e2a9 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3256,7 +3256,10 @@ 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)] +#[skip_traversal( + but_impl_despite_trivial_because = "`Unsafety` impls `Relate`, which is a subtrait of `TypeFoldable`." +)] pub enum Unsafety { Unsafe, Normal, diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 2fcb45ef8aa1..54fb5e4ecf8e 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -1057,7 +1057,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx, predicates .iter() - .filter_map(|(p, _)| Some(p.as_trait_clause()?.map_bound(|t| t.trait_ref))), + .filter_map(|p| Some(p.node.as_trait_clause()?.map_bound(|t| t.trait_ref))), assoc_name, ) }, diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs index 00ff3f836adf..f16c1b410025 100644 --- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs @@ -57,15 +57,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let mut trait_bounds = vec![]; let mut projection_bounds = vec![]; - for (pred, span) in bounds.clauses() { - let bound_pred = pred.kind(); + for pred in bounds.clauses() { + let bound_pred = pred.node.kind(); match bound_pred.skip_binder() { ty::ClauseKind::Trait(trait_pred) => { assert_eq!(trait_pred.polarity, ty::ImplPolarity::Positive); - trait_bounds.push((bound_pred.rebind(trait_pred.trait_ref), span)); + trait_bounds.push((bound_pred.rebind(trait_pred.trait_ref), pred.span)); } ty::ClauseKind::Projection(proj) => { - projection_bounds.push((bound_pred.rebind(proj), span)); + projection_bounds.push((bound_pred.rebind(proj), pred.span)); } ty::ClauseKind::TypeOutlives(_) => { // Do nothing, we deal with regions separately diff --git a/compiler/rustc_hir_analysis/src/bounds.rs b/compiler/rustc_hir_analysis/src/bounds.rs index b6688e0ce29e..f2dbd77aeeba 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 clauses: Vec<(ty::Clause<'tcx>, Span)>, + pub clauses: Vec>>, } impl<'tcx> Bounds<'tcx> { @@ -33,8 +33,10 @@ impl<'tcx> Bounds<'tcx> { region: ty::PolyTypeOutlivesPredicate<'tcx>, span: Span, ) { - self.clauses - .push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).to_predicate(tcx), span)); + self.clauses.push(ty::Spanned { + node: region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).to_predicate(tcx), + span, + }); } pub fn push_trait_bound( @@ -72,14 +74,14 @@ impl<'tcx> Bounds<'tcx> { span: Span, polarity: ty::ImplPolarity, ) { - self.clauses.push(( - trait_ref + self.clauses.push(ty::Spanned { + node: trait_ref .map_bound(|trait_ref| { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity }) }) .to_predicate(tcx), span, - )); + }); } pub fn push_projection_bound( @@ -88,20 +90,20 @@ impl<'tcx> Bounds<'tcx> { projection: ty::PolyProjectionPredicate<'tcx>, span: Span, ) { - self.clauses.push(( - projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).to_predicate(tcx), + self.clauses.push(ty::Spanned { + node: projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).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::TraitRef::new(tcx, sized_def_id, [ty]); // Preferable to put this obligation first, since we report better errors for sized ambiguity. - self.clauses.insert(0, (trait_ref.to_predicate(tcx), span)); + self.clauses.insert(0, ty::Spanned { node: trait_ref.to_predicate(tcx), span }); } - pub fn clauses(&self) -> impl Iterator, Span)> + '_ { + pub fn clauses(&self) -> impl Iterator>> + '_ { self.clauses.iter().cloned() } } 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 857515f971a8..7206a09c4f5d 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -222,7 +222,7 @@ fn compare_method_predicate_entailment<'tcx>( hybrid_preds.predicates.extend( trait_m_predicates .instantiate_own(tcx, trait_to_placeholder_args) - .map(|(predicate, _)| predicate), + .map(|predicate| predicate.node), ); // Construct trait parameter environment and then shift it into the placeholder viewpoint. @@ -238,7 +238,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_args); - 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); @@ -691,7 +691,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( .instantiate_identity(tcx) .into_iter() .chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_to_placeholder_args)) - .map(|(clause, _)| clause); + .map(|clause| clause.node); let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds), Reveal::UserFacing); let param_env = traits::normalize_param_env_or_error( tcx, @@ -1009,7 +1009,7 @@ impl<'tcx> TypeFolder> for ImplTraitInTraitCollector<'_, 'tcx> { }); self.types.insert(proj.def_id, (infer_ty, proj.args)); // Recurse into bounds - for (pred, pred_span) in self + for ty::Spanned { node: pred, span: pred_span } in self .interner() .explicit_item_bounds(proj.def_id) .iter_instantiated_copied(self.interner(), proj.args) @@ -1963,7 +1963,7 @@ fn compare_const_predicate_entailment<'tcx>( hybrid_preds.predicates.extend( trait_ct_predicates .instantiate_own(tcx, trait_to_impl_args) - .map(|(predicate, _)| predicate), + .map(|predicate| predicate.node), ); let param_env = ty::ParamEnv::new(tcx.mk_clauses(&hybrid_preds.predicates), Reveal::UserFacing); @@ -1977,7 +1977,7 @@ fn compare_const_predicate_entailment<'tcx>( let ocx = ObligationCtxt::new(&infcx); let impl_ct_own_bounds = impl_ct_predicates.instantiate_own(tcx, impl_args); - for (predicate, span) in impl_ct_own_bounds { + for ty::Spanned { node: predicate, span } in impl_ct_own_bounds { let cause = ObligationCause::misc(span, impl_ct_def_id); let predicate = ocx.normalize(&cause, param_env, predicate); @@ -2098,7 +2098,7 @@ fn compare_type_predicate_entailment<'tcx>( hybrid_preds.predicates.extend( trait_ty_predicates .instantiate_own(tcx, trait_to_impl_args) - .map(|(predicate, _)| predicate), + .map(|predicate| predicate.node), ); debug!("compare_type_predicate_entailment: bounds={:?}", hybrid_preds); @@ -2112,7 +2112,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); @@ -2210,9 +2210,14 @@ pub(super) fn check_type_bounds<'tcx>( let obligations: Vec<_> = tcx .explicit_item_bounds(trait_ty.def_id) .iter_instantiated_copied(tcx, rebased_args) - .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/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index bc5029a1d5e4..58706eb58474 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -123,7 +123,7 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( .instantiate_identity(tcx) .into_iter() .chain(tcx.predicates_of(trait_m.def_id).instantiate_own(tcx, trait_m_to_impl_m_args)) - .map(|(clause, _)| clause); + .map(|clause| clause.node); let param_env = ty::ParamEnv::new(tcx.mk_clauses_from_iter(hybrid_preds), Reveal::UserFacing); let param_env = normalize_param_env_or_error(tcx, param_env, ObligationCause::dummy()); @@ -193,14 +193,14 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( // too, since we *do not* use the trait solver to prove that the RPITIT's // bounds are not stronger -- we're doing a simple, syntactic compatibility // check between bounds. This is strictly forwards compatible, though. - for (clause, span) in impl_bounds { - if !trait_bounds.contains(&clause) { + for clause in impl_bounds { + if !trait_bounds.contains(&clause.node) { report_mismatched_rpitit_signature( tcx, trait_m_sig_with_self_for_diag, trait_m.def_id, impl_m.def_id, - Some(span), + Some(clause.span), ); return; } @@ -220,12 +220,12 @@ impl<'tcx> TypeVisitor> for ImplTraitInTraitCollector<'tcx> { && self.tcx.is_impl_trait_in_trait(proj.def_id) { if self.types.insert(proj) { - for (pred, _) in self + for pred in self .tcx .explicit_item_bounds(proj.def_id) .iter_instantiated_copied(self.tcx, proj.args) { - pred.visit_with(self)?; + pred.node.visit_with(self)?; } } ControlFlow::Continue(()) @@ -267,7 +267,7 @@ fn report_mismatched_rpitit_signature<'tcx>( let Some(future_output_ty) = tcx .explicit_item_bounds(future_ty.def_id) .iter_instantiated_copied(tcx, future_ty.args) - .find_map(|(clause, _)| match clause.kind().no_bound_vars()? { + .find_map(|clause| match clause.node.kind().no_bound_vars()? { ty::ClauseKind::Projection(proj) => proj.term.ty(), _ => None, }) diff --git a/compiler/rustc_hir_analysis/src/check/dropck.rs b/compiler/rustc_hir_analysis/src/check/dropck.rs index dda3f7425697..f3de3e1db765 100644 --- a/compiler/rustc_hir_analysis/src/check/dropck.rs +++ b/compiler/rustc_hir_analysis/src/check/dropck.rs @@ -132,7 +132,9 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>( let param_env = ty::EarlyBinder::bind(tcx.param_env(adt_def_id)).instantiate(tcx, adt_to_impl_args); - for (pred, span) in tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) { + for ty::Spanned { node: pred, span } in + tcx.predicates_of(drop_impl_def_id).instantiate_identity(tcx) + { let normalize_cause = traits::ObligationCause::misc(span, adt_def_id); let pred = ocx.normalize(&normalize_cause, param_env, pred); let cause = traits::ObligationCause::new(span, adt_def_id, traits::DropImpl); diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 15c5558fc0b0..d4d630c2175e 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -305,13 +305,13 @@ fn default_body_is_unstable( /// Re-sugar `ty::GenericPredicates` in a way suitable to be used in structured suggestions. fn bounds_from_generic_predicates<'tcx>( tcx: TyCtxt<'tcx>, - predicates: impl IntoIterator, Span)>, + predicates: impl IntoIterator>>, ) -> (String, String) { let mut types: FxHashMap, Vec> = FxHashMap::default(); let mut projections = vec![]; - for (predicate, _) in predicates { - debug!("predicate {:?}", predicate); - let bound_predicate = predicate.kind(); + for predicate in predicates { + debug!("predicate {:?}", predicate.node); + let bound_predicate = predicate.node.kind(); match bound_predicate.skip_binder() { ty::ClauseKind::Trait(trait_predicate) => { let entry = types.entry(trait_predicate.self_ty()).or_default(); @@ -382,7 +382,7 @@ fn fn_sig_suggestion<'tcx>( tcx: TyCtxt<'tcx>, sig: ty::FnSig<'tcx>, ident: Ident, - predicates: impl IntoIterator, Span)>, + predicates: impl IntoIterator>>, assoc: ty::AssocItem, ) -> String { let args = sig @@ -429,7 +429,7 @@ fn fn_sig_suggestion<'tcx>( output = if let ty::Alias(_, alias_ty) = *output.kind() { tcx.explicit_item_bounds(alias_ty.def_id) .iter_instantiated_copied(tcx, alias_ty.args) - .find_map(|(bound, _)| bound.as_projection_clause()?.no_bound_vars()?.term.ty()) + .find_map(|bound| bound.node.as_projection_clause()?.no_bound_vars()?.term.ty()) .unwrap_or_else(|| { span_bug!( ident.span, diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index eb4491b89bf1..2a06f50cc75c 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -128,8 +128,7 @@ where let outlives_env = OutlivesEnvironment::with_bounds(param_env, implied_bounds); - wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env)?; - infcx.tainted_by_errors().error_reported() + wfcx.ocx.resolve_regions_and_report_errors(body_def_id, &outlives_env) } fn check_well_formed(tcx: TyCtxt<'_>, def_id: hir::OwnerId) -> Result<(), ErrorGuaranteed> { @@ -1145,17 +1144,16 @@ 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.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| { - let normalized_bound = wfcx.normalize(span, None, bound); - traits::wf::clause_obligations( - wfcx.infcx, - wfcx.param_env, - wfcx.body_def_id, - normalized_bound, - bound_span, - ) - }); + let wf_obligations = bounds.instantiate_identity_iter_copied().flat_map(|bound| { + let normalized_bound = wfcx.normalize(span, None, bound.node); + traits::wf::clause_obligations( + wfcx.infcx, + wfcx.param_env, + wfcx.body_def_id, + normalized_bound, + bound.span, + ) + }); wfcx.register_obligations(wf_obligations); } @@ -1397,7 +1395,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, @@ -1424,18 +1422,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::bind(pred).instantiate(tcx, args); + let has_region = pred.node.visit_with(&mut param_count).is_break(); + let substituted_pred = ty::EarlyBinder::bind(pred.node).instantiate(tcx, args); // 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)| { @@ -1463,8 +1461,8 @@ 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)| { - traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp) + let wf_obligations = predicates.into_iter().flat_map(|p| { + traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p.node, p.span) }); let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect(); wfcx.register_obligations(obligations); @@ -1870,7 +1868,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { // Check elaborated bounds. let implied_obligations = traits::elaborate(tcx, predicates_with_span); - for (pred, obligation_span) in implied_obligations { + for ty::Spanned { node: pred, span: obligation_span } in implied_obligations { // We lower empty bounds like `Vec:` as // `WellFormed(Vec)`, which will later get checked by // regular WF checking diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 9636c6144461..d769ec28c77b 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1493,8 +1493,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 d746e6dea755..692951cd534b 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: LocalDefId, ast_bounds: &'tcx [hir::GenericBound<'tcx>], span: Span, -) -> &'tcx [(ty::Clause<'tcx>, Span)] { +) -> &'tcx [ty::Spanned>] { let item_ty = Ty::new_projection( tcx, assoc_item_def_id.to_def_id(), @@ -34,17 +34,15 @@ fn associated_type_bounds<'tcx>( let trait_def_id = tcx.local_parent(assoc_item_def_id); let trait_predicates = tcx.trait_explicit_predicates_and_bounds(trait_def_id); - let bounds_from_parent = trait_predicates - .predicates - .iter() - .copied() - .filter(|(pred, _)| match pred.kind().skip_binder() { - ty::ClauseKind::Trait(tr) => tr.self_ty() == item_ty, - ty::ClauseKind::Projection(proj) => proj.projection_ty.self_ty() == item_ty, - ty::ClauseKind::TypeOutlives(outlives) => outlives.0 == item_ty, - _ => false, - }) - .map(|(clause, span)| (clause, span)); + let bounds_from_parent = + trait_predicates.predicates.iter().copied().filter(|pred| { + match pred.node.kind().skip_binder() { + ty::ClauseKind::Trait(tr) => tr.self_ty() == item_ty, + ty::ClauseKind::Projection(proj) => proj.projection_ty.self_ty() == item_ty, + ty::ClauseKind::TypeOutlives(outlives) => outlives.0 == item_ty, + _ => false, + } + }); let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent)); debug!( @@ -66,7 +64,7 @@ fn opaque_type_bounds<'tcx>( ast_bounds: &'tcx [hir::GenericBound<'tcx>], item_ty: Ty<'tcx>, span: Span, -) -> &'tcx [(ty::Clause<'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, PredicateFilter::All); @@ -81,7 +79,7 @@ fn opaque_type_bounds<'tcx>( pub(super) fn explicit_item_bounds( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> ty::EarlyBinder<&'_ [(ty::Clause<'_>, Span)]> { +) -> ty::EarlyBinder<&'_ [ty::Spanned>]> { match tcx.opt_rpitit_info(def_id.to_def_id()) { // RPITIT's bounds are the same as opaque type bounds, but with // a projection self type. @@ -153,7 +151,7 @@ pub(super) fn item_bounds( def_id: DefId, ) -> ty::EarlyBinder<&'_ ty::List>> { tcx.explicit_item_bounds(def_id).map_bound(|bounds| { - tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&(bound, _span)| bound))) + tcx.mk_clauses_from_iter(util::elaborate(tcx, bounds.iter().map(|&bound| bound.node))) }) } diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 104da581e019..f344d4322178 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -11,7 +11,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{GenericPredicates, ImplTraitInTraitData, ToPredicate}; use rustc_span::symbol::Ident; -use rustc_span::{sym, Span, DUMMY_SP}; +use rustc_span::{sym, DUMMY_SP}; /// Returns a list of all type predicates (explicit and implicit) for the definition with /// ID `def_id`. This includes all predicates returned by `predicates_defined_on`, plus @@ -41,8 +41,8 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic let non_const_bound = if tcx.features().effects && tcx.has_attr(def_id, sym::const_trait) { // when `Self` is a const trait, also add `Self: Trait<.., true>` as implied bound, // because only implementing `Self: Trait<.., false>` is currently not possible. - Some(( - ty::TraitRef::new( + Some(ty::Spanned { + node: ty::TraitRef::new( tcx, def_id, ty::GenericArgs::for_item(tcx, def_id, |param, _| { @@ -55,7 +55,7 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic ) .to_predicate(tcx), span, - )) + }) } else { None }; @@ -64,10 +64,10 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic .predicates .iter() .copied() - .chain(std::iter::once(( - ty::TraitRef::identity(tcx, def_id).to_predicate(tcx), + .chain(std::iter::once(ty::Spanned { + node: ty::TraitRef::identity(tcx, def_id).to_predicate(tcx), span, - ))) + })) .chain(non_const_bound), ); } @@ -147,7 +147,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // 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::Clause<'_>, Span)> = FxIndexSet::default(); + let mut predicates: FxIndexSet>> = FxIndexSet::default(); let ast_generics = match node { Node::TraitItem(item) => item.generics, @@ -211,7 +211,8 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen // (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.to_predicate(tcx), tcx.def_span(def_id))); + predicates + .insert(ty::Spanned { node: trait_ref.to_predicate(tcx), span: tcx.def_span(def_id) }); } // Collect the predicates that were written inline by the user on each @@ -242,10 +243,10 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen .no_bound_vars() .expect("const parameters cannot be generic"); let ct = icx.astconv().hir_id_to_bound_const(param.hir_id, ct_ty); - predicates.insert(( - ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx), - param.span, - )); + predicates.insert(ty::Spanned { + node: ty::ClauseKind::ConstArgHasType(ct, ct_ty).to_predicate(tcx), + span: param.span, + }); } } } @@ -274,7 +275,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen ty::ClauseKind::WellFormed(ty.into()), bound_vars, ); - predicates.insert((predicate.to_predicate(tcx), span)); + predicates.insert(ty::Spanned { node: predicate.to_predicate(tcx), span }); } } @@ -300,7 +301,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen }; let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)) .to_predicate(tcx); - (pred, span) + ty::Spanned { node: pred, span } })) } @@ -358,7 +359,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen fn compute_bidirectional_outlives_predicates<'tcx>( tcx: TyCtxt<'tcx>, opaque_own_params: &[ty::GenericParamDef], - predicates: &mut Vec<(ty::Clause<'tcx>, Span)>, + predicates: &mut Vec>>, ) { for param in opaque_own_params { let orig_lifetime = tcx.map_rpit_lifetime_to_fn_lifetime(param.def_id.expect_local()); @@ -368,16 +369,22 @@ fn compute_bidirectional_outlives_predicates<'tcx>( ty::EarlyBoundRegion { def_id: param.def_id, index: param.index, name: param.name }, ); let span = tcx.def_span(param.def_id); - predicates.push(( - ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(orig_lifetime, dup_lifetime)) - .to_predicate(tcx), + predicates.push(ty::Spanned { + node: ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( + orig_lifetime, + dup_lifetime, + )) + .to_predicate(tcx), span, - )); - predicates.push(( - ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(dup_lifetime, orig_lifetime)) - .to_predicate(tcx), + }); + predicates.push(ty::Spanned { + node: ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( + dup_lifetime, + orig_lifetime, + )) + .to_predicate(tcx), span, - )); + }); } } } @@ -385,10 +392,10 @@ fn compute_bidirectional_outlives_predicates<'tcx>( fn const_evaluatable_predicates_of( tcx: TyCtxt<'_>, def_id: LocalDefId, -) -> FxIndexSet<(ty::Clause<'_>, Span)> { +) -> FxIndexSet>> { struct ConstCollector<'tcx> { tcx: TyCtxt<'tcx>, - preds: FxIndexSet<(ty::Clause<'tcx>, Span)>, + preds: FxIndexSet>>, } impl<'tcx> intravisit::Visitor<'tcx> for ConstCollector<'tcx> { @@ -396,8 +403,10 @@ 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::ClauseKind::ConstEvaluatable(ct).to_predicate(self.tcx), span)); + self.preds.insert(ty::Spanned { + node: ty::ClauseKind::ConstEvaluatable(ct).to_predicate(self.tcx), + span, + }); } } @@ -486,7 +495,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::ClauseKind::Trait(tr) => !is_assoc_item_ty(tr.self_ty()), ty::ClauseKind::Projection(proj) => !is_assoc_item_ty(proj.projection_ty.self_ty()), ty::ClauseKind::TypeOutlives(outlives) => !is_assoc_item_ty(outlives.0), @@ -529,8 +538,10 @@ pub(super) fn explicit_predicates_of<'tcx>( let filtered_predicates = parent_preds .predicates .into_iter() - .filter(|(pred, _)| { - if let ty::ClauseKind::ConstArgHasType(ct, _) = pred.kind().skip_binder() { + .filter(|pred| { + if let ty::ClauseKind::ConstArgHasType(ct, _) = + pred.node.kind().skip_binder() + { match ct.kind() { ty::ConstKind::Param(param_const) => { let defaulted_param_idx = tcx @@ -664,12 +675,12 @@ pub(super) fn implied_predicates_with_filter( // turn, reach indirect supertraits, so we detect cycles now instead of // overflowing during elaboration. if matches!(filter, PredicateFilter::SelfOnly) { - for &(pred, span) in implied_bounds { - debug!("superbound: {:?}", pred); - if let ty::ClauseKind::Trait(bound) = pred.kind().skip_binder() + for pred in implied_bounds { + debug!("superbound: {:?}", pred.node); + if let ty::ClauseKind::Trait(bound) = pred.node.kind().skip_binder() && bound.polarity == ty::ImplPolarity::Positive { - tcx.at(span).super_predicates_of(bound.def_id()); + tcx.at(pred.span).super_predicates_of(bound.def_id()); } } } @@ -737,7 +748,10 @@ pub(super) fn type_param_predicates( if param_id == item_hir_id { let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id.to_def_id()); - extend = Some((identity_trait_ref.to_predicate(tcx), item.span)); + extend = Some(ty::Spanned { + node: identity_trait_ref.to_predicate(tcx), + span: item.span, + }); } generics } @@ -762,7 +776,7 @@ pub(super) fn type_param_predicates( PredicateFilter::SelfThatDefines(assoc_name), ) .into_iter() - .filter(|(predicate, _)| match predicate.kind().skip_binder() { + .filter(|predicate| match predicate.node.kind().skip_binder() { ty::ClauseKind::Trait(data) => data.self_ty().is_param(index), _ => false, }), @@ -784,7 +798,7 @@ impl<'tcx> ItemCtxt<'tcx> { param_def_id: LocalDefId, ty: Ty<'tcx>, filter: PredicateFilter, - ) -> Vec<(ty::Clause<'tcx>, Span)> { + ) -> Vec>> { let mut bounds = Bounds::default(); for predicate in ast_generics.predicates { 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 6424d1c79311..68794c4ed82d 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1802,8 +1802,8 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { break Some((bound_vars.into_iter().collect(), assoc_item)); } let predicates = tcx.super_predicates_that_define_assoc_item((def_id, 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::ClauseKind::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 ed5e9dd2b5ad..af872addfea0 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::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::Clause<'tcx>, Span)], + predicates: &mut [ty::Spanned>], impl_trait_ref: Option>, input_parameters: &mut FxHashSet, ) { @@ -187,7 +186,8 @@ pub fn setup_constraining_predicates<'tcx>( for j in i..predicates.len() { // 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::ClauseKind::Projection(projection) = predicates[j].0.kind().skip_binder() { + if let ty::ClauseKind::Projection(projection) = 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 // trait. 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 7941861fd2f7..492e634e3485 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 @@ -235,8 +235,8 @@ fn unconstrained_parent_impl_args<'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 (clause, _) in impl_generic_predicates.predicates.iter() { - if let ty::ClauseKind::Projection(proj) = clause.kind().skip_binder() { + for clause in impl_generic_predicates.predicates.iter() { + if let ty::ClauseKind::Projection(proj) = clause.node.kind().skip_binder() { let projection_ty = proj.projection_ty; let projected_ty = proj.term; @@ -354,7 +354,7 @@ fn check_predicates<'tcx>( tcx.predicates_of(impl2_node.def_id()) .instantiate(tcx, impl2_args) .into_iter() - .map(|(c, _s)| c.as_predicate()), + .map(|c| c.node.as_predicate()), ) .collect() }; @@ -378,13 +378,13 @@ fn check_predicates<'tcx>( let always_applicable_traits = impl1_predicates .iter() .copied() - .filter(|&(clause, _span)| { + .filter(|&clause| { matches!( - trait_specialization_kind(tcx, clause), + trait_specialization_kind(tcx, clause.node), Some(TraitSpecializationKind::AlwaysApplicable) ) }) - .map(|(c, _span)| c.as_predicate()); + .map(|c| c.node.as_predicate()); // Include the well-formed predicates of the type parameters of the impl. for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().instantiate_identity().args { @@ -399,12 +399,12 @@ fn check_predicates<'tcx>( } impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits)); - for (clause, span) in impl1_predicates { + for clause in impl1_predicates { if !impl2_predicates .iter() - .any(|pred2| trait_predicates_eq(tcx, clause.as_predicate(), *pred2, span)) + .any(|pred2| trait_predicates_eq(tcx, clause.node.as_predicate(), *pred2, clause.span)) { - check_specialization_on(tcx, clause, span) + check_specialization_on(tcx, clause.node, clause.span) } } } diff --git a/compiler/rustc_hir_analysis/src/outlives/explicit.rs b/compiler/rustc_hir_analysis/src/outlives/explicit.rs index a7fca41f86ac..453e66f10e6e 100644 --- a/compiler/rustc_hir_analysis/src/outlives/explicit.rs +++ b/compiler/rustc_hir_analysis/src/outlives/explicit.rs @@ -28,14 +28,14 @@ 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::ClauseKind::TypeOutlives(OutlivesPredicate(ty, reg)) => { insert_outlives_predicate( tcx, ty.into(), reg, - span, + predicate.span, &mut required_predicates, ) } @@ -45,7 +45,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 9fb39a0e93b6..221ed5a710b5 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -158,15 +158,15 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc let mut collector = OpaqueTypeLifetimeCollector { tcx, root_def_id: item_def_id.to_def_id(), variances }; let id_args = ty::GenericArgs::identity_for_item(tcx, item_def_id); - for (pred, _) in tcx.explicit_item_bounds(item_def_id).iter_instantiated_copied(tcx, id_args) { - debug!(?pred); + for pred in tcx.explicit_item_bounds(item_def_id).iter_instantiated_copied(tcx, id_args) { + debug!(?pred.node); // We only ignore opaque type args if the opaque type is the outermost type. // The opaque type may be nested within itself via recursion in e.g. // type Foo<'a> = impl PartialEq>; // which thus mentions `'a` and should thus accept hidden types that borrow 'a // instead of requiring an additional `+ 'a`. - match pred.kind().skip_binder() { + match pred.node.kind().skip_binder() { ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref: ty::TraitRef { def_id: _, args, .. }, polarity: _, @@ -188,7 +188,7 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc region.visit_with(&mut collector); } _ => { - pred.visit_with(&mut collector); + pred.node.visit_with(&mut collector); } } } diff --git a/compiler/rustc_hir_typeck/src/_match.rs b/compiler/rustc_hir_typeck/src/_match.rs index 84e986488a6a..57bf347082b5 100644 --- a/compiler/rustc_hir_typeck/src/_match.rs +++ b/compiler/rustc_hir_typeck/src/_match.rs @@ -537,12 +537,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } for ty in [first_ty, second_ty] { - for (clause, _) in self + for clause in self .tcx .explicit_item_bounds(rpit_def_id) .iter_instantiated_copied(self.tcx, args) { - let pred = clause.kind().rebind(match clause.kind().skip_binder() { + let pred = clause.node.kind().rebind(match clause.node.kind().skip_binder() { ty::ClauseKind::Trait(trait_pred) => { assert!(matches!( *trait_pred.trait_ref.self_ty().kind(), diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 6b6d1574b2bf..ab2ae56b2992 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, args); - 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({:?}) = {result:?}", predicate.node), ) - .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 a70ead8e57d6..cb57052aa761 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -179,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.tcx .explicit_item_bounds(def_id) .iter_instantiated_copied(self.tcx, args) - .map(|(c, s)| (c.as_predicate(), s)), + .map(|c| ty::Spanned { node: c.node.as_predicate(), span: c.span }), ), ty::Dynamic(ref object_type, ..) => { let sig = object_type.projection_bounds().find_map(|pb| { @@ -193,7 +193,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } ty::Infer(ty::TyVar(vid)) => self.deduce_closure_signature_from_predicates( Ty::new_var(self.tcx, 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 }; @@ -206,12 +207,12 @@ 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; - for (pred, span) in traits::elaborate( + for pred in traits::elaborate( self.tcx, // Reverse the obligations here, since `elaborate_*` uses a stack, // and we want to keep inference generally in the same order of @@ -221,8 +222,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // We only care about self bounds .filter_only_self() { - debug!(?pred); - let bound_predicate = pred.kind(); + debug!(?pred.node); + let bound_predicate = pred.node.kind(); // Given a Projection predicate, we can potentially infer // the complete signature. @@ -231,9 +232,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bound_predicate.skip_binder() { let inferred_sig = self.normalize( - span, + pred.span, self.deduce_sig_from_projection( - Some(span), + Some(pred.span), bound_predicate.rebind(proj_predicate), ), ); @@ -727,7 +728,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .explicit_item_bounds(def_id) .iter_instantiated_copied(self.tcx, args) - .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?, + .find_map(|p| get_future_output(p.node.as_predicate(), p.span))?, ty::Error(_) => return None, _ => span_bug!( closure_span, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 9f439a2b32aa..4576183b6762 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -925,7 +925,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 facbeb8badfa..669ef60dbfb5 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 @@ -603,7 +603,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Err(expr); } - match impl_predicates.predicates[impl_predicate_index].0.kind().skip_binder() { + match impl_predicates.predicates[impl_predicate_index].node.kind().skip_binder() { ty::ClauseKind::Trait(broken_trait) => { // ... self.blame_specific_part_of_expr_corresponding_to_generic_param( diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 33dfa16a651f..331d749c9839 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1995,12 +1995,12 @@ 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 { - if let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() + for predicate in instantiated { + if let ty::ClauseKind::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 e93d180fc139..583b3646b634 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -227,7 +227,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { self.param_env.caller_bounds().iter().filter_map(|predicate| { match predicate.kind().skip_binder() { ty::ClauseKind::Trait(data) if data.self_ty().is_param(index) => { - Some((predicate, span)) + Some(ty::Spanned { node: predicate, span }) } _ => None, } diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 7c73f6a89cdb..838d7a04eb98 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -613,7 +613,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { ty::ClauseKind::Trait(trait_pred) if trait_pred.def_id() == sized_def_id => { let span = predicates .iter() - .find_map(|(p, span)| if p == pred { Some(span) } else { None }) + .find_map(|p| (p.node == pred).then_some(p.span)) .unwrap_or(rustc_span::DUMMY_SP); Some((trait_pred, span)) } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index b30f9b82fbbf..7232af11b594 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -567,7 +567,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_infer/Cargo.toml b/compiler/rustc_infer/Cargo.toml index 00251a192264..5983221f9411 100644 --- a/compiler/rustc_infer/Cargo.toml +++ b/compiler/rustc_infer/Cargo.toml @@ -18,6 +18,7 @@ rustc_middle = { path = "../rustc_middle" } 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"] } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 26d071a01397..1e83aa5cdb28 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -407,8 +407,9 @@ impl<'tcx> InferCtxt<'tcx> { let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0]; self.tcx.explicit_item_bounds(def_id).iter_instantiated_copied(self.tcx, args).find_map( - |(predicate, _)| { + |predicate| { predicate + .node .kind() .map_bound(|kind| match kind { ty::ClauseKind::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 8d3cd23b7fa5..a8e08c790800 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/note.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs @@ -316,18 +316,18 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let trait_item_args = ty::GenericArgs::identity_for_item(self.tcx, impl_item_def_id) .rebase_onto(self.tcx, impl_def_id, trait_args); - let Ok(trait_predicates) = - self.tcx - .explicit_predicates_of(trait_item_def_id) - .instantiate_own(self.tcx, trait_item_args) - .map(|(pred, _)| { - if pred.is_suggestable(self.tcx, false) { - Ok(pred.to_string()) - } else { - Err(()) - } - }) - .collect::, ()>>() + let Ok(trait_predicates) = self + .tcx + .explicit_predicates_of(trait_item_def_id) + .instantiate_own(self.tcx, trait_item_args) + .map(|pred| { + if pred.node.is_suggestable(self.tcx, false) { + Ok(pred.node.to_string()) + } else { + Err(()) + } + }) + .collect::, ()>>() else { return; }; diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs index 7a5dec22fe04..b11059a68a4b 100644 --- a/compiler/rustc_infer/src/infer/opaque_types.rs +++ b/compiler/rustc_infer/src/infer/opaque_types.rs @@ -597,8 +597,8 @@ impl<'tcx> InferCtxt<'tcx> { let tcx = self.tcx; let item_bounds = tcx.explicit_item_bounds(def_id); - for (predicate, _) in item_bounds.iter_instantiated_copied(tcx, args) { - let predicate = predicate.fold_with(&mut BottomUpFolder { + for predicate in item_bounds.iter_instantiated_copied(tcx, args) { + 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/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index a26e676c5217..d760794f1c27 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -36,9 +36,12 @@ 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)] +#[derive(Clone, TypeFoldable, TypeVisitable)] pub struct Obligation<'tcx, T> { /// The reason we have to prove this thing. + // FIXME: provide more detailed justification for `#[skip_traversal]`, or else remove + // see https://github.com/rust-lang/rust/pull/108214#issuecomment-1479424793 + #[skip_traversal(despite_potential_miscompilation_because = "perf")] pub cause: ObligationCause<'tcx>, /// The environment in which we should prove this thing. diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index 8a7c59da09eb..958988e1dcf3 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`. @@ -58,31 +55,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) - } -} diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 3c566e0dd6da..9d444a84d1ce 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -3,7 +3,7 @@ use smallvec::smallvec; use crate::infer::outlives::components::{push_outlives_components, Component}; use crate::traits::{self, Obligation, PredicateObligation}; use rustc_data_structures::fx::FxHashSet; -use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; +use rustc_middle::ty::{self, Spanned, ToPredicate, Ty, TyCtxt}; use rustc_span::symbol::Ident; use rustc_span::Span; @@ -165,6 +165,26 @@ impl<'tcx> Elaboratable<'tcx> for ty::Predicate<'tcx> { } } +impl<'tcx> Elaboratable<'tcx> for ty::Spanned> { + fn predicate(&self) -> ty::Predicate<'tcx> { + self.node + } + + fn child(&self, clause: ty::Clause<'tcx>) -> Self { + ty::Spanned { node: clause.as_predicate(), span: self.span } + } + + fn child_with_derived_cause( + &self, + clause: ty::Clause<'tcx>, + _span: Span, + _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, + _index: usize, + ) -> Self { + ty::Spanned { node: clause.as_predicate(), span: self.span } + } +} + impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) { fn predicate(&self) -> ty::Predicate<'tcx> { self.0 @@ -185,6 +205,26 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) { } } +impl<'tcx> Elaboratable<'tcx> for Spanned> { + fn predicate(&self) -> ty::Predicate<'tcx> { + self.node.as_predicate() + } + + fn child(&self, clause: ty::Clause<'tcx>) -> Self { + Spanned { node: clause, span: self.span } + } + + fn child_with_derived_cause( + &self, + clause: ty::Clause<'tcx>, + _span: Span, + _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, + _index: usize, + ) -> Self { + Spanned { node: clause, span: self.span } + } +} + impl<'tcx> Elaboratable<'tcx> for (ty::Clause<'tcx>, Span) { fn predicate(&self) -> ty::Predicate<'tcx> { self.0.as_predicate() @@ -277,15 +317,16 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { } }; - let obligations = - predicates.predicates.iter().enumerate().map(|(index, &(clause, span))| { + let obligations = predicates.predicates.iter().enumerate().map( + |(index, &Spanned { node: clause, span })| { elaboratable.child_with_derived_cause( clause.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), span, bound_predicate.rebind(data), index, ) - }); + }, + ); debug!(?data, ?obligations, "super_predicates"); self.extend_deduped(obligations); } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 6f6150a4172f..4835bf9ef0db 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1600,8 +1600,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() { ClauseKind::Trait(..) => "trait", ClauseKind::TypeOutlives(..) | ClauseKind::RegionOutlives(..) => "lifetime", @@ -1616,11 +1616,11 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints { // FIXME(generic_const_exprs): `ConstEvaluatable` can be written | ClauseKind::ConstEvaluatable(..) => 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 dfefaf82fd7d..af8204542727 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable { .super_predicates_of(def_id) .predicates .into_iter() - .filter_map(|(pred, _)| pred.as_trait_clause()); + .filter_map(|pred| pred.node.as_trait_clause()); 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 c24846ca9398..8404ef3a2f28 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -74,10 +74,8 @@ 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).instantiate_identity_iter_copied() - { - let predicate = infcx.instantiate_binder_with_placeholders(pred.kind()); + for pred in cx.tcx.explicit_item_bounds(def_id).instantiate_identity_iter_copied() { + let predicate = infcx.instantiate_binder_with_placeholders(pred.node.kind()); let ty::ClauseKind::Projection(proj) = predicate else { continue; }; @@ -110,12 +108,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 .explicit_item_bounds(proj.projection_ty.def_id) .iter_instantiated_copied(cx.tcx, &proj.projection_ty.args) { - 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(), @@ -147,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { }; cx.emit_spanned_lint( OPAQUE_HIDDEN_INFERRED_BOUND, - pred_span, + pred.span, OpaqueHiddenInferredBoundLint { ty: Ty::new_opaque( cx.tcx, @@ -155,7 +153,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound { ty::GenericArgs::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 e812493b3dd3..dc5c6a9af1a1 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -90,8 +90,8 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { use rustc_middle::ty::ClauseKind; let predicates = cx.tcx.explicit_predicates_of(item.owner_id); - for &(predicate, span) in predicates.predicates { - let ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else { + for &predicate in predicates.predicates { + let ClauseKind::Trait(trait_predicate) = predicate.node.kind().skip_binder() else { continue; }; let def_id = trait_predicate.trait_ref.def_id; @@ -103,8 +103,8 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints { let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return }; 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_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 355855b8e2b3..657f9e5515bd 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -292,10 +292,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { ) // We only care about self bounds for the impl-trait .filter_only_self() - .find_map(|(pred, _span)| { + .find_map(|pred| { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::ClauseKind::Trait(ref poly_trait_predicate) = - pred.kind().skip_binder() + pred.node.kind().skip_binder() { let def_id = poly_trait_predicate.trait_ref.def_id; diff --git a/compiler/rustc_macros/Cargo.toml b/compiler/rustc_macros/Cargo.toml index d8d2bef49640..aeea5cd6e715 100644 --- a/compiler/rustc_macros/Cargo.toml +++ b/compiler/rustc_macros/Cargo.toml @@ -13,3 +13,6 @@ quote = "1" syn = { version = "2.0.9", features = ["full"] } synstructure = "0.13.0" # tidy-alphabetical-end + +[dev-dependencies] +syn = { version = "*", features = ["visit-mut"] } diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 193dbd75fbd5..1b4074ef4f3f 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -23,8 +23,7 @@ mod newtype; mod query; mod serialize; mod symbols; -mod type_foldable; -mod type_visitable; +mod traversable; #[proc_macro] pub fn current_rustc_version(input: TokenStream) -> TokenStream { @@ -75,25 +74,94 @@ 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). /// - /// 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`). - type_foldable::type_foldable_derive + /// Folds will produce a value of the same struct or enum variant as the input, with trivial + /// fields unchanged and all non-trivial fields respectively folded (in definition order) using + /// the `TypeFoldable` implementation for its type. A field of type `T` is "trivial" if `T` + /// both does not reference any generic type parameters and either + /// - does not reference any `'tcx` lifetime parameter; or + /// - does not contain anything that could be of interest to folders. + /// + /// Non-trivial fields (e.g. of type `T`) can instead be left unchanged by applying + /// `#[skip_traversal(because_trivial)]` 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 if `T` does not contain anything that may be of interest to folders + /// (thus preventing fields from being so-skipped erroneously). + /// + /// By default, `TypeFoldable` cannot be derived on types that contain nothing that may be of + /// interest to folders as such an implementation is wholly superfluous and probably in error. + /// However, on occasion it may nevertheless be necessary to implement `TypeFoldable` for such + /// types even though any such fold will always be a noop (e.g. so that instances can be used + /// in a generic context that is constrained to implementors of the trait); in such situations + /// one can add a `#[skip_traversal(but_impl_despite_trivial_because = ""]` attribute. + /// + /// In some rare situations, it may be desirable to skip folding of an item or field (or + /// variant) that might otherwise be of interest to folders. This can be achieved via a + /// `#[skip_traversal(despite_potential_miscompilation_because = ""]` attribute. + /// Whereas the preceding usages of the `#[skip_traversal]` attribute are guaranteed to be + /// sound by constraining the relevant type to implementors of the `TriviallyTraversable` + /// trait, use of `despite_potential_miscompilation_because` does not add such constraint or + /// provide any such guarantee. **It is therefore dangerous and could lead to miscompilation + /// if user expectations are not met!** + /// + /// 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, I: Interner> TypeFoldable for Foo<'a>` + /// + /// and + /// + /// `impl<'tcx> TypeFoldable> for Bar<'tcx>` + 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 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`). - type_visitable::type_visitable_derive + /// Each non-trivial field of the struct or enum variant will be visited (in definition order) + /// using the `TypeVisitable` implementation for its type; trivial fields will be ignored. A + /// field of type `T` is "trivial" if `T` both does not reference any generic type parameters + /// and either + /// - does not reference any `'tcx` lifetime parameter; or + /// - does not contain anything that could be of interest to visitors. + /// + /// Non-trivial fields (e.g. of type `T`) can instead be ignored by applying + /// `#[skip_traversal(because_trivial)]` 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 if `T` does not contain anything that may be of interest to visitors + /// (thus preventing fields from being so-skipped erroneously). + /// + /// By default, `TypeVisitable` cannot be derived on types that contain nothing that may be of + /// interest to visitors as such an implementation is wholly superfluous and probably in error. + /// However, on occasion it may nevertheless be necessary to implement `TypeVisitable` for such + /// types even though any such visit will always be a noop (e.g. so that instances can be used + /// in a generic context that is constrained to implementors of the trait); in such situations + /// one can add a `#[skip_traversal(but_impl_despite_trivial_because = ""]` attribute. + /// + /// In some rare situations, it may be desirable to skip visiting of an item or field (or + /// variant) that might otherwise be of interest to visitors. This can be achieved via a + /// `#[skip_traversal(despite_potential_miscompilation_because = ""]` attribute. + /// Whereas the preceding usages of the `#[skip_traversal]` attribute are guaranteed to be + /// sound by constraining the relevant type to implementors of the `TriviallyTraversable` + /// trait, use of `despite_potential_miscompilation_because` does not add such constraint or + /// provide any such guarantee. **It is therefore dangerous and could lead to miscompilation + /// if user expectations are not met!** + /// + /// 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, I: Interner> TypeVisitable for Foo<'a>` + /// + /// and + /// + /// `impl<'tcx> TypeVisitable> for Bar<'tcx>` + 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 000000000000..b1ff75282f74 --- /dev/null +++ b/compiler/rustc_macros/src/traversable.rs @@ -0,0 +1,433 @@ +use proc_macro2::{Ident, Span, TokenStream}; +use quote::{quote, ToTokens}; +use std::collections::{hash_map::Entry, HashMap}; +use syn::{ + meta::ParseNestedMeta, parse::Error, parse_quote, visit, Attribute, Field, Generics, Lifetime, + LitStr, Token, +}; + +#[cfg(test)] +mod tests; + +/// 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()) +} + +#[derive(Clone, Copy, PartialEq)] +enum Type { + /// Describes a type that is not parameterised by the interner, and therefore cannot + /// be of any interest to traversers. + Trivial, + + /// Describes a type that is parameterised by the interner lifetime `'tcx` but that is + /// otherwise not generic. + NotGeneric, + + /// Describes a type that is generic. + Generic, +} +use Type::*; + +#[derive(Clone, Copy)] +enum WhenToSkip { + /// No skip_traversal annotation requires the annotated item to be skipped + Never, + + /// A skip_traversal annotation requires the annotated item to be skipped, with its type + /// constrained to TriviallyTraversable + Always(Span), + + /// A `despite_potential_miscompilation_because` annotation is present, thus requiring the + /// annotated item to be forcibly skipped without its type being constrained to + /// TriviallyTraversable + Forced, +} + +impl Default for WhenToSkip { + fn default() -> Self { + Self::Never + } +} + +impl WhenToSkip { + fn is_skipped(&self) -> bool { + !matches!(self, WhenToSkip::Never) + } +} + +impl std::ops::BitOrAssign for WhenToSkip { + fn bitor_assign(&mut self, rhs: Self) { + match self { + Self::Forced => (), + Self::Always(_) => { + if matches!(rhs, Self::Forced) { + *self = Self::Forced; + } + } + Self::Never => *self = rhs, + } + } +} + +impl WhenToSkip { + fn find(&mut self, attrs: &[Attribute], ty: Type) -> Result<(), Error> { + fn parse_reason(meta: &ParseNestedMeta<'_>) -> Result<(), Error> { + if !meta.value()?.parse::()?.value().trim().is_empty() { + Ok(()) + } else { + Err(meta.error("skip reason must be a non-empty string")) + } + } + + let mut found = None; + for attr in attrs { + if attr.path().is_ident("skip_traversal") { + found = Some(attr); + attr.parse_nested_meta(|meta| { + if IS_TYPE + && ty == Trivial + && meta.path.is_ident("but_impl_despite_trivial_because") + { + parse_reason(&meta)?; + *self |= Self::Always(meta.error("").span()); + return Ok(()); + } + + if meta.path.is_ident("despite_potential_miscompilation_because") { + parse_reason(&meta)?; + *self |= Self::Forced; + return Ok(()); + } + + if !IS_TYPE && ty == Generic && meta.path.is_ident("because_trivial") { + *self |= Self::Always(meta.error("").span()); + return Ok(()); + } + + Err(meta.error("unsupported skip reason")) + })?; + } + } + + if let (Self::Never, Some(attr)) = (self, found) { + Err(Error::new_spanned( + attr, + if IS_TYPE { + match ty { + Trivial => return Ok(()), // triggers error in caller + _ => { + "\ + Justification must be provided for skipping this potentially interesting type, by specifying\n\ + `despite_potential_miscompilation_because = \"\"`\ + " + } + } + } else { + match ty { + Trivial => { + "trivially traversable fields are always skipped, so this attribute is superfluous" + } + _ => { + "\ + Justification must be provided for skipping potentially interesting fields, by specifying EITHER:\n\ + `because_trivial` if concrete instances do not actually contain anything of interest (enforced by the compiler); OR\n\ + `despite_potential_miscompilation_because = \"\"` in the rare case that a field should always be skipped regardless\ + " + } + } + }, + )) + } else { + Ok(()) + } + } +} + +pub enum Interner<'a> { + Middle(&'a Lifetime), + Generic(Ident), +} + +impl<'a> Interner<'a> { + /// Return the interner for the given `structure`. + /// + /// If the input represented by `structure` has a `'tcx` lifetime parameter, then `Middle('tcx)` + /// will be returned; otherwise our derived implementation will be generic over a new parameter. + fn resolve(suffix: impl ToString, generics: &'a Generics) -> Self { + generics + .lifetimes() + .find_map(|def| (def.lifetime.ident == "tcx").then_some(Self::Middle(&def.lifetime))) + .unwrap_or_else(|| Self::Generic(gen_param(suffix, generics))) + } +} + +impl ToTokens for Interner<'_> { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + Interner::Middle(lt) => tokens.extend(quote! { ::rustc_middle::ty::TyCtxt<#lt> }), + Interner::Generic(ident) => ident.to_tokens(tokens), + } + } +} + +pub struct Foldable; +pub struct Visitable; + +/// An abstraction over traversable traits. +pub trait Traversable { + /// The trait that this `Traversable` represents, parameterised by `interner`. + fn traversable(interner: &Interner<'_>) -> TokenStream; + + /// Any supertraits that this trait is required to implement. + fn supertraits(interner: &Interner<'_>) -> TokenStream; + + /// A (`noop`) traversal of this trait upon the `bind` expression. + fn traverse(bind: TokenStream, noop: bool, interner: &Interner<'_>) -> TokenStream; + + /// A `match` arm for `variant`, where `f` generates the tokens for each binding. + fn arm( + variant: &synstructure::VariantInfo<'_>, + f: impl FnMut(&synstructure::BindingInfo<'_>) -> Result, + ) -> TokenStream; + + /// The body of an implementation given the `interner`, `traverser` and match expression `body`. + fn impl_body( + interner: Interner<'_>, + traverser: impl ToTokens, + body: impl ToTokens, + ) -> TokenStream; +} + +impl Traversable for Foldable { + fn traversable(interner: &Interner<'_>) -> TokenStream { + quote! { ::rustc_type_ir::fold::TypeFoldable<#interner> } + } + fn supertraits(interner: &Interner<'_>) -> TokenStream { + Visitable::traversable(interner) + } + fn traverse(bind: TokenStream, noop: bool, interner: &Interner<'_>) -> TokenStream { + if noop { + bind + } else { + quote! { ::rustc_type_ir::noop_if_trivially_traversable!(#bind.try_fold_with::<#interner>(folder))? } + } + } + fn arm( + variant: &synstructure::VariantInfo<'_>, + mut f: impl FnMut(&synstructure::BindingInfo<'_>) -> Result, + ) -> TokenStream { + let bindings = variant.bindings(); + variant.construct(|_, index| f(&bindings[index]).unwrap_or_else(Error::into_compile_error)) + } + fn impl_body( + interner: Interner<'_>, + traverser: impl ToTokens, + body: impl ToTokens, + ) -> TokenStream { + quote! { + fn try_fold_with<#traverser: ::rustc_type_ir::fold::FallibleTypeFolder<#interner>>( + self, + folder: &mut #traverser + ) -> ::core::result::Result { + ::core::result::Result::Ok(#body) + } + } + } +} + +impl Traversable for Visitable { + fn traversable(interner: &Interner<'_>) -> TokenStream { + quote! { ::rustc_type_ir::visit::TypeVisitable<#interner> } + } + fn supertraits(_: &Interner<'_>) -> TokenStream { + quote! { ::core::clone::Clone + ::core::fmt::Debug } + } + fn traverse(bind: TokenStream, noop: bool, interner: &Interner<'_>) -> TokenStream { + if noop { + quote! {} + } else { + quote! { ::rustc_type_ir::noop_if_trivially_traversable!(#bind.visit_with::<#interner>(visitor))?; } + } + } + fn arm( + variant: &synstructure::VariantInfo<'_>, + f: impl FnMut(&synstructure::BindingInfo<'_>) -> Result, + ) -> TokenStream { + variant + .bindings() + .iter() + .map(f) + .collect::>() + .unwrap_or_else(Error::into_compile_error) + } + fn impl_body( + interner: Interner<'_>, + traverser: impl ToTokens, + body: impl ToTokens, + ) -> TokenStream { + quote! { + fn visit_with<#traverser: ::rustc_type_ir::visit::TypeVisitor<#interner>>( + &self, + visitor: &mut #traverser + ) -> ::core::ops::ControlFlow<#traverser::BreakTy> { + #body + ::core::ops::ControlFlow::Continue(()) + } + } + } +} + +impl Interner<'_> { + /// We consider a type to be internable if it references either a generic type parameter or, + /// if the interner is `TyCtxt<'tcx>`, the `'tcx` lifetime. + fn type_of<'a>( + &self, + referenced_ty_params: &[&Ident], + fields: impl IntoIterator, + ) -> Type { + use visit::Visit; + + struct Info<'a> { + interner: &'a Lifetime, + contains_interner: bool, + } + + impl Visit<'_> for Info<'_> { + fn visit_lifetime(&mut self, i: &Lifetime) { + if i == self.interner { + self.contains_interner = true; + } else { + visit::visit_lifetime(self, i) + } + } + } + + if !referenced_ty_params.is_empty() { + Generic + } else if let Interner::Middle(interner) = self && fields.into_iter().any(|field| { + let mut info = Info { interner, contains_interner: false }; + info.visit_type(&field.ty); + info.contains_interner + }) { + NotGeneric + } else { + Trivial + } + } +} + +pub fn traversable_derive( + mut structure: synstructure::Structure<'_>, +) -> Result { + use WhenToSkip::*; + + let ast = structure.ast(); + + let interner = Interner::resolve("I", &ast.generics); + let traverser = gen_param("T", &ast.generics); + let traversable = T::traversable(&interner); + + let skip_traversal = + |t: &dyn ToTokens| parse_quote! { #interner: ::rustc_type_ir::TriviallyTraverses<#t> }; + + structure.underscore_const(true); + structure.add_bounds(synstructure::AddBounds::None); + structure.bind_with(|_| synstructure::BindStyle::Move); + + let not_generic = if let Interner::Generic(ident) = &interner { + structure.add_impl_generic(parse_quote! { #ident: ::rustc_type_ir::Interner }); + Trivial + } else { + NotGeneric + }; + + // 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 ty = if ast.generics.type_params().next().is_some() { + let supertraits = T::supertraits(&interner); + structure.add_where_predicate(parse_quote! { Self: #supertraits }); + Generic + } else { + not_generic + }; + + let mut when_to_skip = WhenToSkip::default(); + when_to_skip.find::(&ast.attrs, ty)?; + let body = if when_to_skip.is_skipped() { + if let Always(_) = when_to_skip { + structure.add_where_predicate(skip_traversal(&::default())); + } + T::traverse(quote! { self }, true, &interner) + } else if ty == Trivial { + return Err(Error::new( + Span::call_site(), + "\ + Traversal of trivial 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_despite_trivial_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 + // 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 variant_ty = interner.type_of(&variant.referenced_ty_params(), variant.ast().fields); + let mut skipped_variant = WhenToSkip::default(); + if let Err(err) = skipped_variant.find::(variant.ast().attrs, variant_ty) { + return err.into_compile_error(); + } + T::arm(variant, |bind| { + let ast = bind.ast(); + let is_skipped = variant_ty == Trivial || { + let field_ty = interner.type_of(&bind.referenced_ty_params(), [ast]); + field_ty == Trivial || { + let mut skipped_field = skipped_variant; + skipped_field.find::(&ast.attrs, field_ty)?; + + match predicates.entry(ast.ty.clone()) { + Entry::Occupied(existing) => match (&mut existing.into_mut().0, skipped_field) { + (Never, Never) | (Never, Forced) | (Forced, Forced) | (Always(_), Always(_)) => (), + (existing @ Forced, Never) => *existing = Never, + (&mut Always(span), _) | (_, Always(span)) => return Err(Error::new(span, format!("\ + This annotation only makes sense if all fields of type `{0}` are annotated identically.\n\ + In particular, the derived impl will only be applicable when `{0}: TriviallyTraversable` and therefore all traversals of `{0}` will be no-ops;\n\ + accordingly it makes no sense for other fields of type `{0}` to omit `#[skip_traversal]` or to include `despite_potential_miscompilation_because`.\ + ", ast.ty.to_token_stream()))), + }, + Entry::Vacant(entry) => { entry.insert((skipped_field, field_ty)); } + } + + skipped_field.is_skipped() + } + }; + + Ok(T::traverse(bind.into_token_stream(), is_skipped, &interner)) + }) + }); + + // the order in which `where` predicates appear in rust source is irrelevant + #[allow(rustc::potential_query_instability)] + for (ty, (when_to_skip, field_ty)) in predicates { + structure.add_where_predicate(match when_to_skip { + Always(_) => skip_traversal(&ty), + // we only need to add traversable predicate for generic types + Never if field_ty == Generic => parse_quote! { #ty: #traversable }, + _ => continue, + }); + } + quote! { match self { #arms } } + }; + + Ok(structure.bound_impl(traversable, T::impl_body(interner, traverser, body))) +} diff --git a/compiler/rustc_macros/src/traversable/tests.rs b/compiler/rustc_macros/src/traversable/tests.rs new file mode 100644 index 000000000000..9a24ec4f8bad --- /dev/null +++ b/compiler/rustc_macros/src/traversable/tests.rs @@ -0,0 +1,392 @@ +use super::{parse_quote, traversable_derive, visit, Error, Foldable, ToTokens}; +use syn::visit_mut::VisitMut; + +/// A folder that normalizes syn types for comparison in tests. +struct Normalizer; + +/// Generates a folding method for [`Normalizer`] that ensures certain collections +/// are sorted consistently, thus eliminating any non-deterministic output. +macro_rules! normalizing_sort { + ($($method:ident($field:ident in $ty:ty);)*) => {$( + fn $method(&mut self, i: &mut $ty) { + syn::visit_mut::$method(self, i); + let mut vec = std::mem::take(&mut i.$field).into_iter().collect::>(); + vec.sort_unstable_by_key(|x| x.to_token_stream().to_string()); + i.$field = vec.into_iter().collect(); + } + )*}; + } + +impl VisitMut for Normalizer { + // Each of the following fields in the following types can be reordered without + // affecting semantics, and therefore need to be normalized. + normalizing_sort! { + visit_where_clause_mut(predicates in syn::WhereClause); + visit_predicate_lifetime_mut(bounds in syn::PredicateLifetime); + visit_bound_lifetimes_mut(lifetimes in syn::BoundLifetimes); + visit_lifetime_param_mut(bounds in syn::LifetimeParam); + visit_type_param_mut(bounds in syn::TypeParam); + visit_type_impl_trait_mut(bounds in syn::TypeImplTrait); + visit_type_trait_object_mut(bounds in syn::TypeTraitObject); + visit_generics_mut(params in syn::Generics); + } + + fn visit_macro_mut(&mut self, i: &mut syn::Macro) { + syn::visit_mut::visit_macro_mut(self, i); + if i.path.is_ident("noop_if_trivially_traversable") { + let mut expr = i + .parse_body() + .expect("body of `noop_if_trivially_traversable` macro should be an expression"); + self.visit_expr_mut(&mut expr); + i.tokens = expr.into_token_stream(); + } + } + + // For convenience, we also simplify paths by removing absolute crate/module + // references. + fn visit_path_mut(&mut self, i: &mut syn::Path) { + syn::visit_mut::visit_path_mut(self, i); + + let n = if i.leading_colon.is_some() && i.segments.len() >= 2 { + let segment = &i.segments[0]; + if *segment == parse_quote! { rustc_type_ir } { + let segment = &i.segments[1]; + if i.segments.len() > 2 && *segment == parse_quote! { fold } + || *segment == parse_quote! { visit } + { + 2 + } else if *segment == parse_quote! { Interner } + || segment.ident == "TriviallyTraverses" + || *segment == parse_quote! { noop_if_trivially_traversable } + { + 1 + } else { + return; + } + } else if *segment == parse_quote! { rustc_middle } { + let segment = &i.segments[1]; + if i.segments.len() > 2 && *segment == parse_quote! { ty } { + 2 + } else { + return; + } + } else if i.segments.len() > 2 && *segment == parse_quote! { core } { + let segment = &i.segments[1]; + if *segment == parse_quote! { ops } { + 2 + } else if *segment == parse_quote! { result } { + i.segments.len() - 1 + } else { + return; + } + } else { + return; + } + } else { + return; + }; + + *i = syn::Path { + leading_colon: None, + segments: std::mem::take(&mut i.segments).into_iter().skip(n).collect(), + }; + } +} + +#[derive(Default, Debug)] +struct ErrorFinder(Vec); + +impl ErrorFinder { + fn contains(&self, message: &str) -> bool { + self.0.iter().any(|error| error.starts_with(message)) + } +} + +impl visit::Visit<'_> for ErrorFinder { + fn visit_macro(&mut self, i: &syn::Macro) { + if i.path == parse_quote! { ::core::compile_error } { + self.0.push( + i.parse_body::() + .expect("expected compile_error macro to be invoked with a string literal") + .value(), + ); + } else { + syn::visit::visit_macro(self, i) + } + } +} + +fn result(input: syn::DeriveInput) -> Result { + traversable_derive::(synstructure::Structure::new(&input)).and_then(syn::parse2) +} + +fn expect_success(input: syn::DeriveInput, expected: syn::ItemImpl) { + let result = result(input).expect("expected compiled code to parse"); + let syn::Expr::Block(syn::ExprBlock { block: syn::Block { stmts, .. }, .. }) = *result.expr + else { + panic!("expected const expr to be a block") + }; + assert_eq!(stmts.len(), 1, "expected const expr to contain a single statement"); + let syn::Stmt::Item(syn::Item::Impl(mut actual)) = stmts.into_iter().next().unwrap() else { + panic!("expected statement in const expr to be an impl") + }; + Normalizer.visit_item_impl_mut(&mut actual); + + assert!( + actual == expected, + "EXPECTED: {}\nACTUAL: {}", + expected.to_token_stream(), + actual.to_token_stream() + ); +} + +fn expect_failure(input: syn::DeriveInput, expected: &str) { + let mut actual = ErrorFinder::default(); + match result(input) { + Ok(result) => visit::Visit::visit_item_const(&mut actual, &result), + Err(err) => actual.0.push(err.to_string()), + } + + assert!(actual.contains(expected), "EXPECTED: {expected}...\nACTUAL: {actual:?}"); +} + +macro_rules! expect { + ({$($input:tt)*} => {$($output:tt)*} $($rest:tt)*) => { + expect_success(parse_quote! { $($input)* }, parse_quote! { $($output)* }); + expect! { $($rest)* } + }; + ({$($input:tt)*} => $msg:literal $($rest:tt)*) => { + expect_failure(parse_quote! { $($input)* }, $msg); + expect! { $($rest)* } + }; + () => {}; +} + +#[test] +fn interesting_fields_are_constrained() { + expect! { + { + struct SomethingInteresting<'a, 'tcx, T>( + T, + T::Assoc, + Const<'tcx>, + Complex<'tcx, T>, + Generic, + Trivial, + TrivialGeneric<'a, Foo>, + ); + } => { + impl<'a, 'tcx, T> TypeFoldable> for SomethingInteresting<'a, 'tcx, T> + where + Complex<'tcx, T>: TypeFoldable>, + Generic: TypeFoldable>, + Self: TypeVisitable>, + T: TypeFoldable>, + T::Assoc: TypeFoldable> + { + fn try_fold_with<_T: FallibleTypeFolder>>(self, folder: &mut _T) -> Result { + Ok(match self { + SomethingInteresting (__binding_0, __binding_1, __binding_2, __binding_3, __binding_4, __binding_5, __binding_6,) => { SomethingInteresting( + noop_if_trivially_traversable!(__binding_0.try_fold_with::< TyCtxt<'tcx> >(folder))?, + noop_if_trivially_traversable!(__binding_1.try_fold_with::< TyCtxt<'tcx> >(folder))?, + noop_if_trivially_traversable!(__binding_2.try_fold_with::< TyCtxt<'tcx> >(folder))?, + noop_if_trivially_traversable!(__binding_3.try_fold_with::< TyCtxt<'tcx> >(folder))?, + noop_if_trivially_traversable!(__binding_4.try_fold_with::< TyCtxt<'tcx> >(folder))?, + __binding_5, + __binding_6, + )} + }) + } + } + } + } +} + +#[test] +fn skipping_trivial_type_requires_justification() { + expect! { + { + struct NothingInteresting<'a>; + } => "Traversal of trivial types are no-ops by default" + + { + #[skip_traversal()] + struct NothingInteresting<'a>; + } => "Traversal of trivial types are no-ops by default" + + { + #[skip_traversal(but_impl_despite_trivial_because = ".", despite_potential_miscompilation_because = ".")] + struct NothingInteresting<'a>; + } => { + impl<'a, I: Interner> TypeFoldable for NothingInteresting<'a> { + fn try_fold_with>(self, folder: &mut T) -> Result { + Ok(self) // no attempt to fold + } + } + } + + { + #[skip_traversal(but_impl_despite_trivial_because = ".")] + struct NothingInteresting<'a>; + } => { + impl<'a, I: Interner> TypeFoldable for NothingInteresting<'a> + where + I: TriviallyTraverses // impl only applies when type actually contains nothing interesting + { + fn try_fold_with>(self, folder: &mut T) -> Result { + Ok(self) // no attempt to fold + } + } + } + } +} + +#[test] +fn skipping_interesting_type_requires_justification() { + expect! { + { + #[skip_traversal()] + struct SomethingInteresting<'tcx>; + } => "Justification must be provided for skipping this potentially interesting type" + + { + #[skip_traversal(because_trivial)] + struct SomethingInteresting<'tcx>; + } => "unsupported skip reason" + + { + #[skip_traversal(despite_potential_miscompilation_because = ".")] + struct SomethingInteresting<'tcx>; + } => { + impl<'tcx> TypeFoldable> for SomethingInteresting<'tcx> { + fn try_fold_with>>(self, folder: &mut T) -> Result { + Ok(self) // no attempt to fold fields + } + } + } + } +} + +#[test] +fn skipping_interesting_field_requires_justification() { + expect! { + { + struct SomethingInteresting<'tcx>( + #[skip_traversal()] + Const<'tcx>, + ); + } => "Justification must be provided for skipping potentially interesting fields" + + { + struct SomethingInteresting<'tcx>( + #[skip_traversal(because_trivial)] + Const<'tcx>, + ); + } => "unsupported skip reason" + + { + struct SomethingInteresting<'tcx>( + #[skip_traversal(despite_potential_miscompilation_because = ".")] + Const<'tcx>, + ); + } => { + impl<'tcx> TypeFoldable> for SomethingInteresting<'tcx> { + fn try_fold_with>>(self, folder: &mut T) -> Result { + Ok(match self { + SomethingInteresting(__binding_0,) => { SomethingInteresting(__binding_0,) } // not folded + }) + } + } + } + } +} + +#[test] +fn skipping_generic_type_requires_justification() { + expect! { + { + #[skip_traversal()] + struct SomethingInteresting; + } => "Justification must be provided for skipping this potentially interesting type" + + { + #[skip_traversal(despite_potential_miscompilation_because = ".")] + struct SomethingInteresting; + } => { + impl TypeFoldable for SomethingInteresting + where + Self: TypeVisitable + { + fn try_fold_with<_T: FallibleTypeFolder>(self, folder: &mut _T) -> Result { + Ok(self) // no attempt to fold fields + } + } + } + } +} + +#[test] +fn skipping_generic_field_requires_justification() { + expect! { + { + struct SomethingInteresting( + #[skip_traversal()] + T, + ); + } => "Justification must be provided for skipping potentially interesting fields" + + { + struct SomethingInteresting( + #[skip_traversal(because_trivial)] + T, + ); + } => { + impl TypeFoldable for SomethingInteresting + where + I: TriviallyTraverses, // `because_trivial` + Self: TypeVisitable + { + fn try_fold_with<_T: FallibleTypeFolder>(self, folder: &mut _T) -> Result { + Ok(match self { + SomethingInteresting(__binding_0,) => { SomethingInteresting(__binding_0,) } // not folded + }) + } + } + } + + { + struct SomethingInteresting( + #[skip_traversal(despite_potential_miscompilation_because = ".")] + T, + ); + } => { + impl TypeFoldable for SomethingInteresting + where + Self: TypeVisitable // no constraint on T + { + fn try_fold_with<_T: FallibleTypeFolder>(self, folder: &mut _T) -> Result { + Ok(match self { + SomethingInteresting(__binding_0,) => { SomethingInteresting(__binding_0,) } // not folded + }) + } + } + } + + { + struct SomethingInteresting( + #[skip_traversal(because_trivial)] + T, + T, + ); + } => "This annotation only makes sense if all fields of type `T` are annotated identically" + + { + struct SomethingInteresting( + #[skip_traversal(despite_potential_miscompilation_because = ".")] + T, + #[skip_traversal(because_trivial)] + T, + ); + } => "This annotation only makes sense if all fields of type `T` are annotated identically" + } +} diff --git a/compiler/rustc_macros/src/type_foldable.rs b/compiler/rustc_macros/src/type_foldable.rs deleted file mode 100644 index 5ee4d8793135..000000000000 --- a/compiler/rustc_macros/src/type_foldable.rs +++ /dev/null @@ -1,56 +0,0 @@ -use quote::{quote, ToTokens}; -use syn::parse_quote; - -pub fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { - if let syn::Data::Union(_) = s.ast().data { - panic!("cannot derive on union") - } - - if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") { - s.add_impl_generic(parse_quote! { 'tcx }); - } - - s.add_bounds(synstructure::AddBounds::Generics); - s.bind_with(|_| synstructure::BindStyle::Move); - let body_fold = s.each_variant(|vi| { - let bindings = vi.bindings(); - vi.construct(|_, index| { - let bind = &bindings[index]; - - let mut fixed = false; - - // retain value of fields with #[type_foldable(identity)] - bind.ast().attrs.iter().for_each(|x| { - if !x.path().is_ident("type_foldable") { - return; - } - let _ = x.parse_nested_meta(|nested| { - if nested.path.is_ident("identity") { - fixed = true; - } - Ok(()) - }); - }); - - 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 dcd505a105e5..000000000000 --- a/compiler/rustc_macros/src/type_visitable.rs +++ /dev/null @@ -1,52 +0,0 @@ -use quote::quote; -use syn::parse_quote; - -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| { - let mut ignored = false; - - bi.ast().attrs.iter().for_each(|attr| { - if !attr.path().is_ident("type_visitable") { - return; - } - let _ = attr.parse_nested_meta(|nested| { - if nested.path.is_ident("ignore") { - ignored = true; - } - Ok(()) - }); - }); - - !ignored - }); - - 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(()) - } - }, - ) -} diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 354023cea9e0..3c7a8bf6689b 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -663,6 +663,12 @@ impl<'a, 'tcx> Decodable> for Symbol { } } +impl<'a, 'tcx> Decodable> for &'tcx [ty::Spanned>] { + fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { + ty::codec::RefDecodable::decode(d) + } +} + impl<'a, 'tcx> Decodable> for &'tcx [(ty::Clause<'tcx>, Span)] { fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self { ty::codec::RefDecodable::decode(d) @@ -1056,7 +1062,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self, index: DefIndex, tcx: TyCtxt<'tcx>, - ) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { + ) -> ty::EarlyBinder<&'tcx [ty::Spanned>]> { let lazy = self.root.tables.explicit_item_bounds.get(self, index); let output = if lazy.is_default() { &mut [] diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 9ae5c0af0b24..fac558e6374b 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -386,7 +386,7 @@ define_tables! { type_alias_is_lazy: 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>, @@ -462,7 +462,7 @@ define_tables! { trait_impl_trait_tys: Table>>>>, doc_link_resolutions: Table>, doc_link_traits_in_scope: Table>, - assumed_wf_types_for_rpitit: Table, Span)>>, + assumed_wf_types_for_rpitit: Table>>>, } #[derive(TyEncodable, TyDecodable)] diff --git a/compiler/rustc_middle/src/hir/place.rs b/compiler/rustc_middle/src/hir/place.rs index 32f3a177508f..916fd5f3a130 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::{FieldIdx, 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 64b63f4c5eb4..b85d4d52b5db 100644 --- a/compiler/rustc_middle/src/infer/canonical.rs +++ b/compiler/rustc_middle/src/infer/canonical.rs @@ -364,11 +364,6 @@ impl<'tcx, R> QueryResponse<'tcx, R> { pub type QueryOutlivesConstraint<'tcx> = (ty::OutlivesPredicate, Region<'tcx>>, ConstraintCategory<'tcx>); -TrivialTypeTraversalImpls! { - crate::infer::canonical::Certainty, - crate::infer::canonical::CanonicalTyVarKind, -} - impl<'tcx> CanonicalVarValues<'tcx> { // Given a list of canonical variables, construct a set of values which are // the identity response. diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 448a3029ae97..25a102f9bb16 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -64,6 +64,7 @@ #![feature(trait_alias)] #![feature(ptr_alignment_type)] #![feature(macro_metavar_expr)] +#![feature(auto_traits)] #![recursion_limit = "512"] #![allow(rustc::potential_query_instability)] #![allow(internal_features)] diff --git a/compiler/rustc_middle/src/macros.rs b/compiler/rustc_middle/src/macros.rs index c1884bb8068d..9f84e0754c2e 100644 --- a/compiler/rustc_middle/src/macros.rs +++ b/compiler/rustc_middle/src/macros.rs @@ -54,48 +54,3 @@ macro_rules! TrivialLiftImpls { )+ }; } - -/// 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 { - ($($ty:ty),+ $(,)?) => { - $( - impl<'tcx> $crate::ty::fold::TypeFoldable<$crate::ty::TyCtxt<'tcx>> for $ty { - fn try_fold_with>>( - self, - _: &mut F, - ) -> ::std::result::Result { - Ok(self) - } - - #[inline] - fn fold_with>>( - self, - _: &mut F, - ) -> Self { - self - } - } - - impl<'tcx> $crate::ty::visit::TypeVisitable<$crate::ty::TyCtxt<'tcx>> for $ty { - #[inline] - fn visit_with>>( - &self, - _: &mut F) - -> ::std::ops::ControlFlow - { - ::std::ops::ControlFlow::Continue(()) - } - } - )+ - }; -} - -#[macro_export] -macro_rules! TrivialTypeTraversalAndLiftImpls { - ($($t:tt)*) => { - TrivialTypeTraversalImpls! { $($t)* } - TrivialLiftImpls! { $($t)* } - } -} diff --git a/compiler/rustc_middle/src/mir/basic_blocks.rs b/compiler/rustc_middle/src/mir/basic_blocks.rs index 3ecd5b9cd345..739d8926a3e8 100644 --- a/compiler/rustc_middle/src/mir/basic_blocks.rs +++ b/compiler/rustc_middle/src/mir/basic_blocks.rs @@ -181,8 +181,6 @@ impl<'tcx> graph::WithPredecessors for BasicBlocks<'tcx> { } } -TrivialTypeTraversalImpls! { Cache } - impl Encodable for Cache { #[inline] fn encode(&self, _s: &mut S) {} diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 08d377a8695f..beae8b942942 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -53,7 +53,7 @@ impl ExpressionId { /// but the zero/counter/expression distinction is also useful for representing /// the value of code/gap mappings, and the true/false arms of branch mappings. #[derive(Copy, Clone, PartialEq, Eq)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub enum CovTerm { Zero, Counter(CounterId), @@ -70,7 +70,7 @@ impl Debug for CovTerm { } } -#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(Clone, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] pub enum CoverageKind { /// Marks the point in MIR control flow represented by a coverage counter. /// @@ -102,7 +102,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, @@ -122,7 +121,6 @@ impl Debug for CodeRegion { } #[derive(Copy, Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub enum Op { Subtract, Add, @@ -139,7 +137,7 @@ impl Op { } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct Expression { pub lhs: CovTerm, pub op: Op, @@ -147,7 +145,7 @@ pub struct Expression { } #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct Mapping { pub code_region: CodeRegion, @@ -164,7 +162,7 @@ pub struct Mapping { /// to be used in conjunction with the individual coverage statements injected /// into the function's basic blocks. #[derive(Clone, Debug)] -#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable)] pub struct FunctionCoverageInfo { pub function_source_hash: u64, pub num_counters: usize, diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 44b22e2d3838..8c1cd0b54b15 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -82,8 +82,6 @@ impl Into for ReportedErrorInfo { } } -TrivialTypeTraversalImpls! { ErrorHandled } - pub type EvalToAllocationRawResult<'tcx> = Result, ErrorHandled>; pub type EvalToConstValueResult<'tcx> = Result, ErrorHandled>; /// `Ok(None)` indicates the constant was fine, but the valtree couldn't be constructed. diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 7054cede2d87..fe47c26ab905 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -11,7 +11,7 @@ use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::visit::TypeVisitableExt; use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, UserTypeAnnotationIndex}; -use crate::ty::{GenericArg, GenericArgsRef}; +use crate::ty::{GenericArg, GenericArgsRef, Spanned}; use rustc_data_structures::captures::Captures; use rustc_errors::{DiagnosticArgValue, DiagnosticMessage, ErrorGuaranteed, IntoDiagnosticArg}; @@ -593,13 +593,13 @@ impl<'tcx> Body<'tcx> { loop { let scope_data = &self.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 from_span(source_info.span); } - source_info.span = callsite_span; + source_info.span = callee.span; } // Skip past all of the parents with `inlined: None`. @@ -759,7 +759,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, @@ -776,12 +776,16 @@ 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)>, + // FIXME: provide actual justification for `#[skip_traversal]`, or else remove + #[skip_traversal( + despite_potential_miscompilation_because = "potential oversight since 0193d1f" + )] + pub opt_match_place: Option>>>, /// The span of the pattern in which this variable was bound. 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>), @@ -791,7 +795,7 @@ pub enum BindingForm<'tcx> { RefForGuard, } -TrivialTypeTraversalImpls! { BindingForm<'tcx> } +TrivialLiftImpls! { BindingForm<'tcx> } mod binding_form_impl { use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -1340,10 +1344,10 @@ impl SourceScope { source_scopes: &IndexSlice>, ) -> 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 } @@ -1358,7 +1362,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` @@ -1410,7 +1414,7 @@ pub struct SourceScopeLocalData { /// 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)>, } @@ -1473,6 +1477,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, @@ -1489,7 +1497,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/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index debd85dad2e0..863239729784 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -415,14 +415,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) @@ -680,7 +684,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!( @@ -703,7 +707,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 mir::Coverage { ref kind }) => write!(fmt, "Coverage::{kind:?}"), diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 0540eb0efd6c..7be6ecc417cb 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -165,8 +165,6 @@ pub struct CoroutineLayout<'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, } @@ -376,7 +374,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(FieldIdx), @@ -401,14 +399,16 @@ pub enum ClosureOutlivesSubject<'tcx> { /// This abstraction is necessary because the type may include `ReVar` regions, /// which is what we use internally within NLL code, and they can't be used in /// a query response. -/// -/// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this -/// type is not recognized as a binder for late-bound region. #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub struct ClosureOutlivesSubjectTy<'tcx> { inner: Ty<'tcx>, } +/// DO NOT implement `TypeVisitable` or `TypeFoldable` traits, because this +/// type is not recognized as a binder for late-bound region. +impl<'tcx, I> !ty::TypeFoldable for ClosureOutlivesSubjectTy<'tcx> {} +impl<'tcx, I> !ty::TypeVisitable for ClosureOutlivesSubjectTy<'tcx> {} + impl<'tcx> ClosureOutlivesSubjectTy<'tcx> { /// All regions of `ty` must be of kind `ReVar` and must represent /// universal regions *external* to the closure. diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index b6543affc6db..ed567c61b3a9 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, Const, Local, UserTypeProjection}; +use super::{AscribeUserType, BasicBlock, Const, Local}; use crate::mir::coverage::CoverageKind; use crate::traits::Reveal; @@ -288,7 +288,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. /// @@ -359,7 +359,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), /// Carries control-flow-sensitive information injected by `-Cinstrument-coverage`, /// such as where to generate physical coverage-counter-increments during codegen. @@ -459,6 +459,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 { @@ -516,7 +520,6 @@ pub enum FakeReadCause { } #[derive(Clone, Debug, PartialEq, TyEncodable, TyDecodable, Hash, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub struct Coverage { pub kind: CoverageKind, } @@ -532,7 +535,6 @@ pub struct CopyNonOverlapping<'tcx> { /// Represents how a `TerminatorKind::Call` was constructed, used for diagnostics #[derive(Clone, Copy, TyEncodable, TyDecodable, Debug, PartialEq, Hash, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub enum CallSource { /// This came from something such as `a > b` or `a + b`. In THIR, if `from_hir_call` /// is false then this is the desugaring. @@ -846,7 +848,6 @@ pub struct SwitchTargets { /// Action to be taken when a stack unwind happens. #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub enum UnwindAction { /// No action is to be taken. Continue unwinding. /// @@ -865,7 +866,6 @@ pub enum UnwindAction { /// The reason we are terminating the process during unwinding. #[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] -#[derive(TypeFoldable, TypeVisitable)] pub enum UnwindTerminateReason { /// Unwinding is just not possible given the ABI of this function. Abi, @@ -1033,7 +1033,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. - Index(V), + Index(#[skip_traversal(because_trivial)] V), /// These indices are generated by slice patterns. Easiest to explain /// by example: @@ -1358,7 +1358,7 @@ pub enum NullOp<'tcx> { } #[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, @@ -1367,7 +1367,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 d5c81b6cd793..1dedd3f587ef 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -1,51 +1,8 @@ //! `TypeFoldable` implementations for MIR types -use rustc_ast::InlineAsmTemplatePiece; - use super::*; use crate::ty; -TrivialTypeTraversalImpls! { - BlockTailInfo, - MirPhase, - SourceInfo, - FakeReadCause, - RetagKind, - SourceScope, - SourceScopeLocalData, - UserTypeAnnotationIndex, - BorrowKind, - CastKind, - hir::Movability, - BasicBlock, - SwitchTargets, - CoroutineKind, - CoroutineSavedLocal, -} - -TrivialTypeTraversalImpls! { - ConstValue<'tcx>, - NullOp<'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/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 0f0ca3a1420e..2edbb2e88132 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -332,7 +332,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); @@ -379,7 +379,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), @@ -425,7 +425,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_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index 113763450529..7c23891e80f8 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -335,6 +335,14 @@ impl<'tcx> Key for (DefId, GenericArgsRef<'tcx>) { } } +impl<'tcx> Key for ty::InstanceOfArg<'tcx> { + type CacheSelector = DefaultCacheSelector; + + 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; diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index f9ec368361c5..7514c21304a6 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -365,7 +365,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) -> ty::EarlyBinder<&'tcx [(ty::Clause<'tcx>, Span)]> { + query explicit_item_bounds(key: DefId) -> ty::EarlyBinder<&'tcx [ty::Spanned>]> { desc { |tcx| "finding item bounds for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } separate_provide_extern @@ -884,13 +884,13 @@ rustc_queries! { /// /// Note that we've liberated the late bound regions of function signatures, so /// this can not be used to check whether these types are well formed. - query assumed_wf_types(key: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { + query assumed_wf_types(key: LocalDefId) -> &'tcx [ty::Spanned>] { desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } } /// We need to store the assumed_wf_types for an RPITIT so that impls of foreign /// traits with return-position impl trait in traits can inherit the right wf types. - query assumed_wf_types_for_rpitit(key: DefId) -> &'tcx [(Ty<'tcx>, Span)] { + query assumed_wf_types_for_rpitit(key: DefId) -> &'tcx [ty::Spanned>] { desc { |tcx| "computing the implied bounds of `{}`", tcx.def_path_str(key) } separate_provide_extern } @@ -2103,7 +2103,7 @@ 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, GenericArgsRef<'tcx>)> + key: ty::ParamEnvAnd<'tcx, ty::InstanceOfArg<'tcx>> ) -> Result>, ErrorGuaranteed> { desc { "resolving instance `{}`", ty::Instance::new(key.value.0, key.value.1) } } diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 280f5d0a84ca..c1257400e808 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -794,6 +794,13 @@ impl<'a, 'tcx> Decodable> } } +impl<'a, 'tcx> Decodable> for &'tcx [ty::Spanned>] { + #[inline] + fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { + RefDecodable::decode(d) + } +} + impl<'a, 'tcx> Decodable> for &'tcx [(ty::Clause<'tcx>, Span)] { #[inline] fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 3086082fe8d5..334be2959612 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -721,9 +721,7 @@ pub enum PatKind<'tcx> { Binding { mutability: Mutability, name: Symbol, - #[type_visitable(ignore)] mode: BindingMode, - #[type_visitable(ignore)] var: LocalVarId, ty: Ty<'tcx>, subpattern: Option>>, @@ -818,7 +816,6 @@ pub enum PatKind<'tcx> { pub struct PatRange<'tcx> { pub lo: PatRangeBoundary<'tcx>, pub hi: PatRangeBoundary<'tcx>, - #[type_visitable(ignore)] pub end: RangeEnd, pub ty: Ty<'tcx>, } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 6cd75e087276..5ed16324541d 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -13,7 +13,7 @@ use crate::infer::canonical::Canonical; use crate::mir::ConstraintCategory; use crate::ty::abstract_const::NotConstEvaluatable; use crate::ty::GenericArgsRef; -use crate::ty::{self, AdtKind, Ty}; +use crate::ty::{self, AdtKind, Spanned, Ty}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, Diagnostic}; @@ -411,7 +411,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, hir::MatchSource), @@ -471,7 +471,7 @@ pub enum IsConstable { Ctor, } -crate::TrivialTypeTraversalAndLiftImpls! { +crate::TrivialLiftImpls! { IsConstable, } @@ -480,7 +480,6 @@ crate::TrivialTypeTraversalAndLiftImpls! { /// 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), @@ -757,8 +756,6 @@ pub enum BuiltinImplSource { TupleUnsizing, } -TrivialTypeTraversalImpls! { BuiltinImplSource } - #[derive(Clone, Debug, PartialEq, Eq, Hash, HashStable, PartialOrd, Ord)] pub enum ObjectSafetyViolation { /// `Self: Sized` declared on the trait. @@ -956,7 +953,7 @@ pub enum CodegenObligationError { FulfillmentError, } -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable)] pub enum DefiningAnchor { /// `DefId` of the item. Bind(LocalDefId), diff --git a/compiler/rustc_middle/src/traits/select.rs b/compiler/rustc_middle/src/traits/select.rs index f33421bbaa6c..6b7f2332093b 100644 --- a/compiler/rustc_middle/src/traits/select.rs +++ b/compiler/rustc_middle/src/traits/select.rs @@ -309,8 +309,6 @@ impl From for OverflowError { } } -TrivialTypeTraversalImpls! { OverflowError } - impl<'tcx> From for SelectionError<'tcx> { fn from(overflow_error: OverflowError) -> SelectionError<'tcx> { match overflow_error { diff --git a/compiler/rustc_middle/src/traits/solve.rs b/compiler/rustc_middle/src/traits/solve.rs index 27a1e64a78bd..0c6bf273ee23 100644 --- a/compiler/rustc_middle/src/traits/solve.rs +++ b/compiler/rustc_middle/src/traits/solve.rs @@ -1,14 +1,9 @@ -use std::ops::ControlFlow; - use rustc_data_structures::intern::Interned; use crate::infer::canonical::{CanonicalVarValues, QueryRegionConstraints}; use crate::traits::query::NoSolution; use crate::traits::{Canonical, DefiningAnchor}; -use crate::ty::{ - self, FallibleTypeFolder, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeVisitable, - TypeVisitor, -}; +use crate::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_span::def_id::DefId; use super::BuiltinImplSource; @@ -52,7 +47,7 @@ pub struct Response<'tcx> { pub external_constraints: ExternalConstraints<'tcx>, } -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable)] pub enum Certainty { Yes, Maybe(MaybeCause), @@ -92,7 +87,7 @@ impl Certainty { } /// Why we failed to evaluate a goal. -#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable, TypeFoldable, TypeVisitable)] +#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash, HashStable)] pub enum MaybeCause { /// We failed due to ambiguity. This ambiguity can either /// be a true ambiguity, i.e. there are multiple different answers, @@ -110,12 +105,12 @@ pub struct QueryInput<'tcx, T> { } /// Additional constraints returned on success. -#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default)] +#[derive(Debug, PartialEq, Eq, Clone, Hash, HashStable, Default, TypeVisitable, TypeFoldable)] pub struct PredefinedOpaquesData<'tcx> { pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>, } -#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable, TypeVisitable, TypeFoldable)] pub struct PredefinedOpaques<'tcx>(pub(crate) Interned<'tcx, PredefinedOpaquesData<'tcx>>); impl<'tcx> std::ops::Deref for PredefinedOpaques<'tcx> { @@ -138,7 +133,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, HashStable)] +#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash, HashStable, TypeFoldable, TypeVisitable)] pub struct ExternalConstraints<'tcx>(pub(crate) Interned<'tcx, ExternalConstraintsData<'tcx>>); impl<'tcx> std::ops::Deref for ExternalConstraints<'tcx> { @@ -157,82 +152,6 @@ pub struct ExternalConstraintsData<'tcx> { pub opaque_types: Vec<(ty::OpaqueTypeKey<'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(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(), - }) - } -} - -impl<'tcx> TypeVisitable> for ExternalConstraints<'tcx> { - fn visit_with>>( - &self, - visitor: &mut V, - ) -> std::ops::ControlFlow { - self.region_constraints.visit_with(visitor)?; - self.opaque_types.visit_with(visitor)?; - ControlFlow::Continue(()) - } -} - -// 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 PredefinedOpaques<'tcx> { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - Ok(FallibleTypeFolder::interner(folder).mk_predefined_opaques_in_body( - PredefinedOpaquesData { - 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_predefined_opaques_in_body(PredefinedOpaquesData { - opaque_types: self.opaque_types.iter().map(|opaque| opaque.fold_with(folder)).collect(), - }) - } -} - -impl<'tcx> TypeVisitable> for PredefinedOpaques<'tcx> { - fn visit_with>>( - &self, - visitor: &mut V, - ) -> std::ops::ControlFlow { - self.opaque_types.visit_with(visitor) - } -} - #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, HashStable)] pub enum IsNormalizesToHack { Yes, diff --git a/compiler/rustc_middle/src/traits/util.rs b/compiler/rustc_middle/src/traits/util.rs index b4054f8ff5ed..12934040d241 100644 --- a/compiler/rustc_middle/src/traits/util.rs +++ b/compiler/rustc_middle/src/traits/util.rs @@ -26,7 +26,7 @@ impl<'tcx> Elaborator<'tcx> { .super_predicates_of(trait_ref.def_id()) .predicates .into_iter() - .flat_map(|(pred, _)| pred.subst_supertrait(self.tcx, &trait_ref).as_trait_clause()) + .flat_map(|pred| pred.node.subst_supertrait(self.tcx, &trait_ref).as_trait_clause()) .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/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index 570f896ba299..caf3b30268cb 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -6,7 +6,7 @@ use crate::ty::{ use rustc_errors::ErrorGuaranteed; #[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, @@ -27,8 +27,6 @@ impl From for NotConstEvaluatable { } } -TrivialTypeTraversalImpls! { NotConstEvaluatable } - pub type BoundAbstractConst<'tcx> = Result>>, ErrorGuaranteed>; impl<'tcx> TyCtxt<'tcx> { diff --git a/compiler/rustc_middle/src/ty/binding.rs b/compiler/rustc_middle/src/ty/binding.rs index af594bc5f24c..0bbfe82d3731 100644 --- a/compiler/rustc_middle/src/ty/binding.rs +++ b/compiler/rustc_middle/src/ty/binding.rs @@ -6,8 +6,6 @@ pub enum BindingMode { BindByValue(Mutability), } -TrivialTypeTraversalImpls! { BindingMode } - impl BindingMode { pub fn convert(BindingAnnotation(by_ref, mutbl): BindingAnnotation) -> BindingMode { match by_ref { diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 74bdd07a1c94..17efeeed9599 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -23,7 +23,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, } @@ -32,7 +31,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, @@ -47,7 +45,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 @@ -80,7 +77,10 @@ pub type MinCaptureList<'tcx> = Vec>; /// You can get the environment type of a closure using /// `tcx.closure_env_ty()`. #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] +#[skip_traversal( + but_impl_despite_trivial_because = "traversed generically in `rustc_type_ir::PredicateKind`" +)] pub enum ClosureKind { // Warning: Ordering is significant here! The ordering is chosen // because the trait Fn is a subtrait of FnMut and so in turn, and @@ -314,7 +314,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 /// @@ -393,7 +392,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/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 8b67e39667b8..5a8e2234e7dd 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -367,6 +367,17 @@ impl<'tcx, D: TyDecoder>> Decodable for AdtDef<'tcx> { } } +impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> + for [ty::Spanned>] +{ + fn decode(decoder: &mut D) -> &'tcx Self { + decoder + .interner() + .arena + .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder))) + } +} + impl<'tcx, D: TyDecoder>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] { fn decode(decoder: &mut D) -> &'tcx Self { decoder diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 4af841fcf9a5..7a8d7b0783a9 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -80,6 +80,10 @@ static_assert_size!(super::ConstKind<'_>, 32); /// An inference variable for a const, for use in const generics. #[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Hash)] +#[derive(TypeFoldable, TypeVisitable)] +#[skip_traversal( + but_impl_despite_trivial_because = "traversed generically in `rustc_type_ir::ConstKind`" +)] pub enum InferConst { /// Infer the value of the const. Var(ty::ConstVid), diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index fb7bf78bafe3..4fcce0eb9d3b 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -17,6 +17,7 @@ use rustc_macros::{HashStable, TyDecodable, TyEncodable}; /// /// `ValTree` does not have this problem with representation, as it only contains integers or /// lists of (nested) `ValTree`. +#[derive(TypeFoldable, TypeVisitable)] pub enum ValTree<'tcx> { /// integers, `bool`, `char` are represented as scalars. /// See the `ScalarInt` documentation for how `ScalarInt` guarantees that equal values diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 551c4a15dd0d..e4da89347889 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -34,7 +34,7 @@ use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; use rustc_ast::{self as ast, attr}; 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::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -67,7 +67,7 @@ use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx} use rustc_target::spec::abi; use rustc_type_ir::TyKind::*; use rustc_type_ir::WithCachedTypeInfo; -use rustc_type_ir::{CollectAndApply, Interner, TypeFlags}; +use rustc_type_ir::{CollectAndApply, Interner, TriviallyTraverses, TypeFlags}; use std::any::Any; use std::borrow::Borrow; @@ -135,6 +135,22 @@ impl<'tcx> Interner for TyCtxt<'tcx> { } } +/// 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. +/// +/// 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 TriviallyTraversable {} +impl TriviallyTraverses for TyCtxt<'_> {} + +impl !TriviallyTraversable for Binder<'_, T> {} +impl !TriviallyTraversable for Ty<'_> {} +impl !TriviallyTraversable for ty::Const<'_> {} +impl !TriviallyTraversable for Region<'_> {} +impl !TriviallyTraversable for Predicate<'_> {} + type InternedSet<'tcx, T> = ShardedHashMap, ()>; pub struct CtxtInterners<'tcx> { @@ -1533,11 +1549,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)) } })+ } @@ -1619,8 +1641,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).skip_binder().iter().any(|&(predicate, _)| { - let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() else { + self.explicit_item_bounds(def_id).skip_binder().iter().any(|&predicate| { + let ty::ClauseKind::Trait(trait_predicate) = predicate.node.kind().skip_binder() else { return false; }; trait_predicate.trait_ref.def_id == future_trait @@ -1642,8 +1664,8 @@ impl<'tcx> TyCtxt<'tcx> { let trait_did = stack.pop()?; let generic_predicates = self.super_predicates_of(trait_did); - for (predicate, _) in generic_predicates.predicates { - if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder() { + for predicate in generic_predicates.predicates { + if let ty::ClauseKind::Trait(data) = predicate.node.kind().skip_binder() { if set.insert(data.def_id()) { stack.push(data.def_id()); } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 00529a1e066c..af558ef3c53e 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -4,7 +4,10 @@ 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, TypeFoldable, TypeFolder, TypeSuperFoldable}, + Interner, +}; /////////////////////////////////////////////////////////////////////////// // Some sample folders diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs index 41a1bf04e5f3..b7518c1f8492 100644 --- a/compiler/rustc_middle/src/ty/generic_args.rs +++ b/compiler/rustc_middle/src/ty/generic_args.rs @@ -47,6 +47,7 @@ const REGION_TAG: usize = 0b01; const CONST_TAG: usize = 0b10; #[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)] +#[derive(Clone, TypeFoldable, TypeVisitable)] pub enum GenericArgKind<'tcx> { Lifetime(ty::Region<'tcx>), Type(Ty<'tcx>), @@ -210,21 +211,13 @@ impl<'tcx> TypeFoldable> for GenericArg<'tcx> { self, folder: &mut F, ) -> Result { - match self.unpack() { - GenericArgKind::Lifetime(lt) => lt.try_fold_with(folder).map(Into::into), - GenericArgKind::Type(ty) => ty.try_fold_with(folder).map(Into::into), - GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into), - } + self.unpack().try_fold_with(folder).map(GenericArgKind::pack) } } impl<'tcx> TypeVisitable> for GenericArg<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - match self.unpack() { - GenericArgKind::Lifetime(lt) => lt.visit_with(visitor), - GenericArgKind::Type(ty) => ty.visit_with(visitor), - GenericArgKind::Const(ct) => ct.visit_with(visitor), - } + self.unpack().visit_with(visitor) } } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 888ee1d237ae..75dc15cf6347 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::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt}; +use super::{ + Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Spanned, Ty, TyCtxt, +}; #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] pub enum GenericParamDefKind { @@ -362,7 +364,7 @@ impl<'tcx> Generics { #[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)] pub struct GenericPredicates<'tcx> { pub parent: Option, - pub predicates: &'tcx [(Clause<'tcx>, Span)], + pub predicates: &'tcx [Spanned>], } impl<'tcx> GenericPredicates<'tcx> { @@ -380,7 +382,7 @@ impl<'tcx> GenericPredicates<'tcx> { &self, tcx: TyCtxt<'tcx>, args: GenericArgsRef<'tcx>, - ) -> impl Iterator, Span)> + DoubleEndedIterator + ExactSizeIterator { + ) -> impl Iterator>> + DoubleEndedIterator + ExactSizeIterator { EarlyBinder::bind(self.predicates).iter_instantiated_copied(tcx, args) } @@ -395,9 +397,9 @@ impl<'tcx> GenericPredicates<'tcx> { tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, args); } instantiated.predicates.extend( - self.predicates.iter().map(|(p, _)| EarlyBinder::bind(*p).instantiate(tcx, args)), + self.predicates.iter().map(|p| EarlyBinder::bind(p.node).instantiate(tcx, args)), ); - instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp)); + instantiated.spans.extend(self.predicates.iter().map(|p| p.span)); } pub fn instantiate_identity(&self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx> { @@ -414,7 +416,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/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index cebefbccc11d..735f58d1702f 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -334,6 +334,9 @@ impl<'tcx> fmt::Display for Instance<'tcx> { } } +#[derive(Clone, Copy, Debug, Eq, Hash, HashStable, PartialEq, TypeFoldable, TypeVisitable)] +pub struct InstanceOfArg<'tcx>(pub DefId, pub GenericArgsRef<'tcx>); + impl<'tcx> Instance<'tcx> { pub fn new(def_id: DefId, args: GenericArgsRef<'tcx>) -> Instance<'tcx> { assert!( @@ -400,7 +403,7 @@ impl<'tcx> Instance<'tcx> { // below is more likely to ignore the bounds in scope (e.g. if the only // generic parameters mentioned by `args` were lifetime ones). let args = tcx.erase_regions(args); - tcx.resolve_instance(tcx.erase_regions(param_env.and((def_id, args)))) + tcx.resolve_instance(tcx.erase_regions(param_env.and(InstanceOfArg(def_id, args)))) } pub fn expect_resolve( diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 4f9c9d85763a..28d4a2dc5bd5 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -45,6 +45,14 @@ extern "C" { type OpaqueListContents; } +// Auto-traits are not automatically implemented for extern types[1], so +// we manually implement it here to ensure that `List`s are automatically +// skipped when appropriate (the `data` field will still ensure the auto +// trait is not implemented for the `List` when it is not appropriate). +// +// [1]: https://github.com/rust-lang/rust/issues/43467#issuecomment-1207257995 +impl super::TriviallyTraversable for OpaqueListContents {} + impl List { /// Returns a reference to the (unique, static) empty list. #[inline(always)] diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e1c616ba0785..4a1709af0336 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -50,6 +50,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, FieldIdx, Integer, IntegerType, VariantIdx}; @@ -88,9 +89,12 @@ pub use self::consts::{ Const, ConstData, ConstInt, Expr, InferConst, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ - tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, + tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TriviallyTraversable, + TyCtxt, TyCtxtFeed, +}; +pub use self::instance::{ + Instance, InstanceDef, InstanceOfArg, ShortInstance, UnusedGenericParams, }; -pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; pub use self::list::List; pub use self::parameterized::ParameterizedOverTcx; pub use self::rvalue_scopes::RvalueScopes; @@ -247,6 +251,9 @@ pub enum ImplSubject<'tcx> { #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] #[derive(TypeFoldable, TypeVisitable)] +#[skip_traversal(but_impl_despite_trivial_because = " + `ImplPolarity` impls `Relate`, which is a subtrait of `TypeFoldable`. +")] pub enum ImplPolarity { /// `impl Trait for Type` Positive, @@ -281,7 +288,6 @@ impl fmt::Display for ImplPolarity { } #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] -#[derive(TypeFoldable, TypeVisitable)] pub enum Asyncness { Yes, No, @@ -302,6 +308,10 @@ pub enum Visibility { } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TyEncodable, TyDecodable)] +#[derive(TypeFoldable, TypeVisitable)] +#[skip_traversal(but_impl_despite_trivial_because = " + `BoundConstness` impls `Relate`, which is a subtrait of `TypeFoldable`. +")] pub enum BoundConstness { /// `T: Trait` NotConst, @@ -1382,27 +1392,34 @@ impl<'tcx> InstantiatedPredicates<'tcx> { } impl<'tcx> IntoIterator for InstantiatedPredicates<'tcx> { - type Item = (Clause<'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((Clause<'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 = (Clause<'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((Clause<'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 }) } } @@ -1510,7 +1527,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> { /// regions/types/consts within the same universe simply have an unknown relationship to one /// another. #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] -#[derive(HashStable, TyEncodable, TyDecodable)] +#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] pub struct Placeholder { pub universe: UniverseIndex, pub bound: T, @@ -1582,16 +1599,23 @@ 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)?, + noop_if_trivially_traversable!( + { self.caller_bounds() }.try_fold_with::>(folder) + )?, + noop_if_trivially_traversable!( + { self.reveal() }.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) + noop_if_trivially_traversable!( + { &self.caller_bounds() }.visit_with::>(visitor) + )?; + noop_if_trivially_traversable!({ &self.reveal() }.visit_with::>(visitor))?; + ControlFlow::Continue(()) } } diff --git a/compiler/rustc_middle/src/ty/parameterized.rs b/compiler/rustc_middle/src/ty/parameterized.rs index 9afa50cf584c..703218dfabcd 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 baf160bcc99d..0cf0e3582939 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>: Printer<'tcx> + fmt::Write { let mut is_sized = false; let mut lifetimes = SmallVec::<[ty::Region<'tcx>; 1]>::new(); - for (predicate, _) in bounds.iter_instantiated_copied(tcx, args) { - let bound_predicate = predicate.kind(); + for predicate in bounds.iter_instantiated_copied(tcx, args) { + let bound_predicate = predicate.node.kind(); match bound_predicate.skip_binder() { ty::ClauseKind::Trait(pred) => { diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 6af68bc5dbab..098a39552ef7 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -9,7 +9,7 @@ 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 rustc_hir::def::Namespace; -use rustc_target::abi::TyAndLayout; +use rustc_span::source_map::Spanned; use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, WithInfcx}; use std::fmt::{self, Debug}; @@ -406,71 +406,16 @@ TrivialLiftImpls! { bool, usize, u64, -} - -// For some things about which the type library does not know, or does not -// provide any traversal implementations, we need to provide a traversal -// implementation (only for TyCtxt<'_> interners). -TrivialTypeTraversalImpls! { - ::rustc_target::abi::FieldIdx, - ::rustc_target::abi::VariantIdx, - crate::middle::region::Scope, - crate::ty::FloatTy, - ::rustc_ast::InlineAsmOptions, - ::rustc_ast::InlineAsmTemplatePiece, - ::rustc_ast::NodeId, - ::rustc_span::symbol::Symbol, - ::rustc_hir::def::Res, - ::rustc_hir::def_id::LocalDefId, - ::rustc_hir::HirId, - ::rustc_hir::MatchSource, - ::rustc_target::asm::InlineAsmRegOrRegClass, - crate::mir::coverage::CounterId, - crate::mir::coverage::ExpressionId, - crate::mir::Local, - crate::mir::Promoted, - 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, - crate::ty::AliasKind, - crate::ty::Placeholder, - crate::ty::Placeholder, - crate::ty::Placeholder, - crate::ty::FreeRegion, - crate::ty::InferTy, - crate::ty::IntVarValue, - crate::ty::adjustment::PointerCoercion, - crate::ty::RegionVid, - crate::ty::Variance, - ::rustc_span::Span, - ::rustc_span::symbol::Ident, - ::rustc_errors::ErrorGuaranteed, - ty::BoundVar, - ty::ValTree<'tcx>, -} -// For some things about which the type library does not know, or does not -// provide any traversal implementations, we need to provide a traversal -// implementation and a lift implementation (the former only for TyCtxt<'_> -// interners). -TrivialTypeTraversalAndLiftImpls! { - ::rustc_hir::def_id::DefId, - ::rustc_hir::Mutability, - ::rustc_hir::Unsafety, - ::rustc_target::spec::abi::Abi, - crate::ty::ClosureKind, - crate::ty::ParamConst, - crate::ty::ParamTy, - interpret::Scalar, - interpret::AllocId, - rustc_target::abi::Size, + ::rustc_hir::def_id::DefId, + ::rustc_hir::Mutability, + ::rustc_hir::Unsafety, + ::rustc_target::spec::abi::Abi, + crate::ty::ClosureKind, + crate::ty::ParamConst, + crate::ty::ParamTy, + interpret::Scalar, + interpret::AllocId, + rustc_target::abi::Size, } /////////////////////////////////////////////////////////////////////////// @@ -499,18 +444,16 @@ impl<'a, 'tcx> Lift<'tcx> for Term<'a> { } } -/////////////////////////////////////////////////////////////////////////// -// Traversal implementations. - -impl<'tcx> TypeVisitable> for ty::AdtDef<'tcx> { - fn visit_with>>( - &self, - _visitor: &mut V, - ) -> ControlFlow { - ControlFlow::Continue(()) +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. + impl<'tcx, T: TypeFoldable>> TypeFoldable> for ty::Binder<'tcx, T> { fn try_fold_with>>( self, @@ -769,18 +712,7 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { folder: &mut F, ) -> Result { let ty = self.ty().try_fold_with(folder)?; - let kind = match self.kind() { - ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?), - ConstKind::Infer(i) => ConstKind::Infer(i.try_fold_with(folder)?), - ConstKind::Bound(d, b) => { - ConstKind::Bound(d.try_fold_with(folder)?, b.try_fold_with(folder)?) - } - ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?), - ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?), - ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?), - ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?), - ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), - }; + let kind = self.kind().try_fold_with(folder)?; if ty != self.ty() || kind != self.kind() { Ok(folder.interner().mk_ct_from_kind(kind, ty)) } else { @@ -795,51 +727,6 @@ impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { visitor: &mut V, ) -> ControlFlow { self.ty().visit_with(visitor)?; - match self.kind() { - ConstKind::Param(p) => p.visit_with(visitor), - ConstKind::Infer(i) => i.visit_with(visitor), - ConstKind::Bound(d, b) => { - d.visit_with(visitor)?; - b.visit_with(visitor) - } - ConstKind::Placeholder(p) => p.visit_with(visitor), - ConstKind::Unevaluated(uv) => uv.visit_with(visitor), - ConstKind::Value(v) => v.visit_with(visitor), - ConstKind::Error(e) => e.visit_with(visitor), - ConstKind::Expr(e) => e.visit_with(visitor), - } - } -} - -impl<'tcx> TypeFoldable> for InferConst { - fn try_fold_with>>( - self, - _folder: &mut F, - ) -> Result { - Ok(self) - } -} - -impl<'tcx> TypeVisitable> for InferConst { - fn visit_with>>( - &self, - _visitor: &mut V, - ) -> ControlFlow { - ControlFlow::Continue(()) - } -} - -impl<'tcx> TypeSuperVisitable> for ty::UnevaluatedConst<'tcx> { - fn super_visit_with>>( - &self, - visitor: &mut V, - ) -> ControlFlow { - self.args.visit_with(visitor) - } -} - -impl<'tcx> TypeVisitable> for TyAndLayout<'tcx, Ty<'tcx>> { - fn visit_with>>(&self, visitor: &mut V) -> ControlFlow { - visitor.visit_ty(self.ty) + self.kind().visit_with(visitor) } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 44592b10d557..3a9bef553799 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1445,7 +1445,10 @@ impl<'tcx> ParamTy { } #[derive(Copy, Clone, Hash, TyEncodable, TyDecodable, Eq, PartialEq, Ord, PartialOrd)] -#[derive(HashStable)] +#[derive(HashStable, TypeFoldable, TypeVisitable)] +#[skip_traversal( + but_impl_despite_trivial_because = "traversed generically in `rustc_type_ir::ConstKind`" +)] pub struct ParamConst { pub index: u32, pub name: Symbol, @@ -1618,7 +1621,8 @@ impl Atom for RegionVid { } rustc_index::newtype_index! { - #[derive(HashStable)] + #[derive(HashStable, TypeFoldable, TypeVisitable)] + #[skip_traversal(but_impl_despite_trivial_because = "traversed generically in `rustc_type_ir::ConstKind`")] #[debug_format = "{}"] pub struct BoundVar {} } diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 8fc5c0302778..90711b435296 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -5,7 +5,10 @@ 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::{TypeSuperVisitable, TypeVisitable, TypeVisitor}, + Interner, +}; pub trait TypeVisitableExt<'tcx>: TypeVisitable> { /// Returns `true` if `self` has any late-bound regions that are either diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index ab4cd24881f6..f2ad5e3df5a0 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -232,7 +232,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, @@ -310,7 +313,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/cfg.rs b/compiler/rustc_mir_build/src/build/cfg.rs index fddcf9de7c7c..d6bcc4ab7e96 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_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index c6a09f6568a5..1f5422b37230 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -482,7 +482,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![] }, )), @@ -509,7 +509,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 a43aae6f4494..640a8415fc5a 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -401,8 +401,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, @@ -586,7 +587,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 @@ -660,7 +664,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, _)), + opt_match_place: Some(ty::Spanned { node: ref mut match_place, .. }), .. })) = **self.local_decls[local].local_info.as_mut().assert_crate_local() else { @@ -697,7 +701,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, @@ -719,7 +723,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, ); }, @@ -1855,7 +1859,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)); @@ -2149,7 +2154,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() }, )), @@ -2271,7 +2276,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 7c729016521b..a5d615d47e1d 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -938,7 +938,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, })) }; @@ -950,7 +950,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_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index ccf3dc7941fe..9765e88c902c 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -376,7 +376,7 @@ impl<'b, 'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> Gatherer<'b, 'a, 'tcx, F> { } 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/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index fc30a718cbb5..9eb84ac2c792 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1848,10 +1848,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).skip_binder() { + for &predicate in tcx.explicit_item_bounds(def).skip_binder() { // We only look at the `DefId`, so it is safe to skip the binder here. if let ty::ClauseKind::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/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 6189e5379ea0..7d4d5fd562d4 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -1,7 +1,7 @@ use rustc_data_structures::captures::Captures; use rustc_middle::mir::{ - self, AggregateKind, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, - TerminatorKind, + self, AggregateKind, FakeReadCause, FakeReadCauseAndPlace, Rvalue, Statement, StatementKind, + Terminator, TerminatorKind, }; use rustc_span::Span; @@ -120,10 +120,10 @@ 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 (FakeReadCause::ForGuardBinding, _)) => None, + StatementKind::FakeRead(box FakeReadCauseAndPlace(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/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index a42eacbf22b4..24eaefa7c1a4 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -171,7 +171,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> { let ty_params = fn_args.types().map(|ty| format!("{ty}")); let const_params = fn_args.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 { " -> _" }; let sugg = format!( diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 793dcf0d994c..44bbfd2531d9 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -889,7 +889,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_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index bf5f0ca7cbd2..236ffc186a6f 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -449,7 +449,7 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> & .predicates_of(body.source.def_id()) .predicates .iter() - .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); + .filter_map(|p| if p.node.is_global() { Some(p.node) } else { None }); if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) { trace!("found unsatisfiable predicates for {:?}", body.source); // Clear the body to only contain a single `unreachable` statement. diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 5aa3c3cfe4dd..9f617886f8b6 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -110,10 +110,10 @@ 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 (_, place)) => Some(place), + | StatementKind::FakeRead(box FakeReadCauseAndPlace(_, place)) => Some(place), StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { Some(local.into()) } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 4bb7e65747f7..0f5b25ef2685 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -115,7 +115,7 @@ trait DefIdVisitor<'tcx> { } fn visit_clauses( &mut self, - clauses: &[(ty::Clause<'tcx>, Span)], + clauses: &[ty::Spanned>], ) -> ControlFlow { self.skeleton().visit_clauses(clauses) } @@ -168,8 +168,11 @@ where } } - fn visit_clauses(&mut self, clauses: &[(ty::Clause<'tcx>, Span)]) -> ControlFlow { - clauses.into_iter().try_for_each(|&(clause, _span)| self.visit_clause(clause)) + fn visit_clauses( + &mut self, + clauses: &[ty::Spanned>], + ) -> ControlFlow { + clauses.into_iter().try_for_each(|&clause| self.visit_clause(clause.node)) } } @@ -1225,8 +1228,8 @@ impl<'tcx> Visitor<'tcx> for TypePrivacyVisitor<'tcx> { self.tcx.types.never, ); - for (clause, _) in bounds.clauses() { - match clause.kind().skip_binder() { + for clause in bounds.clauses() { + match clause.node.kind().skip_binder() { ty::ClauseKind::Trait(trait_predicate) => { if self.visit_trait(trait_predicate.trait_ref).is_break() { return; diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 25bd82bf1ef5..9c20fadf8671 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -166,10 +166,10 @@ impl<'tcx> Context for TablesWrapper<'tcx> { parent: parent.map(|did| tables.trait_def(did)), predicates: predicates .iter() - .map(|(clause, span)| { + .map(|clause| { ( - clause.as_predicate().kind().skip_binder().stable(&mut *tables), - span.stable(&mut *tables), + clause.node.as_predicate().kind().skip_binder().stable(&mut *tables), + clause.span.stable(&mut *tables), ) }) .collect(), @@ -188,10 +188,10 @@ impl<'tcx> Context for TablesWrapper<'tcx> { parent: parent.map(|did| tables.trait_def(did)), predicates: predicates .iter() - .map(|(clause, span)| { + .map(|clause| { ( - clause.as_predicate().kind().skip_binder().stable(&mut *tables), - span.stable(&mut *tables), + clause.node.as_predicate().kind().skip_binder().stable(&mut *tables), + clause.span.stable(&mut *tables), ) }) .collect(), diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index 99de91a068ad..227cc9142a44 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -12,6 +12,7 @@ rustc_data_structures = { path = "../rustc_data_structures" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_serialize = { path = "../rustc_serialize" } +rustc_type_ir = { path = "../rustc_type_ir" } scoped-tls = "1.0" sha1 = "0.10.0" sha2 = "0.10.1" diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index 595babc26ae6..4fd5d4175a01 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -238,7 +238,10 @@ impl Decodable for DefIndex { /// index and a def index. /// /// You can create a `DefId` from a `LocalDefId` using `local_def_id.to_def_id()`. -#[derive(Clone, PartialEq, Eq, Copy)] +#[derive(Clone, PartialEq, Eq, Copy, TypeFoldable, TypeVisitable)] +#[skip_traversal( + but_impl_despite_trivial_because = "traversed generically in `rustc_type_ir::PredicateKind`" +)] // Don't derive order on 64-bit big-endian, so we can be consistent regardless of field order. #[cfg_attr(not(all(target_pointer_width = "64", target_endian = "big")), derive(PartialOrd, Ord))] // On below-64 bit systems we can simply use the derived `Hash` impl diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index fc13bdff36f5..09e17ce93d26 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2247,7 +2247,10 @@ where /// The `()` field is necessary: it is non-`pub`, which means values of this /// type cannot be constructed outside of this crate. #[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)] -#[derive(HashStable_Generic)] +#[derive(HashStable_Generic, TypeFoldable, TypeVisitable)] +#[skip_traversal( + but_impl_despite_trivial_because = "traversed generically in `rustc_type_ir::ConstKind`" +)] pub struct ErrorGuaranteed(()); impl ErrorGuaranteed { diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index dcf346acb334..482f26a8a969 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -68,6 +68,7 @@ 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_target/Cargo.toml b/compiler/rustc_target/Cargo.toml index 94dfeb12dc98..9013f058d3a6 100644 --- a/compiler/rustc_target/Cargo.toml +++ b/compiler/rustc_target/Cargo.toml @@ -14,6 +14,7 @@ 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" } serde_json = "1.0.59" tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_target/src/abi/mod.rs b/compiler/rustc_target/src/abi/mod.rs index b00567e87c65..118cc96ea3a9 100644 --- a/compiler/rustc_target/src/abi/mod.rs +++ b/compiler/rustc_target/src/abi/mod.rs @@ -131,7 +131,7 @@ impl<'a> Layout<'a> { /// 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, PartialEq, Eq, Hash, HashStable_Generic)] +#[derive(Copy, Clone, 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/mod.rs b/compiler/rustc_target/src/spec/abi/mod.rs index 4c1f0c01a041..cdb74397cdee 100644 --- a/compiler/rustc_target/src/spec/abi/mod.rs +++ b/compiler/rustc_target/src/spec/abi/mod.rs @@ -8,7 +8,10 @@ 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)] +#[skip_traversal( + but_impl_despite_trivial_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 diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 667ee3d4e1c6..807c57b5f799 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -22,6 +22,7 @@ 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"] } tracing = "0.1" # tidy-alphabetical-end diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs index 315df06be417..bf879c6343ab 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/select.rs @@ -208,9 +208,9 @@ fn rematch_impl<'tcx>( ); nested.extend( - infcx.tcx.predicates_of(impl_def_id).instantiate(infcx.tcx, args).into_iter().map( - |(pred, _)| Obligation::new(infcx.tcx, ObligationCause::dummy(), goal.param_env, pred), - ), + infcx.tcx.predicates_of(impl_def_id).instantiate(infcx.tcx, args).into_iter().map(|pred| { + Obligation::new(infcx.tcx, ObligationCause::dummy(), goal.param_env, pred.node) + }), ); Ok(Some(ImplSource::UserDefined(ImplSourceUserDefinedData { impl_def_id, args, nested }))) diff --git a/compiler/rustc_trait_selection/src/solve/project_goals/inherent_projection.rs b/compiler/rustc_trait_selection/src/solve/project_goals/inherent_projection.rs index 28fe59b7f6a7..e39ce6cbf537 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals/inherent_projection.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals/inherent_projection.rs @@ -42,7 +42,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { tcx.predicates_of(inherent.def_id) .instantiate(tcx, inherent_substs) .into_iter() - .map(|(pred, _)| goal.with(tcx, pred)), + .map(|pred| goal.with(tcx, pred.node)), ); self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) diff --git a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs index 240141065dcc..926113cb1214 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals/mod.rs @@ -137,7 +137,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ecx.add_goals( tcx.predicates_of(goal.predicate.def_id()) .instantiate_own(tcx, goal.predicate.projection_ty.args) - .map(|(pred, _)| goal.with(tcx, pred)), + .map(|pred| goal.with(tcx, pred.node)), ); then(ecx) @@ -182,7 +182,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> { ecx.add_goals( tcx.predicates_of(goal.predicate.def_id()) .instantiate_own(tcx, goal.predicate.projection_ty.args) - .map(|(pred, _)| goal.with(tcx, pred)), + .map(|pred| goal.with(tcx, pred.node)), ); // In case the associated item is hidden due to specialization, we have to diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index dcf5fd869290..872fb3121c0b 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -152,7 +152,7 @@ fn fresh_impl_header<'tcx>(infcx: &InferCtxt<'tcx>, impl_def_id: DefId) -> ty::I .predicates_of(impl_def_id) .instantiate(tcx, impl_args) .iter() - .map(|(c, _)| c.as_predicate()) + .map(|c| c.node.as_predicate()) .collect(), } } @@ -416,7 +416,7 @@ fn impl_intersection_has_negative_obligation( plug_infer_with_placeholders(infcx, universe, (impl1_header.impl_args, impl2_header.impl_args)); util::elaborate(tcx, tcx.predicates_of(impl2_def_id).instantiate(tcx, impl2_header.impl_args)) - .any(|(clause, _)| try_prove_negated_where_clause(infcx, clause, param_env)) + .any(|clause| try_prove_negated_where_clause(infcx, clause.node, param_env)) } fn plug_infer_with_placeholders<'tcx>( diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs index d9a1a98191d0..6d05d0ddf70c 100644 --- a/compiler/rustc_trait_selection/src/traits/engine.rs +++ b/compiler/rustc_trait_selection/src/traits/engine.rs @@ -229,7 +229,7 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { let tcx = self.infcx.tcx; let mut implied_bounds = FxIndexSet::default(); let mut errors = Vec::new(); - for &(ty, span) in tcx.assumed_wf_types(def_id) { + for &ty in tcx.assumed_wf_types(def_id) { // FIXME(@lcnr): rustc currently does not check wf for types // pre-normalization, meaning that implied bounds are sometimes // incorrect. See #100910 for more details. @@ -242,11 +242,11 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> { // sound and then uncomment this line again. // implied_bounds.insert(ty); - let cause = ObligationCause::misc(span, def_id); + let cause = ObligationCause::misc(ty.span, def_id); match self .infcx .at(&cause, param_env) - .deeply_normalize(ty, &mut **self.engine.borrow_mut()) + .deeply_normalize(ty.node, &mut **self.engine.borrow_mut()) { // Insert well-formed types, ignoring duplicates. Ok(normalized) => drop(implied_bounds.insert(normalized)), diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index 5bc5a12a8fed..3d7e9637d9b1 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -82,8 +82,8 @@ pub fn recompute_applicable_impls<'tcx>( let predicates = tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx); - for (pred, span) in elaborate(tcx, predicates.into_iter()) { - let kind = pred.kind(); + for pred in elaborate(tcx, predicates.into_iter()) { + let kind = pred.node.kind(); if let ty::ClauseKind::Trait(trait_pred) = kind.skip_binder() && param_env_candidate_may_apply(kind.rebind(trait_pred)) { @@ -92,7 +92,7 @@ pub fn recompute_applicable_impls<'tcx>( { ambiguities.push(Ambiguity::ParamEnv(tcx.def_span(trait_pred.def_id()))) } else { - ambiguities.push(Ambiguity::ParamEnv(span)) + ambiguities.push(Ambiguity::ParamEnv(pred.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 6b09bc89873e..035eb07801df 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2038,8 +2038,8 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { // Find another predicate whose self-type is equal to the expected self type, // but whose args don't match. - let other_pred = predicates.into_iter().enumerate().find(|(other_idx, (pred, _))| { - match pred.kind().skip_binder() { + let other_pred = predicates.into_iter().enumerate().find(|(other_idx, pred)| { + match pred.node.kind().skip_binder() { ty::ClauseKind::Trait(trait_pred) if self.tcx.is_fn_trait(trait_pred.def_id()) && other_idx != idx @@ -2047,12 +2047,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 args don't match (i.e. incompatible args) && expected_args != self.tcx.anonymize_bound_vars( - pred.kind().rebind(trait_pred.trait_ref.args), + pred.node.kind().rebind(trait_pred.trait_ref.args), ) => { true @@ -2061,9 +2061,9 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } }); // 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", ); } @@ -3321,10 +3321,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/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index ba2e3d1ae282..f5c575371841 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -1716,8 +1716,13 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { .predicates_of(single.impl_def_id) .instantiate(self.tcx, impl_args) .into_iter() - .map(|(clause, _)| { - Obligation::new(self.tcx, ObligationCause::dummy(), param_env, clause) + .map(|clause| { + Obligation::new( + self.tcx, + ObligationCause::dummy(), + param_env, + clause.node, + ) }), ); if !ocx.select_where_possible().is_empty() { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index fff5510bbfbb..44874ca89132 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -108,11 +108,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, (clause, span))| Obligation { - cause: cause(idx, span), + generic_bounds.into_iter().enumerate().map(move |(idx, clause)| Obligation { + cause: cause(idx, clause.span), recursion_depth: 0, param_env, - predicate: clause.as_predicate(), + predicate: clause.node.as_predicate(), }) } @@ -512,13 +512,13 @@ fn is_impossible_associated_item( 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::bind(*pred).instantiate(tcx, impl_trait_ref.args), + ty::EarlyBinder::bind(pred.node).instantiate(tcx, impl_trait_ref.args), ) }) }); diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 17c7f94ee883..7acb284c8f93 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -264,7 +264,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() } @@ -280,7 +283,7 @@ fn bounds_reference_self(tcx: TyCtxt<'_>, trait_def_id: DefId) -> SmallVec<[Span fn predicate_references_self<'tcx>( tcx: TyCtxt<'tcx>, - (predicate, sp): (ty::Clause<'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()); @@ -329,7 +332,7 @@ fn super_predicates_have_non_lifetime_binders( tcx.super_predicates_of(trait_def_id) .predicates .iter() - .filter_map(|(pred, span)| pred.has_non_region_late_bound().then_some(*span)) + .filter_map(|pred| pred.node.has_non_region_late_bound().then_some(pred.span)) .collect() } @@ -556,7 +559,7 @@ fn virtual_call_violations_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 { @@ -566,7 +569,7 @@ fn virtual_call_violations_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.as_type_outlives_clause().is_some() { + if pred.node.as_type_outlives_clause().is_some() { return false; } @@ -586,7 +589,7 @@ fn virtual_call_violations_for_method<'tcx>( if let ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref: pred_trait_ref, 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) { @@ -597,12 +600,12 @@ fn virtual_call_violations_for_method<'tcx>( if pred_trait_ref.args.len() != 1 { tcx.sess .diagnostic() - .delay_span_bug(span, "auto traits cannot have generic parameters"); + .delay_span_bug(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) }) { errors.push(MethodViolationCode::WhereClauseReferencesSelf); } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 471d10dbdbd8..fd0d2f8898ee 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -674,7 +674,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx let infcx = self.selcx.infcx; self.obligations.extend( infcx.tcx.predicates_of(data.def_id).instantiate_own(infcx.tcx, data.args).map( - |(mut predicate, span)| { + |ty::Spanned { node: mut predicate, span }| { if data.has_escaping_bound_vars() { (predicate, ..) = BoundVarReplacer::replace_bound_vars( infcx, @@ -1370,13 +1370,14 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( // Register the obligations arising from the impl and from the associated type itself. let predicates = tcx.predicates_of(alias_ty.def_id).instantiate(tcx, args); - for (predicate, span) in predicates { + for predicate in predicates { + let span = predicate.span; let predicate = normalize_with_depth_to( selcx, param_env, cause.clone(), depth + 1, - predicate, + predicate.node, obligations, ); @@ -2446,13 +2447,13 @@ fn assoc_ty_own_obligations<'cx, 'tcx>( let predicates = tcx .predicates_of(obligation.predicate.def_id) .instantiate_own(tcx, obligation.predicate.args); - 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, ); @@ -2463,7 +2464,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, @@ -2473,7 +2474,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/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs index 302b6016e5ea..0334326b1929 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs @@ -100,15 +100,15 @@ fn relate_mir_and_user_args<'tcx>( let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args); 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_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index f4b6d3bcfda2..fbdd94262203 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -414,8 +414,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { return false; }; - for &(predicate, _) in self.tcx().predicates_of(impl_def_id).predicates { - let ty::ClauseKind::Trait(pred) = predicate.kind().skip_binder() else { continue }; + for &predicate in self.tcx().predicates_of(impl_def_id).predicates { + let ty::ClauseKind::Trait(pred) = predicate.node.kind().skip_binder() else { continue }; if fn_ptr_trait != pred.trait_ref.def_id { continue; } diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index 4bfa341e3332..a2c3db3818bc 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -182,13 +182,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, args); - 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 cf52e6726a17..fd275d9d34fe 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -2717,7 +2717,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { assert_eq!(predicates.parent, None); let predicates = predicates.instantiate_own(tcx, args); 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 = if Some(parent_trait_pred.def_id()) == tcx.lang_items().coerce_unsized_trait() { cause.clone() @@ -2727,7 +2727,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { derived, impl_or_alias_def_id: def_id, impl_def_predicate_index: Some(index), - span, + span: predicate.span, })) }) }; @@ -2736,7 +2736,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { param_env, cause.clone(), recursion_depth, - predicate, + predicate.node, &mut obligations, ); obligations.push(Obligation { diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index efab29743f4e..8a2bdec37052 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -494,14 +494,14 @@ 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 (p, _) in predicates { - if let Some(poly_trait_ref) = p.as_trait_clause() { + for p in predicates { + if let Some(poly_trait_ref) = p.node.as_trait_clause() { if Some(poly_trait_ref.def_id()) == sized_trait { types_without_default_bounds.remove(&poly_trait_ref.self_ty().skip_binder()); continue; } } - pretty_predicates.push(p.to_string()); + pretty_predicates.push(p.node.to_string()); } pretty_predicates.extend(types_without_default_bounds.iter().map(|ty| format!("{ty}: ?Sized"))); diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index bbde0c82743b..3c13b58dad3b 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -127,10 +127,10 @@ impl<'tcx> TraitAliasExpander<'tcx> { let predicates = tcx.implied_predicates_of(trait_ref.def_id()); debug!(?predicates); - let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { - pred.subst_supertrait(tcx, &trait_ref) - .as_trait_clause() - .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).as_trait_clause().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::>()); @@ -186,7 +186,7 @@ impl Iterator for SupertraitDefIds<'_> { predicates .predicates .iter() - .filter_map(|(pred, _)| pred.as_trait_clause()) + .filter_map(|pred| pred.node.as_trait_clause()) .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 f23c100a686c..a9cbfd515146 100644 --- a/compiler/rustc_trait_selection/src/traits/vtable.rs +++ b/compiler/rustc_trait_selection/src/traits/vtable.rs @@ -123,8 +123,8 @@ fn prepare_vtable_segments_inner<'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).as_trait_clause() + .filter_map(move |pred| { + pred.node.subst_supertrait(tcx, &inner_most_trait_ref).as_trait_clause() }); // Find an unvisited supertrait @@ -282,7 +282,7 @@ fn vtable_entries<'tcx>( let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, args); 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 fe5b625e4836..8e7bc8a91e2f 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -825,11 +825,11 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { debug_assert_eq!(predicates.predicates.len(), origins.len()); iter::zip(predicates, origins.into_iter().rev()) - .map(|((pred, span), origin_def_id)| { - let code = if span.is_dummy() { + .map(|(pred, origin_def_id)| { + let code = if pred.span.is_dummy() { traits::ItemObligation(origin_def_id) } else { - traits::BindingObligation(origin_def_id, span) + traits::BindingObligation(origin_def_id, pred.span) }; let cause = self.cause(code); traits::Obligation::with_depth( @@ -837,7 +837,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> { cause, self.recursion_depth, self.param_env, - pred, + pred.node, ) }) .filter(|pred| !pred.has_escaping_bound_vars()) diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 01bb1ca70eb4..1633029ceaad 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -82,16 +82,15 @@ fn normalize_weak_ty<'tcx>( tcx.infer_ctxt().enter_canonical_trait_query( &goal, |ocx, ParamEnvAnd { param_env, value: goal }| { - let obligations = tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.args).map( - |(predicate, span)| { + let obligations = + tcx.predicates_of(goal.def_id).instantiate_own(tcx, goal.args).map(|predicate| { traits::Obligation::new( tcx, - ObligationCause::dummy_with_span(span), + ObligationCause::dummy_with_span(predicate.span), param_env, - predicate, + predicate.node, ) - }, - ); + }); ocx.register_obligations(obligations); let normalized_ty = tcx.type_of(goal.def_id).instantiate(tcx, goal.args); Ok(NormalizationResult { normalized_ty }) diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml index 07420985a851..43328146fcff 100644 --- a/compiler/rustc_transmute/Cargo.toml +++ b/compiler/rustc_transmute/Cargo.toml @@ -12,6 +12,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} tracing = "0.1" # tidy-alphabetical-end @@ -23,6 +24,7 @@ rustc = [ "rustc_middle", "rustc_span", "rustc_target", + "rustc_type_ir", ] [dev-dependencies] diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 5c34df1ed502..0a7d8c32f230 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -18,7 +18,7 @@ pub fn provide(providers: &mut Providers) { }; } -fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'tcx>, Span)] { +fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [ty::Spanned>] { match tcx.def_kind(def_id) { DefKind::Fn => { let sig = tcx.fn_sig(def_id).instantiate_identity(); @@ -26,7 +26,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' tcx.arena.alloc_from_iter(itertools::zip_eq( liberated_sig.inputs_and_output, fn_sig_spans(tcx, def_id), - )) + ).map(|(node, span)| ty::Spanned { node, span })) } DefKind::AssocFn => { let sig = tcx.fn_sig(def_id).instantiate_identity(); @@ -36,7 +36,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' assumed_wf_types.extend(itertools::zip_eq( liberated_sig.inputs_and_output, fn_sig_spans(tcx, def_id), - )); + ).map(|(node, span)| ty::Spanned { node, span })); tcx.arena.alloc_slice(&assumed_wf_types) } DefKind::Impl { .. } => { @@ -48,7 +48,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' }; let mut impl_spans = impl_spans(tcx, def_id); - tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| (ty, impl_spans.next().unwrap()))) + tcx.arena.alloc_from_iter(tys.into_iter().map(|ty| ty::Spanned { node: ty, span: impl_spans.next().unwrap() })) } DefKind::AssocTy if let Some(data) = tcx.opt_rpitit_info(def_id.to_def_id()) => { match data { diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 1487f40fd994..d598b93b89bd 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -14,9 +14,9 @@ use crate::errors::UnexpectedFnPtrAssociatedItem; fn resolve_instance<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::ParamEnvAnd<'tcx, (DefId, GenericArgsRef<'tcx>)>, + key: ty::ParamEnvAnd<'tcx, ty::InstanceOfArg<'tcx>>, ) -> Result>, ErrorGuaranteed> { - let (param_env, (def_id, args)) = key.into_parts(); + let (param_env, ty::InstanceOfArg(def_id, args)) = key.into_parts(); let result = if let Some(trait_def_id) = tcx.trait_of_item(def_id) { debug!(" => associated item, attempting to find impl in param_env {:#?}", param_env); diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 9242a1a751bc..599614ae21f4 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -171,13 +171,13 @@ impl<'tcx> TypeVisitor> for OpaqueTypeCollector<'tcx> { // Collect opaque types nested within the associated type bounds of this opaque type. // We use identity args here, because we already know that the opaque type uses // only generic parameters, and thus substituting would not give us more information. - for (pred, span) in self + for pred in self .tcx .explicit_item_bounds(alias_ty.def_id) .instantiate_identity_iter_copied() { - trace!(?pred); - self.visit_spanned(span, pred); + trace!(?pred.node); + self.visit_spanned(pred.span, pred.node); } } Err(NotUniqueParam::NotParam(arg)) => { diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index ccdc6120196a..3255f704366a 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -34,8 +34,8 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( for (hir, ty) in hir_sig.inputs.iter().zip(ty_sig.inputs().iter()) { visitor.visit(hir.span, ty.map_bound(|x| *x))?; } - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + for pred in tcx.predicates_of(item).instantiate_identity(tcx) { + visitor.visit(pred.span, pred.node)?; } } // Walk over the type behind the alias @@ -47,21 +47,21 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( _ => tcx.def_span(item), }; visitor.visit(span, tcx.type_of(item).instantiate_identity()); - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + for pred in tcx.predicates_of(item).instantiate_identity(tcx) { + visitor.visit(pred.span, pred.node)?; } } DefKind::OpaqueTy => { - for (pred, span) in tcx.explicit_item_bounds(item).instantiate_identity_iter_copied() { - visitor.visit(span, pred)?; + for pred in tcx.explicit_item_bounds(item).instantiate_identity_iter_copied() { + visitor.visit(pred.span, pred.node)?; } } // Look at field types DefKind::Struct | DefKind::Union | DefKind::Enum => { let span = tcx.def_ident_span(item).unwrap(); visitor.visit(span, tcx.type_of(item).instantiate_identity()); - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + for pred in tcx.predicates_of(item).instantiate_identity(tcx) { + visitor.visit(pred.span, pred.node)?; } } // These are not part of a public API, they can only appear as hidden types, and there @@ -79,13 +79,13 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( _ => tcx.def_span(item), }; visitor.visit(span, tcx.type_of(item).instantiate_identity()); - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + for pred in tcx.predicates_of(item).instantiate_identity(tcx) { + visitor.visit(pred.span, pred.node)?; } } DefKind::TraitAlias | DefKind::Trait => { - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { - visitor.visit(span, pred)?; + for pred in tcx.predicates_of(item).instantiate_identity(tcx) { + visitor.visit(pred.span, pred.node)?; } } | DefKind::Variant diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index abf3e108ed48..871796b67e72 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -53,8 +53,8 @@ fn sized_constraint_for_ty<'tcx>( let Some(sized_trait_def_id) = tcx.lang_items().sized_trait() else { return vec![ty] }; let predicates = tcx.predicates_of(adtdef.did()).predicates; - if predicates.iter().any(|(p, _)| { - p.as_trait_clause().is_some_and(|trait_pred| { + if predicates.iter().any(|p| { + p.node.as_trait_clause().is_some_and(|trait_pred| { trait_pred.def_id() == sized_trait_def_id && trait_pred.self_ty().skip_binder() == ty }) diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index ace9eade7f69..abd5d0fc0b62 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -1,17 +1,14 @@ use std::fmt; use std::hash::Hash; -use std::ops::ControlFlow; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; -use crate::fold::{FallibleTypeFolder, TypeFoldable}; -use crate::visit::{TypeVisitable, TypeVisitor}; use crate::{HashStableContext, Interner, UniverseIndex}; /// A "canonicalized" type `V` is one where all free inference /// variables have been rewritten to "canonical vars". These are /// numbered starting from 0 in order of first appearance. -#[derive(derivative::Derivative)] +#[derive(derivative::Derivative, TypeFoldable, TypeVisitable)] #[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))] #[derive(TyEncodable, TyDecodable)] pub struct Canonical { @@ -102,27 +99,3 @@ impl fmt::Debug for Canonical { } impl Copy for Canonical where I::CanonicalVars: Copy {} - -impl> TypeFoldable for Canonical -where - I::CanonicalVars: TypeFoldable, -{ - fn try_fold_with>(self, folder: &mut F) -> Result { - Ok(Canonical { - value: self.value.try_fold_with(folder)?, - max_universe: self.max_universe.try_fold_with(folder)?, - variables: self.variables.try_fold_with(folder)?, - }) - } -} - -impl> TypeVisitable for Canonical -where - I::CanonicalVars: TypeVisitable, -{ - fn visit_with>(&self, folder: &mut F) -> ControlFlow { - self.value.visit_with(folder)?; - self.max_universe.visit_with(folder)?; - self.variables.visit_with(folder) - } -} diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 33782b13ca8f..704fdc9e41a4 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -7,7 +7,7 @@ use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Int use self::ConstKind::*; /// Represents a constant in Rust. -#[derive(derivative::Derivative)] +#[derive(derivative::Derivative, TypeFoldable, TypeVisitable)] #[derivative( Clone(bound = ""), PartialOrd(bound = ""), diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index fc56400df161..23794ff34689 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -45,11 +45,15 @@ //! - u.fold_with(folder) //! ``` -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::{ + intern::{Internable, Interned}, + sync::Lrc, +}; use rustc_index::{Idx, IndexVec}; +use std::marker::PhantomData; use std::mem; -use crate::{visit::TypeVisitable, Interner}; +use crate::{visit::TypeVisitable, Interner, TriviallyTraverses}; /// This trait is implemented for every type that can be folded, /// providing the skeleton of the traversal. @@ -248,9 +252,66 @@ where } } +pub trait SpecTypeFoldable { + type Interner: Interner; + type Item; + fn spec_try_fold_with>( + self, + value: Self::Item, + folder: &mut F, + ) -> Result; +} + +impl> SpecTypeFoldable for PhantomData<(I, T)> { + type Interner = I; + type Item = T; + + #[inline(always)] + fn spec_try_fold_with>( + self, + value: T, + folder: &mut F, + ) -> Result { + value.try_fold_with(folder) + } +} + +impl, T> SpecTypeFoldable for &PhantomData<(I, T)> { + type Interner = I; + type Item = T; + + #[inline(always)] + fn spec_try_fold_with>( + self, + value: T, + _: &mut F, + ) -> Result { + Ok(value) + } +} + /////////////////////////////////////////////////////////////////////////// -// Traversal implementations. +// Traversable implementations for upstream types. + +// `()` is (obviously) a no-op traversal and therefore the auto-deref specialisation normally +// negates any need for explicit implementation, however there are implementations of +// `QueryTypeOp` that have have unit `QueryResponse` -- and that associated type must be +// traversable for some generic operations to work upon it. +impl TypeFoldable for () { + fn try_fold_with>(self, _: &mut F) -> Result<(), F::Error> { + Ok(()) + } +} +// 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 would +// normally negate any such 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 `BoringTraversable` 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)?)) @@ -345,3 +406,9 @@ impl, Ix: Idx> TypeFoldable 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())) + } +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 7f75e5b35a20..05140a38cc6a 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -66,6 +66,25 @@ pub trait Interner: Sized { fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability); } +/// Marker to signify that the interner type `Self` trivially traverses type `T`, +/// which is to say that traversing (folding or visiting) values of type `T` is +/// *guaranteed* to be a no-op because `T` does not contain anything that could be +/// of interest to a traverser (folder or visitor). Per the traverser traits' +/// methods, traversers are only capable of taking an interest in the following +/// five types: +/// +/// * Self::Binder for any type B +/// * Self::Ty +/// * Self::Region +/// * Self::Const +/// * Self::Predicate +// +// If and when implementations of the super-traverser traits are uplifted to +// this library, the `B` above will likely be restricted to types of interest. +// For now, that is an implementation detail of `rustc_middle` and is therefore +// omitted from this library's documentation. +pub trait TriviallyTraverses: Interner {} + /// 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 cfed84a35c67..29937ac08a3a 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -1,54 +1,28 @@ -/// 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) - } +#[macro_export] +macro_rules! noop_if_trivially_traversable { + ($val:tt.try_fold_with::<$interner:ty>($folder:expr)) => {{ + use $crate::fold::SpecTypeFoldable as _; + $crate::noop_if_trivially_traversable!($val.spec_try_fold_with::<$interner>($folder)) + }}; + ($val:tt.visit_with::<$interner:ty>($visitor:expr)) => {{ + use $crate::visit::SpecTypeVisitable as _; + $crate::noop_if_trivially_traversable!($val.spec_visit_with::<$interner>($visitor)) + }}; + ($val:tt.$method:ident::<$interner:ty>($traverser:expr)) => {{ + let val = $val; - #[inline] - fn fold_with>( - self, - _: &mut F, - ) -> Self { - self - } - } + #[allow(unreachable_code)] + let p = 'p: { + use ::core::marker::PhantomData; - impl $crate::visit::TypeVisitable for $ty { - #[inline] - fn visit_with>( - &self, - _: &mut F) - -> ::std::ops::ControlFlow - { - ::std::ops::ControlFlow::Continue(()) - } + fn unreachable_phantom_constraint(_: T) -> PhantomData<(I, T)> { + unreachable!() } - )+ - }; -} -/////////////////////////////////////////////////////////////////////////// -// Atomic structs -// -// For things that don't carry any arena-allocated data (and are -// copy...), just add them to this list. + break 'p PhantomData; + unreachable_phantom_constraint::<$interner, _>(val) + }; -TrivialTypeTraversalImpls! { - (), - bool, - usize, - u16, - u32, - u64, - String, - crate::DebruijnIndex, - crate::AliasRelationDirection, - crate::UniverseIndex, + (&&p).$method(val, $traverser) + }}; } diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 48662d426423..82f05ed4e459 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -1,14 +1,11 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use std::fmt; -use std::ops::ControlFlow; -use crate::fold::{FallibleTypeFolder, TypeFoldable}; -use crate::visit::{TypeVisitable, TypeVisitor}; use crate::{HashStableContext, Interner}; /// A clause is something that can appear in where bounds or be inferred /// by implied bounds. -#[derive(derivative::Derivative)] +#[derive(derivative::Derivative, TypeFoldable, TypeVisitable)] #[derivative(Clone(bound = ""), Hash(bound = ""))] #[derive(TyEncodable, TyDecodable)] pub enum ClauseKind { @@ -106,60 +103,7 @@ where } } -impl TypeFoldable for ClauseKind -where - I::Ty: TypeFoldable, - I::Const: TypeFoldable, - I::GenericArg: TypeFoldable, - I::TraitPredicate: TypeFoldable, - I::ProjectionPredicate: TypeFoldable, - I::TypeOutlivesPredicate: TypeFoldable, - I::RegionOutlivesPredicate: TypeFoldable, -{ - fn try_fold_with>(self, folder: &mut F) -> Result { - Ok(match self { - ClauseKind::Trait(p) => ClauseKind::Trait(p.try_fold_with(folder)?), - ClauseKind::RegionOutlives(p) => ClauseKind::RegionOutlives(p.try_fold_with(folder)?), - ClauseKind::TypeOutlives(p) => ClauseKind::TypeOutlives(p.try_fold_with(folder)?), - ClauseKind::Projection(p) => ClauseKind::Projection(p.try_fold_with(folder)?), - ClauseKind::ConstArgHasType(c, t) => { - ClauseKind::ConstArgHasType(c.try_fold_with(folder)?, t.try_fold_with(folder)?) - } - ClauseKind::WellFormed(p) => ClauseKind::WellFormed(p.try_fold_with(folder)?), - ClauseKind::ConstEvaluatable(p) => { - ClauseKind::ConstEvaluatable(p.try_fold_with(folder)?) - } - }) - } -} - -impl TypeVisitable for ClauseKind -where - I::Ty: TypeVisitable, - I::Const: TypeVisitable, - I::GenericArg: TypeVisitable, - I::TraitPredicate: TypeVisitable, - I::ProjectionPredicate: TypeVisitable, - I::TypeOutlivesPredicate: TypeVisitable, - I::RegionOutlivesPredicate: TypeVisitable, -{ - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - match self { - ClauseKind::Trait(p) => p.visit_with(visitor), - ClauseKind::RegionOutlives(p) => p.visit_with(visitor), - ClauseKind::TypeOutlives(p) => p.visit_with(visitor), - ClauseKind::Projection(p) => p.visit_with(visitor), - ClauseKind::ConstArgHasType(c, t) => { - c.visit_with(visitor)?; - t.visit_with(visitor) - } - ClauseKind::WellFormed(p) => p.visit_with(visitor), - ClauseKind::ConstEvaluatable(p) => p.visit_with(visitor), - } - } -} - -#[derive(derivative::Derivative)] +#[derive(derivative::Derivative, TypeFoldable, TypeVisitable)] #[derivative(Clone(bound = ""), Hash(bound = ""))] #[derive(TyEncodable, TyDecodable)] pub enum PredicateKind { @@ -289,77 +233,6 @@ where } } -impl TypeFoldable for PredicateKind -where - I::DefId: TypeFoldable, - I::Const: TypeFoldable, - I::GenericArgs: TypeFoldable, - I::Term: TypeFoldable, - I::CoercePredicate: TypeFoldable, - I::SubtypePredicate: TypeFoldable, - I::ClosureKind: TypeFoldable, - ClauseKind: TypeFoldable, -{ - fn try_fold_with>(self, folder: &mut F) -> Result { - Ok(match self { - PredicateKind::Clause(c) => PredicateKind::Clause(c.try_fold_with(folder)?), - PredicateKind::ObjectSafe(d) => PredicateKind::ObjectSafe(d.try_fold_with(folder)?), - PredicateKind::ClosureKind(d, g, k) => PredicateKind::ClosureKind( - d.try_fold_with(folder)?, - g.try_fold_with(folder)?, - k.try_fold_with(folder)?, - ), - PredicateKind::Subtype(s) => PredicateKind::Subtype(s.try_fold_with(folder)?), - PredicateKind::Coerce(s) => PredicateKind::Coerce(s.try_fold_with(folder)?), - PredicateKind::ConstEquate(a, b) => { - PredicateKind::ConstEquate(a.try_fold_with(folder)?, b.try_fold_with(folder)?) - } - PredicateKind::Ambiguous => PredicateKind::Ambiguous, - PredicateKind::AliasRelate(a, b, d) => PredicateKind::AliasRelate( - a.try_fold_with(folder)?, - b.try_fold_with(folder)?, - d.try_fold_with(folder)?, - ), - }) - } -} - -impl TypeVisitable for PredicateKind -where - I::DefId: TypeVisitable, - I::Const: TypeVisitable, - I::GenericArgs: TypeVisitable, - I::Term: TypeVisitable, - I::CoercePredicate: TypeVisitable, - I::SubtypePredicate: TypeVisitable, - I::ClosureKind: TypeVisitable, - ClauseKind: TypeVisitable, -{ - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - match self { - PredicateKind::Clause(p) => p.visit_with(visitor), - PredicateKind::ObjectSafe(d) => d.visit_with(visitor), - PredicateKind::ClosureKind(d, g, k) => { - d.visit_with(visitor)?; - g.visit_with(visitor)?; - k.visit_with(visitor) - } - PredicateKind::Subtype(s) => s.visit_with(visitor), - PredicateKind::Coerce(s) => s.visit_with(visitor), - PredicateKind::ConstEquate(a, b) => { - a.visit_with(visitor)?; - b.visit_with(visitor) - } - PredicateKind::Ambiguous => ControlFlow::Continue(()), - PredicateKind::AliasRelate(a, b, d) => { - a.visit_with(visitor)?; - b.visit_with(visitor)?; - d.visit_with(visitor) - } - } - } -} - #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] #[derive(HashStable_Generic, Encodable, Decodable)] pub enum AliasRelationDirection { diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 9c7b8156b043..f0ff400d49c8 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -41,12 +41,13 @@ //! - u.visit_with(visitor) //! ``` -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::{intern::Interned, sync::Lrc}; use rustc_index::{Idx, IndexVec}; use std::fmt; +use std::marker::PhantomData; use std::ops::ControlFlow; -use crate::Interner; +use crate::{Interner, TriviallyTraverses}; /// This trait is implemented for every type that can be visited, /// providing the skeleton of the traversal. @@ -120,9 +121,62 @@ pub trait TypeVisitor: Sized { } } +pub trait SpecTypeVisitable { + type Interner: Interner; + type Item: ?Sized; + fn spec_visit_with>( + self, + value: &Self::Item, + visitor: &mut V, + ) -> ControlFlow; +} + +impl> SpecTypeVisitable for PhantomData<(I, &T)> { + type Interner = I; + type Item = T; + + #[inline(always)] + fn spec_visit_with>( + self, + value: &T, + visitor: &mut V, + ) -> ControlFlow { + value.visit_with(visitor) + } +} + +impl, T: ?Sized> SpecTypeVisitable for &PhantomData<(I, &T)> { + type Interner = I; + type Item = T; + + #[inline(always)] + fn spec_visit_with>(self, _: &T, _: &mut V) -> ControlFlow { + ControlFlow::Continue(()) + } +} + /////////////////////////////////////////////////////////////////////////// -// Traversal implementations. +// Traversable implementations for upstream types. + +// `()` is (obviously) a no-op traversal and therefore the auto-deref specialisation normally +// negates any need for explicit implementation, however there are implementations of +// `QueryTypeOp` that have have unit `QueryResponse` -- and that associated type must be +// traversable for some generic operations to work upon it. +impl TypeVisitable for () { + fn visit_with>(&self, _: &mut V) -> ControlFlow { + ControlFlow::Continue(()) + } +} +// 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 would +// normally negate any such 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 `BoringTraversable` trait and these implementations will be bypassed; consequently +// explicit implementations on the element types would not then be required. impl, U: TypeVisitable> TypeVisitable for (T, U) { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { self.0.visit_with(visitor)?; @@ -196,3 +250,9 @@ impl, Ix: Idx> TypeVisitable for IndexVec> TypeVisitable for Interned<'_, T> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + (**self).visit_with(visitor) + } +} diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1b7ca7bf7dd0..bea82dc1b1af 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -442,7 +442,7 @@ fn clean_projection<'tcx>( .tcx .explicit_item_bounds(ty.skip_binder().def_id) .iter_instantiated_copied(cx.tcx, ty.skip_binder().args) - .map(|(pred, _)| pred) + .map(|pred| pred.node) .collect::>(); return clean_middle_opaque_bounds(cx, bounds); } @@ -787,10 +787,10 @@ fn clean_ty_generics<'tcx>( let where_predicates = preds .predicates .iter() - .flat_map(|(pred, _)| { + .flat_map(|pred| { let mut projection = None; let param_idx = (|| { - let bound_p = pred.kind(); + let bound_p = pred.node.kind(); match bound_p.skip_binder() { ty::ClauseKind::Trait(pred) => { if let ty::Param(param) = pred.self_ty().kind() { @@ -817,7 +817,7 @@ fn clean_ty_generics<'tcx>( if let Some(param_idx) = param_idx && let Some(bounds) = impl_trait.get_mut(¶m_idx.into()) { - let pred = clean_predicate(*pred, cx)?; + let pred = clean_predicate(pred.node, cx)?; bounds.extend( pred.get_bounds() @@ -840,7 +840,7 @@ fn clean_ty_generics<'tcx>( return None; } - Some(pred) + Some(&pred.node) }) .collect::>(); @@ -2269,7 +2269,7 @@ pub(crate) fn clean_middle_ty<'tcx>( .tcx .explicit_item_bounds(def_id) .iter_instantiated_copied(cx.tcx, args) - .map(|(bound, _)| bound) + .map(|bound| bound.node) .collect::>(); let ty = clean_middle_opaque_bounds(cx, bounds); if let Some(count) = cx.current_type_aliases.get_mut(&def_id) { diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 627f15e67ac3..aafbac768944 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -118,8 +118,8 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId) predicates .predicates .iter() - .filter_map(|(pred, _)| { - if let ty::ClauseKind::Trait(pred) = pred.kind().skip_binder() { + .filter_map(|pred| { + if let ty::ClauseKind::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 3a331564db97..91f0b98239bd 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 ClauseKind::Trait(p) = p.kind().skip_binder() + for p in ty_predicates { + if let ClauseKind::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() { @@ -513,7 +513,7 @@ fn param_env_for_derived_eq(tcx: TyCtxt<'_>, did: DefId, eq_trait_id: DefId) -> } ParamEnv::new( - tcx.mk_clauses_from_iter(ty_predicates.iter().map(|&(p, _)| p).chain( + tcx.mk_clauses_from_iter(ty_predicates.iter().map(|p| p.node).chain( params.iter().filter(|&&(_, needs_eq)| needs_eq).map(|&(param, _)| { ClauseKind::Trait(TraitPredicate { trait_ref: ty::TraitRef::new(tcx, 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 eee5b7540ba7..afe35944d899 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, args, .. }) = *ret_ty.kind() { let preds = cx.tcx.explicit_item_bounds(def_id); let mut is_future = false; - for (p, _span) in preds.iter_instantiated_copied(cx.tcx, args) { - if let Some(trait_pred) = p.as_trait_clause() { + for p in preds.iter_instantiated_copied(cx.tcx, args) { + if let Some(trait_pred) = p.node.as_trait_clause() { if Some(trait_pred.skip_binder().trait_ref.def_id) == cx.tcx.lang_items().future_trait() { is_future = true; break; diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index ff27a5d666d3..628cd67e5cf5 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -265,8 +265,8 @@ fn check(cx: &LateContext<'_>, decl: &FnDecl<'_>) { let implied_by_args = implied_by_path.args.map_or([].as_slice(), |a| a.args); let implied_by_bindings = implied_by_path.args.map_or([].as_slice(), |a| a.bindings); - preds.iter().find_map(|(clause, _)| { - if let ClauseKind::Trait(tr) = clause.kind().skip_binder() + preds.iter().find_map(|clause| { + if let ClauseKind::Trait(tr) = clause.node.kind().skip_binder() && tr.def_id() == def_id && is_same_generics( cx.tcx, 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 e76cc65fd46a..8cdde1b756e6 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 ClauseKind::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 ClauseKind::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 ClauseKind::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 ClauseKind::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.args == trait_pred.trait_ref.args { return Some(projection_pred); } diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs index 28f1d487eb5f..c096f12c46fb 100644 --- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs +++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs @@ -91,11 +91,11 @@ fn into_iter_bound<'tcx>( let param_env = cx.tcx.param_env(fn_did); let mut into_iter_span = None; - for (pred, span) in cx.tcx.explicit_predicates_of(fn_did).predicates { - if let ty::ClauseKind::Trait(tr) = pred.kind().skip_binder() { + for pred in cx.tcx.explicit_predicates_of(fn_did).predicates { + if let ty::ClauseKind::Trait(tr) = pred.node.kind().skip_binder() { if tr.self_ty().is_param(param_index) { if tr.def_id() == into_iter_did { - into_iter_span = Some(*span); + into_iter_span = Some(pred.span); } else { let tr = cx.tcx.erase_regions(tr); if tr.has_escaping_bound_vars() { 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 0bcefba75a7b..4d5c2c875b4e 100644 --- a/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs +++ b/src/tools/clippy/clippy_utils/src/eager_or_lazy.rs @@ -73,7 +73,7 @@ fn fn_eagerness(cx: &LateContext<'_>, fn_id: DefId, name: Symbol, have_one_arg: cx.tcx.type_of(x.did).instantiate_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() { ty::ClauseKind::Trait(pred) => cx.tcx.trait_def(pred.trait_ref.def_id).is_marker, _ => true, }) && subs.types().all(|x| matches!(x.peel_refs().kind(), ty::Param(_))) diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 1181dfc0ef95..168644901afe 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2233,7 +2233,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.node.is_global().then_some(p.node)); traits::impossible_predicates(cx.tcx, traits::elaborate(cx.tcx, predicates).collect::>()) } 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 668ea9fcf3b4..a11b4286a5ef 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 @@ -12,7 +12,7 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::Obligation; 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::traits::{BuiltinImplSource, ImplSource, ObligationCause}; @@ -207,7 +207,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) diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs index 7eff93881b26..075e427ff59e 100644 --- a/src/tools/clippy/clippy_utils/src/ty.rs +++ b/src/tools/clippy/clippy_utils/src/ty.rs @@ -23,7 +23,7 @@ use rustc_middle::ty::{ TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, UintTy, VariantDef, VariantDiscr, }; 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::traits::query::evaluate_obligation::InferCtxtExt as _; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; @@ -96,8 +96,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).instantiate_identity_iter_copied() { - match predicate.kind().skip_binder() { + for predicate in cx.tcx.explicit_item_bounds(def_id).instantiate_identity_iter_copied() { + match predicate.node.kind().skip_binder() { // For `impl Trait`, it will register a predicate of `T: Trait`, so we go through // and check substitutions to find `U`. ty::ClauseKind::Trait(trait_predicate) => { @@ -300,8 +300,8 @@ pub fn is_must_use_ty<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { }, ty::Tuple(args) => args.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).skip_binder() { - if let ty::ClauseKind::Trait(trait_predicate) = predicate.kind().skip_binder() { + for predicate in cx.tcx.explicit_item_bounds(def_id).skip_binder() { + if let ty::ClauseKind::Trait(trait_predicate) = predicate.node.kind().skip_binder() { if cx.tcx.has_attr(trait_predicate.trait_ref.def_id, sym::must_use) { return true; } @@ -599,7 +599,7 @@ fn is_uninit_value_valid_for_ty_fallback<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'t } /// 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| { @@ -777,18 +777,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 .explicit_item_bounds(ty.def_id) .iter_instantiated_copied(cx.tcx, ty.args) { - match pred.kind().skip_binder() { + match pred.node.kind().skip_binder() { ty::ClauseKind::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.args.type_at(1)); + let i = pred.node.kind().rebind(p.trait_ref.args.type_at(1)); if inputs.map_or(false, |inputs| inputs != i) { // Multiple different fn trait impls. Is this even allowed? @@ -801,7 +801,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 965cd534d1e5..87bfe1e0aeea 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -900,7 +900,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);