diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index ddc0b11680627..c058bebddcf03 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -60,45 +60,35 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { } } - fn freshen_ty(&mut self, input: Result, ty::InferTy>, mk_fresh: F) -> Ty<'tcx> + fn freshen_ty(&mut self, input: ty::InferTy, mk_fresh: F) -> Ty<'tcx> where F: FnOnce(u32) -> Ty<'tcx>, { - match input { - Ok(ty) => ty.fold_with(self), - Err(key) => match self.ty_freshen_map.entry(key) { - Entry::Occupied(entry) => *entry.get(), - Entry::Vacant(entry) => { - let index = self.ty_freshen_count; - self.ty_freshen_count += 1; - let t = mk_fresh(index); - entry.insert(t); - t - } - }, + match self.ty_freshen_map.entry(input) { + Entry::Occupied(entry) => *entry.get(), + Entry::Vacant(entry) => { + let index = self.ty_freshen_count; + self.ty_freshen_count += 1; + let t = mk_fresh(index); + entry.insert(t); + t + } } } - fn freshen_const( - &mut self, - input: Result, ty::InferConst>, - freshener: F, - ) -> ty::Const<'tcx> + fn freshen_const(&mut self, input: ty::InferConst, freshener: F) -> ty::Const<'tcx> where F: FnOnce(u32) -> ty::InferConst, { - match input { - Ok(ct) => ct.fold_with(self), - Err(key) => match self.const_freshen_map.entry(key) { - Entry::Occupied(entry) => *entry.get(), - Entry::Vacant(entry) => { - let index = self.const_freshen_count; - self.const_freshen_count += 1; - let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index)); - entry.insert(ct); - ct - } - }, + match self.const_freshen_map.entry(input) { + Entry::Occupied(entry) => *entry.get(), + Entry::Vacant(entry) => { + let index = self.const_freshen_count; + self.const_freshen_count += 1; + let ct = ty::Const::new_infer(self.infcx.tcx, freshener(index)); + entry.insert(ct); + ct + } } } } @@ -130,7 +120,7 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { t } else { match *t.kind() { - ty::Infer(v) => self.fold_infer_ty(v).unwrap_or(t), + ty::Infer(v) => self.fold_infer_ty(v), // This code is hot enough that a non-debug assertion here makes a noticeable // difference on benchmarks like `wg-grammar`. @@ -146,27 +136,24 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { match ct.kind() { ty::ConstKind::Infer(ty::InferConst::Var(v)) => { let mut inner = self.infcx.inner.borrow_mut(); - let input = - inner.const_unification_table().probe_value(v).known().ok_or_else(|| { - ty::InferConst::Var(inner.const_unification_table().find(v).vid) - }); - drop(inner); - self.freshen_const(input, ty::InferConst::Fresh) - } - ty::ConstKind::Infer(ty::InferConst::Fresh(i)) => { - if i >= self.const_freshen_count { - bug!( - "Encountered a freshend const with id {} \ - but our counter is only at {}", - i, - self.const_freshen_count, - ); + match inner.const_unification_table().probe_value(v).known() { + Some(const_) => { + drop(inner); + const_.fold_with(self) + } + None => { + let input = + ty::InferConst::Var(inner.const_unification_table().find(v).vid); + self.freshen_const(input, ty::InferConst::Fresh) + } } - ct + } + ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => { + bug!("trying to freshen already-freshened const {ct:?}"); } ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { - bug!("unexpected const {:?}", ct) + bug!("unexpected const {ct:?}") } ty::ConstKind::Param(_) @@ -181,56 +168,49 @@ impl<'a, 'tcx> TypeFolder> for TypeFreshener<'a, 'tcx> { impl<'a, 'tcx> TypeFreshener<'a, 'tcx> { // This is separate from `fold_ty` to keep that method small and inlinable. #[inline(never)] - fn fold_infer_ty(&mut self, v: ty::InferTy) -> Option> { - match v { + fn fold_infer_ty(&mut self, ty: ty::InferTy) -> Ty<'tcx> { + match ty { ty::TyVar(v) => { let mut inner = self.infcx.inner.borrow_mut(); - let input = inner - .type_variables() - .probe(v) - .known() - .ok_or_else(|| ty::TyVar(inner.type_variables().root_var(v))); - drop(inner); - Some(self.freshen_ty(input, |n| Ty::new_fresh(self.infcx.tcx, n))) + match inner.type_variables().probe(v).known() { + Some(ty) => { + drop(inner); + ty.fold_with(self) + } + None => { + let input = ty::TyVar(inner.type_variables().root_var(v)); + self.freshen_ty(input, |n| Ty::new_fresh(self.infcx.tcx, n)) + } + } } ty::IntVar(v) => { let mut inner = self.infcx.inner.borrow_mut(); let value = inner.int_unification_table().probe_value(v); - let input = match value { - ty::IntVarValue::IntType(ty) => Ok(Ty::new_int(self.infcx.tcx, ty)), - ty::IntVarValue::UintType(ty) => Ok(Ty::new_uint(self.infcx.tcx, ty)), + match value { + ty::IntVarValue::IntType(ty) => Ty::new_int(self.infcx.tcx, ty), + ty::IntVarValue::UintType(ty) => Ty::new_uint(self.infcx.tcx, ty), ty::IntVarValue::Unknown => { - Err(ty::IntVar(inner.int_unification_table().find(v))) + let input = ty::IntVar(inner.int_unification_table().find(v)); + self.freshen_ty(input, |n| Ty::new_fresh_int(self.infcx.tcx, n)) } - }; - drop(inner); - Some(self.freshen_ty(input, |n| Ty::new_fresh_int(self.infcx.tcx, n))) + } } ty::FloatVar(v) => { let mut inner = self.infcx.inner.borrow_mut(); let value = inner.float_unification_table().probe_value(v); - let input = match value { - ty::FloatVarValue::Known(ty) => Ok(Ty::new_float(self.infcx.tcx, ty)), + match value { + ty::FloatVarValue::Known(ty) => Ty::new_float(self.infcx.tcx, ty), ty::FloatVarValue::Unknown => { - Err(ty::FloatVar(inner.float_unification_table().find(v))) + let input = ty::FloatVar(inner.float_unification_table().find(v)); + self.freshen_ty(input, |n| Ty::new_fresh_float(self.infcx.tcx, n)) } - }; - drop(inner); - Some(self.freshen_ty(input, |n| Ty::new_fresh_float(self.infcx.tcx, n))) + } } - ty::FreshTy(ct) | ty::FreshIntTy(ct) | ty::FreshFloatTy(ct) => { - if ct >= self.ty_freshen_count { - bug!( - "Encountered a freshend type with id {} \ - but our counter is only at {}", - ct, - self.ty_freshen_count - ); - } - None + ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { + bug!("trying to freshen already-freshened type {ty:?}"); } } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 53567c6071e3c..c9ea420944e23 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -637,10 +637,6 @@ impl<'tcx> InferCtxt<'tcx> { self.typing_mode } - pub fn freshen>>(&self, t: T) -> T { - t.fold_with(&mut self.freshener()) - } - /// Returns the origin of the type variable identified by `vid`. /// /// No attempt is made to resolve `vid` to its root variable. @@ -658,10 +654,6 @@ impl<'tcx> InferCtxt<'tcx> { } } - pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx> { - freshen::TypeFreshener::new(self) - } - pub fn unresolved_variables(&self) -> Vec> { let mut inner = self.inner.borrow_mut(); let mut vars: Vec> = inner diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 09709291a4b95..2da7c4448ce54 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -13,6 +13,7 @@ use tracing::debug; use super::*; use crate::errors::UnableToConstructConstantValue; +use crate::infer::TypeFreshener; use crate::infer::region_constraints::{ConstraintKind, RegionConstraintData}; use crate::regions::OutlivesEnvironmentBuildExt; use crate::traits::project::ProjectAndUnifyResult; @@ -817,6 +818,6 @@ impl<'tcx> AutoTraitFinder<'tcx> { infcx: &InferCtxt<'tcx>, p: ty::Predicate<'tcx>, ) -> ty::Predicate<'tcx> { - infcx.freshen(p) + p.fold_with(&mut TypeFreshener::new(infcx)) } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ea903bac9d617..13f3a76824f59 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -195,7 +195,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub fn new(infcx: &'cx InferCtxt<'tcx>) -> SelectionContext<'cx, 'tcx> { SelectionContext { infcx, - freshener: infcx.freshener(), + freshener: TypeFreshener::new(infcx), intercrate_ambiguity_causes: None, query_mode: TraitQueryMode::Standard, } @@ -321,10 +321,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.check_recursion_limit(stack.obligation, stack.obligation)?; // Check the cache. Note that we freshen the trait-ref - // separately rather than using `stack.fresh_trait_ref` -- + // separately rather than using `stack.fresh_trait_pred` -- // this is because we want the unbound variables to be // replaced with fresh types starting from index 0. - let cache_fresh_trait_pred = self.infcx.freshen(stack.obligation.predicate); + let cache_fresh_trait_pred = + stack.obligation.predicate.fold_with(&mut TypeFreshener::new(self.infcx)); debug!(?cache_fresh_trait_pred); debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars()); @@ -1135,7 +1136,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { /// `Option>>` is `Send` if `Box>` is /// `Send`. /// - /// Note that we do this comparison using the `fresh_trait_ref` + /// Note that we do this comparison using the `fresh_trait_pred` /// fields. Because these have all been freshened using /// `self.freshener`, we can be sure that (a) this will not /// affect the inferencer state and (b) that if we see two @@ -1219,7 +1220,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if unbound_input_types && stack.iter().skip(1).any(|prev| { stack.obligation.param_env == prev.obligation.param_env - && self.match_fresh_trait_refs(stack.fresh_trait_pred, prev.fresh_trait_pred) + && self.match_fresh_trait_preds(stack.fresh_trait_pred, prev.fresh_trait_pred) }) { debug!("evaluate_stack --> unbound argument, recursive --> giving up",); @@ -2742,7 +2743,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { /////////////////////////////////////////////////////////////////////////// // Miscellany - fn match_fresh_trait_refs( + fn match_fresh_trait_preds( &self, previous: ty::PolyTraitPredicate<'tcx>, current: ty::PolyTraitPredicate<'tcx>, @@ -3031,7 +3032,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { } /// Check the provisional cache for any result for - /// `fresh_trait_ref`. If there is a hit, then you must consider + /// `fresh_trait_pred`. If there is a hit, then you must consider /// it an access to the stack slots at depth /// `reached_depth` (from the returned value). fn get_provisional( diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index f315e8b3e11ce..9a83055d06c4e 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -103,7 +103,7 @@ rustc_index::newtype_index! { pub enum InferConst { /// Infer the value of the const. Var(ConstVid), - /// A fresh const variable. See `infer::freshen` for more details. + /// A fresh const variable. See `TypeFreshener` for more details. Fresh(u32), } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 34bb3cd8a6c35..498797bef653a 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -594,7 +594,7 @@ pub enum InferTy { /// A [`FreshTy`][Self::FreshTy] is one that is generated as a replacement /// for an unbound type variable. This is convenient for caching etc. See - /// `rustc_infer::infer::freshen` for more details. + /// `TypeFreshener` for more details. /// /// Compare with [`TyVar`][Self::TyVar]. FreshTy(u32),