Unnamed repository; edit this file 'description' to name the repository.
Remove methods that do not have a correspondence in rustc
And make `InferenceTable` used by inference only.
Chayim Refael Friedman 4 weeks ago
parent 2147146 · commit 1286db8
-rw-r--r--crates/hir-ty/src/dyn_compatibility.rs14
-rw-r--r--crates/hir-ty/src/infer.rs2
-rw-r--r--crates/hir-ty/src/infer/cast.rs7
-rw-r--r--crates/hir-ty/src/infer/unify.rs141
-rw-r--r--crates/hir-ty/src/lib.rs115
-rw-r--r--crates/hir-ty/src/next_solver/infer/mod.rs18
-rw-r--r--crates/hir-ty/src/next_solver/infer/traits.rs8
-rw-r--r--crates/hir-ty/src/next_solver/ty.rs4
-rw-r--r--crates/hir-ty/src/traits.rs97
-rw-r--r--crates/hir/src/lib.rs18
10 files changed, 111 insertions, 313 deletions
diff --git a/crates/hir-ty/src/dyn_compatibility.rs b/crates/hir-ty/src/dyn_compatibility.rs
index ee7527446a..0cf7f650f0 100644
--- a/crates/hir-ty/src/dyn_compatibility.rs
+++ b/crates/hir-ty/src/dyn_compatibility.rs
@@ -21,11 +21,14 @@ use crate::{
db::{HirDatabase, InternedOpaqueTyId},
lower::{GenericPredicates, associated_ty_item_bounds},
next_solver::{
- AliasTy, Binder, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, Goal, ParamEnv,
- ParamTy, SolverDefId, TraitPredicate, TraitRef, Ty, TypingMode, infer::DbInternerInferExt,
+ AliasTy, Binder, Clause, Clauses, DbInterner, EarlyBinder, GenericArgs, ParamEnv, ParamTy,
+ SolverDefId, TraitPredicate, TraitRef, Ty, TypingMode,
+ infer::{
+ DbInternerInferExt,
+ traits::{Obligation, ObligationCause},
+ },
mk_param,
},
- traits::next_trait_solve_in_ctxt,
};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -474,12 +477,11 @@ fn receiver_is_dispatchable<'db>(
// Receiver: DispatchFromDyn<Receiver[Self => U]>
let predicate =
TraitRef::new(interner, dispatch_from_dyn_did.into(), [receiver_ty, unsized_receiver_ty]);
- let goal = Goal::new(interner, param_env, predicate);
+ let obligation = Obligation::new(interner, ObligationCause::dummy(), param_env, predicate);
let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());
// the receiver is dispatchable iff the obligation holds
- let res = next_trait_solve_in_ctxt(&infcx, goal);
- res.map_or(false, |res| matches!(res.1, rustc_type_ir::solve::Certainty::Yes))
+ infcx.predicate_must_hold_modulo_regions(&obligation)
}
fn receiver_for_self_ty<'db>(
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 54f334b66d..9a6941f8a3 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -1240,7 +1240,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
db.trait_environment(ExpressionStoreOwnerId::VariantFields(variant_id))
}
};
- let table = unify::InferenceTable::new(db, trait_env, resolver.krate(), Some(owner));
+ let table = unify::InferenceTable::new(db, trait_env, resolver.krate(), owner);
let types = crate::next_solver::default_types(db);
InferenceContext {
result: InferenceResult::new(types.types.error),
diff --git a/crates/hir-ty/src/infer/cast.rs b/crates/hir-ty/src/infer/cast.rs
index 09855766d8..d23a32d81b 100644
--- a/crates/hir-ty/src/infer/cast.rs
+++ b/crates/hir-ty/src/infer/cast.rs
@@ -147,7 +147,8 @@ impl<'db> CastCheck<'db> {
return Ok(());
}
- if !self.cast_ty.has_infer_types() && !ctx.table.is_sized(self.cast_ty) {
+ if !self.cast_ty.has_infer_types() && !ctx.table.type_is_sized_modulo_regions(self.cast_ty)
+ {
return Err(InferenceDiagnostic::CastToUnsized {
expr: self.expr,
cast_ty: self.cast_ty.store(),
@@ -199,7 +200,7 @@ impl<'db> CastCheck<'db> {
// array-ptr-cast
CastTy::Ptr(t, m) => {
let t = ctx.table.try_structurally_resolve_type(t);
- if !ctx.table.is_sized(t) {
+ if !ctx.table.type_is_sized_modulo_regions(t) {
return Err(CastError::IllegalCast);
}
self.check_ref_cast(ctx, inner_ty, mutbl, t, m)
@@ -520,7 +521,7 @@ fn pointer_kind<'db>(
) -> Result<Option<PointerKind<'db>>, ()> {
let ty = ctx.table.try_structurally_resolve_type(ty);
- if ctx.table.is_sized(ty) {
+ if ctx.table.type_is_sized_modulo_regions(ty) {
return Ok(Some(PointerKind::Thin));
}
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index b0f916b8c0..1d6a87a157 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -3,10 +3,10 @@
use std::fmt;
use base_db::Crate;
-use hir_def::{AdtId, ExpressionStoreOwnerId, GenericParamId, TraitId};
+use hir_def::{ExpressionStoreOwnerId, GenericParamId, TraitId};
use rustc_hash::FxHashSet;
use rustc_type_ir::{
- TyVid, TypeFoldable, TypeVisitableExt, UpcastFrom,
+ TyVid, TypeFoldable, TypeVisitableExt,
inherent::{Const as _, GenericArg as _, IntoKind, Ty as _},
solve::Certainty,
};
@@ -15,7 +15,7 @@ use smallvec::SmallVec;
use crate::{
db::HirDatabase,
next_solver::{
- Canonical, ClauseKind, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Goal,
+ Canonical, ClauseKind, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
ParamEnv, Predicate, PredicateKind, Region, SolverDefId, Term, TraitRef, Ty, TyKind,
TypingMode,
fulfill::{FulfillmentCtxt, NextSolverError},
@@ -28,10 +28,7 @@ use crate::{
inspect::{InspectConfig, InspectGoal, ProofTreeVisitor},
obligation_ctxt::ObligationCtxt,
},
- traits::{
- NextTraitSolveResult, ParamEnvAndCrate, next_trait_solve_canonical_in_ctxt,
- next_trait_solve_in_ctxt,
- },
+ traits::ParamEnvAndCrate,
};
struct NestedObligationsForSelfTy<'a, 'db> {
@@ -145,14 +142,10 @@ impl<'db> InferenceTable<'db> {
db: &'db dyn HirDatabase,
trait_env: ParamEnv<'db>,
krate: Crate,
- owner: Option<ExpressionStoreOwnerId>,
+ owner: ExpressionStoreOwnerId,
) -> Self {
let interner = DbInterner::new_with(db, krate);
- let typing_mode = match owner {
- Some(owner) => TypingMode::typeck_for_body(interner, owner.into()),
- // IDE things wants to reveal opaque types.
- None => TypingMode::PostAnalysis,
- };
+ let typing_mode = TypingMode::typeck_for_body(interner, owner.into());
let infer_ctxt = interner.infer_ctxt().build(typing_mode);
InferenceTable {
db,
@@ -172,6 +165,10 @@ impl<'db> InferenceTable<'db> {
self.infer_ctxt.type_is_copy_modulo_regions(self.param_env, ty)
}
+ pub(crate) fn type_is_sized_modulo_regions(&self, ty: Ty<'db>) -> bool {
+ self.infer_ctxt.type_is_sized_modulo_regions(self.param_env, ty)
+ }
+
pub(crate) fn type_is_use_cloned_modulo_regions(&self, ty: Ty<'db>) -> bool {
self.infer_ctxt.type_is_use_cloned_modulo_regions(self.param_env, ty)
}
@@ -253,23 +250,6 @@ impl<'db> InferenceTable<'db> {
self.diverging_type_vars.insert(ty);
}
- pub(crate) fn canonicalize<T>(&mut self, t: T) -> rustc_type_ir::Canonical<DbInterner<'db>, T>
- where
- T: TypeFoldable<DbInterner<'db>>,
- {
- // try to resolve obligations before canonicalizing, since this might
- // result in new knowledge about variables
- self.select_obligations_where_possible();
- self.infer_ctxt.canonicalize_response(t)
- }
-
- pub(crate) fn normalize_alias_ty(&mut self, alias: Ty<'db>) -> Ty<'db> {
- self.infer_ctxt
- .at(&ObligationCause::new(), self.param_env)
- .structurally_normalize_ty(alias, &mut self.fulfillment_cx)
- .unwrap_or(alias)
- }
-
pub(crate) fn next_ty_var(&self) -> Ty<'db> {
self.infer_ctxt.next_ty_var()
}
@@ -407,43 +387,6 @@ impl<'db> InferenceTable<'db> {
result
}
- /// Checks an obligation without registering it. Useful mostly to check
- /// whether a trait *might* be implemented before deciding to 'lock in' the
- /// 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 = Goal { param_env: self.param_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 = Goal { param_env: self.param_env, predicate };
- self.register_obligation_in_env(goal)
- }
-
- #[tracing::instrument(level = "debug", skip(self))]
- 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 {
- Ok((_, Certainty::Yes)) => {}
- Err(rustc_type_ir::solve::NoSolution) => {}
- Ok((_, Certainty::Maybe { .. })) => {
- self.fulfillment_cx.register_predicate_obligation(
- &self.infer_ctxt,
- Obligation::new(
- self.interner(),
- ObligationCause::new(),
- goal.param_env,
- goal.predicate,
- ),
- );
- }
- }
- }
-
pub(crate) fn register_bound(&mut self, ty: Ty<'db>, def_id: TraitId, cause: ObligationCause) {
if !ty.references_non_lt_error() {
let trait_ref = TraitRef::new(self.interner(), def_id.into(), [ty]);
@@ -533,70 +476,6 @@ impl<'db> InferenceTable<'db> {
pub(super) fn insert_const_vars_shallow(&mut self, c: Const<'db>) -> Const<'db> {
if c.is_ct_error() { self.next_const_var() } else { c }
}
-
- /// Check if given type is `Sized` or not
- pub(crate) fn is_sized(&mut self, ty: Ty<'db>) -> bool {
- fn short_circuit_trivial_tys(ty: Ty<'_>) -> Option<bool> {
- match ty.kind() {
- TyKind::Bool
- | TyKind::Char
- | TyKind::Int(_)
- | TyKind::Uint(_)
- | TyKind::Float(_)
- | TyKind::Ref(..)
- | TyKind::RawPtr(..)
- | TyKind::Never
- | TyKind::FnDef(..)
- | TyKind::Array(..)
- | TyKind::FnPtr(..) => Some(true),
- TyKind::Slice(..) | TyKind::Str | TyKind::Dynamic(..) => Some(false),
- _ => None,
- }
- }
-
- let mut ty = ty;
- ty = self.try_structurally_resolve_type(ty);
- if let Some(sized) = short_circuit_trivial_tys(ty) {
- return sized;
- }
-
- {
- let mut structs = SmallVec::<[_; 8]>::new();
- // Must use a loop here and not recursion because otherwise users will conduct completely
- // artificial examples of structs that have themselves as the tail field and complain r-a crashes.
- while let Some((AdtId::StructId(id), subst)) = ty.as_adt() {
- let struct_data = id.fields(self.db);
- if let Some((last_field, _)) = struct_data.fields().iter().next_back() {
- let last_field_ty = self.db.field_types(id.into())[last_field]
- .get()
- .instantiate(self.interner(), subst);
- if structs.contains(&ty) {
- // A struct recursively contains itself as a tail field somewhere.
- return true; // Don't overload the users with too many errors.
- }
- structs.push(ty);
- // 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.try_structurally_resolve_type(ty);
- if let Some(sized) = short_circuit_trivial_tys(ty) {
- return sized;
- }
- } else {
- break;
- };
- }
- }
-
- let Some(sized) = self.interner().lang_items().Sized else {
- return false;
- };
- let sized_pred = Predicate::upcast_from(
- TraitRef::new(self.interner(), sized.into(), [ty]),
- self.interner(),
- );
- self.try_obligation(sized_pred).certain()
- }
}
impl fmt::Debug for InferenceTable<'_> {
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index c6c7856c8c..2973b970f3 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -71,7 +71,7 @@ use macros::GenericTypeVisitable;
use mir::{MirEvalError, VTableMap};
use rustc_hash::{FxBuildHasher, FxHashMap, FxHashSet};
use rustc_type_ir::{
- BoundVarIndexKind, TypeSuperVisitable, TypeVisitableExt, UpcastFrom,
+ BoundVarIndexKind, TypeSuperVisitable, TypeVisitableExt,
inherent::{IntoKind, Ty as _},
};
use syntax::ast::{ConstArg, make};
@@ -80,12 +80,17 @@ use traits::FnTrait;
use crate::{
db::HirDatabase,
display::{DisplayTarget, HirDisplay},
- infer::unify::InferenceTable,
lower::SupertraitsInfo,
next_solver::{
AliasTy, Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, Canonical,
- CanonicalVarKind, CanonicalVarKinds, ClauseKind, Const, ConstKind, DbInterner, FnSig,
- GenericArgs, PolyFnSig, Predicate, Region, RegionKind, TraitRef, Ty, TyKind, Tys, abi,
+ CanonicalVarKind, CanonicalVarKinds, ClauseKind, Const, ConstKind, DbInterner, GenericArgs,
+ PolyFnSig, Region, RegionKind, TraitRef, Ty, TyKind, TypingMode,
+ abi::Safety,
+ infer::{
+ DbInternerInferExt,
+ traits::{Obligation, ObligationCause},
+ },
+ obligation_ctxt::ObligationCtxt,
},
};
@@ -525,68 +530,64 @@ pub fn associated_type_shorthand_candidates(
/// To be used from `hir` only.
pub fn callable_sig_from_fn_trait<'db>(
self_ty: Ty<'db>,
- trait_env: ParamEnvAndCrate<'db>,
+ param_env: ParamEnvAndCrate<'db>,
db: &'db dyn HirDatabase,
) -> Option<(FnTrait, PolyFnSig<'db>)> {
- let mut table = InferenceTable::new(db, trait_env.param_env, trait_env.krate, None);
- let lang_items = table.interner().lang_items();
+ let ParamEnvAndCrate { param_env, krate } = param_env;
+ let interner = DbInterner::new_with(db, krate);
+ let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
+ let lang_items = interner.lang_items();
+ let cause = ObligationCause::dummy();
+
+ let impls_trait = |trait_: FnTrait| {
+ let mut ocx = ObligationCtxt::new(&infcx);
+ let tupled_args = infcx.next_ty_var();
+ let args = GenericArgs::new_from_slice(&[self_ty.into(), tupled_args.into()]);
+ let trait_id = trait_.get_id(lang_items)?;
+ let trait_ref = TraitRef::new_from_args(interner, trait_id.into(), args);
+ let obligation = Obligation::new(interner, cause.clone(), param_env, trait_ref);
+ ocx.register_obligation(obligation);
+ if !ocx.try_evaluate_obligations().is_empty() {
+ return None;
+ }
+ let tupled_args =
+ infcx.resolve_vars_if_possible(tupled_args).replace_infer_with_error(interner);
+ if tupled_args.is_tuple() { Some(tupled_args) } else { None }
+ };
- let fn_once_trait = FnTrait::FnOnce.get_id(lang_items)?;
+ let (trait_, args) = 'find_trait: {
+ for trait_ in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
+ if let Some(args) = impls_trait(trait_) {
+ break 'find_trait (trait_, args);
+ }
+ }
+ return None;
+ };
+
+ let fn_once_trait = lang_items.FnOnce?;
let output_assoc_type = fn_once_trait
.trait_items(db)
.associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
-
- // Register two obligations:
- // - Self: FnOnce<?args_ty>
- // - <Self as FnOnce<?args_ty>>::Output == ?ret_ty
- let args_ty = table.next_ty_var();
- let args = GenericArgs::new_from_slice(&[self_ty.into(), args_ty.into()]);
- let trait_ref = TraitRef::new_from_args(table.interner(), fn_once_trait.into(), args);
- let projection = Ty::new_alias(
- table.interner(),
- AliasTy::new_from_args(
- table.interner(),
+ let output_projection = Ty::new_alias(
+ interner,
+ AliasTy::new(
+ interner,
rustc_type_ir::Projection { def_id: output_assoc_type.into() },
- args,
+ [self_ty, args],
),
);
-
- let pred = Predicate::upcast_from(trait_ref, table.interner());
- if !table.try_obligation(pred).no_solution() {
- table.register_obligation(pred);
- let return_ty = table.normalize_alias_ty(projection);
- for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
- let fn_x_trait = fn_x.get_id(lang_items)?;
- let trait_ref = TraitRef::new_from_args(table.interner(), fn_x_trait.into(), args);
- if !table
- .try_obligation(Predicate::upcast_from(trait_ref, table.interner()))
- .no_solution()
- {
- let ret_ty = table.resolve_completely(return_ty);
- let args_ty = table.resolve_completely(args_ty);
- let TyKind::Tuple(params) = args_ty.kind() else {
- return None;
- };
- let inputs_and_output = Tys::new_from_iter(
- table.interner(),
- params.iter().chain(std::iter::once(ret_ty)),
- );
-
- return Some((
- fn_x,
- Binder::dummy(FnSig {
- inputs_and_output,
- c_variadic: false,
- safety: abi::Safety::Safe,
- abi: FnAbi::RustCall,
- }),
- ));
- }
- }
- unreachable!("It should at least implement FnOnce at this point");
- } else {
- None
- }
+ let mut ocx = ObligationCtxt::new(&infcx);
+ let ret = ocx.structurally_normalize_ty(&cause, param_env, output_projection).ok()?;
+ let ret = ret.replace_infer_with_error(interner);
+
+ let sig = Binder::dummy(interner.mk_fn_sig(
+ args.tuple_fields(),
+ ret,
+ false,
+ Safety::Safe,
+ FnAbi::Rust,
+ ));
+ Some((trait_, sig))
}
struct ParamCollector {
diff --git a/crates/hir-ty/src/next_solver/infer/mod.rs b/crates/hir-ty/src/next_solver/infer/mod.rs
index de21c5442b..1eacc295c9 100644
--- a/crates/hir-ty/src/next_solver/infer/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/mod.rs
@@ -58,7 +58,7 @@ pub mod relate;
pub mod resolve;
pub mod select;
pub(crate) mod snapshot;
-pub(crate) mod traits;
+pub mod traits;
mod type_variable;
mod unify_key;
@@ -494,8 +494,7 @@ impl<'db> InferCtxt<'db> {
/// check::<&'_ T>();
/// }
/// ```
- #[expect(dead_code, reason = "this is used in rustc")]
- fn predicate_must_hold_considering_regions(
+ pub fn predicate_must_hold_considering_regions(
&self,
obligation: &PredicateObligation<'db>,
) -> bool {
@@ -507,8 +506,10 @@ impl<'db> InferCtxt<'db> {
/// not entirely accurate if inference variables are involved.
///
/// This version ignores all outlives constraints.
- #[expect(dead_code, reason = "this is used in rustc")]
- fn predicate_must_hold_modulo_regions(&self, obligation: &PredicateObligation<'db>) -> bool {
+ pub fn predicate_must_hold_modulo_regions(
+ &self,
+ obligation: &PredicateObligation<'db>,
+ ) -> bool {
self.evaluate_obligation(obligation).must_apply_modulo_regions()
}
@@ -610,6 +611,13 @@ impl<'db> InferCtxt<'db> {
traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, copy_def_id)
}
+ pub fn type_is_sized_modulo_regions(&self, param_env: ParamEnv<'db>, ty: Ty<'db>) -> bool {
+ let Some(sized_def_id) = self.interner.lang_items().Sized else {
+ return true;
+ };
+ traits::type_known_to_meet_bound_modulo_regions(self, param_env, ty, sized_def_id)
+ }
+
pub fn type_is_use_cloned_modulo_regions(&self, param_env: ParamEnv<'db>, ty: Ty<'db>) -> bool {
let ty = self.resolve_vars_if_possible(ty);
diff --git a/crates/hir-ty/src/next_solver/infer/traits.rs b/crates/hir-ty/src/next_solver/infer/traits.rs
index dde6234836..5b875d2960 100644
--- a/crates/hir-ty/src/next_solver/infer/traits.rs
+++ b/crates/hir-ty/src/next_solver/infer/traits.rs
@@ -185,12 +185,12 @@ impl<'db> PredicateObligation<'db> {
impl<'db, O> Obligation<'db, O> {
pub fn new(
- tcx: DbInterner<'db>,
+ interner: DbInterner<'db>,
cause: ObligationCause,
param_env: ParamEnv<'db>,
predicate: impl Upcast<DbInterner<'db>, O>,
) -> Obligation<'db, O> {
- Self::with_depth(tcx, cause, 0, param_env, predicate)
+ Self::with_depth(interner, cause, 0, param_env, predicate)
}
/// We often create nested obligations without setting the correct depth.
@@ -202,13 +202,13 @@ impl<'db, O> Obligation<'db, O> {
}
pub fn with_depth(
- tcx: DbInterner<'db>,
+ interner: DbInterner<'db>,
cause: ObligationCause,
recursion_depth: usize,
param_env: ParamEnv<'db>,
predicate: impl Upcast<DbInterner<'db>, O>,
) -> Obligation<'db, O> {
- let predicate = predicate.upcast(tcx);
+ let predicate = predicate.upcast(interner);
Obligation { cause, param_env, recursion_depth, predicate }
}
diff --git a/crates/hir-ty/src/next_solver/ty.rs b/crates/hir-ty/src/next_solver/ty.rs
index c953e79602..0fd02eb8ca 100644
--- a/crates/hir-ty/src/next_solver/ty.rs
+++ b/crates/hir-ty/src/next_solver/ty.rs
@@ -626,6 +626,10 @@ impl<'db> Ty<'db> {
}
}
+ pub fn is_tuple(self) -> bool {
+ matches!(self.kind(), TyKind::Tuple(_))
+ }
+
pub fn as_tuple(self) -> Option<Tys<'db>> {
match self.kind() {
TyKind::Tuple(tys) => Some(tys),
diff --git a/crates/hir-ty/src/traits.rs b/crates/hir-ty/src/traits.rs
index 878696c721..0dc834ddcc 100644
--- a/crates/hir-ty/src/traits.rs
+++ b/crates/hir-ty/src/traits.rs
@@ -15,18 +15,15 @@ use hir_def::{
};
use hir_expand::name::Name;
use intern::sym;
-use rustc_next_trait_solver::solve::{HasChanged, SolverDelegateEvalExt};
use rustc_type_ir::{
TypingMode,
- inherent::{AdtDef, BoundExistentialPredicates, IntoKind, Span as _},
- solve::Certainty,
+ inherent::{AdtDef, BoundExistentialPredicates, IntoKind},
};
use crate::{
db::HirDatabase,
next_solver::{
- Canonical, DbInterner, GenericArgs, Goal, ParamEnv, Predicate, SolverContext, Span,
- StoredClauses, Ty, TyKind,
+ DbInterner, GenericArgs, ParamEnv, StoredClauses, Ty, TyKind,
infer::{
DbInternerInferExt, InferCtxt,
traits::{Obligation, ObligationCause},
@@ -79,91 +76,6 @@ pub fn structurally_normalize_ty<'db>(
ty.replace_infer_with_error(infcx.interner)
}
-#[derive(Clone, Debug, PartialEq)]
-pub enum NextTraitSolveResult {
- Certain,
- Uncertain,
- NoSolution,
-}
-
-impl NextTraitSolveResult {
- pub fn no_solution(&self) -> bool {
- matches!(self, NextTraitSolveResult::NoSolution)
- }
-
- pub fn certain(&self) -> bool {
- matches!(self, NextTraitSolveResult::Certain)
- }
-
- pub fn uncertain(&self) -> bool {
- matches!(self, NextTraitSolveResult::Uncertain)
- }
-}
-
-pub fn next_trait_solve_canonical_in_ctxt<'db>(
- infer_ctxt: &InferCtxt<'db>,
- goal: Canonical<'db, Goal<'db, Predicate<'db>>>,
-) -> NextTraitSolveResult {
- infer_ctxt.probe(|_| {
- let context = <&SolverContext<'db>>::from(infer_ctxt);
-
- tracing::info!(?goal);
-
- let (goal, var_values) = context.instantiate_canonical(&goal);
- tracing::info!(?var_values);
-
- let res = context.evaluate_root_goal(goal, Span::dummy(), None);
-
- let obligation = Obligation {
- cause: ObligationCause::dummy(),
- param_env: goal.param_env,
- recursion_depth: 0,
- predicate: goal.predicate,
- };
- infer_ctxt.inspect_evaluated_obligation(&obligation, &res, || {
- Some(context.evaluate_root_goal_for_proof_tree(goal, Span::dummy()).1)
- });
-
- let res = res.map(|r| (r.has_changed, r.certainty));
-
- tracing::debug!("solve_nextsolver({:?}) => {:?}", goal, res);
-
- match res {
- Err(_) => NextTraitSolveResult::NoSolution,
- Ok((_, Certainty::Yes)) => NextTraitSolveResult::Certain,
- Ok((_, Certainty::Maybe { .. })) => NextTraitSolveResult::Uncertain,
- }
- })
-}
-
-/// Solve a trait goal using next trait solver.
-pub fn next_trait_solve_in_ctxt<'db, 'a>(
- infer_ctxt: &'a InferCtxt<'db>,
- goal: Goal<'db, Predicate<'db>>,
-) -> Result<(HasChanged, Certainty), rustc_type_ir::solve::NoSolution> {
- tracing::info!(?goal);
-
- let context = <&SolverContext<'db>>::from(infer_ctxt);
-
- let res = context.evaluate_root_goal(goal, Span::dummy(), None);
-
- let obligation = Obligation {
- cause: ObligationCause::dummy(),
- param_env: goal.param_env,
- recursion_depth: 0,
- predicate: goal.predicate,
- };
- infer_ctxt.inspect_evaluated_obligation(&obligation, &res, || {
- Some(context.evaluate_root_goal_for_proof_tree(goal, Span::dummy()).1)
- });
-
- let res = res.map(|r| (r.has_changed, r.certainty));
-
- tracing::debug!("solve_nextsolver({:?}) => {:?}", goal, res);
-
- res
-}
-
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, salsa::Update)]
pub enum FnTrait {
// Warning: Order is important. If something implements `x` it should also implement
@@ -235,10 +147,9 @@ fn implements_trait_unique_impl<'db>(
let args = create_args(&infcx);
let trait_ref = rustc_type_ir::TraitRef::new_from_args(interner, trait_.into(), args);
- let goal = Goal::new(interner, env.param_env, trait_ref);
- let result = crate::traits::next_trait_solve_in_ctxt(&infcx, goal);
- matches!(result, Ok((_, Certainty::Yes)))
+ let obligation = Obligation::new(interner, ObligationCause::dummy(), env.param_env, trait_ref);
+ infcx.predicate_must_hold_modulo_regions(&obligation)
}
pub fn is_inherent_impl_coherent(db: &dyn HirDatabase, def_map: &DefMap, impl_id: ImplId) -> bool {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index ecd11fb5d7..11598f2a10 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -6561,21 +6561,13 @@ impl<'db> TypeNs<'db> {
);
let trait_ref =
hir_ty::next_solver::TraitRef::new_from_args(infcx.interner, trait_.id.into(), args);
-
- let pred_kind = rustc_type_ir::Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::Trait(rustc_type_ir::TraitPredicate {
- trait_ref,
- polarity: rustc_type_ir::PredicatePolarity::Positive,
- }),
- ));
- let predicate = hir_ty::next_solver::Predicate::new(infcx.interner, pred_kind);
- let goal = hir_ty::next_solver::Goal::new(
+ let obligation = hir_ty::next_solver::infer::traits::Obligation::new(
infcx.interner,
- hir_ty::next_solver::ParamEnv::empty(),
- predicate,
+ hir_ty::next_solver::infer::traits::ObligationCause::dummy(),
+ self.env.param_env,
+ trait_ref,
);
- let res = hir_ty::traits::next_trait_solve_in_ctxt(&infcx, goal);
- res.map_or(false, |res| matches!(res.1, rustc_type_ir::solve::Certainty::Yes))
+ infcx.predicate_must_hold_modulo_regions(&obligation)
}
pub fn is_bool(&self) -> bool {