Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer/unify.rs')
-rw-r--r--crates/hir-ty/src/infer/unify.rs232
1 files changed, 48 insertions, 184 deletions
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index 59e8d84190..0b566497c4 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -7,10 +7,9 @@ use hir_expand::name::Name;
use intern::sym;
use rustc_hash::FxHashSet;
use rustc_type_ir::{
- DebruijnIndex, InferConst, InferTy, RegionVid, TyVid, TypeFoldable, TypeFolder,
- TypeSuperFoldable, TypeVisitableExt, UpcastFrom,
- inherent::{Const as _, IntoKind, Ty as _},
- solve::{Certainty, GoalSource},
+ TyVid, TypeFoldable, TypeVisitableExt, UpcastFrom,
+ inherent::{Const as _, GenericArg as _, IntoKind, SliceLike, Ty as _},
+ solve::Certainty,
};
use smallvec::SmallVec;
use triomphe::Arc;
@@ -18,15 +17,14 @@ use triomphe::Arc;
use crate::{
TraitEnvironment,
db::HirDatabase,
- infer::InferenceContext,
next_solver::{
- self, AliasTy, Binder, Canonical, ClauseKind, Const, ConstKind, DbInterner,
- ErrorGuaranteed, GenericArg, GenericArgs, Predicate, PredicateKind, Region, RegionKind,
- SolverDefId, TraitRef, Ty, TyKind, TypingMode,
+ AliasTy, Canonical, ClauseKind, Const, DbInterner, ErrorGuaranteed, GenericArg,
+ GenericArgs, Goal, Predicate, PredicateKind, Region, SolverDefId, Term, TraitRef, Ty,
+ TyKind, TypingMode,
fulfill::{FulfillmentCtxt, NextSolverError},
infer::{
DbInternerInferExt, InferCtxt, InferOk, InferResult,
- at::ToTrace,
+ at::{At, ToTrace},
snapshot::CombinedSnapshot,
traits::{Obligation, ObligationCause, PredicateObligation},
},
@@ -38,15 +36,6 @@ use crate::{
},
};
-impl<'db> InferenceContext<'_, 'db> {
- pub(super) fn canonicalize<T>(&mut self, t: T) -> rustc_type_ir::Canonical<DbInterner<'db>, T>
- where
- T: rustc_type_ir::TypeFoldable<DbInterner<'db>>,
- {
- self.table.canonicalize(t)
- }
-}
-
struct NestedObligationsForSelfTy<'a, 'db> {
ctx: &'a InferenceTable<'db>,
self_ty: TyVid,
@@ -73,21 +62,7 @@ impl<'a, 'db> ProofTreeVisitor<'db> for NestedObligationsForSelfTy<'a, 'db> {
let db = self.ctx.interner();
let goal = inspect_goal.goal();
- if self.ctx.predicate_has_self_ty(goal.predicate, self.self_ty)
- // We do not push the instantiated forms of goals as it would cause any
- // aliases referencing bound vars to go from having escaping bound vars to
- // being able to be normalized to an inference variable.
- //
- // This is mostly just a hack as arbitrary nested goals could still contain
- // such aliases while having a different `GoalSource`. Closure signature inference
- // however can't really handle *every* higher ranked `Fn` goal also being present
- // in the form of `?c: Fn<(<?x as Trait<'!a>>::Assoc)`.
- //
- // This also just better matches the behaviour of the old solver where we do not
- // encounter instantiated forms of goals, only nested goals that referred to bound
- // vars from instantiated goals.
- && !matches!(inspect_goal.source(), GoalSource::InstantiateHigherRanked)
- {
+ if self.ctx.predicate_has_self_ty(goal.predicate, self.self_ty) {
self.obligations_for_self_ty.push(Obligation::new(
db,
self.root_cause.clone(),
@@ -292,21 +267,7 @@ impl<'db> InferenceTable<'db> {
T: TypeFoldable<DbInterner<'db>> + Clone,
{
let ty = self.resolve_vars_with_obligations(ty);
- self.infer_ctxt
- .at(&ObligationCause::new(), self.trait_env.env)
- .deeply_normalize(ty.clone())
- .unwrap_or(ty)
- }
-
- /// Works almost same as [`Self::normalize_associated_types_in`], but this also resolves shallow
- /// the inference variables
- pub(crate) fn eagerly_normalize_and_resolve_shallow_in<T>(&mut self, ty: T) -> T
- where
- T: TypeFoldable<DbInterner<'db>>,
- {
- let ty = self.resolve_vars_with_obligations(ty);
- let ty = self.normalize_associated_types_in(ty);
- self.resolve_vars_with_obligations(ty)
+ self.at(&ObligationCause::new()).deeply_normalize(ty.clone()).unwrap_or(ty)
}
pub(crate) fn normalize_alias_ty(&mut self, alias: Ty<'db>) -> Ty<'db> {
@@ -316,19 +277,19 @@ impl<'db> InferenceTable<'db> {
.unwrap_or(alias)
}
- pub(crate) fn next_ty_var(&mut self) -> Ty<'db> {
+ pub(crate) fn next_ty_var(&self) -> Ty<'db> {
self.infer_ctxt.next_ty_var()
}
- pub(crate) fn next_const_var(&mut self) -> Const<'db> {
+ pub(crate) fn next_const_var(&self) -> Const<'db> {
self.infer_ctxt.next_const_var()
}
- pub(crate) fn next_int_var(&mut self) -> Ty<'db> {
+ pub(crate) fn next_int_var(&self) -> Ty<'db> {
self.infer_ctxt.next_int_var()
}
- pub(crate) fn next_float_var(&mut self) -> Ty<'db> {
+ pub(crate) fn next_float_var(&self) -> Ty<'db> {
self.infer_ctxt.next_float_var()
}
@@ -338,101 +299,12 @@ impl<'db> InferenceTable<'db> {
var
}
- pub(crate) fn next_region_var(&mut self) -> Region<'db> {
+ pub(crate) fn next_region_var(&self) -> Region<'db> {
self.infer_ctxt.next_region_var()
}
- pub(crate) fn next_var_for_param(&mut self, id: GenericParamId) -> GenericArg<'db> {
- match id {
- GenericParamId::TypeParamId(_) => self.next_ty_var().into(),
- GenericParamId::ConstParamId(_) => self.next_const_var().into(),
- GenericParamId::LifetimeParamId(_) => self.next_region_var().into(),
- }
- }
-
- pub(crate) fn resolve_with_fallback<T>(
- &mut self,
- t: T,
- fallback_ty: &mut dyn FnMut(DebruijnIndex, InferTy) -> Ty<'db>,
- fallback_const: &mut dyn FnMut(DebruijnIndex, InferConst) -> Const<'db>,
- fallback_region: &mut dyn FnMut(DebruijnIndex, RegionVid) -> Region<'db>,
- ) -> T
- where
- T: TypeFoldable<DbInterner<'db>>,
- {
- struct Resolver<'a, 'db> {
- table: &'a mut InferenceTable<'db>,
- binder: DebruijnIndex,
- fallback_ty: &'a mut dyn FnMut(DebruijnIndex, InferTy) -> Ty<'db>,
- fallback_const: &'a mut dyn FnMut(DebruijnIndex, InferConst) -> Const<'db>,
- fallback_region: &'a mut dyn FnMut(DebruijnIndex, RegionVid) -> Region<'db>,
- }
-
- impl<'db> TypeFolder<DbInterner<'db>> for Resolver<'_, 'db> {
- fn cx(&self) -> DbInterner<'db> {
- self.table.interner()
- }
-
- fn fold_binder<T>(&mut self, t: Binder<'db, T>) -> Binder<'db, T>
- where
- T: TypeFoldable<DbInterner<'db>>,
- {
- self.binder.shift_in(1);
- let result = t.super_fold_with(self);
- self.binder.shift_out(1);
- result
- }
-
- fn fold_ty(&mut self, t: Ty<'db>) -> Ty<'db> {
- if !t.has_infer() {
- return t;
- }
-
- if let TyKind::Infer(infer) = t.kind() {
- (self.fallback_ty)(self.binder, infer)
- } else {
- t.super_fold_with(self)
- }
- }
-
- fn fold_const(&mut self, c: Const<'db>) -> Const<'db> {
- if !c.has_infer() {
- return c;
- }
-
- if let ConstKind::Infer(infer) = c.kind() {
- (self.fallback_const)(self.binder, infer)
- } else {
- c.super_fold_with(self)
- }
- }
-
- fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
- if let RegionKind::ReVar(infer) = r.kind() {
- (self.fallback_region)(self.binder, infer)
- } else {
- r
- }
- }
- }
-
- t.fold_with(&mut Resolver {
- table: self,
- binder: DebruijnIndex::ZERO,
- fallback_ty,
- fallback_const,
- fallback_region,
- })
- }
-
- pub(crate) fn instantiate_canonical<T>(
- &mut self,
- canonical: rustc_type_ir::Canonical<DbInterner<'db>, T>,
- ) -> T
- where
- T: rustc_type_ir::TypeFoldable<DbInterner<'db>>,
- {
- self.infer_ctxt.instantiate_canonical(&canonical).0
+ pub(crate) fn next_var_for_param(&self, id: GenericParamId) -> GenericArg<'db> {
+ self.infer_ctxt.next_var_for_param(id)
}
pub(crate) fn resolve_completely<T>(&mut self, value: T) -> T
@@ -456,7 +328,11 @@ impl<'db> InferenceTable<'db> {
/// Unify two relatable values (e.g. `Ty`) and return new trait goals arising from it, so the
/// caller needs to deal with them.
pub(crate) fn try_unify<T: ToTrace<'db>>(&mut self, t1: T, t2: T) -> InferResult<'db, ()> {
- self.infer_ctxt.at(&ObligationCause::new(), self.trait_env.env).eq(t1, t2)
+ self.at(&ObligationCause::new()).eq(t1, t2)
+ }
+
+ pub(crate) fn at<'a>(&'a self, cause: &'a ObligationCause) -> At<'a, 'db> {
+ self.infer_ctxt.at(cause, self.trait_env.env)
}
pub(crate) fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db> {
@@ -486,15 +362,6 @@ impl<'db> InferenceTable<'db> {
self.infer_ctxt.fresh_args_for_item(def)
}
- /// Like `fresh_args_for_item()`, but first uses the args from `first`.
- pub(crate) fn fill_rest_fresh_args(
- &self,
- def_id: SolverDefId,
- first: impl IntoIterator<Item = GenericArg<'db>>,
- ) -> GenericArgs<'db> {
- self.infer_ctxt.fill_rest_fresh_args(def_id, first)
- }
-
/// Try to resolve `ty` to a structural type, normalizing aliases.
///
/// In case there is still ambiguity, the returned type may be an inference
@@ -535,17 +402,6 @@ impl<'db> InferenceTable<'db> {
self.fulfillment_cx = snapshot.obligations;
}
- #[tracing::instrument(skip_all)]
- pub(crate) fn run_in_snapshot<T>(
- &mut self,
- f: impl FnOnce(&mut InferenceTable<'db>) -> T,
- ) -> T {
- let snapshot = self.snapshot();
- let result = f(self);
- self.rollback_to(snapshot);
- result
- }
-
pub(crate) fn commit_if_ok<T, E>(
&mut self,
f: impl FnOnce(&mut InferenceTable<'db>) -> Result<T, E>,
@@ -566,22 +422,19 @@ impl<'db> InferenceTable<'db> {
/// choice (during e.g. method resolution or deref).
#[tracing::instrument(level = "debug", skip(self))]
pub(crate) fn try_obligation(&mut self, predicate: Predicate<'db>) -> NextTraitSolveResult {
- let goal = next_solver::Goal { param_env: self.trait_env.env, predicate };
+ let goal = Goal { param_env: self.trait_env.env, predicate };
let canonicalized = self.canonicalize(goal);
next_trait_solve_canonical_in_ctxt(&self.infer_ctxt, canonicalized)
}
pub(crate) fn register_obligation(&mut self, predicate: Predicate<'db>) {
- let goal = next_solver::Goal { param_env: self.trait_env.env, predicate };
+ let goal = Goal { param_env: self.trait_env.env, predicate };
self.register_obligation_in_env(goal)
}
#[tracing::instrument(level = "debug", skip(self))]
- fn register_obligation_in_env(
- &mut self,
- goal: next_solver::Goal<'db, next_solver::Predicate<'db>>,
- ) {
+ fn register_obligation_in_env(&mut self, goal: Goal<'db, Predicate<'db>>) {
let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal);
tracing::debug!(?result);
match result {
@@ -619,7 +472,7 @@ impl<'db> InferenceTable<'db> {
self.fulfillment_cx.register_predicate_obligation(&self.infer_ctxt, obligation);
}
- pub(super) fn register_predicates<I>(&mut self, obligations: I)
+ pub(crate) fn register_predicates<I>(&mut self, obligations: I)
where
I: IntoIterator<Item = PredicateObligation<'db>>,
{
@@ -628,6 +481,23 @@ impl<'db> InferenceTable<'db> {
});
}
+ /// checking later, during regionck, that `arg` is well-formed.
+ pub(crate) fn register_wf_obligation(&mut self, term: Term<'db>, cause: ObligationCause) {
+ self.register_predicate(Obligation::new(
+ self.interner(),
+ cause,
+ self.trait_env.env,
+ ClauseKind::WellFormed(term),
+ ));
+ }
+
+ /// Registers obligations that all `args` are well-formed.
+ pub(crate) fn add_wf_bounds(&mut self, args: GenericArgs<'db>) {
+ for term in args.iter().filter_map(|it| it.as_term()) {
+ self.register_wf_obligation(term, ObligationCause::new());
+ }
+ }
+
pub(crate) fn callable_sig(
&mut self,
ty: Ty<'db>,
@@ -714,26 +584,20 @@ impl<'db> InferenceTable<'db> {
}
/// Whenever you lower a user-written type, you should call this.
- pub(crate) fn process_user_written_ty<T>(&mut self, ty: T) -> T
- where
- T: TypeFoldable<DbInterner<'db>>,
- {
+ pub(crate) fn process_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
self.process_remote_user_written_ty(ty)
// FIXME: Register a well-formed obligation.
}
/// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation,
/// while `process_user_written_ty()` should (but doesn't currently).
- pub(crate) fn process_remote_user_written_ty<T>(&mut self, ty: T) -> T
- where
- T: TypeFoldable<DbInterner<'db>>,
- {
+ pub(crate) fn process_remote_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
let ty = self.insert_type_vars(ty);
// See https://github.com/rust-lang/rust/blob/cdb45c87e2cd43495379f7e867e3cc15dcee9f93/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs#L487-L495:
// Even though the new solver only lazily normalizes usually, here we eagerly normalize so that not everything needs
// to normalize before inspecting the `TyKind`.
// FIXME(next-solver): We should not deeply normalize here, only shallowly.
- self.normalize_associated_types_in(ty)
+ self.try_structurally_resolve_type(ty)
}
/// Replaces ConstScalar::Unknown by a new type var, so we can maybe still infer it.
@@ -762,7 +626,7 @@ impl<'db> InferenceTable<'db> {
}
let mut ty = ty;
- ty = self.eagerly_normalize_and_resolve_shallow_in(ty);
+ ty = self.try_structurally_resolve_type(ty);
if let Some(sized) = short_circuit_trivial_tys(ty) {
return sized;
}
@@ -784,7 +648,7 @@ impl<'db> InferenceTable<'db> {
// Structs can have DST as its last field and such cases are not handled
// as unsized by the chalk, so we do this manually.
ty = last_field_ty;
- ty = self.eagerly_normalize_and_resolve_shallow_in(ty);
+ ty = self.try_structurally_resolve_type(ty);
if let Some(sized) = short_circuit_trivial_tys(ty) {
return sized;
}
@@ -852,7 +716,7 @@ mod resolve_completely {
{
let value = if self.should_normalize {
let cause = ObligationCause::new();
- let at = self.ctx.infer_ctxt.at(&cause, self.ctx.trait_env.env);
+ let at = self.ctx.at(&cause);
let universes = vec![None; outer_exclusive_binder(value).as_usize()];
match deeply_normalize_with_skipped_universes_and_ambiguous_coroutine_goals(
at, value, universes,