From 21fd55b9d04e7298e77ca6788c979d14259a6369 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 13 Mar 2025 03:42:06 +0000 Subject: [PATCH 1/5] Add clauses to binders, once again --- compiler/rustc_ast_passes/src/feature_gate.rs | 10 ++- compiler/rustc_middle/src/traits/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 24 ++++++ compiler/rustc_middle/src/ty/mod.rs | 4 +- compiler/rustc_middle/src/ty/predicate.rs | 6 ++ compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_type_ir/src/binder.rs | 78 +++++++++++++++---- compiler/rustc_type_ir/src/inherent.rs | 8 +- compiler/rustc_type_ir/src/interner.rs | 4 +- 9 files changed, 110 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index a3fcc110a1666..9f3be98264b8d 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -140,10 +140,12 @@ impl<'a> PostExpansionVisitor<'a> { } } - for param in params { - if !param.bounds.is_empty() { - let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect(); - self.sess.dcx().emit_err(errors::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(); + self.sess.dcx().emit_err(errors::ForbiddenBound { spans }); + } } } } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 7e6151745e2f8..94914f2089326 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -504,7 +504,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, HashStable, TyEncodable, TyDecodable)] #[derive(TypeVisitable, TypeFoldable)] diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 08d4c1f9cf2f3..c649c37e11f56 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2299,6 +2299,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>) -> Option { + // Assert that the set has the right type. + if false { + let _x: &InternedSet<'tcx, ListWithCachedTypeInfo<$lifted>> = + &tcx.interners.$set; + } + + if self.is_empty() { + return Some(ListWithCachedTypeInfo::empty()); + } + tcx.interners + .$set + .contains_pointer_to(&InternedInSet(self)) + .then(|| 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> } @@ -2314,6 +2337,7 @@ nop_list_lift! { poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx> } nop_list_lift! { bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariableKind } +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 ac98cbc8d6cba..710d32c4dda44 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -966,7 +966,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() } } @@ -2207,6 +2207,6 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(PredicateKind<'_>, 32); - static_assert_size!(WithCachedTypeInfo>, 48); + static_assert_size!(WithCachedTypeInfo>, 56); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 02e316dfc3db7..13c5969f1268d 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -179,6 +179,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 74a94d8278453..34cac383030a3 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2090,6 +2090,6 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(ty::RegionKind<'_>, 24); - static_assert_size!(ty::TyKind<'_>, 24); + static_assert_size!(ty::TyKind<'_>, 32); // tidy-alphabetical-end } diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index e9055940310d0..ebf8e5c03612e 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -12,7 +12,9 @@ use crate::data_structures::SsoHashSet; use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; use crate::inherent::*; use crate::lift::Lift; -use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; +use crate::visit::{ + Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, try_visit, +}; use crate::{self as ty, Interner}; /// Binder is a binder for higher-ranked lifetimes or types. It is part of the @@ -34,6 +36,7 @@ use crate::{self as ty, Interner}; pub struct Binder { value: T, bound_vars: I::BoundVarKinds, + clauses: I::Clauses, } // FIXME: We manually derive `Lift` because the `derive(Lift_Generic)` doesn't @@ -42,6 +45,7 @@ impl Lift for Binder where T: Lift, I::BoundVarKinds: Lift, + I::Clauses: Lift, { type Lifted = Binder; @@ -49,6 +53,7 @@ where Some(Binder { value: self.value.lift_to_interner(cx)?, bound_vars: self.bound_vars.lift_to_interner(cx)?, + clauses: self.clauses.lift_to_interner(cx)?, }) } } @@ -106,7 +111,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 { @@ -114,7 +119,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 } } } @@ -135,13 +153,18 @@ impl> TypeSuperFoldable for Binder { self, folder: &mut F, ) -> Result { - self.try_map_bound(|ty| ty.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)) } } 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) } } @@ -166,19 +189,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 @@ -192,26 +219,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 @@ -227,7 +267,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 @@ -245,21 +285,25 @@ impl Binder { 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()) + } } } 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 d4134bdf3a782..14781bfeb6970 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -515,6 +515,12 @@ pub trait Clause>: fn instantiate_supertrait(self, cx: I, trait_ref: ty::Binder>) -> Self; } +pub trait Clauses: + SliceLike + Debug + Hash + Eq + TypeSuperVisitable + TypeFoldable + Flags +{ + fn empty() -> Self; +} + /// Common capabilities of placeholder kinds pub trait PlaceholderLike: Copy + Debug + Hash + Eq { fn universe(self) -> ty::UniverseIndex; @@ -566,7 +572,7 @@ pub trait AdtDef: Copy + Debug + Hash + Eq { } pub trait ParamEnv: Copy + Debug + Hash + Eq + TypeFoldable { - fn caller_bounds(self) -> impl SliceLike; + fn caller_bounds(self) -> I::Clauses; } pub trait Features: Copy { diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 8f86270d7dce7..92e44915bf1ff 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -12,7 +12,7 @@ use crate::ir_print::IrPrint; use crate::lang_items::TraitSolverLangItem; use crate::relate::Relate; use crate::solve::{CanonicalInput, ExternalConstraintsData, PredefinedOpaquesData, QueryResult}; -use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; +use crate::visit::TypeVisitable; use crate::{self as ty, search_graph}; #[cfg_attr(feature = "nightly", rustc_diagnostic_item = "type_ir_interner")] @@ -128,7 +128,7 @@ pub trait Interner: type ParamEnv: ParamEnv; type Predicate: Predicate; type Clause: Clause; - type Clauses: Copy + Debug + Hash + Eq + TypeSuperVisitable + Flags; + type Clauses: Clauses; fn with_global_cache(self, f: impl FnOnce(&mut search_graph::GlobalCache) -> R) -> R; From 0686d829b79c21ff607b70739a4b2901b919c84b Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 13 Mar 2025 04:25:17 +0000 Subject: [PATCH 2/5] Implement support for binders with clauses in new solver --- compiler/rustc_infer/src/infer/context.rs | 20 ++++++ compiler/rustc_infer/src/infer/mod.rs | 46 ++++++++++++++ .../src/infer/relate/higher_ranked.rs | 63 +++++++++++++++++++ compiler/rustc_middle/src/ty/fold.rs | 8 +++ compiler/rustc_middle/src/ty/mod.rs | 14 +++++ .../src/solve/effect_goals.rs | 8 ++- .../src/solve/eval_ctxt/mod.rs | 23 ++++++- .../src/solve/normalizes_to/mod.rs | 8 ++- .../src/solve/trait_goals.rs | 8 ++- compiler/rustc_type_ir/src/infer_ctxt.rs | 12 ++++ compiler/rustc_type_ir/src/visit.rs | 6 ++ 11 files changed, 210 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 75affa1397705..4f23c3d306132 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -113,6 +113,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>, U>( &self, value: ty::Binder<'tcx, T>, @@ -121,6 +132,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 equate_ty_vids_raw(&self, a: rustc_type_ir::TyVid, b: rustc_type_ir::TyVid) { self.inner.borrow_mut().type_variables().equate(a, b); } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index fa8dea064daaa..ab521470ba5ec 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1209,6 +1209,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) -> ty::Region<'tcx> { + self.args[br.var.index()].expect_region() + } + fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { + self.args[bt.var.index()].expect_ty() + } + fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> { + self.args[bv.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 2143f72a3b0a5..85c02242d5ef6 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -57,6 +57,49 @@ 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| { + ty::Region::new_placeholder( + self.tcx, + ty::PlaceholderRegion { universe: next_universe, bound: br }, + ) + }, + types: &mut |bound_ty: ty::BoundTy| { + Ty::new_placeholder( + self.tcx, + ty::PlaceholderType { universe: next_universe, bound: bound_ty }, + ) + }, + consts: &mut |bound_var: ty::BoundVar| { + ty::Const::new_placeholder( + self.tcx, + ty::PlaceholderConst { universe: next_universe, bound: bound_var }, + ) + }, + }; + + 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 @@ -82,6 +125,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 dc2c9e3d9f119..4fc245628b539 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -258,6 +258,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 710d32c4dda44..8661ee1fee7fd 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -998,6 +998,20 @@ impl<'tcx> ParamEnv<'tcx> { pub fn and>>(self, value: T) -> ParamEnvAnd<'tcx, T> { ParamEnvAnd { param_env: self, value } } + + /// 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_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 0b61c368d8e8d..3fc3ae1b2b122 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -55,12 +55,18 @@ where } ecx.probe_trait_candidate(source).enter(|ecx| { - 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) }) } else { 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 7ef36d0e9ae37..e780f8d710948 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 @@ -582,8 +582,8 @@ where } } } else { - self.enter_forall(kind, |ecx, kind| { - let goal = goal.with(ecx.cx(), ty::Binder::dummy(kind)); + self.enter_forall_with_assumptions(kind, goal.param_env, |ecx, kind, param_env| { + let goal = Goal::new(ecx.cx(), param_env, ty::Binder::dummy(kind)); ecx.add_goal(GoalSource::InstantiateHigherRanked, goal); ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }) @@ -1007,6 +1007,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`, but takes `&mut self` and passes it back through the /// callback since it can't be aliased during the call. pub(super) fn enter_forall, U>( @@ -1017,6 +1024,18 @@ where self.delegate.enter_forall(value, |value| f(self, value)) } + /// UwU + pub(super) fn enter_forall_with_assumptions, U>( + &mut self, + value: ty::Binder, + param_env: I::ParamEnv, + f: impl FnOnce(&mut Self, T, I::ParamEnv) -> U, + ) -> U { + self.delegate.enter_forall_with_assumptions(value, param_env, |value, param_env| { + f(self, value, param_env) + }) + } + pub(super) fn resolve_vars_if_possible(&self, value: T) -> T where T: TypeFoldable, diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index de6d21da0f592..7d2a83d226679 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -121,13 +121,17 @@ where return Err(NoSolution); } ecx.probe_trait_candidate(source).enter(|ecx| { - 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); 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 b72f776e5cb48..616d0f9360bda 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -143,12 +143,18 @@ where } ecx.probe_trait_candidate(source).enter(|ecx| { - 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) }) } else { diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index e512e8fc838f1..9f6f90d325458 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -155,12 +155,24 @@ pub trait InferCtxtLike: Sized { value: ty::Binder, ) -> T; + fn instantiate_binder_with_infer_and_goals + Copy>( + &self, + value: ty::Binder, + ) -> (T, ::Clauses); + fn enter_forall, U>( &self, value: ty::Binder, 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 equate_int_vids_raw(&self, a: ty::IntVid, b: ty::IntVid); fn equate_float_vids_raw(&self, a: ty::FloatVid, b: ty::FloatVid); diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 2285e0e75de04..7a50d2b30d14a 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 ad93ded6be2e94d24da4e2816a270d0344a816a2 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 13 Mar 2025 05:54:45 +0000 Subject: [PATCH 3/5] Implement non-lifetime binder lowering --- compiler/rustc_ast_lowering/src/item.rs | 15 ++ compiler/rustc_ast_lowering/src/lib.rs | 18 ++- compiler/rustc_hir/src/hir.rs | 7 +- compiler/rustc_hir/src/intravisit.rs | 3 + .../src/collect/item_bounds.rs | 18 ++- .../src/collect/predicates_of.rs | 144 +++++------------ .../src/collect/resolve_bound_vars.rs | 3 + .../src/hir_ty_lowering/bounds.rs | 153 +++++++++++++++++- .../src/hir_ty_lowering/dyn_compatibility.rs | 1 + .../src/hir_ty_lowering/mod.rs | 5 +- compiler/rustc_type_ir/src/binder.rs | 11 +- 11 files changed, 259 insertions(+), 119 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 43bf951eddc6c..434ad95e3212f 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1818,6 +1818,7 @@ impl<'hir> LoweringContext<'_, 'hir> { bounded_ty: self.arena.alloc(bounded_ty), bounds, bound_generic_params: &[], + bound_assumptions: &[], origin, }) } @@ -1846,6 +1847,20 @@ impl<'hir> LoweringContext<'_, 'hir> { }) => hir::WherePredicateKind::BoundPredicate(hir::WhereBoundPredicate { bound_generic_params: self .lower_generic_params(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, + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + PredicateOrigin::GenericParam, + ) + }), + ), bounded_ty: self .lower_ty(bounded_ty, ImplTraitContext::Disallowed(ImplTraitPosition::Bound)), bounds: self.lower_param_bounds( diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d5d6dcd8d631d..f95f76411311d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -55,7 +55,7 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; use rustc_hir::{ - self as hir, ConstArg, GenericArg, HirId, IsAnonInPath, ItemLocalMap, LangItem, ParamName, + self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, ParamName, PredicateOrigin, TraitCandidate, }; use rustc_index::{Idx, IndexSlice, IndexVec}; @@ -1728,6 +1728,7 @@ impl<'a, 'hir> LoweringContext<'a, '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)), @@ -1948,12 +1949,26 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { p: &PolyTraitRef, itctx: ImplTraitContext, ) -> hir::PolyTraitRef<'hir> { + let bound_assumptions = + self.arena.alloc_from_iter(p.bound_generic_params.iter().filter_map(|param| { + self.lower_generic_bound_predicate( + param.ident, + param.id, + ¶m.kind, + ¶m.bounds, + param.colon_span, + p.span, + ImplTraitContext::Disallowed(ImplTraitPosition::Bound), + PredicateOrigin::GenericParam, + ) + })); let bound_generic_params = self.lower_lifetime_binder(p.trait_ref.ref_id, &p.bound_generic_params); let trait_ref = self.lower_trait_ref(p.modifiers, &p.trait_ref, itctx); let modifiers = self.lower_trait_bound_modifiers(p.modifiers); hir::PolyTraitRef { bound_generic_params, + bound_assumptions, modifiers, trait_ref, span: self.lower_span(p.span), @@ -2362,6 +2377,7 @@ impl<'a, 'hir> LoweringContext<'a, '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 e3e96894ed1f7..6a475262da9a3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -990,6 +990,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`). @@ -3840,6 +3842,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. @@ -4843,7 +4848,7 @@ mod size_asserts { static_assert_size!(ForeignItem<'_>, 88); 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<'_>, 80); static_assert_size!(ImplItem<'_>, 88); diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 506358341b501..208db7e6bc86d 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1082,10 +1082,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 { @@ -1296,6 +1298,7 @@ pub fn walk_poly_trait_ref<'v, V: Visitor<'v>>( trait_ref: &'v PolyTraitRef<'v>, ) -> V::Result { walk_list!(visitor, visit_generic_param, trait_ref.bound_generic_params); + walk_list!(visitor, visit_where_predicate, trait_ref.bound_assumptions); visitor.visit_trait_ref(&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 6e07f0ff53c39..6c723c6a48439 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -37,7 +37,14 @@ fn associated_type_bounds<'tcx>( let icx = ItemCtxt::new(tcx, assoc_item_def_id); let mut bounds = Vec::new(); - icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter); + icx.lowerer().lower_bounds( + item_ty, + hir_bounds, + &mut bounds, + ty::List::empty(), + ty::ListWithCachedTypeInfo::empty(), + filter, + ); // Associated types are implicitly sized unless a `?Sized` bound is found match filter { PredicateFilter::All @@ -326,7 +333,14 @@ fn opaque_type_bounds<'tcx>( ty::print::with_reduced_queries!({ let icx = ItemCtxt::new(tcx, opaque_def_id); let mut bounds = Vec::new(); - icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter); + icx.lowerer().lower_bounds( + item_ty, + hir_bounds, + &mut bounds, + ty::List::empty(), + ty::ListWithCachedTypeInfo::empty(), + filter, + ); // Opaque types are implicitly sized unless a `?Sized` bound is found match filter { PredicateFilter::All diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 4bd89861a9e5a..8fd57a84c1723 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -10,13 +10,13 @@ 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; use crate::constrained_generic_params as cgp; use crate::delegation::inherit_predicates_for_delegation_item; -use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter, RegionInferReason}; +use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter}; /// Returns a list of all type predicates (explicit and implicit) for the definition with /// ID `def_id`. This includes all predicates returned by `explicit_predicates_of`, plus @@ -184,6 +184,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, ); predicates.extend(bounds); @@ -201,105 +202,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(); - // Params are implicitly sized unless a `?Sized` bound is found - icx.lowerer().add_sized_bound( - &mut bounds, - param_ty, - &[], - Some((param.def_id, hir_generics.predicates)), - 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(); - 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); - // Keep the type around in a dummy predicate, in case of no bounds. - // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` - // is still checked for WF. - if bound_pred.bounds.is_empty() { - if let ty::Param(_) = ty.kind() { - // This is a `where T:`, which can be in the HIR from the - // transformation that moves `?Sized` to `T`'s declaration. - // We can skip the predicate because type parameters are - // trivially WF, but also we *should*, to avoid exposing - // users who never wrote `where Type:,` themselves, to - // compiler/tooling bugs from not handling WF predicates. - } else { - 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, - ); - 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) - })) - } - - hir::WherePredicateKind::EqPredicate(..) => { - // FIXME(#20041) - } - } - } + 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)); @@ -624,7 +531,14 @@ pub(super) fn implied_predicates_with_filter<'tcx>( let self_param_ty = tcx.types.self_param; let mut bounds = Vec::new(); - icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter); + icx.lowerer().lower_bounds( + self_param_ty, + superbounds, + &mut bounds, + ty::List::empty(), + ty::ListWithCachedTypeInfo::empty(), + filter, + ); let where_bounds_that_match = icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter); @@ -924,12 +838,24 @@ 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( bound_ty, predicate.bounds, &mut bounds, bound_vars, + bound_assumptions, filter, ); } @@ -1003,12 +929,25 @@ 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 = + icx.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, ); } @@ -1029,6 +968,7 @@ pub(super) fn const_conditions<'tcx>( supertraits, &mut bounds, ty::List::empty(), + ty::ListWithCachedTypeInfo::empty(), PredicateFilter::ConstIfConst, ); } 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 9b0d57bd75b11..3f508c4deb6b1 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -403,6 +403,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); }); } @@ -939,6 +940,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { bounded_ty, bounds, bound_generic_params, + bound_assumptions, origin, .. }) => { @@ -973,6 +975,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 f0dffd780bcc7..817ca42252ae2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -7,15 +7,15 @@ use rustc_hir as hir; use rustc_hir::HirId; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -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::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::traits; use smallvec::SmallVec; -use tracing::{debug, instrument}; +use tracing::{debug, instrument, trace}; use super::errors::GenericsArgsErrExtend; use crate::errors; @@ -24,6 +24,128 @@ use crate::hir_ty_lowering::{ }; impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { + pub(crate) fn lower_where_predicates( + &self, + params: &[hir::GenericParam<'tcx>], + hir_predicates: &[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(); + // Params are implicitly sized unless a `?Sized` bound is found + self.add_sized_bound( + &mut bounds, + param_ty, + &[], + Some((param.def_id, hir_predicates)), + 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(); + 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); + // Keep the type around in a dummy predicate, in case of no bounds. + // That way, `where Ty:` is not a complete noop (see #53696) and `Ty` + // is still checked for WF. + if bound_pred.bounds.is_empty() { + if let ty::Param(_) = ty.kind() { + // This is a `where T:`, which can be in the HIR from the + // transformation that moves `?Sized` to `T`'s declaration. + // We can skip the predicate because type parameters are + // trivially WF, but also we *should*, to avoid exposing + // users who never wrote `where Type:,` themselves, to + // compiler/tooling bugs from not handling WF predicates. + } else { + 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, + ); + 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) + })) + } + + hir::WherePredicateKind::EqPredicate(..) => { + // FIXME(#20041) + } + } + } + } + /// Add a `Sized` bound to the `bounds` if appropriate. /// /// Doesn't add the bound if the HIR bounds contain any of `Sized`, `?Sized` or `!Sized`. @@ -32,7 +154,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, self_ty: Ty<'tcx>, hir_bounds: &'tcx [hir::GenericBound<'tcx>], - self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, + self_ty_where_predicates: Option<(LocalDefId, &[hir::WherePredicate<'tcx>])>, span: Span, ) { let tcx = self.tcx(); @@ -117,7 +239,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } else if let Some(sized_def_id) = sized_def_id { // There was no `?Sized`, `!Sized` or explicit `Sized` bound; // add `Sized` if it's available. - let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [self_ty]); + let trait_ref = ty::Binder::bind_with_vars( + ty::TraitRef::new(tcx, sized_def_id, [self_ty]), + ty::List::empty(), + ); // Preferable to put this obligation first, since we report better errors for sized ambiguity. bounds.insert(0, (trait_ref.upcast(tcx), span)); } @@ -151,6 +276,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, ) where 'tcx: 'hir, @@ -172,12 +298,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { match hir_bound { hir::GenericBound::Trait(poly_trait_ref) => { let hir::TraitBoundModifiers { constness, polarity } = poly_trait_ref.modifiers; + + 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.trait_ref, poly_trait_ref.span, constness, polarity, param_ty, + bound_assumptions, bounds, predicate_filter, ); @@ -192,9 +333,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)); } @@ -421,6 +563,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_bounds, bounds, projection_ty.bound_vars(), + projection_ty.skip_binder_with_clauses().1, predicate_filter, ); } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 27643e715e6b1..73055cb5f922b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -50,6 +50,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir::BoundConstness::Never, hir::BoundPolarity::Positive, dummy_self, + ty::ListWithCachedTypeInfo::empty(), &mut user_written_bounds, PredicateFilter::SelfOnly, ) { 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 76a880da41855..7f581908806a3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -734,6 +734,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { constness: hir::BoundConstness, polarity: hir::BoundPolarity, self_ty: Ty<'tcx>, + bound_assumptions: ty::Clauses<'tcx>, bounds: &mut Vec<(ty::Clause<'tcx>, Span)>, predicate_filter: PredicateFilter, ) -> GenericArgCountResult { @@ -758,9 +759,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); @@ -2647,6 +2649,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { hir_bounds.iter(), &mut bounds, ty::List::empty(), + ty::ListWithCachedTypeInfo::empty(), PredicateFilter::All, ); self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span); diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index ebf8e5c03612e..c3ff613db360c 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -1,7 +1,7 @@ use std::fmt::Debug; 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")] @@ -284,8 +284,7 @@ impl Binder { where T: TypeVisitable, { - // `self.value` is equivalent to `self.skip_binder()` - if self.value.has_escaping_bound_vars() && self.clauses.is_empty() { + if self.value.has_escaping_bound_vars() || !self.clauses.is_empty() { None } else { Some(self.skip_binder()) @@ -326,7 +325,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); @@ -339,7 +338,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(debruijn, bound_ty) if debruijn == self.binder_index => { @@ -367,8 +366,6 @@ impl TypeVisitor for ValidateBoundVars { _ => (), }; - - ControlFlow::Continue(()) } } From 531d3d5dfa99c96011fc7c8a3651c1863c5cb882 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 18 Mar 2025 19:23:07 +0000 Subject: [PATCH 4/5] 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/crashes/120033.rs | 4 +-- tests/ui/attributes/dump-preds.stderr | 32 +++++++++---------- .../binder/bounds-on-closure-type-binders.rs | 3 +- .../bounds-on-closure-type-binders.stderr | 8 +---- tests/ui/stats/input-stats.stderr | 24 +++++++++----- 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 +-- .../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 +- 24 files changed, 88 insertions(+), 77 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 817ca42252ae2..ac448f705500a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -38,7 +38,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(); // Params are implicitly sized unless a `?Sized` bound is found @@ -57,10 +59,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(); 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 85c02242d5ef6..52a3399581052 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -72,7 +72,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| { ty::Region::new_placeholder( diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 8661ee1fee7fd..71a8e22128935 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -999,7 +999,10 @@ impl<'tcx> ParamEnv<'tcx> { ParamEnvAnd { param_env: self, value } } - /// 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 8d47c756fc53c..6028d3beccad3 100644 --- a/src/tools/clippy/clippy_lints/src/lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/lifetimes.rs @@ -633,6 +633,7 @@ where bounded_ty, bounds, bound_generic_params, + bound_assumptions: _, origin: _, }) = predicate.kind { diff --git a/tests/crashes/120033.rs b/tests/crashes/120033.rs index f1502978dc511..a821a8c6edac3 100644 --- a/tests/crashes/120033.rs +++ b/tests/crashes/120033.rs @@ -9,6 +9,6 @@ pub struct Bar {} pub fn f() where - T1: for Foo>, - T2: for Foo = T1::Bar>, + T1: for Foo>, + T2: for Foo = T1::Bar>, {} diff --git a/tests/ui/attributes/dump-preds.stderr b/tests/ui/attributes/dump-preds.stderr index bdfcbed71e9a6..7eca5334d82cf 100644 --- a/tests/ui/attributes/dump-preds.stderr +++ b/tests/ui/attributes/dump-preds.stderr @@ -4,11 +4,11 @@ error: rustc_dump_predicates LL | trait Trait: Iterator | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = 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(<::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 @@ -16,14 +16,14 @@ error: rustc_dump_predicates LL | type Assoc: std::ops::Deref | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = 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(<::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 @@ -31,9 +31,9 @@ error: rustc_dump_item_bounds LL | type Assoc: std::ops::Deref | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: Binder { value: ProjectionPredicate(AliasTerm { args: [Alias(Projection, AliasTy { args: [Self/#0, T/#1, P/#2], def_id: DefId(..), .. })], def_id: DefId(..), .. }, 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(AliasTerm { args: [Alias(Projection, AliasTy { args: [Self/#0, T/#1, P/#2], def_id: DefId(..), .. })], def_id: DefId(..), .. }, 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/closures/binder/bounds-on-closure-type-binders.rs b/tests/ui/closures/binder/bounds-on-closure-type-binders.rs index cf53241407feb..4cebc4cbea11c 100644 --- a/tests/ui/closures/binder/bounds-on-closure-type-binders.rs +++ b/tests/ui/closures/binder/bounds-on-closure-type-binders.rs @@ -9,6 +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 + //~^ 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 9cb921f66314c..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,14 +1,8 @@ -error: bounds cannot be used in this context - --> $DIR/bounds-on-closure-type-binders.rs:11:20 - | -LL | let _ = for || -> () {}; - | ^^^^^ - 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 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/stats/input-stats.stderr b/tests/ui/stats/input-stats.stderr index 191daff2137d8..31426829401ff 100644 --- a/tests/ui/stats/input-stats.stderr +++ b/tests/ui/stats/input-stats.stderr @@ -143,36 +143,44 @@ hir-stats Attribute 128 ( 1.4%) 4 32 hir-stats FieldDef 128 ( 1.4%) 2 64 hir-stats GenericArgs 144 ( 1.6%) 3 48 hir-stats Variant 144 ( 1.6%) 2 72 -hir-stats GenericBound 256 ( 2.9%) 4 64 -hir-stats - Trait 256 ( 2.9%) 4 hir-stats Block 288 ( 3.2%) 6 48 +hir-stats GenericBound 320 ( 3.5%) 4 80 +hir-stats - Trait 320 ( 3.5%) 4 hir-stats Pat 360 ( 4.0%) 5 72 hir-stats - Struct 72 ( 0.8%) 1 hir-stats - Wild 72 ( 0.8%) 1 hir-stats - Binding 216 ( 2.4%) 3 -hir-stats GenericParam 400 ( 4.5%) 5 80 +hir-stats GenericParam 400 ( 4.4%) 5 80 hir-stats Generics 560 ( 6.2%) 10 56 hir-stats Ty 720 ( 8.0%) 15 48 hir-stats - Ptr 48 ( 0.5%) 1 hir-stats - Ref 48 ( 0.5%) 1 hir-stats - Path 624 ( 6.9%) 13 +<<<<<<< HEAD hir-stats Expr 768 ( 8.6%) 12 64 +======= +hir-stats Expr 768 ( 8.5%) 12 64 +>>>>>>> 058f940e7a0 (Bless tests) hir-stats - InlineAsm 64 ( 0.7%) 1 hir-stats - Match 64 ( 0.7%) 1 hir-stats - Path 64 ( 0.7%) 1 hir-stats - Struct 64 ( 0.7%) 1 hir-stats - Lit 128 ( 1.4%) 2 -hir-stats - Block 384 ( 4.3%) 6 -hir-stats Item 968 (10.8%) 11 88 +hir-stats - Block 384 ( 4.2%) 6 +hir-stats Item 968 (10.7%) 11 88 hir-stats - Enum 88 ( 1.0%) 1 hir-stats - ExternCrate 88 ( 1.0%) 1 hir-stats - ForeignMod 88 ( 1.0%) 1 hir-stats - Impl 88 ( 1.0%) 1 hir-stats - Trait 88 ( 1.0%) 1 -hir-stats - Fn 176 ( 2.0%) 2 +hir-stats - Fn 176 ( 1.9%) 2 hir-stats - Use 352 ( 3.9%) 4 -hir-stats Path 1_240 (13.8%) 31 40 -hir-stats PathSegment 1_920 (21.4%) 40 48 +hir-stats Path 1_240 (13.7%) 31 40 +hir-stats PathSegment 1_920 (21.2%) 40 48 hir-stats ---------------------------------------------------------------- +<<<<<<< HEAD hir-stats Total 8_980 180 +======= +hir-stats Total 9_040 180 +>>>>>>> 058f940e7a0 (Bless tests) hir-stats diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr index 167262dcf06b3..db89d37333975 100644 --- a/tests/ui/symbol-names/basic.legacy.stderr +++ b/tests/ui/symbol-names/basic.legacy.stderr @@ -1,10 +1,10 @@ -error: symbol-name(_ZN5basic4main17hc88b9d80a69d119aE) +error: symbol-name(_ZN5basic4main17h204cbd963724a7dbE) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(basic::main::hc88b9d80a69d119a) +error: demangling(basic::main::h204cbd963724a7db) --> $DIR/basic.rs:8:1 | LL | #[rustc_symbol_name] diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr index 4e17bdc45777f..2fca6a3009266 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$3foo17hbddb77d6f71afb32E) +error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17hcd02ed09e88bcb37E) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] | ^^^^^^^^^^^^^^^^^^^^ -error: demangling(issue_60925::foo::Foo::foo::hbddb77d6f71afb32) +error: demangling(issue_60925::foo::Foo::foo::hcd02ed09e88bcb37) --> $DIR/issue-60925.rs:21:9 | LL | #[rustc_symbol_name] diff --git a/tests/ui/traits/cache-reached-depth-ice.rs b/tests/ui/traits/cache-reached-depth-ice.rs index 8c2391113d719..919f81f758edb 100644 --- a/tests/ui/traits/cache-reached-depth-ice.rs +++ b/tests/ui/traits/cache-reached-depth-ice.rs @@ -41,5 +41,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 e84ebc91ae169..574ebad154f65 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:43: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 931879a672262..65f664861907a 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/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 5334118e9ac7d..edc5d94f63a0b 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 @@ -16,8 +16,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 114cac64573ce..df94c47383611 100644 --- a/tests/ui/type-alias-impl-trait/in-where-clause.stderr +++ b/tests/ui/type-alias-impl-trait/in-where-clause.stderr @@ -27,7 +27,7 @@ LL | / fn foo() -> Bar LL | | where LL | | Bar: Send, | |______________^ - = 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 f3652c53ae5e5fa24de8789e181d4ba1a6fbbf4d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 29 Mar 2025 20:45:43 +0000 Subject: [PATCH 5/5] Intern binders in TyKind --- compiler/rustc_ast_lowering/src/lib.rs | 4 +- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +- compiler/rustc_hir_typeck/src/expr.rs | 4 +- compiler/rustc_middle/src/ty/codec.rs | 24 +++++++ compiler/rustc_middle/src/ty/context.rs | 15 +++- compiler/rustc_middle/src/ty/flags.rs | 10 ++- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 7 +- .../rustc_middle/src/ty/structural_impls.rs | 32 +++++++++ compiler/rustc_middle/src/ty/sty.rs | 33 +++++++-- .../rustc_smir/src/rustc_internal/internal.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 4 +- compiler/rustc_ty_utils/src/layout.rs | 2 +- compiler/rustc_ty_utils/src/needs_drop.rs | 2 +- compiler/rustc_type_ir/src/binder.rs | 49 +++++-------- compiler/rustc_type_ir/src/interner.rs | 7 ++ compiler/rustc_type_ir/src/ty_kind.rs | 69 +------------------ src/librustdoc/clean/mod.rs | 2 +- 18 files changed, 145 insertions(+), 127 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index f95f76411311d..0c9f23764aaf6 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -55,8 +55,8 @@ use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey}; use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId}; 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, IndexSlice, 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 f6144a25938ce..4c7edef451437 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1641,7 +1641,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, @@ -1891,7 +1891,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_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a75f6f4caac91..bfdd476473793 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1690,7 +1690,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), _ => { @@ -1727,7 +1727,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 74b34afe616b9..87fc1072550f5 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -621,3 +621,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 c649c37e11f56..b6809935a528f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -80,8 +80,8 @@ use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, GenericArg, GenericArgs, GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, ParamConst, ParamTy, 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, }; #[allow(rustc::usage_of_ty_tykind)] @@ -97,6 +97,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Term = ty::Term<'tcx>; type BoundVarKinds = &'tcx List; + type SigBinderRef = ty::SigBinderRef<'tcx>; + type TyBinderRef = ty::TyBinderRef<'tcx>; + type BoundVarKind = ty::BoundVariableKind; type PredefinedOpaques = solve::PredefinedOpaques<'tcx>; @@ -813,6 +816,8 @@ pub struct CtxtInterners<'tcx> { captures: InternedSet<'tcx, List<&'tcx ty::CapturedPlace<'tcx>>>, offset_of: InternedSet<'tcx, List<(VariantIdx, FieldIdx)>>, valtree: InternedSet<'tcx, ty::ValTreeKind<'tcx>>, + ty_binder: InternedSet<'tcx, ty::Binder<'tcx, Ty<'tcx>>>, + sig_binder: InternedSet<'tcx, ty::Binder<'tcx, ty::FnSigTys<'tcx>>>, } impl<'tcx> CtxtInterners<'tcx> { @@ -849,6 +854,8 @@ impl<'tcx> CtxtInterners<'tcx> { captures: InternedSet::with_capacity(N), offset_of: InternedSet::with_capacity(N), valtree: InternedSet::with_capacity(N), + ty_binder: InternedSet::with_capacity(N), + sig_binder: InternedSet::with_capacity(N), } } @@ -2331,6 +2338,8 @@ 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! { @@ -2595,6 +2604,8 @@ direct_interners! { ExternalConstraints -> ExternalConstraints<'tcx>, predefined_opaques_in_body: pub mk_predefined_opaques_in_body(PredefinedOpaquesData>): PredefinedOpaques -> PredefinedOpaques<'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/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index b0c442d28f0a0..d811e73629f17 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -192,15 +192,13 @@ impl FlagComputation { self.add_args(args); } - &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_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index ebb6a8c08a54c..2ef79ba0c430d 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -828,7 +828,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 71a8e22128935..311e1741f7e0b 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -91,8 +91,9 @@ pub use self::region::{ pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::{ AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, - CoroutineArgsExt, EarlyBinder, FnSig, InlineConstArgs, InlineConstArgsParts, ParamConst, - ParamTy, PolyFnSig, TyKind, TypeAndMut, TypingMode, UpvarArgs, + CoroutineArgsExt, EarlyBinder, FnSig, FnSigTys, InlineConstArgs, InlineConstArgsParts, + ParamConst, ParamTy, PolyFnSig, SigBinderRef, TyBinderRef, TyKind, TypeAndMut, TypingMode, + UpvarArgs, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ @@ -2224,6 +2225,6 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(PredicateKind<'_>, 32); - static_assert_size!(WithCachedTypeInfo>, 56); + static_assert_size!(WithCachedTypeInfo>, 48); // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 60fd531b4d0ee..3ccafdd5bc5ec 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -720,3 +720,35 @@ impl<'tcx> TypeFoldable> for &'tcx ty::List> { ty::util::fold_list(self, folder, |tcx, v| tcx.mk_place_elems(v)) } } + +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) }) + } +} + +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) }) + } +} diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 34cac383030a3..519a7459240a7 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -5,7 +5,7 @@ use std::assert_matches::debug_assert_matches; use std::borrow::Cow; use std::iter; -use std::ops::{ControlFlow, Range}; +use std::ops::{ControlFlow, Deref, Range}; use hir::def::{CtorKind, DefKind}; use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx, VariantIdx}; @@ -37,6 +37,7 @@ pub type FnSig<'tcx> = ir::FnSig>; pub type Binder<'tcx, T> = ir::Binder, T>; pub type EarlyBinder<'tcx, T> = ir::EarlyBinder, T>; pub type TypingMode<'tcx> = ir::TypingMode>; +pub type FnSigTys<'tcx> = ir::FnSigTys>; pub trait Article { fn article(&self) -> &'static str; @@ -704,12 +705,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] @@ -2090,6 +2091,30 @@ mod size_asserts { use super::*; // tidy-alphabetical-start static_assert_size!(ty::RegionKind<'_>, 24); - static_assert_size!(ty::TyKind<'_>, 32); + static_assert_size!(ty::TyKind<'_>, 24); // tidy-alphabetical-end } + +// FIXME: this is a distinct type because we need to define `Encode`/`Decode` impls. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, HashStable)] +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, HashStable)] +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_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs index bb2b2dea2f37f..493ba5c167569 100644 --- a/compiler/rustc_smir/src/rustc_internal/internal.rs +++ b/compiler/rustc_smir/src/rustc_internal/internal.rs @@ -132,7 +132,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 dc8022b95c313..f1306aedbeba4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4973,13 +4973,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 0017186c1b082..5d5d182cbc7ba 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -606,7 +606,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/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 52955ec59a4a0..a36d06a7177c6 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -203,7 +203,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 c3ff613db360c..6448f00763011 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -59,42 +59,27 @@ where } #[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/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 92e44915bf1ff..1d823df2595c8 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -44,6 +44,13 @@ pub trait Interner: type BoundVarKinds: Copy + Debug + Hash + Eq + SliceLike + Default; type BoundVarKind: Copy + Debug + Hash + Eq; + 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 9bea4482b550c..489d582418453 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -1,5 +1,4 @@ use std::fmt; -use std::ops::Deref; use derive_where::derive_where; use rustc_ast_ir::Mutability; @@ -14,8 +13,6 @@ use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Gen use self::TyKind::*; pub use self::closure::*; use crate::inherent::*; -#[cfg(feature = "nightly")] -use crate::visit::TypeVisitable; use crate::{self as ty, DebruijnIndex, Interner}; mod closure; @@ -160,14 +157,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, DynKind), @@ -1003,68 +1000,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, Eq, Hash; I: Interner)] -#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] -#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] -pub struct UnsafeBinderInner(ty::Binder); - -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, Eq, Hash; I: Interner)] #[cfg_attr( diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c08ae168d6927..7b895f784be78 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -2114,7 +2114,7 @@ pub(crate) fn clean_middle_ty<'tcx>( } ty::UnsafeBinder(inner) => { let generic_params = clean_bound_vars(inner.bound_vars()); - 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) => {