Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 59 additions & 79 deletions compiler/rustc_infer/src/infer/freshen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,45 +60,35 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
}
}

fn freshen_ty<F>(&mut self, input: Result<Ty<'tcx>, ty::InferTy>, mk_fresh: F) -> Ty<'tcx>
fn freshen_ty<F>(&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<F>(
&mut self,
input: Result<ty::Const<'tcx>, ty::InferConst>,
freshener: F,
) -> ty::Const<'tcx>
fn freshen_const<F>(&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
}
}
}
}
Expand Down Expand Up @@ -146,27 +136,24 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> 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(_)
Expand All @@ -181,56 +168,49 @@ impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> 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<Ty<'tcx>> {
match v {
fn fold_infer_ty(&mut self, ty: ty::InferTy) -> Option<Ty<'tcx>> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now always returns Some?

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);
Some(ty.fold_with(self))
}
None => {
let input = ty::TyVar(inner.type_variables().root_var(v));
Some(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) => Some(Ty::new_int(self.infcx.tcx, ty)),
ty::IntVarValue::UintType(ty) => Some(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));
Some(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) => Some(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));
Some(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:?}");
}
}
}
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -637,10 +637,6 @@ impl<'tcx> InferCtxt<'tcx> {
self.typing_mode
}

pub fn freshen<T: TypeFoldable<TyCtxt<'tcx>>>(&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.
Expand All @@ -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<Ty<'tcx>> {
let mut inner = self.inner.borrow_mut();
let mut vars: Vec<Ty<'_>> = inner
Expand Down
3 changes: 2 additions & 1 deletion compiler/rustc_trait_selection/src/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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))
}
}
15 changes: 8 additions & 7 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
Expand Down Expand Up @@ -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());

Expand Down Expand Up @@ -1135,7 +1136,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
/// `Option<Box<List<T>>>` is `Send` if `Box<List<T>>` 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
Expand Down Expand Up @@ -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",);
Expand Down Expand 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>,
Expand Down Expand Up @@ -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(
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_type_ir/src/const_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
}

Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_type_ir/src/ty_kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Loading