Skip to content
Draft
4 changes: 2 additions & 2 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1345,9 +1345,9 @@ checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d"

[[package]]
name = "ena"
version = "0.14.3"
version = "0.14.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5"
checksum = "eabffdaee24bd1bf95c5ef7cec31260444317e72ea56c4c91750e8b7ee58d5f1"
dependencies = [
"log",
]
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_data_structures/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ arrayvec = { version = "0.7", default-features = false }
bitflags = "2.4.1"
either = "1.0"
elsa = "1.11.0"
ena = "0.14.3"
ena = "0.14.4"
indexmap = "2.14.0"
jobserver_crate = { version = "0.1.28", package = "jobserver" }
measureme = "12.0.1"
Expand Down
52 changes: 3 additions & 49 deletions compiler/rustc_infer/src/infer/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use rustc_middle::ty::relate::RelateResult;
use rustc_middle::ty::relate::combine::PredicateEmittingRelation;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span};
use rustc_type_ir::solve::TyOrConstInferVar;

use super::{
BoundRegionConversionTime, InferCtxt, OpaqueTypeStorageEntries, RegionVariableOrigin,
Expand Down Expand Up @@ -131,55 +132,8 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> {
self.inner.borrow_mut().unwrap_region_constraints().opportunistic_resolve_var(self.tcx, vid)
}

fn is_changed_arg(&self, arg: ty::GenericArg<'tcx>) -> bool {
match arg.kind() {
ty::GenericArgKind::Lifetime(_) => {
// Lifetimes should not change affect trait selection.
false
}
ty::GenericArgKind::Type(ty) => {
if let ty::Infer(infer_ty) = *ty.kind() {
match infer_ty {
ty::InferTy::TyVar(vid) => {
!self.try_resolve_ty_var(vid).is_err_and(|_| self.root_var(vid) == vid)
}
ty::InferTy::IntVar(vid) => {
let mut inner = self.inner.borrow_mut();
!matches!(
inner.int_unification_table().probe_value(vid),
ty::IntVarValue::Unknown
if inner.int_unification_table().find(vid) == vid
)
}
ty::InferTy::FloatVar(vid) => {
let mut inner = self.inner.borrow_mut();
!matches!(
inner.float_unification_table().probe_value(vid),
ty::FloatVarValue::Unknown
if inner.float_unification_table().find(vid) == vid
)
}
ty::InferTy::FreshTy(_)
| ty::InferTy::FreshIntTy(_)
| ty::InferTy::FreshFloatTy(_) => true,
}
} else {
true
}
}
ty::GenericArgKind::Const(ct) => {
if let ty::ConstKind::Infer(infer_ct) = ct.kind() {
match infer_ct {
ty::InferConst::Var(vid) => !self
.try_resolve_const_var(vid)
.is_err_and(|_| self.root_const_var(vid) == vid),
ty::InferConst::Fresh(_) => true,
}
} else {
true
}
}
}
fn ty_or_const_infer_var_changed(&self, var: TyOrConstInferVar) -> bool {
self.ty_or_const_infer_var_changed(var)
}

fn next_region_infer(&self) -> ty::Region<'tcx> {
Expand Down
95 changes: 26 additions & 69 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ use rustc_middle::traits::solve::Goal;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{
self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs,
GenericArgsRef, GenericParamDefKind, InferConst, IntVid, OpaqueTypeKey, ProvisionalHiddenType,
PseudoCanonicalInput, Term, TermKind, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder,
TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
GenericArgsRef, GenericParamDefKind, InferConst, OpaqueTypeKey, ProvisionalHiddenType,
PseudoCanonicalInput, Term, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
};
use rustc_span::{DUMMY_SP, Span, Symbol};
use rustc_type_ir::MayBeErased;
use snapshot::undo_log::InferCtxtUndoLogs;
use tracing::{debug, instrument};
use ty::solve::TyOrConstInferVar;
use type_variable::TypeVariableOrigin;

use crate::infer::snapshot::undo_log::UndoLog;
Expand Down Expand Up @@ -1208,6 +1209,21 @@ impl<'tcx> InferCtxt<'tcx> {
}
}

/// If `TyVar(vid)` resolves to a type, return that type. Else, return the
/// universe index of `TyVar(vid)`, along with the root vid, which can be
/// cheaply found at the same time.
pub fn try_resolve_ty_var_with_root_vid(
&self,
vid: TyVid,
) -> Result<Ty<'tcx>, (TyVid, ty::UniverseIndex)> {
use self::type_variable::TypeVariableValue;
let (root_vid, res) = self.inner.borrow_mut().type_variables().probe_with_root_vid(vid);
match res {
TypeVariableValue::Known { value } => Ok(value),
TypeVariableValue::Unknown { universe } => Err((root_vid, universe)),
}
}

pub fn shallow_resolve(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
if let ty::Infer(v) = *ty.kind() {
match v {
Expand Down Expand Up @@ -1561,14 +1577,13 @@ impl<'tcx> InferCtxt<'tcx> {
#[inline(always)]
pub fn ty_or_const_infer_var_changed(&self, infer_var: TyOrConstInferVar) -> bool {
match infer_var {
TyOrConstInferVar::Ty(v) => {
use self::type_variable::TypeVariableValue;

// If `inlined_probe` returns a `Known` value, it never equals
// `ty::Infer(ty::TyVar(v))`.
match self.inner.borrow_mut().type_variables().inlined_probe(v) {
TypeVariableValue::Unknown { .. } => false,
TypeVariableValue::Known { .. } => true,
TyOrConstInferVar::Ty(vid) => {
// If `try_resolve_ty_var` returns `Err`, *and* the `root_vid` is unchanged,
// it's definitely unchanged. The check against `root_vid` matters, see
// https://github.com/rust-lang/rust/issues/158441
match self.try_resolve_ty_var_with_root_vid(vid) {
Ok(_) => true,
Err((root_vid, _)) => root_vid != vid,
}
}

Expand Down Expand Up @@ -1610,64 +1625,6 @@ impl<'tcx> InferCtxt<'tcx> {
}
}

/// Helper for [InferCtxt::ty_or_const_infer_var_changed] (see comment on that), currently
/// used only for `traits::fulfill`'s list of `stalled_on` inference variables.
#[derive(Copy, Clone, Debug)]
pub enum TyOrConstInferVar {
/// Equivalent to `ty::Infer(ty::TyVar(_))`.
Ty(TyVid),
/// Equivalent to `ty::Infer(ty::IntVar(_))`.
TyInt(IntVid),
/// Equivalent to `ty::Infer(ty::FloatVar(_))`.
TyFloat(FloatVid),

/// Equivalent to `ty::ConstKind::Infer(ty::InferConst::Var(_))`.
Const(ConstVid),
}

impl<'tcx> TyOrConstInferVar {
/// Tries to extract an inference variable from a type or a constant, returns `None`
/// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and
/// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
pub fn maybe_from_generic_arg(arg: GenericArg<'tcx>) -> Option<Self> {
match arg.kind() {
GenericArgKind::Type(ty) => Self::maybe_from_ty(ty),
GenericArgKind::Const(ct) => Self::maybe_from_const(ct),
GenericArgKind::Lifetime(_) => None,
}
}

/// Tries to extract an inference variable from a type or a constant, returns `None`
/// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`) and
/// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
pub fn maybe_from_term(term: Term<'tcx>) -> Option<Self> {
match term.kind() {
TermKind::Ty(ty) => Self::maybe_from_ty(ty),
TermKind::Const(ct) => Self::maybe_from_const(ct),
}
}

/// Tries to extract an inference variable from a type, returns `None`
/// for types other than `ty::Infer(_)` (or `InferTy::Fresh*`).
fn maybe_from_ty(ty: Ty<'tcx>) -> Option<Self> {
match *ty.kind() {
ty::Infer(ty::TyVar(v)) => Some(TyOrConstInferVar::Ty(v)),
ty::Infer(ty::IntVar(v)) => Some(TyOrConstInferVar::TyInt(v)),
ty::Infer(ty::FloatVar(v)) => Some(TyOrConstInferVar::TyFloat(v)),
_ => None,
}
}

/// Tries to extract an inference variable from a constant, returns `None`
/// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`).
fn maybe_from_const(ct: ty::Const<'tcx>) -> Option<Self> {
match ct.kind() {
ty::ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)),
_ => None,
}
}
}

/// Replace `{integer}` with `i32` and `{float}` with `f64`.
/// Used only for diagnostics.
struct InferenceLiteralEraser<'tcx> {
Expand Down
19 changes: 19 additions & 0 deletions compiler/rustc_infer/src/infer/type_variable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,25 @@ impl<'tcx> TypeVariableTable<'_, 'tcx> {
self.eq_relations().inlined_probe_value(vid)
}

/// Retrieves the type to which `vid` has been instantiated, if
/// any, along with the root `vid`.
pub(crate) fn probe_with_root_vid(
&mut self,
vid: ty::TyVid,
) -> (ty::TyVid, TypeVariableValue<'tcx>) {
self.inlined_probe_with_root_vid(vid)
}

/// An always-inlined variant of `probe_with_root_vid`, for very hot call sites.
#[inline(always)]
pub(crate) fn inlined_probe_with_root_vid(
&mut self,
vid: ty::TyVid,
) -> (ty::TyVid, TypeVariableValue<'tcx>) {
let (id, value) = self.eq_relations().inlined_probe_key_value(vid);
(id.vid, value)
}

#[inline]
fn eq_relations(&mut self) -> super::UnificationTable<'_, 'tcx, TyVidEqKey<'tcx>> {
self.storage.eq_relations.with_log(self.undo_log)
Expand Down
4 changes: 4 additions & 0 deletions compiler/rustc_middle/src/traits/solve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ pub type CanonicalInput<'tcx, P = ty::Predicate<'tcx>> = ir::solve::CanonicalInp
pub type CanonicalResponse<'tcx> = ir::solve::CanonicalResponse<TyCtxt<'tcx>>;
pub type FetchEligibleAssocItemResponse<'tcx> =
ir::solve::FetchEligibleAssocItemResponse<TyCtxt<'tcx>>;
pub type ComputeGoalFastPathOutcome<'tcx> = ir::solve::ComputeGoalFastPathOutcome<TyCtxt<'tcx>>;
pub type GoalStalledOn<'tcx> = ir::solve::GoalStalledOn<TyCtxt<'tcx>>;
pub type GoalStalledOnReason<'tcx> = ir::solve::GoalStalledOnReason<TyCtxt<'tcx>>;
pub type SucceededInErased<'tcx> = ir::solve::SucceededInErased<TyCtxt<'tcx>>;

pub type PredefinedOpaques<'tcx> = &'tcx ty::List<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>;

Expand Down
5 changes: 3 additions & 2 deletions compiler/rustc_next_trait_solver/src/delegate.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use std::ops::Deref;

use rustc_type_ir::solve::{
Certainty, FetchEligibleAssocItemResponse, Goal, NoSolution, VisibleForLeakCheck,
Certainty, ComputeGoalFastPathOutcome, FetchEligibleAssocItemResponse, Goal, NoSolution,
VisibleForLeakCheck,
};
use rustc_type_ir::{self as ty, InferCtxtLike, Interner, TypeFoldable};

Expand All @@ -23,7 +24,7 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
&self,
goal: Goal<Self::Interner, <Self::Interner as Interner>::Predicate>,
span: <Self::Interner as Interner>::Span,
) -> Option<Certainty>;
) -> ComputeGoalFastPathOutcome<Self::Interner>;

fn fresh_var_for_kind_with_span(
&self,
Expand Down
Loading
Loading