Skip to content
Merged
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
46 changes: 3 additions & 43 deletions compiler/rustc_infer/src/infer/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,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 rustc_type_ir::{TypeSuperFoldable, TypeVisitableExt};

use super::type_variable::TypeVariableValue;
Expand Down Expand Up @@ -148,49 +149,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) => !matches!(
self.inner.borrow().try_type_variables_probe_ref(vid),
Some(TypeVariableValue::Unknown { .. })
),
ty::InferTy::IntVar(vid) => !matches!(
self.inner.borrow().int_unification_storage.try_probe_value(vid),
Some(ty::IntVarValue::Unknown)
),
ty::InferTy::FloatVar(vid) => !matches!(
self.inner.borrow().float_unification_storage.try_probe_value(vid),
Some(ty::FloatVarValue::Unknown)
),
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) => !matches!(
self.inner.borrow().const_unification_storage.try_probe_value(vid),
Some(ConstVariableValue::Unknown { .. })
),
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
119 changes: 21 additions & 98 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, RegionExt, Term, TermKind, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder,
GenericArgsRef, GenericParamDefKind, InferConst, OpaqueTypeKey, ProvisionalHiddenType,
PseudoCanonicalInput, RegionExt, 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 @@ -1616,44 +1617,24 @@ impl<'tcx> InferCtxt<'tcx> {
/// inference variables), and it handles both `Ty` and `ty::Const` without
/// having to resort to storing full `GenericArg`s in `stalled_on`.
#[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::TyInt(v) => {
// If `inlined_probe_value` returns a value it's always a
// `ty::Int(_)` or `ty::UInt(_)`, which never matches a
// `ty::Infer(_)`.
self.inner.borrow_mut().int_unification_table().inlined_probe_value(v).is_known()
}

TyOrConstInferVar::TyFloat(v) => {
// If `probe_value` returns a value it's always a
// `ty::Float(_)`, which never matches a `ty::Infer(_)`.
//
// Not `inlined_probe_value(v)` because this call site is colder.
self.inner.borrow_mut().float_unification_table().probe_value(v).is_known()
}

TyOrConstInferVar::Const(v) => {
// If `probe_value` returns a `Known` value, it never equals
// `ty::ConstKind::Infer(ty::InferConst::Var(v))`.
//
// Not `inlined_probe_value(v)` because this call site is colder.
match self.inner.borrow_mut().const_unification_table().probe_value(v) {
ConstVariableValue::Unknown { .. } => false,
ConstVariableValue::Known { .. } => true,
}
}
pub fn ty_or_const_infer_var_changed(&self, var: TyOrConstInferVar) -> bool {
match var {
TyOrConstInferVar::Ty(vid) => !matches!(
self.inner.borrow().try_type_variables_probe_ref(vid),
Some(TypeVariableValue::Unknown { .. })
),
TyOrConstInferVar::TyInt(vid) => !matches!(
self.inner.borrow().int_unification_storage.try_probe_value(vid),
Some(ty::IntVarValue::Unknown)
),
TyOrConstInferVar::TyFloat(vid) => !matches!(
self.inner.borrow().float_unification_storage.try_probe_value(vid),
Some(ty::FloatVarValue::Unknown)
),
TyOrConstInferVar::Const(vid) => !matches!(
self.inner.borrow().const_unification_storage.try_probe_value(vid),
Some(ConstVariableValue::Unknown { .. })
),
}
}

Expand All @@ -1667,64 +1648,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
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ where

// If any of the stalled goal's generic arguments changed,
// rerunning might make progress so we should rerun.
if stalled_vars.iter().any(|value| delegate.is_changed_arg(*value)) {
if stalled_vars.iter().any(|value| delegate.ty_or_const_infer_var_changed(*value)) {
return MayMakeProgress;
}

Expand Down
46 changes: 26 additions & 20 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use rustc_type_ir::search_graph::{CandidateHeadUsages, LowerAvailableDepth, Path
use rustc_type_ir::solve::{
AccessedOpaques, ExternalRegionConstraints, FetchEligibleAssocItemResponse, MaybeInfo,
NoSolutionOrRerunNonErased, OpaqueTypesJank, QueryResultOrRerunNonErased, RerunCondition,
RerunNonErased, RerunReason, RerunResultExt, SmallCopySet,
RerunNonErased, RerunReason, RerunResultExt, SmallCopySet, TyOrConstInferVar,
};
use rustc_type_ir::{
self as ty, CanonicalVarValues, ClauseKind, InferCtxtLike, Interner, MayBeErased,
Expand Down Expand Up @@ -839,29 +839,35 @@ where
&self,
canonical_goal: CanonicalInput<I>,
certainty: Certainty,
mut stalled_vars: ThinVec<I::GenericArg>,
stalled_vars: ThinVec<I::GenericArg>,
previously_succeeded_in_erased: SucceededInErased<I>,
) -> GoalStalledOn<I> {
// Remove the canonicalized universal vars, since we only care about stalled existentials.
let mut sub_roots = ThinVec::new();
stalled_vars.retain(|arg| match arg.kind() {
// Lifetimes can never stall goals.
ty::GenericArgKind::Lifetime(_) => false,
ty::GenericArgKind::Type(ty) => match ty.kind() {
ty::Infer(ty::TyVar(vid)) => {
sub_roots.push(self.delegate.sub_unification_table_root_var(vid));
true
}
ty::Infer(_) => true,
ty::Param(_) | ty::Placeholder(_) => false,
_ => unreachable!("unexpected orig_value: {ty:?}"),
},
ty::GenericArgKind::Const(ct) => match ct.kind() {
ty::ConstKind::Infer(_) => true,
ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) => false,
_ => unreachable!("unexpected orig_value: {ct:?}"),
},
});
let stalled_vars = stalled_vars
.into_iter()
.filter_map(|arg| match arg.kind() {
// Lifetimes can never stall goals.
ty::GenericArgKind::Lifetime(_) => None,
ty::GenericArgKind::Type(ty) => match ty.kind() {
ty::Infer(ty::TyVar(vid)) => {
sub_roots.push(self.delegate.sub_unification_table_root_var(vid));
Some(TyOrConstInferVar::Ty(vid))
}
ty::Infer(ty::IntVar(vid)) => Some(TyOrConstInferVar::TyInt(vid)),
ty::Infer(ty::FloatVar(vid)) => Some(TyOrConstInferVar::TyFloat(vid)),
ty::Param(_) | ty::Placeholder(_) => None,
_ => unreachable!("unexpected orig_value: {ty:?}"),
},
ty::GenericArgKind::Const(ct) => match ct.kind() {
ty::ConstKind::Infer(ty::InferConst::Var(v)) => {
Some(TyOrConstInferVar::Const(v))
}
ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) => None,
_ => unreachable!("unexpected orig_value: {ct:?}"),
},
})
.collect();

GoalStalledOn {
stalled_vars,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ use rustc_middle::ty::{
IsSuggestable, Term, TermKind, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable,
TypeVisitableExt, TypeckResults,
};
use rustc_next_trait_solver::solve::TyOrConstInferVar;
use rustc_span::{BytePos, DUMMY_SP, Ident, Span, sym};
use tracing::{debug, instrument, warn};

Expand All @@ -28,7 +29,7 @@ use crate::diagnostics::{
SpecifyGenericParamsSuggestion,
};
use crate::error_reporting::TypeErrCtxt;
use crate::infer::{InferCtxt, TyOrConstInferVar};
use crate::infer::InferCtxt;

pub enum TypeAnnotationNeeded {
/// ```compile_fail,E0282
Expand Down Expand Up @@ -94,7 +95,7 @@ impl InferenceDiagnosticsData {
} else {
match displayed_ty
.walk()
.filter_map(TyOrConstInferVar::maybe_from_generic_arg)
.filter_map(TyOrConstInferVar::maybe_from_generic_arg::<TyCtxt<'tcx>>)
.take(2)
.count()
{
Expand Down
Loading
Loading