From 726f1f8c6ea4eee87b7b91d12086044fdef6bd99 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 13 Mar 2025 03:42:06 +0000 Subject: [PATCH 1/9] Add clauses to binders, once again --- compiler/rustc_ast_passes/src/feature_gate.rs | 22 +++--- compiler/rustc_middle/src/traits/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 1 + compiler/rustc_middle/src/ty/mod.rs | 3 +- compiler/rustc_middle/src/ty/predicate.rs | 6 ++ compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_type_ir/src/binder.rs | 71 ++++++++++++++----- compiler/rustc_type_ir/src/inherent.rs | 3 +- 8 files changed, 79 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index d2e3c00bb0c07..65336ae93f28f 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -137,16 +137,18 @@ impl<'a> PostExpansionVisitor<'a> { } } - for param in params { - if !param.bounds.is_empty() { - let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); - if param.bounds.iter().any(|bound| matches!(bound, GenericBound::Trait(_))) { - // Issue #149695 - // Abort immediately otherwise items defined in complex bounds will be lowered into HIR, - // which will cause ICEs when errors of the items visit unlowered parents. - self.sess.dcx().emit_fatal(diagnostics::ForbiddenBound { spans }); - } else { - self.sess.dcx().emit_err(diagnostics::ForbiddenBound { spans }); + if !self.features.non_lifetime_binders() { + for param in params { + if !param.bounds.is_empty() { + let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); + if param.bounds.iter().any(|bound| matches!(bound, GenericBound::Trait(_))) { + // Issue #149695 + // Abort immediately otherwise items defined in complex bounds will be lowered into HIR, + // which will cause ICEs when errors of the items visit unlowered parents. + self.sess.dcx().emit_fatal(diagnostics::ForbiddenBound { spans }); + } else { + self.sess.dcx().emit_err(diagnostics::ForbiddenBound { spans }); + } } } } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 4cd124248e093..3b43e7464ed57 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -526,7 +526,7 @@ impl<'tcx> ObligationCauseCode<'tcx> { // `ObligationCauseCode` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(ObligationCauseCode<'_>, 48); +rustc_data_structures::static_assert_size!(ObligationCauseCode<'_>, 56); #[derive(Clone, Debug, PartialEq, Eq, StableHash, TyEncodable, TyDecodable)] #[derive(TypeVisitable, TypeFoldable)] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index c6fa3801fb1bc..60c82a06f7702 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1725,6 +1725,7 @@ nop_list_lift! { patterns; Pattern<'a> => Pattern<'tcx> } nop_list_lift! { outlives; ty::ArgOutlivesPredicate<'a> => ty::ArgOutlivesPredicate<'tcx> } +nop_list_with_cached_type_info_lift! { clauses; Clause<'a> => Clause<'tcx> } // This is the impl for `&'a GenericArgs<'a>`. nop_list_lift! { args; GenericArg<'a> => GenericArg<'tcx> } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 3d8ab41b37a31..e10ecdbf00d81 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1009,7 +1009,7 @@ pub struct ParamEnv<'tcx> { } impl<'tcx> rustc_type_ir::inherent::ParamEnv> for ParamEnv<'tcx> { - fn caller_bounds(self) -> impl inherent::SliceLike> { + fn caller_bounds(self) -> Clauses<'tcx> { self.caller_bounds() } } @@ -2601,6 +2601,5 @@ fn typetree_from_ty_impl_inner<'tcx>( } } } - TypeTree::new() } diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 26108f7be6964..656c645d2cdb0 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -147,6 +147,12 @@ impl<'tcx> rustc_type_ir::inherent::Clause> for Clause<'tcx> { } } +impl<'tcx> rustc_type_ir::inherent::Clauses> for ty::Clauses<'tcx> { + fn empty() -> Self { + ty::ListWithCachedTypeInfo::empty() + } +} + impl<'tcx> rustc_type_ir::inherent::IntoKind for Clause<'tcx> { type Kind = ty::Binder<'tcx, ClauseKind<'tcx>>; diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 9db9b1769ab9c..c09831ee606b8 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2171,7 +2171,7 @@ mod size_asserts { use super::*; // tidy-alphabetical-start - static_assert_size!(TyKind<'_>, 32); + static_assert_size!(TyKind<'_>, 40); static_assert_size!(ty::WithCachedTypeInfo>, 40); // tidy-alphabetical-end } diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index dbd8beed2ed26..28efb9333b6b8 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -31,6 +31,7 @@ use crate::{self as ty, DebruijnIndex, Interner, UniverseIndex, Unnormalized}; pub struct Binder { value: T, bound_vars: I::BoundVarKinds, + clauses: I::Clauses, } impl Eq for Binder {} @@ -88,7 +89,7 @@ where !value.has_escaping_bound_vars(), "`{value:?}` has escaping bound vars, so it cannot be wrapped in a dummy binder." ); - Binder { value, bound_vars: Default::default() } + Binder { value, bound_vars: Default::default(), clauses: I::Clauses::empty() } } pub fn bind_with_vars(value: T, bound_vars: I::BoundVarKinds) -> Binder { @@ -96,7 +97,20 @@ where let mut validator = ValidateBoundVars::new(bound_vars); let _ = value.visit_with(&mut validator); } - Binder { value, bound_vars } + Binder { value, bound_vars, clauses: I::Clauses::empty() } + } + + pub fn bind_with_vars_and_clauses( + value: T, + bound_vars: I::BoundVarKinds, + clauses: I::Clauses, + ) -> Binder { + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(bound_vars); + value.visit_with(&mut validator); + clauses.visit_with(&mut validator); + } + Binder { bound_vars, value, clauses } } } @@ -121,17 +135,25 @@ impl> TypeSuperFoldable for Binder { self, folder: &mut F, ) -> Result { - self.try_map_bound(|t| t.try_fold_with(folder)) + let Binder { bound_vars, value, clauses } = self; + let clauses = clauses.try_fold_with(folder)?; + let value = value.try_fold_with(folder)?; + Ok(Binder::bind_with_vars_and_clauses(value, bound_vars, clauses)) } fn super_fold_with>(self, folder: &mut F) -> Self { - self.map_bound(|t| t.fold_with(folder)) + let Binder { bound_vars, value, clauses } = self; + let clauses = clauses.fold_with(folder); + let value = value.fold_with(folder); + Binder::bind_with_vars_and_clauses(value, bound_vars, clauses) } } impl> TypeSuperVisitable for Binder { fn super_visit_with>(&self, visitor: &mut V) -> V::Result { - self.as_ref().skip_binder().visit_with(visitor) + let (value, clauses) = self.as_ref().skip_binder_with_clauses(); + try_visit!(clauses.visit_with(visitor)); + value.visit_with(visitor) } } @@ -153,19 +175,23 @@ impl Binder { self.value } + pub fn skip_binder_with_clauses(self) -> (T, I::Clauses) { + (self.value, self.clauses) + } + pub fn bound_vars(&self) -> I::BoundVarKinds { self.bound_vars } pub fn as_ref(&self) -> Binder { - Binder { value: &self.value, bound_vars: self.bound_vars } + Binder { value: &self.value, bound_vars: self.bound_vars, clauses: self.clauses } } pub fn as_deref(&self) -> Binder where T: Deref, { - Binder { value: &self.value, bound_vars: self.bound_vars } + Binder { value: &self.value, bound_vars: self.bound_vars, clauses: self.clauses } } pub fn map_bound_ref>(&self, f: F) -> Binder @@ -179,26 +205,39 @@ impl Binder { where F: FnOnce(T) -> U, { - let Binder { value, bound_vars } = self; + let Binder { value, bound_vars, clauses } = self; let value = f(value); if cfg!(debug_assertions) { let mut validator = ValidateBoundVars::new(bound_vars); let _ = value.visit_with(&mut validator); } - Binder { value, bound_vars } + Binder { value, bound_vars, clauses } + } + + pub fn map_clauses>(self, f: F) -> Self + where + F: FnOnce(I::Clauses) -> I::Clauses, + { + let Binder { value, bound_vars, clauses } = self; + let clauses = f(clauses); + if cfg!(debug_assertions) { + let mut validator = ValidateBoundVars::new(bound_vars); + clauses.visit_with(&mut validator); + } + Binder { value, bound_vars, clauses } } pub fn try_map_bound, E>(self, f: F) -> Result, E> where F: FnOnce(T) -> Result, { - let Binder { value, bound_vars } = self; + let Binder { value, bound_vars, clauses } = self; let value = f(value)?; if cfg!(debug_assertions) { let mut validator = ValidateBoundVars::new(bound_vars); let _ = value.visit_with(&mut validator); } - Ok(Binder { value, bound_vars }) + Ok(Binder { value, bound_vars, clauses }) } /// Wraps a `value` in a binder, using the same bound variables as the @@ -214,7 +253,7 @@ impl Binder { where U: TypeVisitable, { - Binder::bind_with_vars(value, self.bound_vars) + Binder::bind_with_vars_and_clauses(value, self.bound_vars, self.clauses) } /// Unwraps and returns the value within, but only if it contains @@ -238,15 +277,15 @@ impl Binder { impl Binder> { pub fn transpose(self) -> Option> { - let Binder { value, bound_vars } = self; - value.map(|value| Binder { value, bound_vars }) + let Binder { value, bound_vars, clauses } = self; + value.map(|value| Binder { value, bound_vars, clauses }) } } impl Binder { pub fn iter(self) -> impl Iterator> { - let Binder { value, bound_vars } = self; - value.into_iter().map(move |value| Binder { value, bound_vars }) + let Binder { value, bound_vars, clauses } = self; + value.into_iter().map(move |value| Binder { value, bound_vars, clauses }) } } diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index bffb6aa8060ed..91bb8cfb1917e 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -576,6 +576,7 @@ pub trait Clauses>: + Flags + SliceLike { + fn empty() -> Self; } #[rust_analyzer::prefer_underscore_import] @@ -629,7 +630,7 @@ pub trait AdtDef: Copy + Debug + Hash + Eq { #[rust_analyzer::prefer_underscore_import] pub trait ParamEnv: Copy + Debug + Hash + Eq + TypeFoldable { - fn caller_bounds(self) -> impl SliceLike; + fn caller_bounds(self) -> I::Clauses; } #[rust_analyzer::prefer_underscore_import] From f72c29045ae95a5f75231bbe9939b109dea5f4d8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 13 Mar 2025 04:25:17 +0000 Subject: [PATCH 2/9] Implement support for binders with clauses in new solver --- compiler/rustc_infer/src/infer/context.rs | 20 +++++++ compiler/rustc_infer/src/infer/mod.rs | 47 +++++++++++++++ .../src/infer/relate/higher_ranked.rs | 57 +++++++++++++++++++ compiler/rustc_middle/src/ty/fold.rs | 8 +++ compiler/rustc_middle/src/ty/mod.rs | 14 +++++ compiler/rustc_middle/src/ty/predicate.rs | 2 - .../src/canonical/canonicalizer.rs | 14 ++--- .../src/solve/effect_goals.rs | 8 ++- .../src/solve/eval_ctxt/mod.rs | 17 ++++-- .../src/solve/normalizes_to.rs | 5 +- .../src/solve/trait_goals.rs | 14 +++-- compiler/rustc_type_ir/src/binder.rs | 6 +- compiler/rustc_type_ir/src/infer_ctxt.rs | 11 ++++ compiler/rustc_type_ir/src/interner.rs | 1 + .../rustc_type_ir/src/region_constraint.rs | 1 + compiler/rustc_type_ir/src/visit.rs | 6 ++ 16 files changed, 205 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index c23bc4adf914c..d561d6d408c26 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -209,6 +209,17 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { ) } + fn instantiate_binder_with_infer_and_goals> + Copy>( + &self, + value: ty::Binder<'tcx, T>, + ) -> (T, ty::Clauses<'tcx>) { + self.instantiate_binder_with_fresh_vars_and_goals( + DUMMY_SP, + BoundRegionConversionTime::HigherRankedType, + value, + ) + } + fn enter_forall_without_assumptions>, U>( &self, value: ty::Binder<'tcx, T>, @@ -217,6 +228,15 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.enter_forall(value, f) } + fn enter_forall_with_assumptions>, U>( + &self, + value: ty::Binder<'tcx, T>, + param_env: ty::ParamEnv<'tcx>, + f: impl FnOnce(T, ty::ParamEnv<'tcx>) -> U, + ) -> U { + self.enter_forall_with_assumptions(value, param_env, f) + } + fn enter_forall_with_empty_assumptions>, U>( &self, value: ty::Binder<'tcx, T>, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 0d93e1478c420..43a7f3d8694e6 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -39,6 +39,7 @@ use snapshot::undo_log::InferCtxtUndoLogs; use tracing::{debug, instrument}; use type_variable::TypeVariableOrigin; +use crate::infer::RegionVariableOrigin::BoundRegion; use crate::infer::snapshot::undo_log::UndoLog; use crate::infer::type_variable::FloatVariableOrigin; use crate::infer::unify_key::{ConstVariableOrigin, ConstVariableValue, ConstVidKey}; @@ -1429,6 +1430,52 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx.replace_bound_vars_uncached(value, delegate) } + pub fn instantiate_binder_with_fresh_vars_and_goals( + &self, + span: Span, + lbrct: BoundRegionConversionTime, + binder: ty::Binder<'tcx, T>, + ) -> (T, ty::Clauses<'tcx>) + where + T: TypeFoldable> + Copy, + { + if !binder.as_ref().skip_binder_with_clauses().has_escaping_bound_vars() { + return binder.skip_binder_with_clauses(); + } + + let bound_vars = binder.bound_vars(); + let mut args = Vec::with_capacity(bound_vars.len()); + + for bound_var_kind in bound_vars { + let arg: ty::GenericArg<'_> = match bound_var_kind { + ty::BoundVariableKind::Ty(_) => self.next_ty_var(span).into(), + ty::BoundVariableKind::Region(br) => { + self.next_region_var(BoundRegion(span, br, lbrct)).into() + } + ty::BoundVariableKind::Const => self.next_const_var(span).into(), + }; + args.push(arg); + } + + struct ToFreshVars<'tcx> { + args: Vec>, + } + + impl<'tcx> BoundVarReplacerDelegate<'tcx> for ToFreshVars<'tcx> { + fn replace_region(&mut self, br: ty::BoundRegion<'tcx>) -> ty::Region<'tcx> { + self.args[br.var.index()].expect_region() + } + fn replace_ty(&mut self, bt: ty::BoundTy<'tcx>) -> Ty<'tcx> { + self.args[bt.var.index()].expect_ty() + } + fn replace_const(&mut self, bc: ty::BoundConst<'tcx>) -> ty::Const<'tcx> { + self.args[bc.var.index()].expect_const() + } + } + let delegate = ToFreshVars { args }; + self.tcx.replace_bound_vars_uncached_with_clauses(binder, delegate) + } + /// See the [`region_constraints::RegionConstraintCollector::verify_generic_bound`] method. pub(crate) fn verify_generic_bound( &self, diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 324725a079bbe..7c8bbb4b1b2c3 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -51,6 +51,43 @@ impl<'tcx> InferCtxt<'tcx> { self.tcx.replace_bound_vars_uncached(binder, delegate) } + pub fn enter_forall_with_assumptions_and_leak_universe( + &self, + binder: ty::Binder<'tcx, T>, + param_env: ty::ParamEnv<'tcx>, + ) -> (T, ty::ParamEnv<'tcx>) + where + T: TypeFoldable>, + { + if !binder.as_ref().skip_binder_with_clauses().has_escaping_bound_vars() { + let (value, assumptions) = binder.skip_binder_with_clauses(); + return (value, param_env.extend(self.tcx, assumptions)); + } + + let next_universe = self.create_next_universe(); + + // TODO: Deduplicate this with above. + let delegate = FnMutDelegate { + regions: &mut |br: ty::BoundRegion<'tcx>| { + ty::Region::new_placeholder(self.tcx, ty::PlaceholderRegion::new(next_universe, br)) + }, + types: &mut |bound_ty: ty::BoundTy<'tcx>| { + Ty::new_placeholder(self.tcx, ty::PlaceholderType::new(next_universe, bound_ty)) + }, + consts: &mut |bound_ct: ty::BoundConst<'tcx>| { + ty::Const::new_placeholder( + self.tcx, + ty::PlaceholderConst::new(next_universe, bound_ct), + ) + }, + }; + + debug!(?next_universe); + let (value, assumptions) = + self.tcx.replace_bound_vars_uncached_with_clauses(binder, delegate); + (value, param_env.extend(self.tcx, assumptions)) + } + /// Replaces all bound variables (lifetimes, types, and constants) bound by /// `binder` with placeholder variables in a new universe and then calls the /// closure `f` with the instantiated value. The new placeholders can only be @@ -76,6 +113,26 @@ impl<'tcx> InferCtxt<'tcx> { f(value) } + #[instrument(level = "debug", skip(self, f))] + pub fn enter_forall_with_assumptions( + &self, + forall: ty::Binder<'tcx, T>, + param_env: ty::ParamEnv<'tcx>, + f: impl FnOnce(T, ty::ParamEnv<'tcx>) -> U, + ) -> U + where + T: TypeFoldable>, + { + // FIXME: currently we do nothing to prevent placeholders with the new universe being + // used after exiting `f`. For example region subtyping can result in outlives constraints + // that name placeholders created in this function. Nested goals from type relations can + // also contain placeholders created by this function. + let (value, param_env) = + self.enter_forall_with_assumptions_and_leak_universe(forall, param_env); + debug!(?value); + f(value, param_env) + } + /// See [RegionConstraintCollector::leak_check][1]. We only check placeholder /// leaking into `outer_universe`, i.e. placeholders which cannot be named by that /// universe. diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 3d9148d6ed7ba..3b4c8adb14f23 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -269,6 +269,14 @@ impl<'tcx> TyCtxt<'tcx> { self.replace_escaping_bound_vars_uncached(value.skip_binder(), delegate) } + pub fn replace_bound_vars_uncached_with_clauses>>( + self, + value: Binder<'tcx, T>, + delegate: impl BoundVarReplacerDelegate<'tcx>, + ) -> (T, ty::Clauses<'tcx>) { + self.replace_escaping_bound_vars_uncached(value.skip_binder_with_clauses(), delegate) + } + /// Replaces any late-bound regions bound in `value` with /// free variants attached to `all_outlive_scope`. pub fn liberate_late_bound_regions( diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e10ecdbf00d81..1ec5035f0e1d8 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1052,6 +1052,20 @@ impl<'tcx> ParamEnv<'tcx> { ParamEnv::new(tcx.reveal_opaque_types_in_bounds(self.caller_bounds)) } } + + /// TODO: + pub fn extend(self, tcx: TyCtxt<'tcx>, assumptions: ty::Clauses<'tcx>) -> Self { + if assumptions.is_empty() { + self + } else if self.caller_bounds.is_empty() { + ParamEnv { caller_bounds: assumptions } + } else { + ParamEnv { + caller_bounds: tcx + .mk_clauses_from_iter(self.caller_bounds.iter().chain(assumptions)), + } + } + } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TypeFoldable, TypeVisitable)] diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 656c645d2cdb0..a106de8ed1c59 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -212,8 +212,6 @@ impl<'tcx> Clause<'tcx> { } } -impl<'tcx> rustc_type_ir::inherent::Clauses> for ty::Clauses<'tcx> {} - #[extension(pub trait ExistentialPredicateStableCmpExt<'tcx>)] impl<'tcx> ExistentialPredicate<'tcx> { /// Compares via an ordering that will not change if modules are reordered or other changes are diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index 824c78094a69b..84411d00c4367 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -581,13 +581,13 @@ impl, I: Interner> TypeFolder for Canonicaliz } fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses { - match self.canonicalize_mode { - CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv) - | CanonicalizeMode::Response { max_input_universe: _ } => {} - CanonicalizeMode::Input(CanonicalizeInputKind::Predicate) => { - panic!("erasing 'static in env") - } - } + // match self.canonicalize_mode { + // CanonicalizeMode::Input(CanonicalizeInputKind::ParamEnv) + // | CanonicalizeMode::Response { max_input_universe: _ } => {} + // CanonicalizeMode::Input(CanonicalizeInputKind::Predicate) => { + // panic!("erasing 'static in env") + // } + // } if !c.flags().intersects(NEEDS_CANONICAL) { c } else { c.super_fold_with(self) } } } diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 75ba3285e13f2..d0fbeb0246500 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -66,9 +66,11 @@ where ) -> QueryResultOrRerunNonErased { let host_clause = assumption.as_host_effect_clause().unwrap(); - let assumption_trait_pred = ecx.instantiate_binder_with_infer(host_clause); + let (assumption_trait_pred, goals) = + ecx.instantiate_binder_with_infer_and_goals(host_clause); ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; - + let cx = ecx.cx(); + ecx.add_goals(GoalSource::Misc, goals.iter().map(|clause| goal.with(cx, clause))); then(ecx) } @@ -260,7 +262,7 @@ where structural_traits::instantiate_constituent_tys_for_copy_clone_trait(ecx, self_ty)?; ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { - ecx.enter_forall_with_assumptions(constituent_tys, goal.param_env, |ecx, tys| { + ecx.enter_forall_with_assumptions(constituent_tys, goal.param_env, |ecx, tys, _| { ecx.add_goals( GoalSource::ImplWhereBound, tys.into_iter().map(|ty| { diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 97aaf076a9d9a..b69fd99281d7a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -905,8 +905,9 @@ where goal: Goal, ) -> QueryResultOrRerunNonErased { let Goal { param_env, predicate } = goal; + debug!(?predicate); let kind = predicate.kind(); - self.enter_forall_with_assumptions(kind, param_env, |ecx, kind| { + self.enter_forall_with_assumptions(kind, param_env, |ecx, kind, param_env| { Ok(match kind { ty::PredicateKind::Clause(ty::ClauseKind::Trait(predicate)) => { ecx.compute_trait_goal(Goal { param_env, predicate }).map(|(r, _via)| r)? @@ -1360,6 +1361,13 @@ where self.delegate.instantiate_binder_with_infer(value) } + pub(super) fn instantiate_binder_with_infer_and_goals + Copy>( + &self, + value: ty::Binder, + ) -> (T, I::Clauses) { + self.delegate.instantiate_binder_with_infer_and_goals(value) + } + /// `enter_forall_with_assumptions`, but takes `&mut self` and passes it back through /// the callback since it can't be aliased during the call. /// @@ -1367,13 +1375,14 @@ where /// assumptions associated with the binder. /// /// FIXME(inherent_associated_types): fix this? + // (temp)self reminder: fix the doc pub(super) fn enter_forall_with_assumptions, U>( &mut self, value: ty::Binder, param_env: I::ParamEnv, - f: impl FnOnce(&mut Self, T) -> U, + f: impl FnOnce(&mut Self, T, I::ParamEnv) -> U, ) -> U { - self.delegate.enter_forall_without_assumptions(value, |value| { + self.delegate.enter_forall_with_assumptions(value, param_env, |value, param_env| { let u = self.delegate.universe(); let assumptions = if self.cx().assumptions_on_binders() { self.region_assumptions_for_placeholders_in_universe(value.clone(), u, param_env) @@ -1381,7 +1390,7 @@ where None }; self.delegate.insert_placeholder_assumptions(u, assumptions); - f(self, value) + f(self, value, param_env) }) } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs index e49e6147b5251..636a471124c00 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs @@ -211,9 +211,10 @@ where ) -> QueryResultOrRerunNonErased { let cx = ecx.cx(); let projection_pred = assumption.as_projection_clause().unwrap(); - let assumption_projection_pred = ecx.instantiate_binder_with_infer(projection_pred); + let (assumption_projection_pred, goals) = + ecx.instantiate_binder_with_infer_and_goals(projection_pred); ecx.eq(goal.param_env, goal.predicate.alias, assumption_projection_pred.projection_term)?; - + ecx.add_goals(GoalSource::Misc, goals.iter().map(|clause| goal.with(cx, clause))); ecx.instantiate_normalizes_to_term(goal, assumption_projection_pred.term); // Add GAT where clauses from the trait's definition diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index a8c5b95415621..e63a0e45c4ae4 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -193,9 +193,11 @@ where return Self::match_assumption(ecx, goal, meta_sized_clause, then); } - let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause); + let (assumption_trait_pred, goals) = + ecx.instantiate_binder_with_infer_and_goals(trait_clause); ecx.eq(goal.param_env, goal.predicate.trait_ref, assumption_trait_pred.trait_ref)?; - + let cx = ecx.cx(); + ecx.add_goals(GoalSource::Misc, goals.iter().map(|clause| goal.with(cx, clause))); then(ecx) } @@ -1078,7 +1080,7 @@ where ecx.enter_forall_with_assumptions( target_projection, param_env, - |ecx, target_projection| { + |ecx, target_projection, param_env| { let source_projection = ecx.instantiate_binder_with_infer(source_projection); ecx.eq(param_env, source_projection, target_projection)?; @@ -1101,7 +1103,7 @@ where ecx.enter_forall_with_assumptions( target_principal, param_env, - |ecx, target_principal| { + |ecx, target_principal, param_env| { let source_principal = ecx.instantiate_binder_with_infer(source_principal); ecx.eq(param_env, source_principal, target_principal)?; @@ -1133,7 +1135,7 @@ where ecx.enter_forall_with_assumptions( target_projection, param_env, - |ecx, target_projection| { + |ecx, target_projection, param_env| { let source_projection = ecx.instantiate_binder_with_infer(source_projection); ecx.eq(param_env, source_projection, target_projection)?; @@ -1367,7 +1369,7 @@ where let goals = ecx.enter_forall_with_assumptions( constituent_tys(ecx, goal.predicate.self_ty())?, goal.param_env, - |ecx, tys| { + |ecx, tys, _| { tys.into_iter() .map(|ty| { goal.with(ecx.cx(), goal.predicate.with_replaced_self_ty(ecx.cx(), ty)) diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 28efb9333b6b8..0b98f8ae1e25f 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -14,7 +14,9 @@ use tracing::instrument; use crate::data_structures::SsoHashSet; use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; use crate::inherent::*; -use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; +use crate::visit::{ + Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, try_visit, +}; use crate::{self as ty, DebruijnIndex, Interner, UniverseIndex, Unnormalized}; /// `Binder` is a binder for higher-ranked lifetimes or types. It is part of the @@ -342,7 +344,7 @@ impl TypeVisitor for ValidateBoundVars { fn visit_const(&mut self, c: I::Const) -> Self::Result { if c.outer_exclusive_binder() < self.binder_index { - return ControlFlow::Break(()); + return; } match c.kind() { ty::ConstKind::Bound(debruijn, bound_const) diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index e61e96c70f2e5..42861fc7dc96a 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -411,6 +411,10 @@ pub trait InferCtxtLike: Sized { value: ty::Binder, f: impl FnOnce(T) -> U, ) -> U; + fn instantiate_binder_with_infer_and_goals + Copy>( + &self, + value: ty::Binder, + ) -> (T, ::Clauses); /// FIXME(-Zassumptions-on-binders): Any usage of this method is likely wrong /// and should be replaced in the long term by actually taking assumptions into @@ -421,6 +425,13 @@ pub trait InferCtxtLike: Sized { f: impl FnOnce(T) -> U, ) -> U; + fn enter_forall_with_assumptions, U>( + &self, + value: ty::Binder, + param_env: ::ParamEnv, + f: impl FnOnce(T, ::ParamEnv) -> U, + ) -> U; + fn equate_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid); fn sub_unify_ty_vids_raw(&self, a: ty::TyVid, b: ty::TyVid); fn equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid); diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 5a98ff74cea42..84ad88245a2f6 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -496,6 +496,7 @@ macro_rules! declare_lift_into { declare_lift_into! { BoundVarKinds, + Clauses, Const, DefId, FreeConstAliasId, diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 4b23bfd0f7765..213893b178a19 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -133,6 +133,7 @@ where I::OpaqueTyId: StableHash, I::FreeTyAliasId: StableHash, I::BoundVarKinds: StableHash, + I::Clauses: StableHash, { #[inline] fn stable_hash(&self, hcx: &mut CTX, hasher: &mut StableHasher) { diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 492c37481298b..5ae544c3452a3 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -132,6 +132,12 @@ pub trait TypeVisitor: Sized { /////////////////////////////////////////////////////////////////////////// // Traversal implementations. +impl> TypeVisitable for &T { + fn visit_with>(&self, visitor: &mut V) -> V::Result { + (**self).visit_with(visitor) + } +} + impl, U: TypeVisitable> TypeVisitable for (T, U) { fn visit_with>(&self, visitor: &mut V) -> V::Result { try_visit!(self.0.visit_with(visitor)); From c6b9b68db31de386328fcef4a7c7de25e38872e5 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 13 Mar 2025 05:54:45 +0000 Subject: [PATCH 3/9] Implement non-lifetime binder lowering --- compiler/rustc_ast_lowering/src/item.rs | 18 ++- compiler/rustc_ast_lowering/src/lib.rs | 26 +++- compiler/rustc_hir/src/hir.rs | 7 +- compiler/rustc_hir/src/intravisit.rs | 6 +- .../src/collect/item_bounds.rs | 2 + .../src/collect/predicates_of.rs | 134 ++++------------ .../src/collect/resolve_bound_vars.rs | 3 + .../src/hir_ty_lowering/bounds.rs | 146 +++++++++++++++++- .../src/hir_ty_lowering/dyn_trait.rs | 1 + .../src/hir_ty_lowering/mod.rs | 6 +- compiler/rustc_type_ir/src/binder.rs | 15 +- 11 files changed, 245 insertions(+), 119 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 6340d125cb72c..08d309c89c284 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1985,6 +1985,7 @@ impl<'hir> LoweringContext<'_, 'hir> { bounded_ty: self.arena.alloc(bounded_ty), bounds, bound_generic_params: &[], + bound_assumptions: &[], origin, }) } @@ -2017,7 +2018,7 @@ impl<'hir> LoweringContext<'_, 'hir> { bounded_ty, bounds, }) => { - let rbp = if bound_generic_params.is_empty() + let mut rbp = if bound_generic_params.is_empty() && let Some(res) = self.get_partial_res(bounded_ty.id).and_then(|r| r.full_res()) && let Res::Def(DefKind::TyParam, def_id) = res @@ -2032,6 +2033,21 @@ impl<'hir> LoweringContext<'_, 'hir> { bound_generic_params, hir::GenericParamSource::Binder, ), + bound_assumptions: self.arena.alloc_from_iter( + bound_generic_params.iter().filter_map(|param| { + self.lower_generic_bound_predicate( + param.ident, + param.id, + ¶m.kind, + ¶m.bounds, + param.colon_span, + span, + rbp.reborrow(), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + PredicateOrigin::GenericParam, + ) + }), + ), bounded_ty: self.lower_ty_alloc( bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound), diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b8d708d42ff10..92d42587ae028 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -57,7 +57,12 @@ use rustc_hir::definitions::PerParentDisambiguatorState; use rustc_hir::lints::DelayedLint; use rustc_hir::{ self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource, - LifetimeSyntax, MissingLifetimeKind, ParamName, Target, TraitCandidate, find_attr, + LifetimeSyntax, MissingLifetimeKind, ParamName, PredicateOrigin, Target, TraitCandidate, + find_attr, +}; +use rustc_hir::{ + self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, ParamName, PredicateOrigin, + TraitCandidate, }; use rustc_index::{Idx, IndexVec}; use rustc_macros::extension; @@ -2076,6 +2081,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::GenericBound::Trait(hir::PolyTraitRef { bound_generic_params: &[], + bound_assumptions: &[], modifiers: hir::TraitBoundModifiers::NONE, trait_ref: hir::TraitRef { path: self.make_lang_item_path(trait_lang_item, opaque_ty_span, Some(bound_args)), @@ -2328,9 +2334,23 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_poly_trait_ref( &mut self, PolyTraitRef { bound_generic_params, modifiers, trait_ref, span, parens: _ }: &PolyTraitRef, - rbp: RelaxedBoundPolicy<'_>, + mut rbp: RelaxedBoundPolicy<'_>, itctx: ImplTraitContext, ) -> hir::PolyTraitRef<'hir> { + let bound_assumptions = + self.arena.alloc_from_iter(bound_generic_params.iter().filter_map(|param| { + self.lower_generic_bound_predicate( + param.ident, + param.id, + ¶m.kind, + ¶m.bounds, + param.colon_span, + *span, + rbp.reborrow(), + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + PredicateOrigin::GenericParam, + ) + })); let bound_generic_params = self.lower_lifetime_binder(trait_ref.ref_id, bound_generic_params); let trait_ref = self.lower_trait_ref(*modifiers, trait_ref, itctx); @@ -2342,6 +2362,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::PolyTraitRef { bound_generic_params, + bound_assumptions, modifiers, trait_ref, span: self.lower_span(*span), @@ -3102,6 +3123,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Res::Def(DefKind::Trait | DefKind::TraitAlias, _) => { let principal = hir::PolyTraitRef { bound_generic_params: &[], + bound_assumptions: &[], modifiers: hir::TraitBoundModifiers::NONE, trait_ref: hir::TraitRef { path, hir_ref_id: hir_id }, span: self.lower_span(span), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 8d886e7ac6fbf..511d6c304f072 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1227,6 +1227,8 @@ pub struct WhereBoundPredicate<'hir> { pub origin: PredicateOrigin, /// Any generics from a `for` binding. pub bound_generic_params: &'hir [GenericParam<'hir>], + /// The `'a + Trait` in `for ...` + pub bound_assumptions: &'hir [WherePredicate<'hir>], /// The type being bounded. pub bounded_ty: &'hir Ty<'hir>, /// Trait and lifetime bounds (e.g., `Clone + Send + 'static`). @@ -4447,6 +4449,9 @@ pub struct PolyTraitRef<'hir> { /// The `'a` in `for<'a> Foo<&'a T>`. pub bound_generic_params: &'hir [GenericParam<'hir>], + /// The `'a + Trait` in `for ...` + pub bound_assumptions: &'hir [WherePredicate<'hir>], + /// The constness and polarity of the trait ref. /// /// The `async` modifier is lowered directly into a different trait for now. @@ -5470,7 +5475,7 @@ mod size_asserts { static_assert_size!(ForeignItem<'_>, 96); static_assert_size!(ForeignItemKind<'_>, 56); static_assert_size!(GenericArg<'_>, 16); - static_assert_size!(GenericBound<'_>, 64); + static_assert_size!(GenericBound<'_>, 80); static_assert_size!(Generics<'_>, 56); static_assert_size!(Impl<'_>, 48); static_assert_size!(ImplItem<'_>, 88); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index d5c5e8845f41b..10367d7762a8f 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1186,10 +1186,12 @@ pub fn walk_where_predicate<'v, V: Visitor<'v>>( ref bounded_ty, bounds, bound_generic_params, + bound_assumptions, origin: _, }) => { try_visit!(visitor.visit_ty_unambig(bounded_ty)); walk_list!(visitor, visit_param_bound, bounds); + walk_list!(visitor, visit_where_predicate, bound_assumptions); walk_list!(visitor, visit_generic_param, bound_generic_params); } WherePredicateKind::RegionPredicate(WhereRegionPredicate { @@ -1392,8 +1394,10 @@ pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>( visitor: &mut V, trait_ref: &'v PolyTraitRef<'v>, ) -> V::Result { - let PolyTraitRef { bound_generic_params, modifiers: _, trait_ref, span: _ } = trait_ref; + let PolyTraitRef { bound_generic_params, bound_assumptions, modifiers: _, trait_ref, span: _ } = + trait_ref; walk_list!(visitor, visit_generic_param, *bound_generic_params); + walk_list!(visitor, visit_where_predicate, *bound_assumptions); visitor.visit_trait_ref(trait_ref) } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 7603f11b7ebef..c3130279c2bba 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -44,6 +44,7 @@ fn associated_type_bounds<'tcx>( hir_bounds, &mut bounds, ty::List::empty(), + ty::ListWithCachedTypeInfo::empty(), filter, OverlappingAsssocItemConstraints::Allowed, ); @@ -373,6 +374,7 @@ fn opaque_type_bounds<'tcx>( hir_bounds, &mut bounds, ty::List::empty(), + ty::ListWithCachedTypeInfo::empty(), filter, OverlappingAsssocItemConstraints::Allowed, ); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 6e6b6602f3a74..d4ef83b281cef 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_middle::ty::{ }; use rustc_middle::{bug, span_bug}; use rustc_span::{DUMMY_SP, Ident, Span}; -use tracing::{debug, instrument, trace}; +use tracing::{debug, instrument}; use super::item_bounds::explicit_item_bounds_with_filter; use crate::collect::ItemCtxt; @@ -19,7 +19,6 @@ use crate::constrained_generic_params as cgp; use crate::delegation::inherit_predicates_for_delegation_item; use crate::hir_ty_lowering::{ HirTyLowerer, ImpliedBoundsContext, OverlappingAsssocItemConstraints, PredicateFilter, - RegionInferReason, }; /// Returns a list of all type predicates (explicit and implicit) for the definition with @@ -193,6 +192,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen self_bounds, &mut bounds, ty::List::empty(), + ty::ListWithCachedTypeInfo::empty(), PredicateFilter::All, OverlappingAsssocItemConstraints::Allowed, ); @@ -227,107 +227,11 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen predicates.insert((trait_ref.upcast(tcx), tcx.def_span(def_id))); } - // Add implicit predicates that should be treated as if the user has written them, - // including the implicit `T: Sized` for all generic parameters, and `ConstArgHasType` - // for const params. - for param in hir_generics.params { - match param.kind { - GenericParamKind::Lifetime { .. } => (), - GenericParamKind::Type { .. } => { - let param_ty = icx.lowerer().lower_ty_param(param.hir_id); - let mut bounds = Vec::new(); - // Implicit bounds are added to type params unless a `?Trait` bound is found - icx.lowerer().add_implicit_sizedness_bounds( - &mut bounds, - param_ty, - &[], - hir_generics.predicates, - ImpliedBoundsContext::TyParam(param.def_id), - param.span, - ); - icx.lowerer().add_default_traits( - &mut bounds, - param_ty, - &[], - hir_generics.predicates, - ImpliedBoundsContext::TyParam(param.def_id), - param.span, - ); - trace!(?bounds); - predicates.extend(bounds); - trace!(?predicates); - } - hir::GenericParamKind::Const { .. } => { - let param_def_id = param.def_id.to_def_id(); - let ct_ty = tcx.type_of(param_def_id).instantiate_identity().skip_norm_wip(); - let ct = icx.lowerer().lower_const_param(param_def_id, param.hir_id); - predicates - .insert((ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), param.span)); - } - } - } - - trace!(?predicates); - // Add inline `` bounds and bounds in the where clause. - for predicate in hir_generics.predicates { - match predicate.kind { - hir::WherePredicateKind::BoundPredicate(bound_pred) => { - let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty); - let bound_vars = tcx.late_bound_vars(predicate.hir_id); - - // This is a `where Ty:` (sic!). - if bound_pred.bounds.is_empty() { - if let ty::Param(_) = ty.kind() { - // We can skip the predicate because type parameters are trivially WF. - } else { - // Keep the type around in a dummy predicate. That way, it's not a complete - // noop (see #53696) and `Ty` is still checked for WF. - - let span = bound_pred.bounded_ty.span; - let predicate = ty::Binder::bind_with_vars( - ty::ClauseKind::WellFormed(ty.into()), - bound_vars, - ); - predicates.insert((predicate.upcast(tcx), span)); - } - } - - let mut bounds = Vec::new(); - icx.lowerer().lower_bounds( - ty, - bound_pred.bounds, - &mut bounds, - bound_vars, - PredicateFilter::All, - OverlappingAsssocItemConstraints::Allowed, - ); - predicates.extend(bounds); - } - - hir::WherePredicateKind::RegionPredicate(region_pred) => { - let r1 = icx - .lowerer() - .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate); - predicates.extend(region_pred.bounds.iter().map(|bound| { - let (r2, span) = match bound { - hir::GenericBound::Outlives(lt) => ( - icx.lowerer().lower_lifetime(lt, RegionInferReason::RegionPredicate), - lt.ident.span, - ), - bound => { - span_bug!( - bound.span(), - "lifetime param bounds must be outlives, but found {bound:?}" - ) - } - }; - let pred = - ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)).upcast(tcx); - (pred, span) - })) - } - } - } + icx.lowerer().lower_where_predicates( + hir_generics.params, + hir_generics.predicates, + &mut predicates, + ); if tcx.features().generic_const_exprs() { predicates.extend(const_evaluatable_predicates_of(tcx, def_id, &predicates)); @@ -684,6 +588,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>( superbounds, &mut bounds, ty::List::empty(), + ty::ListWithCachedTypeInfo::empty(), filter, OverlappingAsssocItemConstraints::Allowed, ); @@ -1040,6 +945,16 @@ impl<'tcx> ItemCtxt<'tcx> { } let bound_ty = self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty); + let mut bound_assumptions = FxIndexSet::default(); + if self.tcx.features().non_lifetime_binders() { + self.lowerer().lower_where_predicates( + predicate.bound_generic_params, + predicate.bound_assumptions, + &mut bound_assumptions, + ); + } + let bound_assumptions = + self.tcx().mk_clauses_from_iter(bound_assumptions.into_iter().map(|(c, _)| c)); let bound_vars = self.tcx.late_bound_vars(hir_id); self.lowerer().lower_bounds( @@ -1047,6 +962,7 @@ impl<'tcx> ItemCtxt<'tcx> { predicate.bounds, &mut bounds, bound_vars, + bound_assumptions, filter, OverlappingAsssocItemConstraints::Allowed, ); @@ -1127,12 +1043,23 @@ pub(super) fn const_conditions<'tcx>( match pred.kind { hir::WherePredicateKind::BoundPredicate(bound_pred) => { let ty = icx.lowerer().lower_ty_maybe_return_type_notation(bound_pred.bounded_ty); + let mut bound_assumptions = FxIndexSet::default(); + if tcx.features().non_lifetime_binders() { + icx.lowerer().lower_where_predicates( + bound_pred.bound_generic_params, + bound_pred.bound_assumptions, + &mut bound_assumptions, + ); + } + let bound_assumptions = + tcx.mk_clauses_from_iter(bound_assumptions.into_iter().map(|(c, _)| c)); let bound_vars = tcx.late_bound_vars(pred.hir_id); icx.lowerer().lower_bounds( ty, bound_pred.bounds.iter(), &mut bounds, bound_vars, + bound_assumptions, PredicateFilter::ConstIfConst, OverlappingAsssocItemConstraints::Allowed, ); @@ -1156,6 +1083,7 @@ pub(super) fn const_conditions<'tcx>( supertraits, &mut bounds, ty::List::empty(), + ty::ListWithCachedTypeInfo::empty(), PredicateFilter::ConstIfConst, OverlappingAsssocItemConstraints::Allowed, ); 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 70129192faa2c..3e41efa5486ae 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -418,6 +418,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { }; self.with(scope, |this| { walk_list!(this, visit_generic_param, trait_ref.bound_generic_params); + walk_list!(this, visit_where_predicate, trait_ref.bound_assumptions); this.visit_trait_ref(&trait_ref.trait_ref); }); } @@ -996,6 +997,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { bounded_ty, bounds, bound_generic_params, + bound_assumptions, origin, .. }) => { @@ -1030,6 +1032,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { self.with(scope, |this| { walk_list!(this, visit_generic_param, bound_generic_params); this.visit_ty_unambig(bounded_ty); + walk_list!(this, visit_where_predicate, bound_assumptions); walk_list!(this, visit_param_bound, bounds); }) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 74d5447b03e80..002330c431067 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -7,14 +7,14 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{PolyTraitRef, find_attr}; -use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, }; +use rustc_middle::{bug, span_bug}; use rustc_span::{DesugaringKind, ErrorGuaranteed, Ident, Span, kw}; use rustc_trait_selection::traits; -use tracing::{debug, instrument}; +use tracing::{debug, instrument, trace}; use crate::diagnostics; use crate::hir_ty_lowering::{ @@ -134,12 +134,136 @@ fn add_trait_bound<'tcx>( span: Span, ) { let trait_ref = ty::TraitRef::new(tcx, did, [self_ty]); + let trait_ref = ty::Binder::bind_with_vars(trait_ref, ty::List::empty()); // Preferable to put sizedness obligations first, since we report better errors for `Sized` // ambiguity. bounds.insert(0, (trait_ref.upcast(tcx), span)); } impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { + pub(crate) fn lower_where_predicates( + &self, + params: &[hir::GenericParam<'tcx>], + hir_predicates: &'tcx [hir::WherePredicate<'tcx>], + predicates: &mut FxIndexSet<(ty::Clause<'tcx>, Span)>, + ) { + let tcx = self.tcx(); + // Add implicit predicates that should be treated as if the user has written them, + // including the implicit `T: Sized` for all generic parameters, and `ConstArgHasType` + // for const params. + for param in params { + match param.kind { + hir::GenericParamKind::Lifetime { .. } => (), + hir::GenericParamKind::Type { .. } => { + // TODO: + let param_ty = ty::shift_vars(self.tcx(), self.lower_ty_param(param.hir_id), 1); + let mut bounds = Vec::new(); + // Implicit bounds are added to type params unless a `?Trait` bound is found + self.add_implicit_sizedness_bounds( + &mut bounds, + param_ty, + &[], + hir_predicates, + ImpliedBoundsContext::TyParam(param.def_id), + param.span, + ); + self.add_default_traits( + &mut bounds, + param_ty, + &[], + hir_predicates, + ImpliedBoundsContext::TyParam(param.def_id), + param.span, + ); + trace!(?bounds); + predicates.extend(bounds); + trace!(?predicates); + } + hir::GenericParamKind::Const { .. } => { + let param_def_id = param.def_id.to_def_id(); + let ct_ty = tcx.type_of(param_def_id).instantiate_identity().skip_norm_wip(); + let ct = self.lower_const_param(param_def_id, param.hir_id); + predicates.insert(( + ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), + param.span, + )); + } + } + } + + // Add inline `` bounds and bounds in the where clause. + for predicate in hir_predicates { + match predicate.kind { + hir::WherePredicateKind::BoundPredicate(bound_pred) => { + let ty = self.lower_ty_maybe_return_type_notation(bound_pred.bounded_ty); + let mut bound_assumptions = FxIndexSet::default(); + if self.tcx().features().non_lifetime_binders() { + self.lower_where_predicates( + bound_pred.bound_generic_params, + bound_pred.bound_assumptions, + &mut bound_assumptions, + ); + } + let bound_assumptions = self.tcx().mk_clauses_from_iter( + bound_assumptions.into_iter().map(|(clause, _)| clause), + ); + let bound_vars = tcx.late_bound_vars(predicate.hir_id); + + // This is a `where Ty:` (sic!). + if bound_pred.bounds.is_empty() { + if let ty::Param(_) = ty.kind() { + // We can skip the predicate because type parameters are trivially WF. + } else { + // Keep the type around in a dummy predicate. That way, it's not a complete + // noop (see #53696) and `Ty` is still checked for WF. + + let span = bound_pred.bounded_ty.span; + let predicate = ty::Binder::bind_with_vars( + ty::ClauseKind::WellFormed(ty.into()), + bound_vars, + ); + predicates.insert((predicate.upcast(tcx), span)); + } + } + + let mut bounds = Vec::new(); + self.lower_bounds( + ty, + bound_pred.bounds, + &mut bounds, + bound_vars, + bound_assumptions, + PredicateFilter::All, + OverlappingAsssocItemConstraints::Allowed, + ); + predicates.extend(bounds); + } + + hir::WherePredicateKind::RegionPredicate(region_pred) => { + let r1 = self + .lower_lifetime(region_pred.lifetime, RegionInferReason::RegionPredicate); + predicates.extend(region_pred.bounds.iter().map(|bound| { + let (r2, span) = match bound { + hir::GenericBound::Outlives(lt) => ( + self.lower_lifetime(lt, RegionInferReason::RegionPredicate), + lt.ident.span, + ), + bound => { + span_bug!( + bound.span(), + "lifetime param bounds must be outlives, but found {bound:?}" + ) + } + }; + let pred = ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r1, r2)) + .upcast(tcx); + (pred, span) + })) + } + } + } + } + /// Adds sizedness bounds to a trait, trait alias, parameter, opaque type or associated type. /// /// - On parameters, opaque type and associated types, add default `Sized` bound if no explicit @@ -349,6 +473,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_bounds: I, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, bound_vars: &'tcx ty::List>, + bound_assumptions: ty::Clauses<'tcx>, predicate_filter: PredicateFilter, overlapping_assoc_constraints: OverlappingAsssocItemConstraints, ) where @@ -370,9 +495,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match hir_bound { hir::GenericBound::Trait(poly_trait_ref) => { + let mut additional_bound_assumptions = FxIndexSet::default(); + if self.tcx().features().non_lifetime_binders() { + self.lower_where_predicates( + poly_trait_ref.bound_generic_params, + poly_trait_ref.bound_assumptions, + &mut additional_bound_assumptions, + ); + } + let bound_assumptions = + self.tcx().mk_clauses_from_iter(bound_assumptions.into_iter().chain( + additional_bound_assumptions.into_iter().map(|(clause, _)| clause), + )); let _ = self.lower_poly_trait_ref( poly_trait_ref, param_ty, + bound_assumptions, bounds, predicate_filter, overlapping_assoc_constraints, @@ -388,9 +526,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound); - let bound = ty::Binder::bind_with_vars( + let bound = ty::Binder::bind_with_vars_and_clauses( ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)), bound_vars, + bound_assumptions, ); bounds.push((bound.upcast(self.tcx()), lifetime.ident.span)); } @@ -631,6 +770,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_bounds, bounds, projection_ty.bound_vars(), + projection_ty.skip_binder_with_clauses().1, predicate_filter, OverlappingAsssocItemConstraints::Allowed, ); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index c161652cafd11..d775f7d6d10bc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -67,6 +67,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let result = self.lower_poly_trait_ref( poly_trait_ref, dummy_self, + ty::ListWithCachedTypeInfo::empty(), &mut user_written_bounds, PredicateFilter::SelfOnly, OverlappingAsssocItemConstraints::Forbidden, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 871aef76704e4..28a21cb83eacf 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -955,8 +955,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { modifiers: hir::TraitBoundModifiers { constness, polarity }, trait_ref, span, + .. }: &hir::PolyTraitRef<'tcx>, self_ty: Ty<'tcx>, + bound_assumptions: ty::Clauses<'tcx>, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, predicate_filter: PredicateFilter, overlapping_assoc_item_constraints: OverlappingAsssocItemConstraints, @@ -1029,9 +1031,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let bound_vars = tcx.late_bound_vars(trait_ref.hir_ref_id); debug!(?bound_vars); - let poly_trait_ref = ty::Binder::bind_with_vars( + let poly_trait_ref = ty::Binder::bind_with_vars_and_clauses( ty::TraitRef::new_from_args(tcx, trait_def_id, generic_args), bound_vars, + bound_assumptions, ); debug!(?poly_trait_ref); @@ -3089,6 +3092,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_bounds.iter(), &mut bounds, ty::List::empty(), + ty::ListWithCachedTypeInfo::empty(), PredicateFilter::All, OverlappingAsssocItemConstraints::Allowed, ); diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 0b98f8ae1e25f..020d8c192c6cb 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -1,7 +1,7 @@ use std::fmt; use std::hash::Hash; use std::marker::PhantomData; -use std::ops::{ControlFlow, Deref}; +use std::ops::Deref; use derive_where::derive_where; #[cfg(feature = "nightly")] @@ -272,8 +272,11 @@ impl Binder { where T: TypeVisitable, { - // `self.value` is equivalent to `self.skip_binder()` - if self.value.has_escaping_bound_vars() { None } else { Some(self.skip_binder()) } + if self.value.has_escaping_bound_vars() || !self.clauses.is_empty() { + None + } else { + Some(self.skip_binder()) + } } } @@ -311,7 +314,7 @@ impl ValidateBoundVars { } impl TypeVisitor for ValidateBoundVars { - type Result = ControlFlow<()>; + type Result = (); fn visit_binder>(&mut self, t: &Binder) -> Self::Result { self.binder_index.shift_in(1); @@ -324,7 +327,7 @@ impl TypeVisitor for ValidateBoundVars { if t.outer_exclusive_binder() < self.binder_index || !self.visited.insert((self.binder_index, t)) { - return ControlFlow::Break(()); + return; } match t.kind() { ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ty) @@ -374,8 +377,6 @@ impl TypeVisitor for ValidateBoundVars { _ => (), }; - - ControlFlow::Continue(()) } } From 4c793868f103accfd61e366781af7e48146bbd48 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 18 Mar 2025 19:23:07 +0000 Subject: [PATCH 4/9] Bless tests --- .../src/hir_ty_lowering/bounds.rs | 24 +++++-- .../src/infer/relate/higher_ranked.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 5 +- .../clippy/clippy_lints/src/lifetimes.rs | 1 + tests/ui/attributes/dump-preds.stderr | 30 ++++----- .../binder/bounds-on-closure-type-binders.rs | 2 +- .../bounds-on-closure-type-binders.stderr | 6 +- .../byte-string-u8-validation.rs | 4 +- .../byte-string-u8-validation.stderr | 4 +- tests/ui/stats/input-stats.stderr | 6 +- tests/ui/symbol-names/basic.legacy.stderr | 4 +- .../ui/symbol-names/issue-60925.legacy.stderr | 4 +- tests/ui/traits/cache-reached-depth-ice.rs | 2 +- .../ui/traits/cache-reached-depth-ice.stderr | 2 +- .../issue-83538-tainted-cache-after-cycle.rs | 8 +-- ...sue-83538-tainted-cache-after-cycle.stderr | 8 +-- .../traits/issue-85360-eval-obligation-ice.rs | 4 +- .../issue-85360-eval-obligation-ice.stderr | 4 +- .../traits/non_lifetime_binders/bad-bounds.rs | 13 ++-- .../non_lifetime_binders/bad-bounds.stderr | 67 ++++++++++++++----- .../bounds-on-type-binders.rs | 4 +- .../bounds-on-type-binders.stderr | 8 --- ...unifying-placeholders-in-query-response.rs | 4 +- tests/ui/traits/project-modulo-regions.rs | 4 +- .../project-modulo-regions.with_clause.stderr | 2 +- ...oject-modulo-regions.without_clause.stderr | 2 +- .../in-where-clause.stderr | 2 +- 27 files changed, 135 insertions(+), 91 deletions(-) delete mode 100644 tests/ui/traits/non_lifetime_binders/bounds-on-type-binders.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 002330c431067..59ba4efbb8bbc 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -155,7 +155,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match param.kind { hir::GenericParamKind::Lifetime { .. } => (), hir::GenericParamKind::Type { .. } => { - // TODO: + // We shift the predicate by one because for a non-lifetime binder like, + // `for T: Trait`, we start out with a `T` with a debruijn index of `N`, + // but we need to shift it to be `N + 1` when we construct a clause below. let param_ty = ty::shift_vars(self.tcx(), self.lower_ty_param(param.hir_id), 1); let mut bounds = Vec::new(); // Implicit bounds are added to type params unless a `?Trait` bound is found @@ -183,10 +185,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let param_def_id = param.def_id.to_def_id(); let ct_ty = tcx.type_of(param_def_id).instantiate_identity().skip_norm_wip(); let ct = self.lower_const_param(param_def_id, param.hir_id); - predicates.insert(( - ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), - param.span, - )); + if let ty::ConstKind::Bound(..) = ct.kind() { + // We don't allow const params in non-lifetime binders today. + tcx.dcx().span_delayed_bug( + tcx.def_span(param_def_id), + "const param in non-lifetime binder not allowed", + ); + } else { + predicates.insert(( + ty::Binder::bind_with_vars( + ty::ClauseKind::ConstArgHasType(ct, ct_ty), + ty::List::empty(), + ) + .upcast(tcx), + param.span, + )); + } } } } diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 7c8bbb4b1b2c3..da1857d7ff691 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -66,7 +66,7 @@ impl<'tcx> InferCtxt<'tcx> { let next_universe = self.create_next_universe(); - // TODO: Deduplicate this with above. + // FIXME(non_lifetime_binders): Deduplicate this with above. let delegate = FnMutDelegate { regions: &mut |br: ty::BoundRegion<'tcx>| { ty::Region::new_placeholder(self.tcx, ty::PlaceholderRegion::new(next_universe, br)) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1ec5035f0e1d8..0beb26ee4aded 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1053,7 +1053,10 @@ impl<'tcx> ParamEnv<'tcx> { } } - /// TODO: + /// Creates a new param-env by augmenting the previous param-env with more predicates. + /// + /// N.B. this method does not elaborate the assumptions, and you probably should do that. + // FIXME(non_lifetime_binders): We should elaborate these predicates somewhere. pub fn extend(self, tcx: TyCtxt<'tcx>, assumptions: ty::Clauses<'tcx>) -> Self { if assumptions.is_empty() { self diff --git a/src/tools/clippy/clippy_lints/src/lifetimes.rs b/src/tools/clippy/clippy_lints/src/lifetimes.rs index 2b4828872b202..6ac6dce7cd951 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -653,6 +653,7 @@ where bounded_ty, bounds, bound_generic_params, + bound_assumptions: _, origin: _, }) = predicate.kind { diff --git a/tests/ui/attributes/dump-preds.stderr b/tests/ui/attributes/dump-preds.stderr index b4be76450c6a9..12fc5516cb797 100644 --- a/tests/ui/attributes/dump-preds.stderr +++ b/tests/ui/attributes/dump-preds.stderr @@ -4,12 +4,12 @@ error: rustc_dump_predicates LL | trait Trait: Iterator | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(<::Item as std::marker::Copy>, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(<::Item as std::marker::Copy>, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [], clauses: [] } error: rustc_dump_predicates --> $DIR/dump-preds.rs:13:5 @@ -17,15 +17,15 @@ error: rustc_dump_predicates LL | type Assoc: std::ops::Deref | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(<::Item as std::marker::Copy>, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(

, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(

, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(<>::Assoc<()> as std::marker::Copy>, polarity:Positive), bound_vars: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(<::Item as std::marker::Copy>, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(>, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(

, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(

, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(<>::Assoc<()> as std::marker::Copy>, polarity:Positive), bound_vars: [], clauses: [] } error: rustc_dump_item_bounds --> $DIR/dump-preds.rs:13:5 diff --git a/tests/ui/closures/binder/bounds-on-closure-type-binders.rs b/tests/ui/closures/binder/bounds-on-closure-type-binders.rs index 80f48a1e2b400..95f0eea53bf6b 100644 --- a/tests/ui/closures/binder/bounds-on-closure-type-binders.rs +++ b/tests/ui/closures/binder/bounds-on-closure-type-binders.rs @@ -9,5 +9,5 @@ trait Trait {} fn main() { // Regression test for issue #119067 let _ = for || -> () {}; - //~^ ERROR bounds cannot be used in this context + //~^ ERROR: late-bound type parameter not allowed on closures } diff --git a/tests/ui/closures/binder/bounds-on-closure-type-binders.stderr b/tests/ui/closures/binder/bounds-on-closure-type-binders.stderr index 50fa11ed0ed1c..c1cd9ce1fc88a 100644 --- a/tests/ui/closures/binder/bounds-on-closure-type-binders.stderr +++ b/tests/ui/closures/binder/bounds-on-closure-type-binders.stderr @@ -1,8 +1,8 @@ -error: bounds cannot be used in this context - --> $DIR/bounds-on-closure-type-binders.rs:11:20 +error: late-bound type parameter not allowed on closures + --> $DIR/bounds-on-closure-type-binders.rs:11:17 | LL | let _ = for || -> () {}; - | ^^^^^ + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.rs b/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.rs index 5d6e34804c5cc..28cb42f4b3c92 100644 --- a/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.rs +++ b/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.rs @@ -7,8 +7,8 @@ #[rustc_dump_predicates] struct ConstBytes //~^ ERROR rustc_dump_predicates -//~| NOTE Binder { value: ConstArgHasType(T/#0, &'static [*mut u8; 3_usize]), bound_vars: [] } -//~| NOTE Binder { value: TraitPredicate( as std::marker::Sized>, polarity:Positive), bound_vars: [] } +//~| NOTE Binder { value: ConstArgHasType(T/#0, &'static [*mut u8; 3_usize]), bound_vars: [], clauses: [] } +//~| NOTE Binder { value: TraitPredicate( as std::marker::Sized>, polarity:Positive), bound_vars: [], clauses: [] } //~| NOTE expected because of the type of the const parameter where diff --git a/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.stderr b/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.stderr index 34c65af7cd970..f81134f1d6ef7 100644 --- a/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.stderr +++ b/tests/ui/const-generics/adt_const_params/byte-string-u8-validation.stderr @@ -18,8 +18,8 @@ error: rustc_dump_predicates LL | struct ConstBytes | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: Binder { value: ConstArgHasType(T/#0, &'static [*mut u8; 3_usize]), bound_vars: [] } - = note: Binder { value: TraitPredicate( as std::marker::Sized>, polarity:Positive), bound_vars: [] } + = note: Binder { value: ConstArgHasType(T/#0, &'static [*mut u8; 3_usize]), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate( as std::marker::Sized>, polarity:Positive), bound_vars: [], clauses: [] } error: aborting due to 2 previous errors diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index b4d8277a46c00..99321548139b2 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -90,9 +90,9 @@ hir-stats - Struct 80 (NN.N%) 1 hir-stats - Wild 80 (NN.N%) 1 hir-stats - Binding 240 (NN.N%) 3 hir-stats GenericParam 400 (NN.N%) 5 80 +hir-stats GenericBound 320 (NN.N%) 4 80 +hir-stats - Trait 320 (NN.N%) 4 hir-stats Block 288 (NN.N%) 6 48 -hir-stats GenericBound 256 (NN.N%) 4 64 -hir-stats - Trait 256 (NN.N%) 4 hir-stats Attribute 160 (NN.N%) 4 40 hir-stats Variant 144 (NN.N%) 2 72 hir-stats GenericArgs 144 (NN.N%) 3 48 @@ -119,5 +119,5 @@ hir-stats TraitItemId 8 (NN.N%) 2 4 hir-stats ImplItemId 8 (NN.N%) 2 4 hir-stats ForeignItemId 4 (NN.N%) 1 4 hir-stats ---------------------------------------------------------------- -hir-stats Total 8_576 172 +hir-stats Total 8_640 172 hir-stats ================================================================ diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr index f88fdf7509c76..13499ba0fae1b 100644 --- a/tests/ui/symbol-names/basic.legacy.stderr +++ b/tests/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17h27f62b2d0b2beac6E) +error: symbol-name(_ZN5basic4main17h94b01178080d6693E) --> $DIR/basic.rs:8:1 | LL | #[rustc_dump_symbol_name] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::h27f62b2d0b2beac6) +error: demangling(basic::main::h94b01178080d6693) --> $DIR/basic.rs:8:1 | LL | #[rustc_dump_symbol_name] diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr index c1fc9f4b1cea1..d2e0ab7828b4f 100644 --- a/tests/ui/symbol-names/issue-60925.legacy.stderr +++ b/tests/ui/symbol-names/issue-60925.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17h1eb769490ff06e77E) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hd1fa6ea44e103983E) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_dump_symbol_name] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::h1eb769490ff06e77) +error: demangling(issue_60925::foo::Foo::foo::hd1fa6ea44e103983) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_dump_symbol_name] diff --git a/tests/ui/traits/cache-reached-depth-ice.rs b/tests/ui/traits/cache-reached-depth-ice.rs index bc62adf4842d3..21c40e85995a5 100644 --- a/tests/ui/traits/cache-reached-depth-ice.rs +++ b/tests/ui/traits/cache-reached-depth-ice.rs @@ -42,5 +42,5 @@ fn test() {} fn main() { test::(); - //~^ ERROR evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) + //~^ ERROR evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOk) } diff --git a/tests/ui/traits/cache-reached-depth-ice.stderr b/tests/ui/traits/cache-reached-depth-ice.stderr index fd76dc92dfbd7..3f87025cb0d36 100644 --- a/tests/ui/traits/cache-reached-depth-ice.stderr +++ b/tests/ui/traits/cache-reached-depth-ice.stderr @@ -1,4 +1,4 @@ -error: evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) +error: evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOk) --> $DIR/cache-reached-depth-ice.rs:44:5 | LL | fn test() {} diff --git a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs index 5136aef4f7aa7..ab14dd39b07ec 100644 --- a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs +++ b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.rs @@ -57,10 +57,10 @@ fn main() { // Key is that Vec is "ok" and Third<'_, Ty> is "ok modulo regions": forward(); - //~^ ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) + //~^ ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOkModuloRegions) reverse(); - //~^ ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) - //~| ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) + //~^ ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOk) + //~| ERROR evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOkModuloRegions) } diff --git a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr index 96baec76a17ec..93dde33e1869e 100644 --- a/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr +++ b/tests/ui/traits/issue-83538-tainted-cache-after-cycle.stderr @@ -1,4 +1,4 @@ -error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) +error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOk) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5 | LL | Vec: Unpin, @@ -7,7 +7,7 @@ LL | Vec: Unpin, LL | forward(); | ^^^^^^^ -error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:59:5 | LL | Third<'a, Ty>: Unpin, @@ -16,7 +16,7 @@ LL | Third<'a, Ty>: Unpin, LL | forward(); | ^^^^^^^ -error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5 | LL | Third<'a, Ty>: Unpin, @@ -25,7 +25,7 @@ LL | Third<'a, Ty>: Unpin, LL | reverse(); | ^^^^^^^ -error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) +error: evaluate(Binder { value: TraitPredicate( as std::marker::Unpin>, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOk) --> $DIR/issue-83538-tainted-cache-after-cycle.rs:63:5 | LL | Vec: Unpin, diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.rs b/tests/ui/traits/issue-85360-eval-obligation-ice.rs index f7c49049e2d33..916d1268dec4b 100644 --- a/tests/ui/traits/issue-85360-eval-obligation-ice.rs +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.rs @@ -7,10 +7,10 @@ use core::marker::PhantomData; fn main() { test::>>(make()); - //~^ ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) + //~^ ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOk) test::>>(make()); - //~^ ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) + //~^ ERROR evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOkModuloRegions) } #[rustc_evaluate_where_clauses] diff --git a/tests/ui/traits/issue-85360-eval-obligation-ice.stderr b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr index d2b00a45a4f15..5b0867f8a48d5 100644 --- a/tests/ui/traits/issue-85360-eval-obligation-ice.stderr +++ b/tests/ui/traits/issue-85360-eval-obligation-ice.stderr @@ -1,4 +1,4 @@ -error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) +error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOk) --> $DIR/issue-85360-eval-obligation-ice.rs:9:5 | LL | test::>>(make()); @@ -7,7 +7,7 @@ LL | test::>>(make()); LL | fn test(_: T) {} | ----- predicate -error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder { value: TraitPredicate(> as std::marker::Sized>, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOkModuloRegions) --> $DIR/issue-85360-eval-obligation-ice.rs:12:5 | LL | test::>>(make()); diff --git a/tests/ui/traits/non_lifetime_binders/bad-bounds.rs b/tests/ui/traits/non_lifetime_binders/bad-bounds.rs index 4fccaf1d84f3c..514f4a6f66927 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-bounds.rs +++ b/tests/ui/traits/non_lifetime_binders/bad-bounds.rs @@ -3,11 +3,14 @@ #![feature(non_lifetime_binders)] #![expect(incomplete_features)] -fn produce() -> for for; //~ ERROR the name `A` is defined multiple times -}>> Trait {} //~ ERROR cannot find trait `Trait` in this scope + enum A {} //~ ERROR: missing generics for struct `produce::{constant#0}::A` + struct A; //~ ERROR: the name `A` is defined multiple times + //~^ ERROR: type parameter `A` is never used + }>> Trait{ //~ ERROR: cannot find trait `Trait` in this scope +} fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/bad-bounds.stderr b/tests/ui/traits/non_lifetime_binders/bad-bounds.stderr index ffc238c3f3436..199ae6c1ebbc2 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-bounds.stderr +++ b/tests/ui/traits/non_lifetime_binders/bad-bounds.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `A` is defined multiple times - --> $DIR/bad-bounds.rs:10:5 + --> $DIR/bad-bounds.rs:11:5 | LL | enum A {} | ------ previous definition of the type `A` here @@ -16,31 +16,62 @@ LL | fn produce() -> for; -LL | | }>> Trait {} - | |__^ not a trait +... | +LL | | }>> Trait{ + | |______^ not a trait error[E0405]: cannot find trait `Trait` in this scope - --> $DIR/bad-bounds.rs:11:5 + --> $DIR/bad-bounds.rs:13:9 | -LL | }>> Trait {} - | ^^^^^ not found in this scope +LL | }>> Trait{ + | ^^^^^ not found in this scope -error: bounds cannot be used in this context - --> $DIR/bad-bounds.rs:6:24 +error: late-bound type parameter not allowed on trait object types + --> $DIR/bad-bounds.rs:6:21 + | +LL | fn produce() -> for $DIR/bad-bounds.rs:6:17 | LL | fn produce() -> for; -LL | | }>> Trait {} - | |__^ +... | +LL | | }>> Trait{ + | |_____________^ + +error[E0107]: missing generics for struct `produce::{constant#0}::A` + --> $DIR/bad-bounds.rs:10:10 + | +LL | enum A {} + | ^ expected 1 generic argument + | +note: struct defined here, with 1 generic parameter: `A` + --> $DIR/bad-bounds.rs:11:12 + | +LL | struct A; + | ^ - +help: add missing generic argument + | +LL | enum A {} + | +++ + +error[E0392]: type parameter `A` is never used + --> $DIR/bad-bounds.rs:11:14 + | +LL | struct A; + | ^ unused type parameter + | + = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `A` to be a const parameter, use `const A: /* Type */` instead -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0404, E0405, E0428. -For more information about an error, try `rustc --explain E0404`. +Some errors have detailed explanations: E0107, E0392, E0404, E0405, E0428, E0782. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/traits/non_lifetime_binders/bounds-on-type-binders.rs b/tests/ui/traits/non_lifetime_binders/bounds-on-type-binders.rs index b73b34549adf4..bf6b7892bf07a 100644 --- a/tests/ui/traits/non_lifetime_binders/bounds-on-type-binders.rs +++ b/tests/ui/traits/non_lifetime_binders/bounds-on-type-binders.rs @@ -1,4 +1,4 @@ -//@ check-fail +//@ check-pass #![allow(incomplete_features)] #![feature(non_lifetime_binders)] @@ -8,7 +8,7 @@ trait Trait {} trait Trait2 where for ():, -{ //~^ ERROR bounds cannot be used in this context +{ } fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/bounds-on-type-binders.stderr b/tests/ui/traits/non_lifetime_binders/bounds-on-type-binders.stderr deleted file mode 100644 index 0a2f4cea61493..0000000000000 --- a/tests/ui/traits/non_lifetime_binders/bounds-on-type-binders.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: bounds cannot be used in this context - --> $DIR/bounds-on-type-binders.rs:10:12 - | -LL | for ():, - | ^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs index caad8bf65a90c..eaabba878fcf6 100644 --- a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs +++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs @@ -18,8 +18,8 @@ impl Foo for () { pub fn f(a: T1, b: T2) where - T1: for Foo = T>, - T2: for Foo = >::Bar>, + T1: for Foo = T>, + T2: for Foo = >::Bar>, { } diff --git a/tests/ui/traits/project-modulo-regions.rs b/tests/ui/traits/project-modulo-regions.rs index 3af5fbc7ea76d..91be85956603e 100644 --- a/tests/ui/traits/project-modulo-regions.rs +++ b/tests/ui/traits/project-modulo-regions.rs @@ -48,8 +48,8 @@ fn test(val: MyStruct) where Helper: HelperTrait { fn foo(val: MyStruct) { test(val); - //[with_clause]~^ ERROR evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) - //[without_clause]~^^ ERROR evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) + //[with_clause]~^ ERROR evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOkModuloRegions) + //[without_clause]~^^ ERROR evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOk) } fn main() {} diff --git a/tests/ui/traits/project-modulo-regions.with_clause.stderr b/tests/ui/traits/project-modulo-regions.with_clause.stderr index 0e3081ddfdfeb..9d877ee0d27fd 100644 --- a/tests/ui/traits/project-modulo-regions.with_clause.stderr +++ b/tests/ui/traits/project-modulo-regions.with_clause.stderr @@ -1,4 +1,4 @@ -error: evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOkModuloRegions) +error: evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOkModuloRegions) --> $DIR/project-modulo-regions.rs:50:5 | LL | fn test(val: MyStruct) where Helper: HelperTrait { diff --git a/tests/ui/traits/project-modulo-regions.without_clause.stderr b/tests/ui/traits/project-modulo-regions.without_clause.stderr index 830a07c4f5f79..397a1ce44c458 100644 --- a/tests/ui/traits/project-modulo-regions.without_clause.stderr +++ b/tests/ui/traits/project-modulo-regions.without_clause.stderr @@ -1,4 +1,4 @@ -error: evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }) = Ok(EvaluatedToOk) +error: evaluate(Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] }) = Ok(EvaluatedToOk) --> $DIR/project-modulo-regions.rs:50:5 | LL | fn test(val: MyStruct) where Helper: HelperTrait { diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.stderr b/tests/ui/type-alias-impl-trait/in-where-clause.stderr index 122cfdcabadd5..aa80a7cee329f 100644 --- a/tests/ui/type-alias-impl-trait/in-where-clause.stderr +++ b/tests/ui/type-alias-impl-trait/in-where-clause.stderr @@ -21,7 +21,7 @@ note: ...which requires computing revealed normalized predicates of `foo::{const | LL | [0; 1 + 2] | ^^^^^ - = note: ...which requires revealing opaque types in `[Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [] }]`... + = note: ...which requires revealing opaque types in `[Binder { value: TraitPredicate(, polarity:Positive), bound_vars: [], clauses: [] }]`... note: ...which requires computing type of `Bar::{opaque#0}`... --> $DIR/in-where-clause.rs:5:12 | From 4a605e109c69bee5050f2a3a68455d668d0e8b6f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 29 Mar 2025 20:45:43 +0000 Subject: [PATCH 5/9] Intern binders in TyKind --- compiler/rustc_ast_lowering/src/lib.rs | 4 +- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +- .../src/const_eval/type_info.rs | 2 +- compiler/rustc_hir_typeck/src/expr.rs | 4 +- compiler/rustc_middle/src/ty/codec.rs | 24 +++++++ compiler/rustc_middle/src/ty/context.rs | 36 +++++++++- .../src/ty/context/impl_interner.rs | 4 ++ compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 12 +--- .../rustc_middle/src/ty/structural_impls.rs | 41 +++++++++++ compiler/rustc_middle/src/ty/sty.rs | 39 ++++++++-- .../src/unstable/convert/internal.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 4 +- compiler/rustc_ty_utils/src/layout.rs | 2 +- .../rustc_ty_utils/src/layout/invariant.rs | 2 +- compiler/rustc_ty_utils/src/needs_drop.rs | 2 +- compiler/rustc_type_ir/src/binder.rs | 49 +++++-------- compiler/rustc_type_ir/src/flags.rs | 10 ++- compiler/rustc_type_ir/src/interner.rs | 7 ++ compiler/rustc_type_ir/src/ty_kind.rs | 71 +------------------ src/librustdoc/clean/mod.rs | 2 +- 21 files changed, 182 insertions(+), 141 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 92d42587ae028..d8ad5f97d2c20 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -61,8 +61,8 @@ use rustc_hir::{ find_attr, }; use rustc_hir::{ - self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, ParamName, PredicateOrigin, - TraitCandidate, + self as hir, ConstArg, GenericArg, HirId, IsAnonInPath, ItemLocalMap, LangItem, ParamName, + PredicateOrigin, TraitCandidate, }; use rustc_index::{Idx, IndexVec}; use rustc_macros::extension; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 450ac46aab521..f53eafc394e7b 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1679,7 +1679,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let expected_ty = self.infcx.instantiate_binder_with_fresh_vars( self.body().source_info(location).span, BoundRegionConversionTime::HigherRankedType, - binder_ty.into(), + *binder_ty, ); self.sub_types( operand_ty, @@ -1924,7 +1924,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let found_ty = self.infcx.instantiate_binder_with_fresh_vars( self.body.source_info(location).span, BoundRegionConversionTime::HigherRankedType, - binder_ty.into(), + *binder_ty, ); self.relate_types( ty, diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index 3d8d9592459c4..fb47d129c2302 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -386,7 +386,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { pub(crate) fn write_fn_ptr_type_info( &mut self, place: impl Writeable<'tcx, CtfeProvenance>, - sig: &FnSigTys>, + sig: &FnSigTys<'tcx>, fn_header: &FnHeader>, ) -> InterpResult<'tcx> { let FnHeader { fn_sig_kind } = fn_header; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 4465bbc34a562..6349cd471e6f9 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1574,7 +1574,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::UnsafeBinder(binder) => self.instantiate_binder_with_fresh_vars( inner_expr.span, infer::BoundRegionConversionTime::HigherRankedType, - binder.into(), + *binder, ), ty::Error(e) => Ty::new_error(self.tcx, e), _ => { @@ -1611,7 +1611,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::UnsafeBinder(binder) => self.instantiate_binder_with_fresh_vars( inner_expr.span, infer::BoundRegionConversionTime::HigherRankedType, - binder.into(), + *binder, ), ty::Error(e) => Ty::new_error(self.tcx, e), _ => { diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 8b1e812582783..9cdacfcae2383 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -612,3 +612,27 @@ macro_rules! implement_ty_decoder { } } } + +impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::TyBinderRef<'tcx> { + fn encode(&self, encoder: &mut E) { + (**self).encode(encoder) + } +} + +impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::TyBinderRef<'tcx> { + fn decode(decoder: &mut D) -> Self { + decoder.interner().mk_ty_binder(Decodable::decode(decoder)) + } +} + +impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::SigBinderRef<'tcx> { + fn encode(&self, encoder: &mut E) { + (**self).encode(encoder) + } +} + +impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::SigBinderRef<'tcx> { + fn decode(decoder: &mut D) -> Self { + decoder.interner().mk_sig_binder(Decodable::decode(decoder)) + } +} diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 60c82a06f7702..ff2bbe7a9741b 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -70,8 +70,8 @@ use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, FnSigKind, GenericArg, GenericArgs, GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, ParamConst, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, PredicateKind, - PredicatePolarity, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, - ValTree, ValTreeKind, Visibility, + PredicatePolarity, Region, RegionKind, ReprOptions, SigBinderRef, TraitObjectVisitor, Ty, + TyBinderRef, TyKind, TyVid, ValTree, ValTreeKind, Visibility, }; impl<'tcx> rustc_type_ir::inherent::DefId> for DefId { @@ -162,6 +162,8 @@ pub struct CtxtInterners<'tcx> { valtree: InternedSet<'tcx, ty::ValTreeKind>>, patterns: InternedSet<'tcx, List>>, outlives: InternedSet<'tcx, List>>, + ty_binder: InternedSet<'tcx, ty::Binder<'tcx, Ty<'tcx>>>, + sig_binder: InternedSet<'tcx, ty::Binder<'tcx, ty::FnSigTys<'tcx>>>, } impl<'tcx> CtxtInterners<'tcx> { @@ -200,6 +202,8 @@ impl<'tcx> CtxtInterners<'tcx> { valtree: InternedSet::with_capacity(N), patterns: InternedSet::with_capacity(N), outlives: InternedSet::with_capacity(N), + ty_binder: InternedSet::with_capacity(N), + sig_binder: InternedSet::with_capacity(N), } } @@ -1705,6 +1709,29 @@ macro_rules! nop_list_lift { }; } +macro_rules! nop_list_with_cached_type_info_lift { + ($set:ident; $ty:ty => $lifted:ty) => { + impl<'a, 'tcx> Lift> for &'a ListWithCachedTypeInfo<$ty> { + type Lifted = &'tcx ListWithCachedTypeInfo<$lifted>; + fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted { + // Assert that the set has the right type. + if false { + let _x: &InternedSet<'tcx, ListWithCachedTypeInfo<$lifted>> = + &tcx.interners.$set; + } + + if self.is_empty() { + return ListWithCachedTypeInfo::empty(); + } + assert!(tcx.interners.$set.contains_pointer_to(&InternedInSet(&*self))); + // SAFETY: we just checked that `self` is interned and therefore is valid for the + // entire lifetime of the `TyCtxt`. + unsafe { mem::transmute(self) } + } + } + }; +} + nop_lift! { type_; Ty<'a> => Ty<'tcx> } nop_lift! { region; Region<'a> => Region<'tcx> } nop_lift! { const_; Const<'a> => Const<'tcx> } @@ -1714,9 +1741,10 @@ nop_lift! { predicate; Predicate<'a> => Predicate<'tcx> } nop_lift! { predicate; Clause<'a> => Clause<'tcx> } nop_lift! { layout; Layout<'a> => Layout<'tcx> } nop_lift! { valtree; ValTree<'a> => ValTree<'tcx> } +nop_lift! { ty_binder; TyBinderRef<'a> => TyBinderRef<'tcx> } +nop_lift! { sig_binder; SigBinderRef<'a> => SigBinderRef<'tcx> } nop_list_lift! { type_lists; Ty<'a> => Ty<'tcx> } -nop_list_lift! { clauses: ListWithCachedTypeInfo; Clause<'a> => Clause<'tcx> } nop_list_lift! { poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx> } @@ -1983,6 +2011,8 @@ direct_interners! { adt_def: pub mk_adt_def_from_data(AdtDefData): AdtDef -> AdtDef<'tcx>, external_constraints: pub mk_external_constraints(ExternalConstraintsData>): ExternalConstraints -> ExternalConstraints<'tcx>, + ty_binder: pub mk_ty_binder(ty::Binder<'tcx, Ty<'tcx>>): TyBinderRef -> TyBinderRef<'tcx>, + sig_binder: pub mk_sig_binder(ty::Binder<'tcx, ty::FnSigTys<'tcx>>): SigBinderRef -> SigBinderRef<'tcx>, } macro_rules! slice_interners { diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index c6989ddd36199..4b78ea43d3dca 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -63,6 +63,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type GenericArgsSlice = &'tcx [ty::GenericArg<'tcx>]; type GenericArg = ty::GenericArg<'tcx>; type Term = ty::Term<'tcx>; + + type SigBinderRef = ty::SigBinderRef<'tcx>; + type TyBinderRef = ty::TyBinderRef<'tcx>; + type BoundVarKinds = &'tcx List>; type PredefinedOpaques = solve::PredefinedOpaques<'tcx>; diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index a0dd7b5c5cb5e..60835128bfbeb 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -863,7 +863,7 @@ where } ty::UnsafeBinder(bound_ty) => { - let ty = tcx.instantiate_bound_regions_with_erased(bound_ty.into()); + let ty = tcx.instantiate_bound_regions_with_erased(*bound_ty); field_ty_or_layout(TyAndLayout { ty, ..this }, cx, i) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 0beb26ee4aded..5de94034c5549 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -56,12 +56,6 @@ use rustc_span::{DUMMY_SP, ExpnId, ExpnKind, Ident, Span, Symbol}; use rustc_target::callconv::FnAbi; pub use rustc_type_ir::data_structures::{DelayedMap, DelayedSet}; pub use rustc_type_ir::fast_reject::DeepRejectCtxt; -#[allow( - hidden_glob_reexports, - rustc::usage_of_type_ir_inherent, - rustc::non_glob_import_of_type_ir_inherent -)] -use rustc_type_ir::inherent; pub use rustc_type_ir::relate::VarianceDiagInfo; pub use rustc_type_ir::solve::{CandidatePreferenceMode, SizedTraitKind, VisibleForLeakCheck}; pub use rustc_type_ir::*; @@ -106,9 +100,9 @@ pub use self::region::{ pub use self::sty::{ AliasTy, AliasTyKind, Article, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, CoroutineArgsExt, EarlyBinder, FnSig, - FnSigKind, InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PlaceholderConst, - PlaceholderRegion, PlaceholderType, PolyFnSig, TyKind, TypeAndMut, TypingMode, - TypingModeEqWrapper, Unnormalized, UpvarArgs, + FnSigKind, FnSigTys, InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, + PlaceholderConst, PlaceholderRegion, PlaceholderType, PolyFnSig, SigBinderRef, TyBinderRef, + TyKind, TypeAndMut, TypingMode, TypingModeEqWrapper, Unnormalized, UpvarArgs, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 19dc2705e7f5b..7f322857ef38c 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -805,3 +805,44 @@ list_fold! { &'tcx ty::List> : mk_outlives, &'tcx ty::List> : mk_const_list, } + +impl<'tcx> TypeVisitable> for ty::TyBinderRef<'tcx> { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + (**self).visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable> for ty::TyBinderRef<'tcx> { + fn try_fold_with>>( + self, + folder: &mut F, + ) -> Result { + let folded = (*self).try_fold_with(folder)?; + Ok(if *self == folded { self } else { folder.cx().mk_ty_binder(folded) }) + } + + fn fold_with>>(self, folder: &mut F) -> Self { + let folded = (*self).fold_with(folder); + if *self == folded { self } else { folder.cx().mk_ty_binder(folded) } + } +} + +impl<'tcx> TypeVisitable> for ty::SigBinderRef<'tcx> { + fn visit_with>>(&self, visitor: &mut V) -> V::Result { + (**self).visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable> for ty::SigBinderRef<'tcx> { + fn try_fold_with>>( + self, + folder: &mut F, + ) -> Result { + let folded = (*self).try_fold_with(folder)?; + Ok(if *self == folded { self } else { folder.cx().mk_sig_binder(folded) }) + } + fn fold_with>>(self, folder: &mut F) -> Self { + let folded = (*self).fold_with(folder); + if *self == folded { self } else { folder.cx().mk_sig_binder(folded) } + } +} diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index c09831ee606b8..fa14ab3320519 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use std::debug_assert_matches; -use std::ops::{ControlFlow, Range}; +use std::ops::{ControlFlow, Deref, Range}; use hir::def::{CtorKind, DefKind}; use rustc_abi::{FIRST_VARIANT, FieldIdx, NumScalableVectors, ScalableElt, VariantIdx}; @@ -55,6 +55,7 @@ pub type BoundRegion<'tcx> = ir::BoundRegion>; pub type BoundVariableKind<'tcx> = ir::BoundVariableKind>; pub type BoundRegionKind<'tcx> = ir::BoundRegionKind>; pub type BoundTyKind<'tcx> = ir::BoundTyKind>; +pub type FnSigTys<'tcx> = ir::FnSigTys>; pub trait Article { fn article(&self) -> &'static str; @@ -726,12 +727,12 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_fn_ptr(tcx: TyCtxt<'tcx>, fty: PolyFnSig<'tcx>) -> Ty<'tcx> { let (sig_tys, hdr) = fty.split(); - Ty::new(tcx, FnPtr(sig_tys, hdr)) + Ty::new(tcx, FnPtr(tcx.mk_sig_binder(sig_tys), hdr)) } #[inline] pub fn new_unsafe_binder(tcx: TyCtxt<'tcx>, b: Binder<'tcx, Ty<'tcx>>) -> Ty<'tcx> { - Ty::new(tcx, UnsafeBinder(b.into())) + Ty::new(tcx, UnsafeBinder(tcx.mk_ty_binder(b))) } #[inline] @@ -1649,7 +1650,7 @@ impl<'tcx> Ty<'tcx> { Some(args.as_coroutine().variant_range(*def_id, tcx)) } TyKind::UnsafeBinder(bound_ty) => { - tcx.instantiate_bound_regions_with_erased((*bound_ty).into()).variant_range(tcx) + tcx.instantiate_bound_regions_with_erased(**bound_ty).variant_range(tcx) } _ => None, } @@ -1673,7 +1674,7 @@ impl<'tcx> Ty<'tcx> { Some(args.as_coroutine().discriminant_for_variant(*def_id, tcx, variant_index)) } TyKind::UnsafeBinder(bound_ty) => tcx - .instantiate_bound_regions_with_erased((*bound_ty).into()) + .instantiate_bound_regions_with_erased(**bound_ty) .discriminant_for_variant(tcx, variant_index), _ => None, } @@ -1694,7 +1695,7 @@ impl<'tcx> Ty<'tcx> { ty::Pat(ty, _) => ty.discriminant_ty(tcx), ty::UnsafeBinder(bound_ty) => { - tcx.instantiate_bound_regions_with_erased((*bound_ty).into()).discriminant_ty(tcx) + tcx.instantiate_bound_regions_with_erased(**bound_ty).discriminant_ty(tcx) } ty::Bool @@ -2171,7 +2172,31 @@ mod size_asserts { use super::*; // tidy-alphabetical-start - static_assert_size!(TyKind<'_>, 40); + static_assert_size!(TyKind<'_>, 32); static_assert_size!(ty::WithCachedTypeInfo>, 40); // tidy-alphabetical-end } + +// FIXME: this is a distinct type because we need to define `Encode`/`Decode` impls. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, StableHash)] +pub struct TyBinderRef<'tcx>(pub ty::Interned<'tcx, ty::Binder<'tcx, Ty<'tcx>>>); + +impl<'tcx> Deref for TyBinderRef<'tcx> { + type Target = ty::Binder<'tcx, Ty<'tcx>>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +// FIXME: this is a distinct type because we need to define `Encode`/`Decode` impls. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, StableHash)] +pub struct SigBinderRef<'tcx>(pub ty::Interned<'tcx, ty::Binder<'tcx, FnSigTys<'tcx>>>); + +impl<'tcx> Deref for SigBinderRef<'tcx> { + type Target = ty::Binder<'tcx, FnSigTys<'tcx>>; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} diff --git a/compiler/rustc_public/src/unstable/convert/internal.rs b/compiler/rustc_public/src/unstable/convert/internal.rs index 81b32f4da10f6..a67bdfaf0d1d0 100644 --- a/compiler/rustc_public/src/unstable/convert/internal.rs +++ b/compiler/rustc_public/src/unstable/convert/internal.rs @@ -176,7 +176,7 @@ impl RustcInternal for RigidTy { } RigidTy::FnPtr(sig) => { let (sig_tys, hdr) = sig.internal(tables, tcx).split(); - rustc_ty::TyKind::FnPtr(sig_tys, hdr) + rustc_ty::TyKind::FnPtr(tcx.mk_sig_binder(sig_tys), hdr) } RigidTy::Closure(def, args) => { rustc_ty::TyKind::Closure(def.0.internal(tables, tcx), args.internal(tables, tcx)) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index c3f4a09b2d431..5f4c895e19131 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -6059,13 +6059,13 @@ fn hint_missing_borrow<'tcx>( } let found_args = match found.kind() { - ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()), + ty::FnPtr(sig_tys, _) => infcx.enter_forall(**sig_tys, |sig_tys| sig_tys.inputs().iter()), kind => { span_bug!(span, "found was converted to a FnPtr above but is now {:?}", kind) } }; let expected_args = match expected.kind() { - ty::FnPtr(sig_tys, _) => infcx.enter_forall(*sig_tys, |sig_tys| sig_tys.inputs().iter()), + ty::FnPtr(sig_tys, _) => infcx.enter_forall(**sig_tys, |sig_tys| sig_tys.inputs().iter()), kind => { span_bug!(span, "expected was converted to a FnPtr above but is now {:?}", kind) } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index eb0cc98736adb..73da00987610f 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -797,7 +797,7 @@ fn layout_of_uncached<'tcx>( } ty::UnsafeBinder(bound_ty) => { - let ty = tcx.instantiate_bound_regions_with_erased(bound_ty.into()); + let ty = tcx.instantiate_bound_regions_with_erased(*bound_ty); cx.layout_of(ty)?.layout } diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 8c07a7ec3d2de..408a81b316c5a 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -54,7 +54,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou fn skip_newtypes<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayout<'tcx>) -> TyAndLayout<'tcx> { match *layout.ty.kind() { ty::UnsafeBinder(bound_ty) => { - let ty = cx.tcx().instantiate_bound_regions_with_erased(bound_ty.into()); + let ty = cx.tcx().instantiate_bound_regions_with_erased(*bound_ty); return skip_newtypes(cx, &TyAndLayout { ty, ..*layout }); } _ => {} diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index e2529e7a77226..4a4a401f078d1 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -237,7 +237,7 @@ where } ty::UnsafeBinder(bound_ty) => { - let ty = self.tcx.instantiate_bound_regions_with_erased(bound_ty.into()); + let ty = self.tcx.instantiate_bound_regions_with_erased(*bound_ty); queue_type(self, ty); } diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 020d8c192c6cb..9d6dafb322ed0 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -39,42 +39,27 @@ pub struct Binder { impl Eq for Binder {} #[cfg(feature = "nightly")] -macro_rules! impl_binder_encode_decode { - ($($t:ty),+ $(,)?) => { - $( - impl rustc_serialize::Encodable for ty::Binder - where - $t: rustc_serialize::Encodable, - I::BoundVarKinds: rustc_serialize::Encodable, - { - fn encode(&self, e: &mut E) { - self.bound_vars().encode(e); - self.as_ref().skip_binder().encode(e); - } - } - impl rustc_serialize::Decodable for ty::Binder - where - $t: TypeVisitable + rustc_serialize::Decodable, - I::BoundVarKinds: rustc_serialize::Decodable, - { - fn decode(decoder: &mut D) -> Self { - let bound_vars = rustc_serialize::Decodable::decode(decoder); - ty::Binder::bind_with_vars(rustc_serialize::Decodable::decode(decoder), bound_vars) - } - } - )* +impl rustc_serialize::Encodable for ty::Binder +where + T: rustc_serialize::Encodable, + I::BoundVarKinds: rustc_serialize::Encodable, +{ + fn encode(&self, e: &mut E) { + self.bound_vars().encode(e); + self.as_ref().skip_binder().encode(e); } } #[cfg(feature = "nightly")] -impl_binder_encode_decode! { - ty::FnSig, - ty::FnSigTys, - ty::TraitPredicate, - ty::ExistentialPredicate, - ty::TraitRef, - ty::ExistentialTraitRef, - ty::HostEffectPredicate, +impl rustc_serialize::Decodable for ty::Binder +where + T: TypeVisitable + rustc_serialize::Decodable, + I::BoundVarKinds: rustc_serialize::Decodable, +{ + fn decode(decoder: &mut D) -> Self { + let bound_vars = rustc_serialize::Decodable::decode(decoder); + ty::Binder::bind_with_vars(rustc_serialize::Decodable::decode(decoder), bound_vars) + } } impl Binder diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 19c59df0604c3..44e9c4f418856 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -351,15 +351,13 @@ impl FlagComputation { self.add_args(args.as_slice()); } - ty::FnPtr(sig_tys, _) => self.bound_computation(sig_tys, |computation, sig_tys| { + ty::FnPtr(sig_tys, _) => self.bound_computation(*sig_tys, |computation, sig_tys| { computation.add_tys(sig_tys.inputs_and_output); }), - ty::UnsafeBinder(bound_ty) => { - self.bound_computation(bound_ty.into(), |computation, ty| { - computation.add_ty(ty); - }) - } + ty::UnsafeBinder(bound_ty) => self.bound_computation(*bound_ty, |computation, ty| { + computation.add_ty(ty); + }), } } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 84ad88245a2f6..a9bca46cb2f36 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -98,6 +98,13 @@ pub trait Interner: type BoundVarKinds: BoundVarKinds; + type SigBinderRef: Deref>> + + Copy + + Debug + + Hash + + Eq; + type TyBinderRef: Deref> + Copy + Debug + Hash + Eq; + type PredefinedOpaques: Copy + Debug + Hash diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index c3d52f4a191ac..0eb68685958e7 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -1,6 +1,5 @@ use std::fmt; use std::marker::PhantomData; -use std::ops::Deref; use derive_where::derive_where; use rustc_abi::ExternAbi; @@ -18,8 +17,6 @@ use self::TyKind::*; pub use self::closure::*; use crate::inherent::*; use crate::ty::AliasTy; -#[cfg(feature = "nightly")] -use crate::visit::TypeVisitable; use crate::{self as ty, BoundVarIndexKind, FloatTy, IntTy, Interner, UintTy}; mod closure; @@ -182,14 +179,14 @@ pub enum TyKind { /// splitting that into two pieces, we get a more compact data layout that /// reduces the size of `TyKind` by 8 bytes. It is a very hot type, so it's /// worth the mild inconvenience. - FnPtr(ty::Binder>, FnHeader), + FnPtr(I::SigBinderRef, FnHeader), /// An unsafe binder type. /// /// A higher-ranked type used to represent a type which has had some of its /// lifetimes erased. This can be used to represent types in positions where /// a lifetime is literally inexpressible, such as self-referential types. - UnsafeBinder(UnsafeBinderInner), + UnsafeBinder(I::TyBinderRef), /// A trait object. Written as `dyn for<'b> Trait<'b, Assoc = u32> + Send + 'a`. Dynamic(I::BoundExistentialPredicates, I::Region), @@ -981,70 +978,6 @@ impl fmt::Debug for FnSig { } } -// FIXME: this is a distinct type because we need to define `Encode`/`Decode` -// impls in this crate for `Binder`. -#[derive_where(Clone, Copy, PartialEq, Hash; I: Interner)] -#[cfg_attr(feature = "nightly", derive(StableHash_NoContext))] -#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)] -pub struct UnsafeBinderInner(ty::Binder); - -impl Eq for UnsafeBinderInner {} - -impl From> for UnsafeBinderInner { - fn from(value: ty::Binder) -> Self { - UnsafeBinderInner(value) - } -} - -impl From> for ty::Binder { - fn from(value: UnsafeBinderInner) -> Self { - value.0 - } -} - -impl fmt::Debug for UnsafeBinderInner { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - self.0.fmt(f) - } -} - -impl Deref for UnsafeBinderInner { - type Target = ty::Binder; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -#[cfg(feature = "nightly")] -impl rustc_serialize::Encodable - for UnsafeBinderInner -where - I::Ty: rustc_serialize::Encodable, - I::BoundVarKinds: rustc_serialize::Encodable, -{ - fn encode(&self, e: &mut E) { - self.bound_vars().encode(e); - self.as_ref().skip_binder().encode(e); - } -} - -#[cfg(feature = "nightly")] -impl rustc_serialize::Decodable - for UnsafeBinderInner -where - I::Ty: TypeVisitable + rustc_serialize::Decodable, - I::BoundVarKinds: rustc_serialize::Decodable, -{ - fn decode(decoder: &mut D) -> Self { - let bound_vars = rustc_serialize::Decodable::decode(decoder); - UnsafeBinderInner(ty::Binder::bind_with_vars( - rustc_serialize::Decodable::decode(decoder), - bound_vars, - )) - } -} - // This is just a `FnSig` without the `FnHeader` fields. #[derive_where(Clone, Copy, Debug, PartialEq, Hash; I: Interner)] #[cfg_attr( diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 4f6cee62f4721..d9dda0ede7bba 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2184,7 +2184,7 @@ pub(crate) fn clean_middle_ty<'tcx>( } ty::UnsafeBinder(inner) => { let generic_params = clean_bound_vars(inner.bound_vars(), cx.tcx); - let ty = clean_middle_ty(inner.into(), cx, None, None); + let ty = clean_middle_ty(*inner, cx, None, None); UnsafeBinder(Box::new(UnsafeBinderTy { generic_params, ty })) } ty::Adt(def, args) => { From 1bbf95969b0210efa058a15c6db2bd78b035fece Mon Sep 17 00:00:00 2001 From: Makai Date: Wed, 17 Jun 2026 21:39:04 +0800 Subject: [PATCH 6/9] rustc_public stub --- compiler/rustc_public/src/unstable/convert/internal.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_public/src/unstable/convert/internal.rs b/compiler/rustc_public/src/unstable/convert/internal.rs index a67bdfaf0d1d0..0e84e467713e8 100644 --- a/compiler/rustc_public/src/unstable/convert/internal.rs +++ b/compiler/rustc_public/src/unstable/convert/internal.rs @@ -174,9 +174,8 @@ impl RustcInternal for RigidTy { RigidTy::FnDef(def, args) => { rustc_ty::TyKind::FnDef(def.0.internal(tables, tcx), args.internal(tables, tcx)) } - RigidTy::FnPtr(sig) => { - let (sig_tys, hdr) = sig.internal(tables, tcx).split(); - rustc_ty::TyKind::FnPtr(tcx.mk_sig_binder(sig_tys), hdr) + RigidTy::FnPtr(_sig) => { + unimplemented!("FIXME") } RigidTy::Closure(def, args) => { rustc_ty::TyKind::Closure(def.0.internal(tables, tcx), args.internal(tables, tcx)) From b2f586df54a8eeba50106508c6d18ea89d887b83 Mon Sep 17 00:00:00 2001 From: Makai Date: Wed, 17 Jun 2026 21:46:39 +0800 Subject: [PATCH 7/9] fmt --- compiler/rustc_ast_lowering/src/lib.rs | 10 +++------- .../rustc_hir_analysis/src/hir_ty_lowering/bounds.rs | 10 +++++----- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d8ad5f97d2c20..57ebb83c02ab6 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -56,13 +56,9 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::PerParentDisambiguatorState; use rustc_hir::lints::DelayedLint; use rustc_hir::{ - self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource, - LifetimeSyntax, MissingLifetimeKind, ParamName, PredicateOrigin, Target, TraitCandidate, - find_attr, -}; -use rustc_hir::{ - self as hir, ConstArg, GenericArg, HirId, IsAnonInPath, ItemLocalMap, LangItem, ParamName, - PredicateOrigin, TraitCandidate, + self as hir, AngleBrackets, ConstArg, GenericArg, HirId, IsAnonInPath, ItemLocalMap, LangItem, + LifetimeSource, LifetimeSyntax, MissingLifetimeKind, ParamName, PredicateOrigin, Target, + TraitCandidate, find_attr, }; use rustc_index::{Idx, IndexVec}; use rustc_macros::extension; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 59ba4efbb8bbc..8101678c2fc54 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -193,11 +193,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); } else { predicates.insert(( - ty::Binder::bind_with_vars( - ty::ClauseKind::ConstArgHasType(ct, ct_ty), - ty::List::empty(), - ) - .upcast(tcx), + ty::Binder::bind_with_vars( + ty::ClauseKind::ConstArgHasType(ct, ct_ty), + ty::List::empty(), + ) + .upcast(tcx), param.span, )); } From 561ba493ac9576bbfc12007fecd2605bec7030f3 Mon Sep 17 00:00:00 2001 From: Makai Date: Wed, 17 Jun 2026 22:07:18 +0800 Subject: [PATCH 8/9] tidy check --- compiler/rustc_ast_lowering/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 57ebb83c02ab6..d8f18ab903917 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -56,9 +56,9 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::PerParentDisambiguatorState; use rustc_hir::lints::DelayedLint; use rustc_hir::{ - self as hir, AngleBrackets, ConstArg, GenericArg, HirId, IsAnonInPath, ItemLocalMap, LangItem, - LifetimeSource, LifetimeSyntax, MissingLifetimeKind, ParamName, PredicateOrigin, Target, - TraitCandidate, find_attr, + self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource, + LifetimeSyntax, MissingLifetimeKind, ParamName, PredicateOrigin, Target, TraitCandidate, + find_attr, }; use rustc_index::{Idx, IndexVec}; use rustc_macros::extension; From c4b7ff75ea710250ae2f7fd08802fcd753438f4d Mon Sep 17 00:00:00 2001 From: Makai Date: Wed, 17 Jun 2026 22:40:16 +0800 Subject: [PATCH 9/9] Bless tests --- tests/ui/attributes/dump-preds.stderr | 6 +++--- tests/ui/offset-of/inside-array-length.stderr | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/ui/attributes/dump-preds.stderr b/tests/ui/attributes/dump-preds.stderr index 12fc5516cb797..08cfb492c87ed 100644 --- a/tests/ui/attributes/dump-preds.stderr +++ b/tests/ui/attributes/dump-preds.stderr @@ -33,9 +33,9 @@ error: rustc_dump_item_bounds LL | type Assoc: std::ops::Deref | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: Binder { value: ProjectionPredicate(Alias { kind: ProjectionTy { def_id: DefId(..) }, args: [Alias(Alias { kind: Projection { def_id: DefId(..) }, args: [Self/#0, T/#1, P/#2], .. })], .. }, Term::Ty(())), bound_vars: [] } - = note: Binder { value: TraitPredicate(<>::Assoc

as std::ops::Deref>, polarity:Positive), bound_vars: [] } - = note: Binder { value: TraitPredicate(<>::Assoc

as std::marker::Sized>, polarity:Positive), bound_vars: [] } + = note: Binder { value: ProjectionPredicate(Alias { kind: ProjectionTy { def_id: DefId(..) }, args: [Alias(Alias { kind: Projection { def_id: DefId(..) }, args: [Self/#0, T/#1, P/#2], .. })], .. }, Term::Ty(())), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(<>::Assoc

as std::ops::Deref>, polarity:Positive), bound_vars: [], clauses: [] } + = note: Binder { value: TraitPredicate(<>::Assoc

as std::marker::Sized>, polarity:Positive), bound_vars: [], clauses: [] } error: aborting due to 3 previous errors diff --git a/tests/ui/offset-of/inside-array-length.stderr b/tests/ui/offset-of/inside-array-length.stderr index 4b2a50acf82cb..c09d515041a36 100644 --- a/tests/ui/offset-of/inside-array-length.stderr +++ b/tests/ui/offset-of/inside-array-length.stderr @@ -37,7 +37,7 @@ LL | fn foo<'a, T: 'a>(_: [(); std::mem::offset_of!((T,), 0)]) {} = note: ...which requires caching mir of `foo::{constant#0}` for CTFE... = note: ...which requires elaborating drops for `foo::{constant#0}`... = note: ...which requires borrow-checking `foo::{constant#0}`... - = note: ...which requires normalizing `Binder { value: ConstEvaluatable(Alias { kind: Anon { def_id: DefId(0:7 ~ inside_array_length[07d6]::foo::{constant#0}) }, args: ['^c_1, T/#1], .. }), bound_vars: [] }`... + = note: ...which requires normalizing `Binder { value: ConstEvaluatable(Alias { kind: Anon { def_id: DefId(0:7 ~ inside_array_length[07d6]::foo::{constant#0}) }, args: ['^c_1, T/#1], .. }), bound_vars: [], clauses: [] }`... = note: ...which again requires evaluating type-level constant, completing the cycle = note: cycle used when normalizing `inside_array_length::::foo::{constant#0}` = note: for more information, see and