Fix failing tests and fill-in missing details

This commit is contained in:
Shoyu Vanilla 2025-08-29 21:47:10 +09:00
parent d24e8c1d38
commit 4a8bc8db38
36 changed files with 917 additions and 1431 deletions

View file

@ -13,7 +13,7 @@ use triomphe::Arc;
use crate::{ use crate::{
Canonical, Goal, Interner, ProjectionTyExt, TraitEnvironment, Ty, TyBuilder, TyKind, Canonical, Goal, Interner, ProjectionTyExt, TraitEnvironment, Ty, TyBuilder, TyKind,
db::HirDatabase, infer::unify::InferenceTable, db::HirDatabase, infer::unify::InferenceTable, next_solver::mapping::ChalkToNextSolver,
}; };
const AUTODEREF_RECURSION_LIMIT: usize = 20; const AUTODEREF_RECURSION_LIMIT: usize = 20;
@ -98,7 +98,7 @@ impl<'table, 'db> Autoderef<'table, 'db> {
explicit: bool, explicit: bool,
use_receiver_trait: bool, use_receiver_trait: bool,
) -> Self { ) -> Self {
let ty = table.resolve_ty_shallow(&ty); let ty = table.structurally_resolve_type(&ty);
Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit, use_receiver_trait } Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit, use_receiver_trait }
} }
@ -114,7 +114,7 @@ impl<'table, 'db> Autoderef<'table, 'db, usize> {
explicit: bool, explicit: bool,
use_receiver_trait: bool, use_receiver_trait: bool,
) -> Self { ) -> Self {
let ty = table.resolve_ty_shallow(&ty); let ty = table.structurally_resolve_type(&ty);
Autoderef { table, ty, at_start: true, steps: 0, explicit, use_receiver_trait } Autoderef { table, ty, at_start: true, steps: 0, explicit, use_receiver_trait }
} }
} }
@ -160,7 +160,7 @@ pub(crate) fn autoderef_step(
use_receiver_trait: bool, use_receiver_trait: bool,
) -> Option<(AutoderefKind, Ty)> { ) -> Option<(AutoderefKind, Ty)> {
if let Some(derefed) = builtin_deref(table.db, &ty, explicit) { if let Some(derefed) = builtin_deref(table.db, &ty, explicit) {
Some((AutoderefKind::Builtin, table.resolve_ty_shallow(derefed))) Some((AutoderefKind::Builtin, table.structurally_resolve_type(derefed)))
} else { } else {
Some((AutoderefKind::Overloaded, deref_by_trait(table, ty, use_receiver_trait)?)) Some((AutoderefKind::Overloaded, deref_by_trait(table, ty, use_receiver_trait)?))
} }
@ -187,7 +187,7 @@ pub(crate) fn deref_by_trait(
use_receiver_trait: bool, use_receiver_trait: bool,
) -> Option<Ty> { ) -> Option<Ty> {
let _p = tracing::info_span!("deref_by_trait").entered(); let _p = tracing::info_span!("deref_by_trait").entered();
if table.resolve_ty_shallow(&ty).inference_var(Interner).is_some() { if table.structurally_resolve_type(&ty).inference_var(Interner).is_some() {
// don't try to deref unknown variables // don't try to deref unknown variables
return None; return None;
} }
@ -229,8 +229,8 @@ pub(crate) fn deref_by_trait(
return None; return None;
} }
table.register_obligation(implements_goal); table.register_obligation(implements_goal.to_nextsolver(table.interner));
let result = table.normalize_projection_ty(projection); let result = table.normalize_projection_ty(projection);
Some(table.resolve_ty_shallow(&result)) Some(table.structurally_resolve_type(&result))
} }

View file

@ -245,10 +245,7 @@ impl TyExt for Ty {
} }
fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> { fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
match self.kind(Interner) { let handle_async_block_type_impl_trait = |def: DefWithBodyId| {
TyKind::OpaqueType(opaque_ty_id, subst) => {
match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
let krate = def.module(db).krate(); let krate = def.module(db).krate();
if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) { if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) {
// This is only used by type walking. // This is only used by type walking.
@ -265,6 +262,13 @@ impl TyExt for Ty {
} else { } else {
None None
} }
};
match self.kind(Interner) {
TyKind::OpaqueType(opaque_ty_id, subst) => {
match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
handle_async_block_type_impl_trait(def)
} }
ImplTraitId::ReturnTypeImplTrait(func, idx) => { ImplTraitId::ReturnTypeImplTrait(func, idx) => {
db.return_type_impl_traits(func).map(|it| { db.return_type_impl_traits(func).map(|it| {
@ -299,8 +303,9 @@ impl TyExt for Ty {
data.substitute(Interner, &opaque_ty.substitution) data.substitute(Interner, &opaque_ty.substitution)
}) })
} }
// It always has an parameter for Future::Output type. ImplTraitId::AsyncBlockTypeImplTrait(def, _) => {
ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(), return handle_async_block_type_impl_trait(def);
}
}; };
predicates.map(|it| it.into_value_and_skipped_binders().0) predicates.map(|it| it.into_value_and_skipped_binders().0)

View file

@ -27,7 +27,7 @@ use crate::{
next_solver::{ next_solver::{
Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
ParamConst, SolverDefId, Ty, ValueConst, ParamConst, SolverDefId, Ty, ValueConst,
mapping::{ChalkToNextSolver, convert_binder_to_early_binder}, mapping::{ChalkToNextSolver, NextSolverToChalk, convert_binder_to_early_binder},
}, },
}; };
@ -145,7 +145,7 @@ pub fn try_const_usize<'db>(db: &'db dyn HirDatabase, c: Const<'db>) -> Option<u
SolverDefId::StaticId(id) => GeneralConstId::StaticId(id), SolverDefId::StaticId(id) => GeneralConstId::StaticId(id),
_ => unreachable!(), _ => unreachable!(),
}; };
let subst = ChalkToNextSolver::from_nextsolver(unevaluated_const.args, interner); let subst = unevaluated_const.args.to_chalk(interner);
let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner); let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner);
try_const_usize(db, ec) try_const_usize(db, ec)
} }
@ -168,7 +168,7 @@ pub fn try_const_isize<'db>(db: &'db dyn HirDatabase, c: &Const<'db>) -> Option<
SolverDefId::StaticId(id) => GeneralConstId::StaticId(id), SolverDefId::StaticId(id) => GeneralConstId::StaticId(id),
_ => unreachable!(), _ => unreachable!(),
}; };
let subst = ChalkToNextSolver::from_nextsolver(unevaluated_const.args, interner); let subst = unevaluated_const.args.to_chalk(interner);
let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner); let ec = db.const_eval(c, subst, None).ok()?.to_nextsolver(interner);
try_const_isize(db, &ec) try_const_isize(db, &ec)
} }

View file

@ -55,10 +55,9 @@ use stdx::{always, never};
use triomphe::Arc; use triomphe::Arc;
use crate::{ use crate::{
AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId, AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, ImplTraitId, ImplTraitIdx,
ImplTraitIdx, InEnvironment, IncorrectGenericsLenKind, Interner, Lifetime, OpaqueTyId, IncorrectGenericsLenKind, Interner, Lifetime, OpaqueTyId, ParamLoweringMode,
ParamLoweringMode, PathLoweringDiagnostic, ProjectionTy, Substitution, TraitEnvironment, Ty, PathLoweringDiagnostic, ProjectionTy, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt,
TyBuilder, TyExt,
db::HirDatabase, db::HirDatabase,
fold_tys, fold_tys,
generics::Generics, generics::Generics,
@ -70,6 +69,7 @@ use crate::{
}, },
lower::{ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic}, lower::{ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic},
mir::MirSpan, mir::MirSpan,
next_solver::{self, mapping::ChalkToNextSolver},
static_lifetime, to_assoc_type_id, static_lifetime, to_assoc_type_id,
traits::FnTrait, traits::FnTrait,
utils::UnevaluatedConstEvaluatorFolder, utils::UnevaluatedConstEvaluatorFolder,
@ -182,13 +182,13 @@ impl BindingMode {
} }
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct InferOk<T> { pub(crate) struct InferOk<'db, T> {
value: T, value: T,
goals: Vec<InEnvironment<Goal>>, goals: Vec<next_solver::Goal<'db, next_solver::Predicate<'db>>>,
} }
impl<T> InferOk<T> { impl<'db, T> InferOk<'db, T> {
fn map<U>(self, f: impl FnOnce(T) -> U) -> InferOk<U> { fn map<U>(self, f: impl FnOnce(T) -> U) -> InferOk<'db, U> {
InferOk { value: f(self.value), goals: self.goals } InferOk { value: f(self.value), goals: self.goals }
} }
} }
@ -203,7 +203,7 @@ pub enum InferenceTyDiagnosticSource {
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct TypeError; pub(crate) struct TypeError;
pub(crate) type InferResult<T> = Result<InferOk<T>, TypeError>; pub(crate) type InferResult<'db, T> = Result<InferOk<'db, T>, TypeError>;
#[derive(Debug, PartialEq, Eq, Clone)] #[derive(Debug, PartialEq, Eq, Clone)]
pub enum InferenceDiagnostic { pub enum InferenceDiagnostic {
@ -832,6 +832,7 @@ impl<'db> InferenceContext<'db> {
coercion_casts, coercion_casts,
diagnostics: _, diagnostics: _,
} = &mut result; } = &mut result;
table.resolve_obligations_as_possible();
table.fallback_if_possible(); table.fallback_if_possible();
// Comment from rustc: // Comment from rustc:
@ -1480,7 +1481,8 @@ impl<'db> InferenceContext<'db> {
} }
fn push_obligation(&mut self, o: DomainGoal) { fn push_obligation(&mut self, o: DomainGoal) {
self.table.register_obligation(o.cast(Interner)); let goal: crate::Goal = o.cast(Interner);
self.table.register_obligation(goal.to_nextsolver(self.table.interner));
} }
fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
@ -1746,7 +1748,7 @@ impl<'db> InferenceContext<'db> {
ty = self.table.insert_type_vars(ty); ty = self.table.insert_type_vars(ty);
ty = self.table.normalize_associated_types_in(ty); ty = self.table.normalize_associated_types_in(ty);
ty = self.table.resolve_ty_shallow(&ty); ty = self.table.structurally_resolve_type(&ty);
if ty.is_unknown() { if ty.is_unknown() {
return (self.err_ty(), None); return (self.err_ty(), None);
} }
@ -1817,7 +1819,7 @@ impl<'db> InferenceContext<'db> {
let ty = match ty.kind(Interner) { let ty = match ty.kind(Interner) {
TyKind::Alias(AliasTy::Projection(proj_ty)) => { TyKind::Alias(AliasTy::Projection(proj_ty)) => {
let ty = self.table.normalize_projection_ty(proj_ty.clone()); let ty = self.table.normalize_projection_ty(proj_ty.clone());
self.table.resolve_ty_shallow(&ty) self.table.structurally_resolve_type(&ty)
} }
_ => ty, _ => ty,
}; };
@ -2047,7 +2049,7 @@ impl Expectation {
fn adjust_for_branches(&self, table: &mut unify::InferenceTable<'_>) -> Expectation { fn adjust_for_branches(&self, table: &mut unify::InferenceTable<'_>) -> Expectation {
match self { match self {
Expectation::HasType(ety) => { Expectation::HasType(ety) => {
let ety = table.resolve_ty_shallow(ety); let ety = table.structurally_resolve_type(ety);
if ety.is_ty_var() { Expectation::None } else { Expectation::HasType(ety) } if ety.is_ty_var() { Expectation::None } else { Expectation::HasType(ety) }
} }
Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()), Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()),

View file

@ -39,6 +39,7 @@ use crate::{
infer::{BreakableKind, CoerceMany, Diverges, coerce::CoerceNever}, infer::{BreakableKind, CoerceMany, Diverges, coerce::CoerceNever},
make_binders, make_binders,
mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem}, mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem},
next_solver::mapping::ChalkToNextSolver,
to_assoc_type_id, to_assoc_type_id,
traits::FnTrait, traits::FnTrait,
utils::{self, elaborate_clause_supertraits}, utils::{self, elaborate_clause_supertraits},
@ -437,10 +438,10 @@ impl InferenceContext<'_> {
associated_ty_id: to_assoc_type_id(future_output), associated_ty_id: to_assoc_type_id(future_output),
substitution: Substitution::from1(Interner, ret_param_future.clone()), substitution: Substitution::from1(Interner, ret_param_future.clone()),
}); });
self.table.register_obligation( let goal: crate::Goal =
crate::AliasEq { alias: future_projection, ty: ret_param_future_output.clone() } crate::AliasEq { alias: future_projection, ty: ret_param_future_output.clone() }
.cast(Interner), .cast(Interner);
); self.table.register_obligation(goal.to_nextsolver(self.table.interner));
Some(FnSubst(Substitution::from_iter( Some(FnSubst(Substitution::from_iter(
Interner, Interner,
@ -568,7 +569,10 @@ impl InferenceContext<'_> {
let supplied_sig = self.supplied_sig_of_closure(body, ret_type, arg_types, closure_kind); let supplied_sig = self.supplied_sig_of_closure(body, ret_type, arg_types, closure_kind);
let snapshot = self.table.snapshot(); let snapshot = self.table.snapshot();
if !self.table.unify::<_, crate::next_solver::GenericArgs<'_>>(&expected_sig.substitution.0, &supplied_sig.expected_sig.substitution.0) { if !self.table.unify::<_, crate::next_solver::GenericArgs<'_>>(
&expected_sig.substitution.0,
&supplied_sig.expected_sig.substitution.0,
) {
self.table.rollback_to(snapshot); self.table.rollback_to(snapshot);
} }

View file

@ -8,24 +8,27 @@
use std::iter; use std::iter;
use chalk_ir::{BoundVar, Mutability, TyKind, TyVariableKind, cast::Cast}; use chalk_ir::{BoundVar, Mutability, TyKind, TyVariableKind, cast::Cast};
use hir_def::{ use hir_def::{hir::ExprId, lang_item::LangItem};
hir::ExprId,
lang_item::LangItem,
};
use rustc_type_ir::solve::Certainty; use rustc_type_ir::solve::Certainty;
use stdx::always; use stdx::always;
use triomphe::Arc; use triomphe::Arc;
use crate::{ use crate::{
autoderef::{Autoderef, AutoderefKind}, db::HirDatabase, infer::{ Canonical, FnAbi, FnPointer, FnSig, Goal, Interner, Lifetime, Substitution, TraitEnvironment,
Ty, TyBuilder, TyExt,
autoderef::{Autoderef, AutoderefKind},
db::HirDatabase,
infer::{
Adjust, Adjustment, AutoBorrow, InferOk, InferenceContext, OverloadedDeref, PointerCast, Adjust, Adjustment, AutoBorrow, InferOk, InferenceContext, OverloadedDeref, PointerCast,
TypeError, TypeMismatch, TypeError, TypeMismatch,
}, utils::ClosureSubst, Canonical, FnAbi, FnPointer, FnSig, Goal, InEnvironment, Interner, Lifetime, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt },
next_solver,
utils::ClosureSubst,
}; };
use super::unify::InferenceTable; use super::unify::InferenceTable;
pub(crate) type CoerceResult = Result<InferOk<(Vec<Adjustment>, Ty)>, TypeError>; pub(crate) type CoerceResult<'db> = Result<InferOk<'db, (Vec<Adjustment>, Ty)>, TypeError>;
/// Do not require any adjustments, i.e. coerce `x -> x`. /// Do not require any adjustments, i.e. coerce `x -> x`.
fn identity(_: Ty) -> Vec<Adjustment> { fn identity(_: Ty) -> Vec<Adjustment> {
@ -37,11 +40,11 @@ fn simple(kind: Adjust) -> impl FnOnce(Ty) -> Vec<Adjustment> {
} }
/// This always returns `Ok(...)`. /// This always returns `Ok(...)`.
fn success( fn success<'db>(
adj: Vec<Adjustment>, adj: Vec<Adjustment>,
target: Ty, target: Ty,
goals: Vec<InEnvironment<Goal>>, goals: Vec<next_solver::Goal<'db, next_solver::Predicate<'db>>>,
) -> CoerceResult { ) -> CoerceResult<'db> {
Ok(InferOk { goals, value: (adj, target) }) Ok(InferOk { goals, value: (adj, target) })
} }
@ -107,9 +110,9 @@ impl CoerceMany {
/// coerce both to function pointers; /// coerce both to function pointers;
/// - if we were concerned with lifetime subtyping, we'd need to look for a /// - if we were concerned with lifetime subtyping, we'd need to look for a
/// least upper bound. /// least upper bound.
pub(super) fn coerce( pub(super) fn coerce<'db>(
&mut self, &mut self,
ctx: &mut InferenceContext<'_>, ctx: &mut InferenceContext<'db>,
expr: Option<ExprId>, expr: Option<ExprId>,
expr_ty: &Ty, expr_ty: &Ty,
cause: CoercionCause, cause: CoercionCause,
@ -276,7 +279,7 @@ impl InferenceContext<'_> {
} }
} }
impl InferenceTable<'_> { impl<'db> InferenceTable<'db> {
/// Unify two types, but may coerce the first one to the second one /// Unify two types, but may coerce the first one to the second one
/// using "implicit coercion rules" if needed. /// using "implicit coercion rules" if needed.
pub(crate) fn coerce( pub(crate) fn coerce(
@ -285,8 +288,8 @@ impl InferenceTable<'_> {
to_ty: &Ty, to_ty: &Ty,
coerce_never: CoerceNever, coerce_never: CoerceNever,
) -> Result<(Vec<Adjustment>, Ty), TypeError> { ) -> Result<(Vec<Adjustment>, Ty), TypeError> {
let from_ty = self.resolve_ty_shallow(from_ty); let from_ty = self.structurally_resolve_type(from_ty);
let to_ty = self.resolve_ty_shallow(to_ty); let to_ty = self.structurally_resolve_type(to_ty);
match self.coerce_inner(from_ty, &to_ty, coerce_never) { match self.coerce_inner(from_ty, &to_ty, coerce_never) {
Ok(InferOk { value: (adjustments, ty), goals }) => { Ok(InferOk { value: (adjustments, ty), goals }) => {
self.register_infer_ok(InferOk { value: (), goals }); self.register_infer_ok(InferOk { value: (), goals });
@ -299,10 +302,15 @@ impl InferenceTable<'_> {
} }
} }
fn coerce_inner(&mut self, from_ty: Ty, to_ty: &Ty, coerce_never: CoerceNever) -> CoerceResult { fn coerce_inner(
&mut self,
from_ty: Ty,
to_ty: &Ty,
coerce_never: CoerceNever,
) -> CoerceResult<'db> {
if from_ty.is_never() { if from_ty.is_never() {
if let TyKind::InferenceVar(tv, TyVariableKind::General) = to_ty.kind(Interner) { if let TyKind::InferenceVar(tv, TyVariableKind::General) = to_ty.kind(Interner) {
self.set_diverging(*tv, TyVariableKind::General, true); self.set_diverging(*tv, TyVariableKind::General);
} }
if coerce_never == CoerceNever::Yes { if coerce_never == CoerceNever::Yes {
// Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
@ -370,7 +378,7 @@ impl InferenceTable<'_> {
} }
/// Unify two types (using sub or lub) and produce a specific coercion. /// Unify two types (using sub or lub) and produce a specific coercion.
fn unify_and<F>(&mut self, t1: &Ty, t2: &Ty, f: F) -> CoerceResult fn unify_and<F>(&mut self, t1: &Ty, t2: &Ty, f: F) -> CoerceResult<'db>
where where
F: FnOnce(Ty) -> Vec<Adjustment>, F: FnOnce(Ty) -> Vec<Adjustment>,
{ {
@ -378,7 +386,7 @@ impl InferenceTable<'_> {
.and_then(|InferOk { goals, .. }| success(f(t1.clone()), t1.clone(), goals)) .and_then(|InferOk { goals, .. }| success(f(t1.clone()), t1.clone(), goals))
} }
fn coerce_ptr(&mut self, from_ty: Ty, to_ty: &Ty, to_mt: Mutability) -> CoerceResult { fn coerce_ptr(&mut self, from_ty: Ty, to_ty: &Ty, to_mt: Mutability) -> CoerceResult<'db> {
let (is_ref, from_mt, from_inner) = match from_ty.kind(Interner) { let (is_ref, from_mt, from_inner) = match from_ty.kind(Interner) {
TyKind::Ref(mt, _, ty) => (true, mt, ty), TyKind::Ref(mt, _, ty) => (true, mt, ty),
TyKind::Raw(mt, ty) => (false, mt, ty), TyKind::Raw(mt, ty) => (false, mt, ty),
@ -420,7 +428,7 @@ impl InferenceTable<'_> {
to_ty: &Ty, to_ty: &Ty,
to_mt: Mutability, to_mt: Mutability,
to_lt: &Lifetime, to_lt: &Lifetime,
) -> CoerceResult { ) -> CoerceResult<'db> {
let (_from_lt, from_mt) = match from_ty.kind(Interner) { let (_from_lt, from_mt) = match from_ty.kind(Interner) {
TyKind::Ref(mt, lt, _) => { TyKind::Ref(mt, lt, _) => {
coerce_mutabilities(*mt, to_mt)?; coerce_mutabilities(*mt, to_mt)?;
@ -524,7 +532,7 @@ impl InferenceTable<'_> {
} }
/// Attempts to coerce from the type of a Rust function item into a function pointer. /// Attempts to coerce from the type of a Rust function item into a function pointer.
fn coerce_from_fn_item(&mut self, from_ty: Ty, to_ty: &Ty) -> CoerceResult { fn coerce_from_fn_item(&mut self, from_ty: Ty, to_ty: &Ty) -> CoerceResult<'db> {
match to_ty.kind(Interner) { match to_ty.kind(Interner) {
TyKind::Function(_) => { TyKind::Function(_) => {
let from_sig = from_ty.callable_sig(self.db).expect("FnDef had no sig"); let from_sig = from_ty.callable_sig(self.db).expect("FnDef had no sig");
@ -566,7 +574,7 @@ impl InferenceTable<'_> {
from_ty: Ty, from_ty: Ty,
from_f: &FnPointer, from_f: &FnPointer,
to_ty: &Ty, to_ty: &Ty,
) -> CoerceResult { ) -> CoerceResult<'db> {
self.coerce_from_safe_fn( self.coerce_from_safe_fn(
from_ty, from_ty,
from_f, from_f,
@ -583,7 +591,7 @@ impl InferenceTable<'_> {
to_ty: &Ty, to_ty: &Ty,
to_unsafe: F, to_unsafe: F,
normal: G, normal: G,
) -> CoerceResult ) -> CoerceResult<'db>
where where
F: FnOnce(Ty) -> Vec<Adjustment>, F: FnOnce(Ty) -> Vec<Adjustment>,
G: FnOnce(Ty) -> Vec<Adjustment>, G: FnOnce(Ty) -> Vec<Adjustment>,
@ -606,7 +614,7 @@ impl InferenceTable<'_> {
from_ty: Ty, from_ty: Ty,
from_substs: &Substitution, from_substs: &Substitution,
to_ty: &Ty, to_ty: &Ty,
) -> CoerceResult { ) -> CoerceResult<'db> {
match to_ty.kind(Interner) { match to_ty.kind(Interner) {
// if from_substs is non-capturing (FIXME) // if from_substs is non-capturing (FIXME)
TyKind::Function(fn_ty) => { TyKind::Function(fn_ty) => {
@ -631,7 +639,7 @@ impl InferenceTable<'_> {
/// Coerce a type using `from_ty: CoerceUnsized<ty_ty>` /// Coerce a type using `from_ty: CoerceUnsized<ty_ty>`
/// ///
/// See: <https://doc.rust-lang.org/nightly/std/marker/trait.CoerceUnsized.html> /// See: <https://doc.rust-lang.org/nightly/std/marker/trait.CoerceUnsized.html>
fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty) -> CoerceResult { fn try_coerce_unsized(&mut self, from_ty: &Ty, to_ty: &Ty) -> CoerceResult<'db> {
// These 'if' statements require some explanation. // These 'if' statements require some explanation.
// The `CoerceUnsized` trait is special - it is only // The `CoerceUnsized` trait is special - it is only
// possible to write `impl CoerceUnsized<B> for A` where // possible to write `impl CoerceUnsized<B> for A` where
@ -707,12 +715,9 @@ impl InferenceTable<'_> {
let goal: Goal = coerce_unsized_tref.cast(Interner); let goal: Goal = coerce_unsized_tref.cast(Interner);
self.commit_if_ok(|table| { self.commit_if_ok(|table| match table.solve_obligation(goal) {
match table.solve_obligation(goal) {
Ok(Certainty::Yes) => Ok(()), Ok(Certainty::Yes) => Ok(()),
Ok(Certainty::Maybe(_)) => Ok(()), _ => Err(TypeError),
Err(_) => Err(TypeError),
}
})?; })?;
let unsize = let unsize =

View file

@ -23,9 +23,29 @@ use stdx::always;
use syntax::ast::RangeOp; use syntax::ast::RangeOp;
use crate::{ use crate::{
autoderef::{builtin_deref, deref_by_trait, Autoderef}, consteval, generics::generics, infer::{ Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, CallableSig, DeclContext,
coerce::{CoerceMany, CoerceNever, CoercionCause}, find_continuable, pat::contains_explicit_ref_binding, BreakableKind DeclOrigin, IncorrectGenericsLenKind, Interner, LifetimeElisionKind, Rawness, Scalar,
}, lang_items::lang_items_for_bin_op, lower::{lower_to_chalk_mutability, path::{substs_from_args_and_bindings, GenericArgsLowerer, TypeLikeConst}, ParamLoweringMode}, mapping::{from_chalk, ToChalk}, method_resolution::{self, VisibleFromModule}, next_solver::mapping::ChalkToNextSolver, primitive::{self, UintTy}, static_lifetime, to_chalk_trait_id, traits::FnTrait, Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, CallableSig, DeclContext, DeclOrigin, IncorrectGenericsLenKind, Interner, LifetimeElisionKind, Rawness, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind,
autoderef::{Autoderef, builtin_deref, deref_by_trait},
consteval,
generics::generics,
infer::{
BreakableKind,
coerce::{CoerceMany, CoerceNever, CoercionCause},
find_continuable,
pat::contains_explicit_ref_binding,
},
lang_items::lang_items_for_bin_op,
lower::{
ParamLoweringMode, lower_to_chalk_mutability,
path::{GenericArgsLowerer, TypeLikeConst, substs_from_args_and_bindings},
},
mapping::{ToChalk, from_chalk},
method_resolution::{self, VisibleFromModule},
next_solver::mapping::ChalkToNextSolver,
primitive::{self, UintTy},
static_lifetime, to_chalk_trait_id,
traits::FnTrait,
}; };
use super::{ use super::{
@ -383,7 +403,7 @@ impl InferenceContext<'_> {
let matchee_diverges = mem::replace(&mut self.diverges, Diverges::Maybe); let matchee_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
let mut all_arms_diverge = Diverges::Always; let mut all_arms_diverge = Diverges::Always;
for arm in arms.iter() { for arm in arms.iter() {
let input_ty = self.resolve_ty_shallow(&input_ty); let input_ty = self.table.structurally_resolve_type(&input_ty);
self.infer_top_pat(arm.pat, &input_ty, None); self.infer_top_pat(arm.pat, &input_ty, None);
} }
@ -633,7 +653,7 @@ impl InferenceContext<'_> {
&Expr::Box { expr } => self.infer_expr_box(expr, expected), &Expr::Box { expr } => self.infer_expr_box(expr, expected),
Expr::UnaryOp { expr, op } => { Expr::UnaryOp { expr, op } => {
let inner_ty = self.infer_expr_inner(*expr, &Expectation::none(), ExprIsRead::Yes); let inner_ty = self.infer_expr_inner(*expr, &Expectation::none(), ExprIsRead::Yes);
let inner_ty = self.resolve_ty_shallow(&inner_ty); let inner_ty = self.table.structurally_resolve_type(&inner_ty);
// FIXME: Note down method resolution her // FIXME: Note down method resolution her
match op { match op {
UnaryOp::Deref => { UnaryOp::Deref => {
@ -651,7 +671,7 @@ impl InferenceContext<'_> {
); );
} }
if let Some(derefed) = builtin_deref(self.table.db, &inner_ty, true) { if let Some(derefed) = builtin_deref(self.table.db, &inner_ty, true) {
self.resolve_ty_shallow(derefed) self.table.structurally_resolve_type(derefed)
} else { } else {
deref_by_trait(&mut self.table, inner_ty, false) deref_by_trait(&mut self.table, inner_ty, false)
.unwrap_or_else(|| self.err_ty()) .unwrap_or_else(|| self.err_ty())
@ -807,10 +827,10 @@ impl InferenceContext<'_> {
let index_ty = self.infer_expr(*index, &Expectation::none(), ExprIsRead::Yes); let index_ty = self.infer_expr(*index, &Expectation::none(), ExprIsRead::Yes);
if let Some(index_trait) = self.resolve_lang_trait(LangItem::Index) { if let Some(index_trait) = self.resolve_lang_trait(LangItem::Index) {
let canonicalized = ChalkToNextSolver::from_nextsolver(self.canonicalize(base_ty.clone().to_nextsolver(self.table.interner)), self.table.interner); let canonicalized =
self.canonicalize(base_ty.clone().to_nextsolver(self.table.interner));
let receiver_adjustments = method_resolution::resolve_indexing_op( let receiver_adjustments = method_resolution::resolve_indexing_op(
self.db, &mut self.table,
self.table.trait_env.clone(),
canonicalized, canonicalized,
index_trait, index_trait,
); );
@ -983,7 +1003,7 @@ impl InferenceContext<'_> {
// allows them to be inferred based on how they are used later in the // allows them to be inferred based on how they are used later in the
// function. // function.
if is_input { if is_input {
let ty = this.resolve_ty_shallow(&ty); let ty = this.table.structurally_resolve_type(&ty);
match ty.kind(Interner) { match ty.kind(Interner) {
TyKind::FnDef(def, parameters) => { TyKind::FnDef(def, parameters) => {
let fnptr_ty = TyKind::Function( let fnptr_ty = TyKind::Function(
@ -1405,10 +1425,11 @@ impl InferenceContext<'_> {
// use knowledge of built-in binary ops, which can sometimes help inference // use knowledge of built-in binary ops, which can sometimes help inference
let builtin_ret = self.enforce_builtin_binop_types(&lhs_ty, &rhs_ty, op); let builtin_ret = self.enforce_builtin_binop_types(&lhs_ty, &rhs_ty, op);
self.unify(&builtin_ret, &ret_ty); self.unify(&builtin_ret, &ret_ty);
} builtin_ret
} else {
ret_ty ret_ty
} }
}
fn infer_block( fn infer_block(
&mut self, &mut self,
@ -1660,7 +1681,8 @@ impl InferenceContext<'_> {
None => { None => {
// no field found, lets attempt to resolve it like a function so that IDE things // no field found, lets attempt to resolve it like a function so that IDE things
// work out while people are typing // work out while people are typing
let canonicalized_receiver = self.canonicalize(receiver_ty.clone().to_nextsolver(self.table.interner)); let canonicalized_receiver =
self.canonicalize(receiver_ty.clone().to_nextsolver(self.table.interner));
let resolved = method_resolution::lookup_method( let resolved = method_resolution::lookup_method(
self.db, self.db,
&canonicalized_receiver, &canonicalized_receiver,
@ -1806,7 +1828,8 @@ impl InferenceContext<'_> {
expected: &Expectation, expected: &Expectation,
) -> Ty { ) -> Ty {
let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none(), ExprIsRead::Yes); let receiver_ty = self.infer_expr_inner(receiver, &Expectation::none(), ExprIsRead::Yes);
let canonicalized_receiver = self.canonicalize(receiver_ty.clone().to_nextsolver(self.table.interner)); let canonicalized_receiver =
self.canonicalize(receiver_ty.clone().to_nextsolver(self.table.interner));
let resolved = method_resolution::lookup_method( let resolved = method_resolution::lookup_method(
self.db, self.db,
@ -2216,7 +2239,7 @@ impl InferenceContext<'_> {
} }
fn register_obligations_for_call(&mut self, callable_ty: &Ty) { fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
let callable_ty = self.resolve_ty_shallow(callable_ty); let callable_ty = self.table.structurally_resolve_type(callable_ty);
if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) { if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(Interner) {
let def: CallableDefId = from_chalk(self.db, *fn_def); let def: CallableDefId = from_chalk(self.db, *fn_def);
let generic_predicates = let generic_predicates =
@ -2305,9 +2328,9 @@ impl InferenceContext<'_> {
/// Dereferences a single level of immutable referencing. /// Dereferences a single level of immutable referencing.
fn deref_ty_if_possible(&mut self, ty: &Ty) -> Ty { fn deref_ty_if_possible(&mut self, ty: &Ty) -> Ty {
let ty = self.resolve_ty_shallow(ty); let ty = self.table.structurally_resolve_type(ty);
match ty.kind(Interner) { match ty.kind(Interner) {
TyKind::Ref(Mutability::Not, _, inner) => self.resolve_ty_shallow(inner), TyKind::Ref(Mutability::Not, _, inner) => self.table.structurally_resolve_type(inner),
_ => ty, _ => ty,
} }
} }

View file

@ -190,7 +190,7 @@ impl InferenceContext<'_> {
subs: &[PatId], subs: &[PatId],
decl: Option<DeclContext>, decl: Option<DeclContext>,
) -> Ty { ) -> Ty {
let expected = self.resolve_ty_shallow(expected); let expected = self.table.structurally_resolve_type(expected);
let expectations = match expected.as_tuple() { let expectations = match expected.as_tuple() {
Some(parameters) => parameters.as_slice(Interner), Some(parameters) => parameters.as_slice(Interner),
_ => &[], _ => &[],
@ -238,7 +238,7 @@ impl InferenceContext<'_> {
mut default_bm: BindingMode, mut default_bm: BindingMode,
decl: Option<DeclContext>, decl: Option<DeclContext>,
) -> Ty { ) -> Ty {
let mut expected = self.resolve_ty_shallow(expected); let mut expected = self.table.structurally_resolve_type(expected);
if matches!(&self.body[pat], Pat::Ref { .. }) || self.inside_assignment { if matches!(&self.body[pat], Pat::Ref { .. }) || self.inside_assignment {
cov_mark::hit!(match_ergonomics_ref); cov_mark::hit!(match_ergonomics_ref);
@ -251,7 +251,7 @@ impl InferenceContext<'_> {
let mut pat_adjustments = Vec::new(); let mut pat_adjustments = Vec::new();
while let Some((inner, _lifetime, mutability)) = expected.as_reference() { while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
pat_adjustments.push(expected.clone()); pat_adjustments.push(expected.clone());
expected = self.resolve_ty_shallow(inner); expected = self.table.structurally_resolve_type(inner);
default_bm = match default_bm { default_bm = match default_bm {
BindingMode::Move => BindingMode::Ref(mutability), BindingMode::Move => BindingMode::Ref(mutability),
BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not), BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not),
@ -494,7 +494,7 @@ impl InferenceContext<'_> {
default_bm: BindingMode, default_bm: BindingMode,
decl: Option<DeclContext>, decl: Option<DeclContext>,
) -> Ty { ) -> Ty {
let expected = self.resolve_ty_shallow(expected); let expected = self.table.structurally_resolve_type(expected);
// If `expected` is an infer ty, we try to equate it to an array if the given pattern // If `expected` is an infer ty, we try to equate it to an array if the given pattern
// allows it. See issue #16609 // allows it. See issue #16609
@ -506,7 +506,7 @@ impl InferenceContext<'_> {
self.unify(&expected, &resolved_array_ty); self.unify(&expected, &resolved_array_ty);
} }
let expected = self.resolve_ty_shallow(&expected); let expected = self.table.structurally_resolve_type(&expected);
let elem_ty = match expected.kind(Interner) { let elem_ty = match expected.kind(Interner) {
TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(), TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
_ => self.err_ty(), _ => self.err_ty(),
@ -542,7 +542,7 @@ impl InferenceContext<'_> {
if let Expr::Literal(Literal::ByteString(_)) = self.body[expr] if let Expr::Literal(Literal::ByteString(_)) = self.body[expr]
&& let Some((inner, ..)) = expected.as_reference() && let Some((inner, ..)) = expected.as_reference()
{ {
let inner = self.resolve_ty_shallow(inner); let inner = self.table.structurally_resolve_type(inner);
if matches!(inner.kind(Interner), TyKind::Slice(_)) { if matches!(inner.kind(Interner), TyKind::Slice(_)) {
let elem_ty = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner); let elem_ty = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner);
let slice_ty = TyKind::Slice(elem_ty).intern(Interner); let slice_ty = TyKind::Slice(elem_ty).intern(Interner);

View file

@ -10,7 +10,15 @@ use hir_expand::name::Name;
use stdx::never; use stdx::never;
use crate::{ use crate::{
builder::ParamKind, consteval, error_lifetime, generics::generics, infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext, method_resolution::{self, VisibleFromModule}, next_solver::mapping::ChalkToNextSolver, to_chalk_trait_id, InferenceDiagnostic, Interner, LifetimeElisionKind, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, ValueTyDefId InferenceDiagnostic, Interner, LifetimeElisionKind, Substitution, TraitRef, TraitRefExt, Ty,
TyBuilder, TyExt, TyKind, ValueTyDefId,
builder::ParamKind,
consteval, error_lifetime,
generics::generics,
infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext,
method_resolution::{self, VisibleFromModule},
next_solver::mapping::ChalkToNextSolver,
to_chalk_trait_id,
}; };
use super::{ExprOrPatId, InferenceContext, InferenceTyDiagnosticSource}; use super::{ExprOrPatId, InferenceContext, InferenceTyDiagnosticSource};
@ -384,7 +392,7 @@ impl InferenceContext<'_> {
name: &Name, name: &Name,
id: ExprOrPatId, id: ExprOrPatId,
) -> Option<(ValueNs, Substitution)> { ) -> Option<(ValueNs, Substitution)> {
let ty = self.resolve_ty_shallow(ty); let ty = self.table.structurally_resolve_type(ty);
let (enum_id, subst) = match ty.as_adt() { let (enum_id, subst) = match ty.as_adt() {
Some((AdtId::EnumId(e), subst)) => (e, subst), Some((AdtId::EnumId(e), subst)) => (e, subst),
_ => return None, _ => return None,

View file

@ -3,7 +3,8 @@
use std::{fmt, mem}; use std::{fmt, mem};
use chalk_ir::{ use chalk_ir::{
cast::Cast, fold::TypeFoldable, interner::HasInterner, CanonicalVarKind, FloatTy, IntTy, TyVariableKind, CanonicalVarKind, FloatTy, IntTy, TyVariableKind, cast::Cast, fold::TypeFoldable,
interner::HasInterner,
}; };
use either::Either; use either::Either;
use hir_def::{AdtId, lang_item::LangItem}; use hir_def::{AdtId, lang_item::LangItem};
@ -11,13 +12,36 @@ use hir_expand::name::Name;
use intern::sym; use intern::sym;
use rustc_hash::{FxHashMap, FxHashSet}; use rustc_hash::{FxHashMap, FxHashSet};
use rustc_next_trait_solver::solve::HasChanged; use rustc_next_trait_solver::solve::HasChanged;
use rustc_type_ir::{inherent::Span, relate::{solver_relating::RelateExt, Relate}, solve::{Certainty, NoSolution}, FloatVid, IntVid, TyVid}; use rustc_type_ir::{
AliasRelationDirection, FloatVid, IntVid, TyVid,
inherent::{Span, Term as _},
relate::{Relate, solver_relating::RelateExt},
solve::{Certainty, NoSolution},
};
use smallvec::SmallVec; use smallvec::SmallVec;
use triomphe::Arc; use triomphe::Arc;
use super::{InferOk, InferResult, InferenceContext, TypeError}; use super::{InferOk, InferResult, InferenceContext, TypeError};
use crate::{ use crate::{
consteval::unknown_const, db::HirDatabase, fold_generic_args, fold_tys_and_consts, next_solver::{infer::{canonical::canonicalizer::OriginalQueryValues, snapshot::CombinedSnapshot, DbInternerInferExt, InferCtxt}, mapping::{ChalkToNextSolver, InferenceVarExt}, DbInterner, ParamEnvAnd, SolverDefIds}, to_chalk_trait_id, traits::{next_trait_solve, next_trait_solve_canonical, next_trait_solve_in_ctxt, FnTrait, NextTraitSolveResult}, AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, DomainGoal, GenericArg, GenericArgData, Goal, GoalData, InEnvironment, InferenceVar, Interner, Lifetime, OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyBuilder, TyExt, TyKind, VariableKind, WhereClause AliasEq, AliasTy, BoundVar, Canonical, Const, ConstValue, DebruijnIndex, DomainGoal,
GenericArg, GenericArgData, Goal, GoalData, InEnvironment, InferenceVar, Interner, Lifetime,
OpaqueTyId, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Substitution, TraitEnvironment,
TraitRef, Ty, TyBuilder, TyExt, TyKind, VariableKind, WhereClause,
consteval::unknown_const,
db::HirDatabase,
fold_generic_args, fold_tys_and_consts,
next_solver::{
self, Binder, DbInterner, ParamEnvAnd, Predicate, PredicateKind, SolverDefIds, Term,
infer::{
DbInternerInferExt, InferCtxt, canonical::canonicalizer::OriginalQueryValues,
snapshot::CombinedSnapshot,
},
mapping::{ChalkToNextSolver, InferenceVarExt, NextSolverToChalk},
},
to_chalk_trait_id,
traits::{
FnTrait, NextTraitSolveResult, next_trait_solve_canonical_in_ctxt, next_trait_solve_in_ctxt,
},
}; };
impl<'db> InferenceContext<'db> { impl<'db> InferenceContext<'db> {
@ -38,7 +62,7 @@ impl<'db> InferenceContext<'db> {
let pending_obligations = mem::take(&mut self.table.pending_obligations); let pending_obligations = mem::take(&mut self.table.pending_obligations);
let obligations = pending_obligations let obligations = pending_obligations
.iter() .iter()
.filter_map(|obligation| match obligation.goal.data(Interner) { .filter_map(|obligation| match obligation.to_chalk(self.table.interner).goal.data(Interner) {
GoalData::DomainGoal(DomainGoal::Holds(clause)) => { GoalData::DomainGoal(DomainGoal::Holds(clause)) => {
let ty = match clause { let ty = match clause {
WhereClause::AliasEq(AliasEq { WhereClause::AliasEq(AliasEq {
@ -67,51 +91,6 @@ impl<'db> InferenceContext<'db> {
} }
} }
#[derive(Debug, Clone)]
pub(crate) struct Canonicalized<T>
where
T: HasInterner<Interner = Interner>,
{
pub(crate) value: Canonical<T>,
free_vars: Vec<GenericArg>,
}
impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
pub(crate) fn apply_solution(
&self,
ctx: &mut InferenceTable<'_>,
solution: Canonical<Substitution>,
) {
// the solution may contain new variables, which we need to convert to new inference vars
let new_vars = Substitution::from_iter(
Interner,
solution.binders.iter(Interner).map(|k| match &k.kind {
VariableKind::Ty(TyVariableKind::General) => ctx.new_type_var().cast(Interner),
VariableKind::Ty(TyVariableKind::Integer) => ctx.new_integer_var().cast(Interner),
VariableKind::Ty(TyVariableKind::Float) => ctx.new_float_var().cast(Interner),
// Chalk can sometimes return new lifetime variables. We just replace them by errors
// for now.
VariableKind::Lifetime => ctx.new_lifetime_var().cast(Interner),
VariableKind::Const(ty) => ctx.new_const_var(ty.clone()).cast(Interner),
}),
);
for (i, v) in solution.value.iter(Interner).enumerate() {
let var = &self.free_vars[i];
if let Some(ty) = v.ty(Interner) {
// eagerly replace projections in the type; we may be getting types
// e.g. from where clauses where this hasn't happened yet
let ty = ctx.normalize_associated_types_in(new_vars.apply(ty.clone(), Interner));
tracing::debug!("unifying {:?} {:?}", var, ty);
ctx.unify(var.assert_ty_ref(Interner), &ty);
} else {
let v = new_vars.apply(v.clone(), Interner);
tracing::debug!("try_unifying {:?} {:?}", var, v);
let _ = ctx.try_unify(var, &v);
}
}
}
}
/// Check if types unify. /// Check if types unify.
/// ///
/// Note that we consider placeholder types to unify with everything. /// Note that we consider placeholder types to unify with everything.
@ -207,23 +186,21 @@ bitflags::bitflags! {
} }
} }
type ChalkInferenceTable = chalk_solve::infer::InferenceTable<Interner>;
#[derive(Clone)] #[derive(Clone)]
pub(crate) struct InferenceTable<'a> { pub(crate) struct InferenceTable<'a> {
pub(crate) db: &'a dyn HirDatabase, pub(crate) db: &'a dyn HirDatabase,
pub(crate) interner: DbInterner<'a>, pub(crate) interner: DbInterner<'a>,
pub(crate) trait_env: Arc<TraitEnvironment>, pub(crate) trait_env: Arc<TraitEnvironment>,
pub(crate) tait_coercion_table: Option<FxHashMap<OpaqueTyId, Ty>>, pub(crate) tait_coercion_table: Option<FxHashMap<OpaqueTyId, Ty>>,
infer_ctxt: InferCtxt<'a>, pub(crate) infer_ctxt: InferCtxt<'a>,
diverging_tys: FxHashSet<Ty>, diverging_tys: FxHashSet<Ty>,
pending_obligations: Vec<InEnvironment<Goal>>, pending_obligations: Vec<next_solver::Goal<'a, next_solver::Predicate<'a>>>,
} }
pub(crate) struct InferenceTableSnapshot { pub(crate) struct InferenceTableSnapshot<'a> {
ctxt_snapshot: CombinedSnapshot, ctxt_snapshot: CombinedSnapshot,
diverging_tys: FxHashSet<Ty>, diverging_tys: FxHashSet<Ty>,
pending_obligations: Vec<InEnvironment<Goal>>, pending_obligations: Vec<next_solver::Goal<'a, next_solver::Predicate<'a>>>,
} }
impl<'a> InferenceTable<'a> { impl<'a> InferenceTable<'a> {
@ -234,7 +211,9 @@ impl<'a> InferenceTable<'a> {
interner, interner,
trait_env, trait_env,
tait_coercion_table: None, tait_coercion_table: None,
infer_ctxt: interner.infer_ctxt().build(rustc_type_ir::TypingMode::Analysis { defining_opaque_types_and_generators: SolverDefIds::new_from_iter(interner, []) }), infer_ctxt: interner.infer_ctxt().build(rustc_type_ir::TypingMode::Analysis {
defining_opaque_types_and_generators: SolverDefIds::new_from_iter(interner, []),
}),
diverging_tys: FxHashSet::default(), diverging_tys: FxHashSet::default(),
pending_obligations: Vec::new(), pending_obligations: Vec::new(),
} }
@ -250,40 +229,55 @@ impl<'a> InferenceTable<'a> {
let mut new_tys = FxHashSet::default(); let mut new_tys = FxHashSet::default();
for ty in self.diverging_tys.iter() { for ty in self.diverging_tys.iter() {
match ty.kind(Interner) { match ty.kind(Interner) {
TyKind::InferenceVar(var, kind) => { TyKind::InferenceVar(var, kind) => match kind {
match kind {
TyVariableKind::General => { TyVariableKind::General => {
let root = InferenceVar::from(self.infer_ctxt.root_var(TyVid::from_u32(var.index())).as_u32()); let root = InferenceVar::from(
self.infer_ctxt.root_var(TyVid::from_u32(var.index())).as_u32(),
);
if root.index() != var.index() { if root.index() != var.index() {
new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner)); new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner));
} }
} }
TyVariableKind::Integer => { TyVariableKind::Integer => {
let root = InferenceVar::from(self.infer_ctxt.inner.borrow_mut().int_unification_table().find(IntVid::from_usize(var.index() as usize)).as_u32()); let root = InferenceVar::from(
self.infer_ctxt
.inner
.borrow_mut()
.int_unification_table()
.find(IntVid::from_usize(var.index() as usize))
.as_u32(),
);
if root.index() != var.index() { if root.index() != var.index() {
new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner)); new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner));
} }
} }
TyVariableKind::Float => { TyVariableKind::Float => {
let root = InferenceVar::from(self.infer_ctxt.inner.borrow_mut().float_unification_table().find(FloatVid::from_usize(var.index() as usize)).as_u32()); let root = InferenceVar::from(
self.infer_ctxt
.inner
.borrow_mut()
.float_unification_table()
.find(FloatVid::from_usize(var.index() as usize))
.as_u32(),
);
if root.index() != var.index() { if root.index() != var.index() {
new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner)); new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner));
} }
} }
} },
}
_ => {} _ => {}
} }
} }
self.diverging_tys.extend(new_tys.into_iter()); self.diverging_tys.extend(new_tys);
} }
pub(super) fn set_diverging(&mut self, iv: InferenceVar, kind: TyVariableKind, diverging: bool) { pub(super) fn set_diverging(&mut self, iv: InferenceVar, kind: TyVariableKind) {
self.diverging_tys.insert(TyKind::InferenceVar(iv, kind).intern(Interner)); self.diverging_tys.insert(TyKind::InferenceVar(iv, kind).intern(Interner));
} }
fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
let is_diverging = self.diverging_tys.contains(&TyKind::InferenceVar(iv, kind).intern(Interner)); let is_diverging =
self.diverging_tys.contains(&TyKind::InferenceVar(iv, kind).intern(Interner));
if is_diverging { if is_diverging {
return TyKind::Never.intern(Interner); return TyKind::Never.intern(Interner);
} }
@ -295,19 +289,6 @@ impl<'a> InferenceTable<'a> {
.intern(Interner) .intern(Interner)
} }
pub(crate) fn canonicalize_with_free_vars<T>(&mut self, t: ParamEnvAnd<'a, T>) -> (rustc_type_ir::Canonical<DbInterner<'a>, ParamEnvAnd<'a, T>>, OriginalQueryValues<'a>)
where
T: rustc_type_ir::TypeFoldable<DbInterner<'a>>,
{
// try to resolve obligations before canonicalizing, since this might
// result in new knowledge about variables
self.resolve_obligations_as_possible();
let mut orig_values = OriginalQueryValues::default();
let result = self.infer_ctxt.canonicalize_query(t, &mut orig_values);
(result.canonical, orig_values)
}
pub(crate) fn canonicalize<T>(&mut self, t: T) -> rustc_type_ir::Canonical<DbInterner<'a>, T> pub(crate) fn canonicalize<T>(&mut self, t: T) -> rustc_type_ir::Canonical<DbInterner<'a>, T>
where where
T: rustc_type_ir::TypeFoldable<DbInterner<'a>>, T: rustc_type_ir::TypeFoldable<DbInterner<'a>>,
@ -341,7 +322,7 @@ impl<'a> InferenceTable<'a> {
self.resolve_ty_shallow(&ty) self.resolve_ty_shallow(&ty)
} }
TyKind::AssociatedType(id, subst) => { TyKind::AssociatedType(id, subst) => {
return Either::Left(self.resolve_ty_shallow(&ty)); // return Either::Left(self.resolve_ty_shallow(&ty));
if ty.data(Interner).flags.intersects( if ty.data(Interner).flags.intersects(
chalk_ir::TypeFlags::HAS_TY_INFER chalk_ir::TypeFlags::HAS_TY_INFER
| chalk_ir::TypeFlags::HAS_CT_INFER, | chalk_ir::TypeFlags::HAS_CT_INFER,
@ -365,51 +346,44 @@ impl<'a> InferenceTable<'a> {
); );
let in_env = InEnvironment::new(&self.trait_env.env, goal); let in_env = InEnvironment::new(&self.trait_env.env, goal);
let goal = in_env.to_nextsolver(self.interner); let goal = in_env.to_nextsolver(self.interner);
let goal = ParamEnvAnd { param_env: goal.param_env, value: goal.predicate }; let goal =
ParamEnvAnd { param_env: goal.param_env, value: goal.predicate };
let (canonical_goal, _orig_values) = { let (canonical_goal, orig_values) = {
let mut orig_values = OriginalQueryValues::default(); let mut orig_values = OriginalQueryValues::default();
let result = self.infer_ctxt.canonicalize_query(goal, &mut orig_values); let result =
self.infer_ctxt.canonicalize_query(goal, &mut orig_values);
(result.canonical, orig_values) (result.canonical, orig_values)
}; };
let canonical_goal = rustc_type_ir::Canonical { let canonical_goal = rustc_type_ir::Canonical {
max_universe: canonical_goal.max_universe, max_universe: canonical_goal.max_universe,
variables: canonical_goal.variables, variables: canonical_goal.variables,
value: crate::next_solver::Goal { param_env: canonical_goal.value.param_env, predicate: canonical_goal.value.value }, value: crate::next_solver::Goal {
param_env: canonical_goal.value.param_env,
predicate: canonical_goal.value.value,
},
}; };
let solution = next_trait_solve_canonical( let solution = next_trait_solve_canonical_in_ctxt(
self.db, &self.infer_ctxt,
self.trait_env.krate, canonical_goal,
self.trait_env.block,
canonical_goal.clone(),
); );
if let NextTraitSolveResult::Certain(canonical_subst) = solution { if let NextTraitSolveResult::Certain(canonical_subst) = solution {
// This is not great :) But let's just assert this for now and come back to it later. let subst = self.instantiate_canonical(canonical_subst).subst;
if canonical_subst.value.subst.len(Interner) != 1 { if subst.len(Interner) != orig_values.var_values.len() {
ty ty
} else { } else {
let normalized = canonical_subst.value.subst.as_slice(Interner) let target_ty = var.to_nextsolver(self.interner);
[0] subst
.assert_ty_ref(Interner); .iter(Interner)
match normalized.kind(Interner) { .zip(orig_values.var_values.iter())
TyKind::Alias(AliasTy::Projection(proj_ty)) => { .find_map(|(new, orig)| {
if id == &proj_ty.associated_ty_id if orig.ty() == Some(target_ty) {
&& subst == &proj_ty.substitution Some(new.assert_ty_ref(Interner).clone())
{
ty
} else { } else {
normalized.clone() None
}
}
TyKind::AssociatedType(new_id, new_subst) => {
if new_id == id && new_subst == subst {
ty
} else {
normalized.clone()
}
}
_ => normalized.clone(),
} }
})
.unwrap_or(ty)
} }
} else { } else {
ty ty
@ -504,8 +478,8 @@ impl<'a> InferenceTable<'a> {
pub(crate) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { pub(crate) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
let var = self.new_type_var(); let var = self.new_type_var();
let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
let obligation = alias_eq.cast(Interner); let obligation: Goal = alias_eq.cast(Interner);
self.register_obligation(obligation); self.register_obligation(obligation.to_nextsolver(self.interner));
var var
} }
@ -575,7 +549,9 @@ impl<'a> InferenceTable<'a> {
Substitution::from_iter( Substitution::from_iter(
Interner, Interner,
binders.iter().map(|kind| match &kind.kind { binders.iter().map(|kind| match &kind.kind {
chalk_ir::VariableKind::Ty(ty_variable_kind) => self.new_var(*ty_variable_kind, false).cast(Interner), chalk_ir::VariableKind::Ty(ty_variable_kind) => {
self.new_var(*ty_variable_kind, false).cast(Interner)
}
chalk_ir::VariableKind::Lifetime => self.new_lifetime_var().cast(Interner), chalk_ir::VariableKind::Lifetime => self.new_lifetime_var().cast(Interner),
chalk_ir::VariableKind::Const(ty) => self.new_const_var(ty.clone()).cast(Interner), chalk_ir::VariableKind::Const(ty) => self.new_const_var(ty.clone()).cast(Interner),
}), }),
@ -590,7 +566,10 @@ impl<'a> InferenceTable<'a> {
subst.apply(canonical.value, Interner) subst.apply(canonical.value, Interner)
} }
pub(crate) fn instantiate_canonical_ns<T>(&mut self, canonical: rustc_type_ir::Canonical<DbInterner<'a>, T>) -> T pub(crate) fn instantiate_canonical_ns<T>(
&mut self,
canonical: rustc_type_ir::Canonical<DbInterner<'a>, T>,
) -> T
where where
T: rustc_type_ir::TypeFoldable<DbInterner<'a>>, T: rustc_type_ir::TypeFoldable<DbInterner<'a>>,
{ {
@ -605,7 +584,7 @@ impl<'a> InferenceTable<'a> {
where where
T: HasInterner<Interner = Interner> + TypeFoldable<Interner>, T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
{ {
let mut var_stack = &mut vec![]; let var_stack = &mut vec![];
t.fold_with( t.fold_with(
&mut resolve::Resolver { table: self, var_stack, fallback }, &mut resolve::Resolver { table: self, var_stack, fallback },
DebruijnIndex::INNERMOST, DebruijnIndex::INNERMOST,
@ -618,6 +597,7 @@ impl<'a> InferenceTable<'a> {
{ {
let t = self.resolve_with_fallback(t, &|_, _, d, _| d); let t = self.resolve_with_fallback(t, &|_, _, d, _| d);
let t = self.normalize_associated_types_in(t); let t = self.normalize_associated_types_in(t);
// let t = self.resolve_opaque_tys_in(t);
// Resolve again, because maybe normalization inserted infer vars. // Resolve again, because maybe normalization inserted infer vars.
self.resolve_with_fallback(t, &|_, _, d, _| d) self.resolve_with_fallback(t, &|_, _, d, _| d)
} }
@ -650,7 +630,7 @@ impl<'a> InferenceTable<'a> {
} }
let float_vars = self.infer_ctxt.inner.borrow_mut().float_unification_table().len(); let float_vars = self.infer_ctxt.inner.borrow_mut().float_unification_table().len();
for v in 0..float_vars { for v in 0..float_vars {
let var = InferenceVar::from(v as u32).to_ty(Interner, TyVariableKind::Integer); let var = InferenceVar::from(v as u32).to_ty(Interner, TyVariableKind::Float);
let maybe_resolved = self.resolve_ty_shallow(&var); let maybe_resolved = self.resolve_ty_shallow(&var);
if let TyKind::InferenceVar(_, kind) = maybe_resolved.kind(Interner) { if let TyKind::InferenceVar(_, kind) = maybe_resolved.kind(Interner) {
// I don't think we can ever unify these vars with float vars, but keep this here for now // I don't think we can ever unify these vars with float vars, but keep this here for now
@ -665,7 +645,11 @@ impl<'a> InferenceTable<'a> {
} }
/// Unify two relatable values (e.g. `Ty`) and register new trait goals that arise from that. /// Unify two relatable values (e.g. `Ty`) and register new trait goals that arise from that.
pub(crate) fn unify<T: ChalkToNextSolver<'a, U>, U: Relate<DbInterner<'a>>>(&mut self, ty1: &T, ty2: &T) -> bool { pub(crate) fn unify<T: ChalkToNextSolver<'a, U>, U: Relate<DbInterner<'a>>>(
&mut self,
ty1: &T,
ty2: &T,
) -> bool {
let result = match self.try_unify(ty1, ty2) { let result = match self.try_unify(ty1, ty2) {
Ok(r) => r, Ok(r) => r,
Err(_) => return false, Err(_) => return false,
@ -675,17 +659,17 @@ impl<'a> InferenceTable<'a> {
} }
/// Unify two relatable values (e.g. `Ty`) and check whether trait goals which arise from that could be fulfilled /// Unify two relatable values (e.g. `Ty`) and check whether trait goals which arise from that could be fulfilled
pub(crate) fn unify_deeply<T: ChalkToNextSolver<'a, U>, U: Relate<DbInterner<'a>>>(&mut self, ty1: &T, ty2: &T) -> bool { pub(crate) fn unify_deeply<T: ChalkToNextSolver<'a, U>, U: Relate<DbInterner<'a>>>(
&mut self,
ty1: &T,
ty2: &T,
) -> bool {
let result = match self.try_unify(ty1, ty2) { let result = match self.try_unify(ty1, ty2) {
Ok(r) => r, Ok(r) => r,
Err(_) => return false, Err(_) => return false,
}; };
result.goals.iter().all(|goal| { result.goals.into_iter().all(|goal| {
let goal = goal.to_nextsolver(self.interner); matches!(next_trait_solve_in_ctxt(&self.infer_ctxt, goal), Ok((_, Certainty::Yes)))
match next_trait_solve_in_ctxt(&self.infer_ctxt, goal) {
Ok((_, Certainty::Yes)) => true,
_ => false,
}
}) })
} }
@ -695,20 +679,15 @@ impl<'a> InferenceTable<'a> {
&mut self, &mut self,
t1: &T, t1: &T,
t2: &T, t2: &T,
) -> InferResult<()> { ) -> InferResult<'a, ()> {
let param_env = self.trait_env.env.to_nextsolver(self.interner); let param_env = self.trait_env.env.to_nextsolver(self.interner);
let lhs = t1.to_nextsolver(self.interner); let lhs = t1.to_nextsolver(self.interner);
let rhs = t2.to_nextsolver(self.interner); let rhs = t2.to_nextsolver(self.interner);
let variance = rustc_type_ir::Variance::Invariant; let variance = rustc_type_ir::Variance::Invariant;
let span = crate::next_solver::Span::dummy(); let span = crate::next_solver::Span::dummy();
match self.infer_ctxt.relate(param_env, lhs, variance, rhs, span) { match self.infer_ctxt.relate(param_env, lhs, variance, rhs, span) {
Ok(res) => { Ok(goals) => Ok(InferOk { goals, value: () }),
let goals = res.into_iter().map(|g| ChalkToNextSolver::from_nextsolver(g, self.interner)).collect(); Err(_) => Err(TypeError),
Ok(InferOk { goals, value: () })
}
Err(_) => {
Err(TypeError)
}
} }
} }
@ -719,19 +698,75 @@ impl<'a> InferenceTable<'a> {
if !ty.data(Interner).flags.intersects(chalk_ir::TypeFlags::HAS_FREE_LOCAL_NAMES) { if !ty.data(Interner).flags.intersects(chalk_ir::TypeFlags::HAS_FREE_LOCAL_NAMES) {
return ty.clone(); return ty.clone();
} }
self.resolve_obligations_as_possible(); self.infer_ctxt
ChalkToNextSolver::from_nextsolver(self.infer_ctxt.resolve_vars_if_possible(ty.to_nextsolver(self.interner)), self.interner) .resolve_vars_if_possible(ty.to_nextsolver(self.interner))
.to_chalk(self.interner)
} }
pub(crate) fn snapshot(&mut self) -> InferenceTableSnapshot { pub(crate) fn resolve_vars_with_obligations<T>(&mut self, t: T) -> T
where
T: rustc_type_ir::TypeFoldable<DbInterner<'a>>,
{
use rustc_type_ir::TypeVisitableExt;
if !t.has_non_region_infer() {
return t;
}
let t = self.infer_ctxt.resolve_vars_if_possible(t);
if !t.has_non_region_infer() {
return t;
}
self.resolve_obligations_as_possible();
self.infer_ctxt.resolve_vars_if_possible(t)
}
pub(crate) fn structurally_resolve_type(&mut self, ty: &Ty) -> Ty {
if let TyKind::Alias(..) = ty.kind(Interner) {
self.structurally_normalize_ty(ty)
} else {
self.resolve_vars_with_obligations(ty.to_nextsolver(self.interner))
.to_chalk(self.interner)
}
}
fn structurally_normalize_ty(&mut self, ty: &Ty) -> Ty {
self.structurally_normalize_term(ty.to_nextsolver(self.interner).into())
.expect_ty()
.to_chalk(self.interner)
}
fn structurally_normalize_term(&mut self, term: Term<'a>) -> Term<'a> {
if term.to_alias_term().is_none() {
return term;
}
let new_infer = self.infer_ctxt.next_term_var_of_kind(term);
self.register_obligation(Predicate::new(
self.interner,
Binder::dummy(PredicateKind::AliasRelate(
term,
new_infer,
AliasRelationDirection::Equate,
)),
));
self.resolve_obligations_as_possible();
let res = self.infer_ctxt.resolve_vars_if_possible(new_infer);
if res == new_infer { term } else { res }
}
pub(crate) fn snapshot(&mut self) -> InferenceTableSnapshot<'a> {
let ctxt_snapshot = self.infer_ctxt.start_snapshot(); let ctxt_snapshot = self.infer_ctxt.start_snapshot();
let diverging_tys = self.diverging_tys.clone(); let diverging_tys = self.diverging_tys.clone();
let pending_obligations = self.pending_obligations.clone(); let pending_obligations = self.pending_obligations.clone();
InferenceTableSnapshot {ctxt_snapshot, pending_obligations, diverging_tys } InferenceTableSnapshot { ctxt_snapshot, pending_obligations, diverging_tys }
} }
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
pub(crate) fn rollback_to(&mut self, snapshot: InferenceTableSnapshot) { pub(crate) fn rollback_to(&mut self, snapshot: InferenceTableSnapshot<'a>) {
self.infer_ctxt.rollback_to(snapshot.ctxt_snapshot); self.infer_ctxt.rollback_to(snapshot.ctxt_snapshot);
self.diverging_tys = snapshot.diverging_tys; self.diverging_tys = snapshot.diverging_tys;
self.pending_obligations = snapshot.pending_obligations; self.pending_obligations = snapshot.pending_obligations;
@ -745,7 +780,10 @@ impl<'a> InferenceTable<'a> {
result result
} }
pub(crate) fn commit_if_ok<T, E>(&mut self, f: impl FnOnce(&mut InferenceTable<'_>) -> Result<T, E>) -> Result<T, E> { pub(crate) fn commit_if_ok<T, E>(
&mut self,
f: impl FnOnce(&mut InferenceTable<'_>) -> Result<T, E>,
) -> Result<T, E> {
let snapshot = self.snapshot(); let snapshot = self.snapshot();
let result = f(self); let result = f(self);
match result { match result {
@ -765,59 +803,31 @@ impl<'a> InferenceTable<'a> {
let in_env = InEnvironment::new(&self.trait_env.env, goal); let in_env = InEnvironment::new(&self.trait_env.env, goal);
let canonicalized = self.canonicalize(in_env.to_nextsolver(self.interner)); let canonicalized = self.canonicalize(in_env.to_nextsolver(self.interner));
next_trait_solve_canonical(self.db, self.trait_env.krate, self.trait_env.block, canonicalized) next_trait_solve_canonical_in_ctxt(&self.infer_ctxt, canonicalized)
} }
#[tracing::instrument(level = "debug", skip(self))] #[tracing::instrument(level = "debug", skip(self))]
pub(crate) fn solve_obligation(&mut self, goal: Goal) -> Result<Certainty, NoSolution> { pub(crate) fn solve_obligation(&mut self, goal: Goal) -> Result<Certainty, NoSolution> {
let goal = InEnvironment::new(&self.trait_env.env, goal); let goal = InEnvironment::new(&self.trait_env.env, goal);
let Some(goal) = self.unify_opaque_instead_of_solve(goal) else {
return Ok(Certainty::Yes);
};
let goal = goal.to_nextsolver(self.interner); let goal = goal.to_nextsolver(self.interner);
let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal); let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal);
result.map(|m| m.1) result.map(|m| m.1)
} }
pub(crate) fn register_obligation(&mut self, goal: Goal) { pub(crate) fn register_obligation(&mut self, predicate: Predicate<'a>) {
let in_env = InEnvironment::new(&self.trait_env.env, goal); let goal = next_solver::Goal {
self.register_obligation_in_env(in_env) param_env: self.trait_env.env.to_nextsolver(self.interner),
} predicate,
};
// If this goal is an `AliasEq` for an opaque type, just unify instead of trying to solve (since the next-solver is lazy) self.register_obligation_in_env(goal)
fn unify_opaque_instead_of_solve(&mut self, goal: InEnvironment<Goal>) -> Option<InEnvironment<Goal>> {
match goal.goal.data(Interner) {
chalk_ir::GoalData::DomainGoal(chalk_ir::DomainGoal::Holds(
chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }),
)) => {
if ty.inference_var(Interner).is_some() {
match alias {
chalk_ir::AliasTy::Opaque(opaque) => {
if self.unify(
&chalk_ir::TyKind::OpaqueType(
opaque.opaque_ty_id,
opaque.substitution.clone(),
)
.intern(Interner),
ty,
) {
return None;
}
}
_ => {}
}
}
}
_ => {}
}
Some(goal)
} }
#[tracing::instrument(level = "debug", skip(self))] #[tracing::instrument(level = "debug", skip(self))]
fn register_obligation_in_env(&mut self, goal: InEnvironment<Goal>) { fn register_obligation_in_env(
let Some(goal) = self.unify_opaque_instead_of_solve(goal) else { return }; &mut self,
let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal.to_nextsolver(self.interner)); goal: next_solver::Goal<'a, next_solver::Predicate<'a>>,
) {
let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal);
tracing::debug!(?result); tracing::debug!(?result);
match result { match result {
Ok((_, Certainty::Yes)) => {} Ok((_, Certainty::Yes)) => {}
@ -828,7 +838,7 @@ impl<'a> InferenceTable<'a> {
} }
} }
pub(crate) fn register_infer_ok<T>(&mut self, infer_ok: InferOk<T>) { pub(crate) fn register_infer_ok<T>(&mut self, infer_ok: InferOk<'a, T>) {
infer_ok.goals.into_iter().for_each(|goal| self.register_obligation_in_env(goal)); infer_ok.goals.into_iter().for_each(|goal| self.register_obligation_in_env(goal));
} }
@ -841,12 +851,7 @@ impl<'a> InferenceTable<'a> {
for goal in obligations.drain(..) { for goal in obligations.drain(..) {
tracing::debug!(obligation = ?goal); tracing::debug!(obligation = ?goal);
let Some(goal) = self.unify_opaque_instead_of_solve(goal) else { let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal);
changed = true;
continue;
};
let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal.to_nextsolver(self.interner));
let (has_changed, certainty) = match result { let (has_changed, certainty) = match result {
Ok(result) => result, Ok(result) => result,
Err(_) => { Err(_) => {
@ -934,40 +939,6 @@ impl<'a> InferenceTable<'a> {
.fold_with(&mut VarFudger { table: self, highest_known_var }, DebruijnIndex::INNERMOST) .fold_with(&mut VarFudger { table: self, highest_known_var }, DebruijnIndex::INNERMOST)
} }
#[tracing::instrument(level = "debug", skip(self))]
fn try_resolve_obligation(
&mut self,
canonicalized: &Canonicalized<InEnvironment<Goal>>,
) -> NextTraitSolveResult {
let solution = next_trait_solve(
self.db,
self.trait_env.krate,
self.trait_env.block,
canonicalized.value.clone(),
);
tracing::debug!(?solution, ?canonicalized);
match &solution {
NextTraitSolveResult::Certain(v) => {
canonicalized.apply_solution(
self,
Canonical {
binders: v.binders.clone(),
// FIXME handle constraints
value: v.value.subst.clone(),
},
);
}
// ...so, should think about how to get some actually get some guidance here
NextTraitSolveResult::Uncertain(v) => {
canonicalized.apply_solution(self, v.clone());
}
NextTraitSolveResult::NoSolution => {}
}
solution
}
pub(crate) fn callable_sig( pub(crate) fn callable_sig(
&mut self, &mut self,
ty: &Ty, ty: &Ty,
@ -1027,7 +998,7 @@ impl<'a> InferenceTable<'a> {
let goal: Goal = trait_ref.clone().cast(Interner); let goal: Goal = trait_ref.clone().cast(Interner);
if !self.try_obligation(goal.clone()).no_solution() { if !self.try_obligation(goal.clone()).no_solution() {
self.register_obligation(goal); self.register_obligation(goal.to_nextsolver(self.interner));
let return_ty = self.normalize_projection_ty(projection); let return_ty = self.normalize_projection_ty(projection);
for &fn_x in subtraits { for &fn_x in subtraits {
let fn_x_trait = fn_x.get_id(self.db, krate)?; let fn_x_trait = fn_x.get_id(self.db, krate)?;
@ -1067,7 +1038,7 @@ impl<'a> InferenceTable<'a> {
match ty.kind(Interner) { match ty.kind(Interner) {
TyKind::Error => self.new_type_var(), TyKind::Error => self.new_type_var(),
TyKind::InferenceVar(..) => { TyKind::InferenceVar(..) => {
let ty_resolved = self.resolve_ty_shallow(&ty); let ty_resolved = self.structurally_resolve_type(&ty);
if ty_resolved.is_unknown() { self.new_type_var() } else { ty } if ty_resolved.is_unknown() { self.new_type_var() } else { ty }
} }
_ => ty, _ => ty,
@ -1165,7 +1136,9 @@ impl fmt::Debug for InferenceTable<'_> {
mod resolve { mod resolve {
use super::InferenceTable; use super::InferenceTable;
use crate::{ use crate::{
next_solver::mapping::ChalkToNextSolver, ConcreteConst, Const, ConstData, ConstScalar, ConstValue, DebruijnIndex, GenericArg, InferenceVar, Interner, Lifetime, Ty, TyVariableKind, VariableKind ConcreteConst, Const, ConstData, ConstScalar, ConstValue, DebruijnIndex, GenericArg,
InferenceVar, Interner, Lifetime, Ty, TyVariableKind, VariableKind,
next_solver::mapping::NextSolverToChalk,
}; };
use chalk_ir::{ use chalk_ir::{
cast::Cast, cast::Cast,
@ -1220,7 +1193,7 @@ mod resolve {
.clone(); .clone();
} }
if let Ok(known_ty) = self.table.infer_ctxt.probe_ty_var(vid) { if let Ok(known_ty) = self.table.infer_ctxt.probe_ty_var(vid) {
let known_ty: Ty = ChalkToNextSolver::from_nextsolver(known_ty, self.table.interner); let known_ty: Ty = known_ty.to_chalk(self.table.interner);
// known_ty may contain other variables that are known by now // known_ty may contain other variables that are known by now
self.var_stack.push((var, VarKind::Ty(kind))); self.var_stack.push((var, VarKind::Ty(kind)));
let result = known_ty.fold_with(self, outer_binder); let result = known_ty.fold_with(self, outer_binder);
@ -1234,7 +1207,13 @@ mod resolve {
} }
} }
TyVariableKind::Integer => { TyVariableKind::Integer => {
let vid = self.table.infer_ctxt.inner.borrow_mut().int_unification_table().find(IntVid::from(var.index())); let vid = self
.table
.infer_ctxt
.inner
.borrow_mut()
.int_unification_table()
.find(IntVid::from(var.index()));
let var = InferenceVar::from(vid.as_u32()); let var = InferenceVar::from(vid.as_u32());
if self.var_stack.contains(&(var, VarKind::Ty(kind))) { if self.var_stack.contains(&(var, VarKind::Ty(kind))) {
// recursive type // recursive type
@ -1244,7 +1223,7 @@ mod resolve {
.clone(); .clone();
} }
if let Some(known_ty) = self.table.infer_ctxt.resolve_int_var(vid) { if let Some(known_ty) = self.table.infer_ctxt.resolve_int_var(vid) {
let known_ty: Ty = ChalkToNextSolver::from_nextsolver(known_ty, self.table.interner); let known_ty: Ty = known_ty.to_chalk(self.table.interner);
// known_ty may contain other variables that are known by now // known_ty may contain other variables that are known by now
self.var_stack.push((var, VarKind::Ty(kind))); self.var_stack.push((var, VarKind::Ty(kind)));
let result = known_ty.fold_with(self, outer_binder); let result = known_ty.fold_with(self, outer_binder);
@ -1258,7 +1237,13 @@ mod resolve {
} }
} }
TyVariableKind::Float => { TyVariableKind::Float => {
let vid = self.table.infer_ctxt.inner.borrow_mut().float_unification_table().find(FloatVid::from(var.index())); let vid = self
.table
.infer_ctxt
.inner
.borrow_mut()
.float_unification_table()
.find(FloatVid::from(var.index()));
let var = InferenceVar::from(vid.as_u32()); let var = InferenceVar::from(vid.as_u32());
if self.var_stack.contains(&(var, VarKind::Ty(kind))) { if self.var_stack.contains(&(var, VarKind::Ty(kind))) {
// recursive type // recursive type
@ -1268,7 +1253,7 @@ mod resolve {
.clone(); .clone();
} }
if let Some(known_ty) = self.table.infer_ctxt.resolve_float_var(vid) { if let Some(known_ty) = self.table.infer_ctxt.resolve_float_var(vid) {
let known_ty: Ty = ChalkToNextSolver::from_nextsolver(known_ty, self.table.interner); let known_ty: Ty = known_ty.to_chalk(self.table.interner);
// known_ty may contain other variables that are known by now // known_ty may contain other variables that are known by now
self.var_stack.push((var, VarKind::Ty(kind))); self.var_stack.push((var, VarKind::Ty(kind)));
let result = known_ty.fold_with(self, outer_binder); let result = known_ty.fold_with(self, outer_binder);
@ -1290,7 +1275,10 @@ mod resolve {
var: InferenceVar, var: InferenceVar,
outer_binder: DebruijnIndex, outer_binder: DebruijnIndex,
) -> Const { ) -> Const {
let vid = self.table.infer_ctxt.root_const_var(rustc_type_ir::ConstVid::from_u32(var.index())); let vid = self
.table
.infer_ctxt
.root_const_var(rustc_type_ir::ConstVid::from_u32(var.index()));
let var = InferenceVar::from(vid.as_u32()); let var = InferenceVar::from(vid.as_u32());
let default = ConstData { let default = ConstData {
ty: ty.clone(), ty: ty.clone(),
@ -1305,7 +1293,7 @@ mod resolve {
.clone(); .clone();
} }
if let Ok(known_const) = self.table.infer_ctxt.probe_const_var(vid) { if let Ok(known_const) = self.table.infer_ctxt.probe_const_var(vid) {
let known_const: Const = ChalkToNextSolver::from_nextsolver(known_const, self.table.interner); let known_const: Const = known_const.to_chalk(self.table.interner);
// known_ty may contain other variables that are known by now // known_ty may contain other variables that are known by now
self.var_stack.push((var, VarKind::Const)); self.var_stack.push((var, VarKind::Const));
let result = known_const.fold_with(self, outer_binder); let result = known_const.fold_with(self, outer_binder);

View file

@ -101,7 +101,10 @@ use crate::{
display::{DisplayTarget, HirDisplay}, display::{DisplayTarget, HirDisplay},
generics::Generics, generics::Generics,
infer::unify::InferenceTable, infer::unify::InferenceTable,
next_solver::{DbInterner, mapping::convert_ty_for_result}, next_solver::{
DbInterner,
mapping::{ChalkToNextSolver, convert_ty_for_result},
},
}; };
pub use autoderef::autoderef; pub use autoderef::autoderef;
@ -957,8 +960,10 @@ pub fn callable_sig_from_fn_trait(
) )
.build(); .build();
if !table.try_obligation(trait_ref.clone().cast(Interner)).no_solution() { let goal: Goal = trait_ref.clone().cast(Interner);
table.register_obligation(trait_ref.clone().cast(Interner)); let pred = goal.to_nextsolver(table.interner);
if !table.try_obligation(goal).no_solution() {
table.register_obligation(pred);
let return_ty = table.normalize_projection_ty(projection); let return_ty = table.normalize_projection_ty(projection);
for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] { for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
let fn_x_trait = fn_x.get_id(db, krate)?; let fn_x_trait = fn_x.get_id(db, krate)?;

View file

@ -22,7 +22,25 @@ use stdx::never;
use triomphe::Arc; use triomphe::Arc;
use crate::{ use crate::{
autoderef::{self, AutoderefKind}, db::HirDatabase, from_chalk_trait_id, from_foreign_def_id, infer::{unify::InferenceTable, Adjust, Adjustment, OverloadedDeref, PointerCast}, lang_items::is_box, next_solver::{mapping::ChalkToNextSolver, SolverDefId}, primitive::{FloatTy, IntTy, UintTy}, to_chalk_trait_id, traits::{next_trait_solve_canonical}, utils::all_super_traits, AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData, Goal, InEnvironment, Interner, Mutability, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind, VariableKind, WhereClause AdtId, AliasTy, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId,
GenericArgData, Goal, InEnvironment, Interner, Mutability, Scalar, Substitution,
TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind,
VariableKind, WhereClause,
autoderef::{self, AutoderefKind},
db::HirDatabase,
from_chalk_trait_id, from_foreign_def_id,
infer::{Adjust, Adjustment, OverloadedDeref, PointerCast, unify::InferenceTable},
lang_items::is_box,
next_solver::{
self, SolverDefId,
fulfill::FulfillmentCtxt,
infer::DefineOpaqueTypes,
mapping::{ChalkToNextSolver, NextSolverToChalk},
},
primitive::{FloatTy, IntTy, UintTy},
to_chalk_trait_id,
traits::next_trait_solve_canonical_in_ctxt,
utils::all_super_traits,
}; };
/// This is used as a key for indexing impls. /// This is used as a key for indexing impls.
@ -89,6 +107,7 @@ impl TyFingerprint {
} }
TyKind::AssociatedType(_, _) TyKind::AssociatedType(_, _)
| TyKind::OpaqueType(_, _) | TyKind::OpaqueType(_, _)
| TyKind::Alias(AliasTy::Opaque(_))
| TyKind::FnDef(_, _) | TyKind::FnDef(_, _)
| TyKind::Closure(_, _) | TyKind::Closure(_, _)
| TyKind::Coroutine(..) | TyKind::Coroutine(..)
@ -106,7 +125,7 @@ impl TyFingerprint {
} }
/// Creates a TyFingerprint for looking up a trait impl. /// Creates a TyFingerprint for looking up a trait impl.
pub fn for_trait_impl_ns<'db>(ty: &crate::next_solver::Ty<'db>) -> Option<TyFingerprint> { pub fn for_trait_impl_ns<'db>(ty: &next_solver::Ty<'db>) -> Option<TyFingerprint> {
use rustc_type_ir::TyKind; use rustc_type_ir::TyKind;
let fp = match (*ty).kind() { let fp = match (*ty).kind() {
TyKind::Str => TyFingerprint::Str, TyKind::Str => TyFingerprint::Str,
@ -523,7 +542,7 @@ pub fn def_crates(db: &dyn HirDatabase, ty: &Ty, cur_crate: Crate) -> Option<Sma
/// Look up the method with the given name. /// Look up the method with the given name.
pub(crate) fn lookup_method<'db>( pub(crate) fn lookup_method<'db>(
db: &'db dyn HirDatabase, db: &'db dyn HirDatabase,
ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule, visible_from_module: VisibleFromModule,
@ -605,7 +624,7 @@ pub struct ReceiverAdjustments {
impl ReceiverAdjustments { impl ReceiverAdjustments {
pub(crate) fn apply(&self, table: &mut InferenceTable<'_>, ty: Ty) -> (Ty, Vec<Adjustment>) { pub(crate) fn apply(&self, table: &mut InferenceTable<'_>, ty: Ty) -> (Ty, Vec<Adjustment>) {
let mut ty = table.resolve_ty_shallow(&ty); let mut ty = table.structurally_resolve_type(&ty);
let mut adjust = Vec::new(); let mut adjust = Vec::new();
for _ in 0..self.autoderefs { for _ in 0..self.autoderefs {
match autoderef::autoderef_step(table, ty.clone(), true, false) { match autoderef::autoderef_step(table, ty.clone(), true, false) {
@ -686,7 +705,7 @@ impl ReceiverAdjustments {
// lifetime problems, because we need to borrow temp `CrateImplDefs`. // lifetime problems, because we need to borrow temp `CrateImplDefs`.
// FIXME add a context type here? // FIXME add a context type here?
pub(crate) fn iterate_method_candidates<'db, T>( pub(crate) fn iterate_method_candidates<'db, T>(
ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
db: &'db dyn HirDatabase, db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
@ -887,7 +906,7 @@ fn find_matching_impl(
if table.try_obligation(goal.clone()).no_solution() { if table.try_obligation(goal.clone()).no_solution() {
return None; return None;
} }
table.register_obligation(goal); table.register_obligation(goal.to_nextsolver(table.interner));
} }
Some((impl_.impl_items(db), table.resolve_completely(impl_substs))) Some((impl_.impl_items(db), table.resolve_completely(impl_substs)))
}) })
@ -1035,7 +1054,7 @@ pub fn check_orphan_rules(db: &dyn HirDatabase, impl_: ImplId) -> bool {
} }
pub fn iterate_path_candidates<'db>( pub fn iterate_path_candidates<'db>(
ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
db: &'db dyn HirDatabase, db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
@ -1057,7 +1076,7 @@ pub fn iterate_path_candidates<'db>(
} }
pub fn iterate_method_candidates_dyn<'db>( pub fn iterate_method_candidates_dyn<'db>(
ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
db: &'db dyn HirDatabase, db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
@ -1096,7 +1115,7 @@ pub fn iterate_method_candidates_dyn<'db>(
// types*. // types*.
let mut table = InferenceTable::new(db, env); let mut table = InferenceTable::new(db, env);
let ty = table.instantiate_canonical_ns(ty.clone()); let ty = table.instantiate_canonical_ns(*ty);
let deref_chain = autoderef_method_receiver(&mut table, ty); let deref_chain = autoderef_method_receiver(&mut table, ty);
deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| { deref_chain.into_iter().try_for_each(|(receiver_ty, adj)| {
@ -1129,18 +1148,13 @@ pub fn iterate_method_candidates_dyn<'db>(
#[tracing::instrument(skip_all, fields(name = ?name))] #[tracing::instrument(skip_all, fields(name = ?name))]
fn iterate_method_candidates_with_autoref<'db>( fn iterate_method_candidates_with_autoref<'db>(
table: &mut InferenceTable<'db>, table: &mut InferenceTable<'db>,
receiver_ty: crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, receiver_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
first_adjustment: ReceiverAdjustments, first_adjustment: ReceiverAdjustments,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule, visible_from_module: VisibleFromModule,
name: Option<&Name>, name: Option<&Name>,
callback: &mut dyn MethodCandidateCallback, callback: &mut dyn MethodCandidateCallback,
) -> ControlFlow<()> { ) -> ControlFlow<()> {
if matches!(receiver_ty.value.kind(), rustc_type_ir::TyKind::Bound(..)) {
// don't try to resolve methods on unknown types
return ControlFlow::Continue(());
}
let interner = table.interner; let interner = table.interner;
let mut iterate_method_candidates_by_receiver = move |receiver_ty, first_adjustment| { let mut iterate_method_candidates_by_receiver = move |receiver_ty, first_adjustment| {
@ -1166,12 +1180,17 @@ fn iterate_method_candidates_with_autoref<'db>(
maybe_reborrowed.autoderefs += 1; maybe_reborrowed.autoderefs += 1;
} }
iterate_method_candidates_by_receiver(receiver_ty.clone(), maybe_reborrowed)?; iterate_method_candidates_by_receiver(receiver_ty, maybe_reborrowed)?;
let refed = crate::next_solver::Canonical { let refed = next_solver::Canonical {
max_universe: receiver_ty.max_universe, max_universe: receiver_ty.max_universe,
variables: receiver_ty.variables, variables: receiver_ty.variables,
value: crate::next_solver::Ty::new_ref(interner, crate::next_solver::Region::error(interner), receiver_ty.value, rustc_ast_ir::Mutability::Not), value: next_solver::Ty::new_ref(
interner,
next_solver::Region::error(interner),
receiver_ty.value,
rustc_ast_ir::Mutability::Not,
),
}; };
iterate_method_candidates_by_receiver( iterate_method_candidates_by_receiver(
@ -1179,10 +1198,15 @@ fn iterate_method_candidates_with_autoref<'db>(
first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Not)), first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Not)),
)?; )?;
let ref_muted = crate::next_solver::Canonical { let ref_muted = next_solver::Canonical {
max_universe: receiver_ty.max_universe, max_universe: receiver_ty.max_universe,
variables: receiver_ty.variables, variables: receiver_ty.variables,
value: crate::next_solver::Ty::new_ref(interner, crate::next_solver::Region::error(interner), receiver_ty.value, rustc_ast_ir::Mutability::Mut), value: next_solver::Ty::new_ref(
interner,
next_solver::Region::error(interner),
receiver_ty.value,
rustc_ast_ir::Mutability::Mut,
),
}; };
iterate_method_candidates_by_receiver( iterate_method_candidates_by_receiver(
@ -1190,10 +1214,12 @@ fn iterate_method_candidates_with_autoref<'db>(
first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Mut)), first_adjustment.with_autoref(AutorefOrPtrAdjustment::Autoref(Mutability::Mut)),
)?; )?;
if let rustc_type_ir::TyKind::RawPtr(ty, rustc_ast_ir::Mutability::Mut) = receiver_ty.value.kind() { if let rustc_type_ir::TyKind::RawPtr(ty, rustc_ast_ir::Mutability::Mut) =
receiver_ty.value.kind()
{
let const_ptr_ty = rustc_type_ir::Canonical { let const_ptr_ty = rustc_type_ir::Canonical {
max_universe: rustc_type_ir::UniverseIndex::ZERO, max_universe: rustc_type_ir::UniverseIndex::ZERO,
value: crate::next_solver::Ty::new_ptr(interner, ty, rustc_ast_ir::Mutability::Not), value: next_solver::Ty::new_ptr(interner, ty, rustc_ast_ir::Mutability::Not),
variables: receiver_ty.variables, variables: receiver_ty.variables,
}; };
iterate_method_candidates_by_receiver( iterate_method_candidates_by_receiver(
@ -1247,7 +1273,7 @@ where
#[tracing::instrument(skip_all, fields(name = ?name))] #[tracing::instrument(skip_all, fields(name = ?name))]
fn iterate_method_candidates_by_receiver<'db>( fn iterate_method_candidates_by_receiver<'db>(
table: &mut InferenceTable<'db>, table: &mut InferenceTable<'db>,
receiver_ty: crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, receiver_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
receiver_adjustments: ReceiverAdjustments, receiver_adjustments: ReceiverAdjustments,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
visible_from_module: VisibleFromModule, visible_from_module: VisibleFromModule,
@ -1255,7 +1281,7 @@ fn iterate_method_candidates_by_receiver<'db>(
callback: &mut dyn MethodCandidateCallback, callback: &mut dyn MethodCandidateCallback,
) -> ControlFlow<()> { ) -> ControlFlow<()> {
let receiver_ty = table.instantiate_canonical_ns(receiver_ty); let receiver_ty = table.instantiate_canonical_ns(receiver_ty);
let receiver_ty: crate::Ty = ChalkToNextSolver::from_nextsolver(receiver_ty, table.interner); let receiver_ty: crate::Ty = receiver_ty.to_chalk(table.interner);
// We're looking for methods with *receiver* type receiver_ty. These could // We're looking for methods with *receiver* type receiver_ty. These could
// be found in any of the derefs of receiver_ty, so we have to go through // be found in any of the derefs of receiver_ty, so we have to go through
// that, including raw derefs. // that, including raw derefs.
@ -1270,6 +1296,7 @@ fn iterate_method_candidates_by_receiver<'db>(
Some(&receiver_ty), Some(&receiver_ty),
Some(receiver_adjustments.clone()), Some(receiver_adjustments.clone()),
visible_from_module, visible_from_module,
LookupMode::MethodCall,
&mut |adjustments, item, is_visible| { &mut |adjustments, item, is_visible| {
callback.on_inherent_method(adjustments, item, is_visible) callback.on_inherent_method(adjustments, item, is_visible)
}, },
@ -1293,6 +1320,7 @@ fn iterate_method_candidates_by_receiver<'db>(
name, name,
Some(&receiver_ty), Some(&receiver_ty),
Some(receiver_adjustments.clone()), Some(receiver_adjustments.clone()),
LookupMode::MethodCall,
&mut |adjustments, item, is_visible| { &mut |adjustments, item, is_visible| {
callback.on_trait_method(adjustments, item, is_visible) callback.on_trait_method(adjustments, item, is_visible)
}, },
@ -1304,7 +1332,7 @@ fn iterate_method_candidates_by_receiver<'db>(
#[tracing::instrument(skip_all, fields(name = ?name))] #[tracing::instrument(skip_all, fields(name = ?name))]
fn iterate_method_candidates_for_self_ty<'db>( fn iterate_method_candidates_for_self_ty<'db>(
self_ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, self_ty: &next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
db: &'db dyn HirDatabase, db: &'db dyn HirDatabase,
env: Arc<TraitEnvironment>, env: Arc<TraitEnvironment>,
traits_in_scope: &FxHashSet<TraitId>, traits_in_scope: &FxHashSet<TraitId>,
@ -1313,7 +1341,7 @@ fn iterate_method_candidates_for_self_ty<'db>(
callback: &mut dyn MethodCandidateCallback, callback: &mut dyn MethodCandidateCallback,
) -> ControlFlow<()> { ) -> ControlFlow<()> {
let mut table = InferenceTable::new(db, env); let mut table = InferenceTable::new(db, env);
let self_ty = ChalkToNextSolver::from_nextsolver(table.instantiate_canonical_ns(self_ty.clone()), table.interner); let self_ty = table.instantiate_canonical_ns(*self_ty).to_chalk(table.interner);
iterate_inherent_methods( iterate_inherent_methods(
&self_ty, &self_ty,
&mut table, &mut table,
@ -1321,6 +1349,7 @@ fn iterate_method_candidates_for_self_ty<'db>(
None, None,
None, None,
visible_from_module, visible_from_module,
LookupMode::Path,
&mut |adjustments, item, is_visible| { &mut |adjustments, item, is_visible| {
callback.on_inherent_method(adjustments, item, is_visible) callback.on_inherent_method(adjustments, item, is_visible)
}, },
@ -1332,6 +1361,7 @@ fn iterate_method_candidates_for_self_ty<'db>(
name, name,
None, None,
None, None,
LookupMode::Path,
&mut |adjustments, item, is_visible| { &mut |adjustments, item, is_visible| {
callback.on_trait_method(adjustments, item, is_visible) callback.on_trait_method(adjustments, item, is_visible)
}, },
@ -1346,12 +1376,13 @@ fn iterate_trait_method_candidates(
name: Option<&Name>, name: Option<&Name>,
receiver_ty: Option<&Ty>, receiver_ty: Option<&Ty>,
receiver_adjustments: Option<ReceiverAdjustments>, receiver_adjustments: Option<ReceiverAdjustments>,
mode: LookupMode,
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
) -> ControlFlow<()> { ) -> ControlFlow<()> {
let db = table.db; let db = table.db;
let canonical_self_ty = ChalkToNextSolver::from_nextsolver(table.canonicalize(self_ty.clone().to_nextsolver(table.interner)), table.interner); let canonical_self_ty = table.canonicalize(self_ty.clone().to_nextsolver(table.interner));
let TraitEnvironment { krate, block, .. } = *table.trait_env; let TraitEnvironment { krate, .. } = *table.trait_env;
'traits: for &t in traits_in_scope { 'traits: for &t in traits_in_scope {
let data = db.trait_signature(t); let data = db.trait_signature(t);
@ -1391,15 +1422,22 @@ fn iterate_trait_method_candidates(
for &(_, item) in t.trait_items(db).items.iter() { for &(_, item) in t.trait_items(db).items.iter() {
// Don't pass a `visible_from_module` down to `is_valid_candidate`, // Don't pass a `visible_from_module` down to `is_valid_candidate`,
// since only inherent methods should be included into visibility checking. // since only inherent methods should be included into visibility checking.
let visible = let visible = match is_valid_trait_method_candidate(
match is_valid_trait_method_candidate(table, t, name, receiver_ty, item, self_ty) { table,
t,
name,
receiver_ty,
item,
self_ty,
mode,
) {
IsValidCandidate::Yes => true, IsValidCandidate::Yes => true,
IsValidCandidate::NotVisible => false, IsValidCandidate::NotVisible => false,
IsValidCandidate::No => continue, IsValidCandidate::No => continue,
}; };
if !known_implemented { if !known_implemented {
let goal = generic_implements_goal(db, &table.trait_env, t, &canonical_self_ty); let goal = generic_implements_goal_ns(table, t, canonical_self_ty);
if db.trait_solve(krate, block, goal.cast(Interner)).no_solution() { if next_trait_solve_canonical_in_ctxt(&table.infer_ctxt, goal).no_solution() {
continue 'traits; continue 'traits;
} }
} }
@ -1418,6 +1456,7 @@ fn iterate_inherent_methods(
receiver_ty: Option<&Ty>, receiver_ty: Option<&Ty>,
receiver_adjustments: Option<ReceiverAdjustments>, receiver_adjustments: Option<ReceiverAdjustments>,
visible_from_module: VisibleFromModule, visible_from_module: VisibleFromModule,
mode: LookupMode,
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
) -> ControlFlow<()> { ) -> ControlFlow<()> {
let db = table.db; let db = table.db;
@ -1441,6 +1480,7 @@ fn iterate_inherent_methods(
receiver_adjustments.clone(), receiver_adjustments.clone(),
callback, callback,
traits, traits,
mode,
)?; )?;
} }
TyKind::Dyn(_) => { TyKind::Dyn(_) => {
@ -1454,6 +1494,7 @@ fn iterate_inherent_methods(
receiver_adjustments.clone(), receiver_adjustments.clone(),
callback, callback,
traits.into_iter(), traits.into_iter(),
mode,
)?; )?;
} }
} }
@ -1512,6 +1553,7 @@ fn iterate_inherent_methods(
receiver_adjustments: Option<ReceiverAdjustments>, receiver_adjustments: Option<ReceiverAdjustments>,
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>, callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
traits: impl Iterator<Item = TraitId>, traits: impl Iterator<Item = TraitId>,
mode: LookupMode,
) -> ControlFlow<()> { ) -> ControlFlow<()> {
let db = table.db; let db = table.db;
for t in traits { for t in traits {
@ -1525,6 +1567,7 @@ fn iterate_inherent_methods(
receiver_ty, receiver_ty,
item, item,
self_ty, self_ty,
mode,
) { ) {
IsValidCandidate::Yes => true, IsValidCandidate::Yes => true,
IsValidCandidate::NotVisible => false, IsValidCandidate::NotVisible => false,
@ -1571,22 +1614,17 @@ fn iterate_inherent_methods(
} }
/// Returns the receiver type for the index trait call. /// Returns the receiver type for the index trait call.
pub(crate) fn resolve_indexing_op( pub(crate) fn resolve_indexing_op<'db>(
db: &dyn HirDatabase, table: &mut InferenceTable<'db>,
env: Arc<TraitEnvironment>, ty: next_solver::Canonical<'db, next_solver::Ty<'db>>,
ty: Canonical<Ty>,
index_trait: TraitId, index_trait: TraitId,
) -> Option<ReceiverAdjustments> { ) -> Option<ReceiverAdjustments> {
let mut table = InferenceTable::new(db, env); let ty = table.instantiate_canonical_ns(ty);
let ty = table.instantiate_canonical(ty); let deref_chain = autoderef_method_receiver(table, ty);
let interner = table.interner;
let deref_chain = autoderef_method_receiver(&mut table, ty.to_nextsolver(interner));
for (ty, adj) in deref_chain { for (ty, adj) in deref_chain {
//let goal = generic_implements_goal_ns(db, &table.trait_env, index_trait, &ty); //let goal = generic_implements_goal_ns(db, &table.trait_env, index_trait, &ty);
let goal = generic_implements_goal(db, &table.trait_env, index_trait, &ChalkToNextSolver::from_nextsolver(ty, interner)); let goal = generic_implements_goal_ns(table, index_trait, ty);
let goal: chalk_ir::Canonical<chalk_ir::InEnvironment<chalk_ir::Goal<Interner>>> = goal.cast(Interner); if !next_trait_solve_canonical_in_ctxt(&table.infer_ctxt, goal).no_solution() {
let goal = goal.to_nextsolver(interner);
if !next_trait_solve_canonical(db, table.trait_env.krate, table.trait_env.block, goal).no_solution() {
return Some(adj); return Some(adj);
} }
} }
@ -1666,6 +1704,7 @@ fn is_valid_trait_method_candidate(
receiver_ty: Option<&Ty>, receiver_ty: Option<&Ty>,
item: AssocItemId, item: AssocItemId,
self_ty: &Ty, self_ty: &Ty,
mode: LookupMode,
) -> IsValidCandidate { ) -> IsValidCandidate {
let db = table.db; let db = table.db;
match item { match item {
@ -1693,6 +1732,35 @@ fn is_valid_trait_method_candidate(
let expected_receiver = let expected_receiver =
sig.map(|s| s.params()[0].clone()).substitute(Interner, &fn_subst); sig.map(|s| s.params()[0].clone()).substitute(Interner, &fn_subst);
// FIXME: Clean up this mess with some context struct like rustc's `ProbeContext`
let variance = match mode {
LookupMode::MethodCall => rustc_type_ir::Variance::Covariant,
LookupMode::Path => rustc_type_ir::Variance::Invariant,
};
let res = table
.infer_ctxt
.at(
&next_solver::infer::traits::ObligationCause::dummy(),
table.trait_env.env.to_nextsolver(table.interner),
)
.relate(
DefineOpaqueTypes::No,
expected_receiver.to_nextsolver(table.interner),
variance,
receiver_ty.to_nextsolver(table.interner),
);
let Ok(infer_ok) = res else {
return IsValidCandidate::No;
};
if !infer_ok.obligations.is_empty() {
let mut ctxt = FulfillmentCtxt::new(&table.infer_ctxt);
for pred in infer_ok.into_obligations() {
ctxt.register_predicate_obligation(&table.infer_ctxt, pred);
}
check_that!(ctxt.select_all_or_error(&table.infer_ctxt).is_empty());
}
check_that!(table.unify(receiver_ty, &expected_receiver)); check_that!(table.unify(receiver_ty, &expected_receiver));
} }
@ -1839,53 +1907,36 @@ fn generic_implements_goal(
Canonical { binders, value } Canonical { binders, value }
} }
/*
/// This creates Substs for a trait with the given Self type and type variables /// This creates Substs for a trait with the given Self type and type variables
/// for all other parameters, to query the trait solver with it. /// for all other parameters, to query the trait solver with it.
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
fn generic_implements_goal_ns<'db>( fn generic_implements_goal_ns<'db>(
db: &'db dyn HirDatabase, table: &mut InferenceTable<'db>,
interner: DbInterner<'db>,
env: &TraitEnvironment,
trait_: TraitId, trait_: TraitId,
self_ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, self_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
) -> crate::next_solver::Canonical<'db, crate::next_solver::Goal<'db, crate::next_solver::Predicate<'db>>> { ) -> next_solver::Canonical<'db, next_solver::Goal<'db, crate::next_solver::Predicate<'db>>> {
let variables = self_ty.variables; let args = table.infer_ctxt.fresh_args_for_item(SolverDefId::TraitId(trait_));
let trait_ref = TyBuilder::trait_ref(db, trait_) let self_ty = table.instantiate_canonical_ns(self_ty);
.push(ChalkToNextSolver::from_nextsolver(self_ty.value, interner)) let trait_ref =
.fill_with_bound_vars(DebruijnIndex::INNERMOST, variables.len()) rustc_type_ir::TraitRef::new_from_args(table.infer_ctxt.interner, trait_.into(), args)
.build(); .with_replaced_self_ty(table.infer_ctxt.interner, self_ty);
let goal = next_solver::Goal::new(
table.infer_ctxt.interner,
table.trait_env.env.to_nextsolver(table.infer_ctxt.interner),
trait_ref,
);
let infer_ctxt = interner.infer_ctxt().build(TypingMode::non_body_analysis()); table.canonicalize(goal)
let args = infer_ctxt.fresh_args_for_item(SolverDefId::TraitId(trait_));
rustc_type_ir::TraitRef::new(interner, SolverDefId::TraitId(trait_)).with_self_ty(interner, self_ty.value);
let kinds =
binders.iter().cloned().chain(trait_ref.substitution.iter(Interner).skip(1).map(|it| {
let vk = match it.data(Interner) {
GenericArgData::Ty(_) => VariableKind::Ty(chalk_ir::TyVariableKind::General),
GenericArgData::Lifetime(_) => VariableKind::Lifetime,
GenericArgData::Const(c) => VariableKind::Const(c.data(Interner).ty.clone()),
};
WithKind::new(vk, UniverseIndex::ROOT)
}));
let binders = CanonicalVarKinds::from_iter(Interner, kinds);
let obligation = trait_ref.cast(Interner);
let value = InEnvironment::new(&env.env, obligation);
crate::next_solver::Canonical { max_universe, value, variables }
} }
*/
fn autoderef_method_receiver<'db>( fn autoderef_method_receiver<'db>(
table: &mut InferenceTable<'db>, table: &mut InferenceTable<'db>,
ty: crate::next_solver::Ty<'db>, ty: next_solver::Ty<'db>,
) -> Vec<(crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ReceiverAdjustments)> { ) -> Vec<(next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ReceiverAdjustments)> {
let interner = table.interner; let interner = table.interner;
let mut deref_chain = Vec::new(); let mut deref_chain = Vec::new();
let mut autoderef = autoderef::Autoderef::new_no_tracking(table, ChalkToNextSolver::from_nextsolver(ty, interner), false, true); let mut autoderef =
autoderef::Autoderef::new_no_tracking(table, ty.to_chalk(interner), false, true);
while let Some((ty, derefs)) = autoderef.next() { while let Some((ty, derefs)) = autoderef.next() {
deref_chain.push(( deref_chain.push((
autoderef.table.canonicalize(ty.to_nextsolver(interner)), autoderef.table.canonicalize(ty.to_nextsolver(interner)),
@ -1894,11 +1945,11 @@ fn autoderef_method_receiver<'db>(
} }
// As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!) // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
if let Some((rustc_type_ir::Array(parameters, _), variables, max_universe, adj)) = if let Some((rustc_type_ir::Array(parameters, _), variables, max_universe, adj)) =
deref_chain.last().map(|d| (d.0.value.kind(), d.0.variables.clone(), d.0.max_universe, d.1.clone())) deref_chain.last().map(|d| (d.0.value.kind(), d.0.variables, d.0.max_universe, d.1.clone()))
{ {
let unsized_ty = crate::next_solver::Ty::new_slice(interner, parameters); let unsized_ty = next_solver::Ty::new_slice(interner, parameters);
deref_chain.push(( deref_chain.push((
crate::next_solver::Canonical { max_universe, value: unsized_ty, variables, }, next_solver::Canonical { max_universe, value: unsized_ty, variables },
ReceiverAdjustments { unsize_array: true, ..adj.clone() }, ReceiverAdjustments { unsize_array: true, ..adj.clone() },
)); ));
} }

View file

@ -34,8 +34,7 @@ pub use eval::{
}; };
pub use lower::{MirLowerError, lower_to_mir, mir_body_for_closure_query, mir_body_query}; pub use lower::{MirLowerError, lower_to_mir, mir_body_for_closure_query, mir_body_query};
pub use monomorphization::{ pub use monomorphization::{
monomorphize_mir_body_bad, monomorphized_mir_body_for_closure_query, monomorphized_mir_body_for_closure_query, monomorphized_mir_body_query,
monomorphized_mir_body_query,
}; };
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use smallvec::{SmallVec, smallvec}; use smallvec::{SmallVec, smallvec};

View file

@ -38,7 +38,6 @@ struct Filler<'a> {
trait_env: Arc<TraitEnvironment>, trait_env: Arc<TraitEnvironment>,
subst: &'a Substitution, subst: &'a Substitution,
generics: Option<Generics>, generics: Option<Generics>,
owner: DefWithBodyId,
} }
impl FallibleTypeFolder<Interner> for Filler<'_> { impl FallibleTypeFolder<Interner> for Filler<'_> {
type Error = MirLowerError; type Error = MirLowerError;
@ -66,7 +65,11 @@ impl FallibleTypeFolder<Interner> for Filler<'_> {
})) }))
.intern(Interner)) .intern(Interner))
} }
TyKind::OpaqueType(id, subst) => { TyKind::Alias(chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy {
opaque_ty_id: id,
substitution: subst,
}))
| TyKind::OpaqueType(id, subst) => {
let impl_trait_id = self.db.lookup_intern_impl_trait_id((*id).into()); let impl_trait_id = self.db.lookup_intern_impl_trait_id((*id).into());
let subst = subst.clone().try_fold_with(self.as_dyn(), outer_binder)?; let subst = subst.clone().try_fold_with(self.as_dyn(), outer_binder)?;
match impl_trait_id { match impl_trait_id {
@ -74,7 +77,6 @@ impl FallibleTypeFolder<Interner> for Filler<'_> {
let infer = self.db.infer(func.into()); let infer = self.db.infer(func.into());
let filler = &mut Filler { let filler = &mut Filler {
db: self.db, db: self.db,
owner: self.owner,
trait_env: self.trait_env.clone(), trait_env: self.trait_env.clone(),
subst: &subst, subst: &subst,
generics: Some(generics(self.db, func.into())), generics: Some(generics(self.db, func.into())),
@ -306,7 +308,7 @@ pub fn monomorphized_mir_body_query(
trait_env: Arc<crate::TraitEnvironment>, trait_env: Arc<crate::TraitEnvironment>,
) -> Result<Arc<MirBody>, MirLowerError> { ) -> Result<Arc<MirBody>, MirLowerError> {
let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def)); let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def));
let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner }; let filler = &mut Filler { db, subst: &subst, trait_env, generics };
let body = db.mir_body(owner)?; let body = db.mir_body(owner)?;
let mut body = (*body).clone(); let mut body = (*body).clone();
filler.fill_body(&mut body)?; filler.fill_body(&mut body)?;
@ -330,23 +332,9 @@ pub fn monomorphized_mir_body_for_closure_query(
) -> Result<Arc<MirBody>, MirLowerError> { ) -> Result<Arc<MirBody>, MirLowerError> {
let InternedClosure(owner, _) = db.lookup_intern_closure(closure); let InternedClosure(owner, _) = db.lookup_intern_closure(closure);
let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def)); let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def));
let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner }; let filler = &mut Filler { db, subst: &subst, trait_env, generics };
let body = db.mir_body_for_closure(closure)?; let body = db.mir_body_for_closure(closure)?;
let mut body = (*body).clone(); let mut body = (*body).clone();
filler.fill_body(&mut body)?; filler.fill_body(&mut body)?;
Ok(Arc::new(body)) Ok(Arc::new(body))
} }
// FIXME: remove this function. Monomorphization is a time consuming job and should always be a query.
pub fn monomorphize_mir_body_bad(
db: &dyn HirDatabase,
mut body: MirBody,
subst: Substitution,
trait_env: Arc<crate::TraitEnvironment>,
) -> Result<MirBody, MirLowerError> {
let owner = body.owner;
let generics = owner.as_generic_def_id(db).map(|g_def| generics(db, g_def));
let filler = &mut Filler { db, subst: &subst, trait_env, generics, owner };
filler.fill_body(&mut body)?;
Ok(body)
}

View file

@ -5,11 +5,10 @@ pub mod abi;
mod consts; mod consts;
mod def_id; mod def_id;
pub mod fold; pub mod fold;
mod fulfill; pub mod fulfill;
mod generic_arg; mod generic_arg;
pub mod generics; pub mod generics;
pub mod infer; pub mod infer;
//mod infer_new;
pub mod interner; pub mod interner;
mod ir_print; mod ir_print;
pub mod mapping; pub mod mapping;
@ -24,7 +23,6 @@ pub mod util;
pub use consts::*; pub use consts::*;
pub use def_id::*; pub use def_id::*;
pub use generic_arg::*; pub use generic_arg::*;
//pub use infer_new::*;
pub use interner::*; pub use interner::*;
pub use opaques::*; pub use opaques::*;
pub use predicate::*; pub use predicate::*;

View file

@ -1,14 +1,28 @@
//! This module contains code to canonicalize values into a `Canonical<'db, T>`.
//!
//! For an overview of what canonicalization is and how it fits into
//! rustc, check out the [chapter in the rustc dev guide][c].
//!
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use rustc_index::Idx; use rustc_index::Idx;
use rustc_type_ir::inherent::{Const as _, IntoKind as _, Region as _, SliceLike, Ty as _};
use rustc_type_ir::InferTy::{self, FloatVar, IntVar, TyVar}; use rustc_type_ir::InferTy::{self, FloatVar, IntVar, TyVar};
use rustc_type_ir::{BoundVar, CanonicalQueryInput, CanonicalTyVarKind, DebruijnIndex, Flags, InferConst, RegionKind, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, UniverseIndex}; use rustc_type_ir::inherent::{Const as _, IntoKind as _, Region as _, SliceLike, Ty as _};
use rustc_type_ir::{
BoundVar, CanonicalQueryInput, CanonicalTyVarKind, DebruijnIndex, Flags, InferConst,
RegionKind, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
UniverseIndex,
};
use smallvec::SmallVec; use smallvec::SmallVec;
use tracing::debug; use tracing::debug;
use crate::next_solver::infer::InferCtxt; use crate::next_solver::infer::InferCtxt;
use crate::next_solver::{Binder, BoundRegion, BoundRegionKind, BoundTy, Canonical, CanonicalVarKind, CanonicalVars, Const, ConstKind, DbInterner, GenericArg, ParamEnvAnd, Placeholder, Region, Ty, TyKind}; use crate::next_solver::{
Binder, BoundConst, BoundRegion, BoundRegionKind, BoundTy, Canonical, CanonicalVarKind,
CanonicalVars, Const, ConstKind, DbInterner, GenericArg, ParamEnvAnd, Placeholder, Region, Ty,
TyKind,
};
/// When we canonicalize a value to form a query, we wind up replacing /// When we canonicalize a value to form a query, we wind up replacing
/// various parts of it with canonical variables. This struct stores /// various parts of it with canonical variables. This struct stores
@ -65,7 +79,7 @@ impl<'db> InferCtxt<'db> {
// `param_env` because they are treated differently by trait selection. // `param_env` because they are treated differently by trait selection.
let canonical_param_env = Canonicalizer::canonicalize( let canonical_param_env = Canonicalizer::canonicalize(
param_env, param_env,
None, self,
self.interner, self.interner,
&CanonicalizeFreeRegionsOtherThanStatic, &CanonicalizeFreeRegionsOtherThanStatic,
query_state, query_state,
@ -74,7 +88,7 @@ impl<'db> InferCtxt<'db> {
let canonical = Canonicalizer::canonicalize_with_base( let canonical = Canonicalizer::canonicalize_with_base(
canonical_param_env, canonical_param_env,
value, value,
Some(self), self,
self.interner, self.interner,
&CanonicalizeAllFreeRegions, &CanonicalizeAllFreeRegions,
query_state, query_state,
@ -115,7 +129,7 @@ impl<'db> InferCtxt<'db> {
let mut query_state = OriginalQueryValues::default(); let mut query_state = OriginalQueryValues::default();
Canonicalizer::canonicalize( Canonicalizer::canonicalize(
value, value,
Some(self), self,
self.interner, self.interner,
&CanonicalizeQueryResponse, &CanonicalizeQueryResponse,
&mut query_state, &mut query_state,
@ -129,7 +143,7 @@ impl<'db> InferCtxt<'db> {
let mut query_state = OriginalQueryValues::default(); let mut query_state = OriginalQueryValues::default();
Canonicalizer::canonicalize( Canonicalizer::canonicalize(
value, value,
Some(self), self,
self.interner, self.interner,
&CanonicalizeUserTypeAnnotation, &CanonicalizeUserTypeAnnotation,
&mut query_state, &mut query_state,
@ -165,7 +179,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
canonicalizer: &mut Canonicalizer<'_, 'db>, canonicalizer: &mut Canonicalizer<'_, 'db>,
mut r: Region<'db>, mut r: Region<'db>,
) -> Region<'db> { ) -> Region<'db> {
let infcx = canonicalizer.infcx.unwrap(); let infcx = canonicalizer.infcx;
if let RegionKind::ReVar(vid) = r.kind() { if let RegionKind::ReVar(vid) = r.kind() {
r = infcx r = infcx
@ -180,12 +194,14 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
}; };
match r.kind() { match r.kind() {
RegionKind::ReLateParam(_) | RegionKind::ReErased | RegionKind::ReStatic | RegionKind::ReEarlyParam(..) | RegionKind::ReError(..) => r, RegionKind::ReLateParam(_)
| RegionKind::ReErased
| RegionKind::ReStatic
| RegionKind::ReEarlyParam(..)
| RegionKind::ReError(..) => r,
RegionKind::RePlaceholder(placeholder) => canonicalizer.canonical_var_for_region( RegionKind::RePlaceholder(placeholder) => canonicalizer
CanonicalVarKind::PlaceholderRegion(placeholder), .canonical_var_for_region(CanonicalVarKind::PlaceholderRegion(placeholder), r),
r,
),
RegionKind::ReVar(vid) => { RegionKind::ReVar(vid) => {
let universe = infcx let universe = infcx
@ -194,10 +210,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
.unwrap_region_constraints() .unwrap_region_constraints()
.probe_value(vid) .probe_value(vid)
.unwrap_err(); .unwrap_err();
canonicalizer.canonical_var_for_region( canonicalizer.canonical_var_for_region(CanonicalVarKind::Region(universe), r)
CanonicalVarKind::Region(universe),
r,
)
} }
_ => { _ => {
@ -240,7 +253,7 @@ impl CanonicalizeMode for CanonicalizeUserTypeAnnotation {
RegionKind::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r), RegionKind::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r),
RegionKind::RePlaceholder(..) | RegionKind::ReBound(..) => { RegionKind::RePlaceholder(..) | RegionKind::ReBound(..) => {
// We only expect region names that the user can type. // We only expect region names that the user can type.
panic!("unexpected region in query response: `{:?}`", r) panic!("unexpected region in query response: `{r:?}`")
} }
} }
} }
@ -296,7 +309,7 @@ impl CanonicalizeMode for CanonicalizeFreeRegionsOtherThanStatic {
struct Canonicalizer<'cx, 'db> { struct Canonicalizer<'cx, 'db> {
/// Set to `None` to disable the resolution of inference variables. /// Set to `None` to disable the resolution of inference variables.
infcx: Option<&'cx InferCtxt<'db>>, infcx: &'cx InferCtxt<'db>,
tcx: DbInterner<'db>, tcx: DbInterner<'db>,
variables: SmallVec<[CanonicalVarKind<'db>; 8]>, variables: SmallVec<[CanonicalVarKind<'db>; 8]>,
query_state: &'cx mut OriginalQueryValues<'db>, query_state: &'cx mut OriginalQueryValues<'db>,
@ -350,14 +363,14 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> {
// We need to canonicalize the *root* of our ty var. // We need to canonicalize the *root* of our ty var.
// This is so that our canonical response correctly reflects // This is so that our canonical response correctly reflects
// any equated inference vars correctly! // any equated inference vars correctly!
let root_vid = self.infcx.unwrap().root_var(vid); let root_vid = self.infcx.root_var(vid);
if root_vid != vid { if root_vid != vid {
t = Ty::new_var(self.tcx, root_vid); t = Ty::new_var(self.tcx, root_vid);
vid = root_vid; vid = root_vid;
} }
debug!("canonical: type var found with vid {:?}", vid); debug!("canonical: type var found with vid {:?}", vid);
match self.infcx.unwrap().probe_ty_var(vid) { match self.infcx.probe_ty_var(vid) {
// `t` could be a float / int variable; canonicalize that instead. // `t` could be a float / int variable; canonicalize that instead.
Ok(t) => { Ok(t) => {
debug!("(resolved to {:?})", t); debug!("(resolved to {:?})", t);
@ -380,29 +393,25 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> {
} }
TyKind::Infer(IntVar(vid)) => { TyKind::Infer(IntVar(vid)) => {
let nt = self.infcx.unwrap().opportunistic_resolve_int_var(vid); let nt = self.infcx.opportunistic_resolve_int_var(vid);
if nt != t { if nt != t {
return self.fold_ty(nt); self.fold_ty(nt)
} else { } else {
self.canonicalize_ty_var( self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Int), t)
CanonicalVarKind::Ty(CanonicalTyVarKind::Int),
t,
)
} }
} }
TyKind::Infer(FloatVar(vid)) => { TyKind::Infer(FloatVar(vid)) => {
let nt = self.infcx.unwrap().opportunistic_resolve_float_var(vid); let nt = self.infcx.opportunistic_resolve_float_var(vid);
if nt != t { if nt != t {
return self.fold_ty(nt); self.fold_ty(nt)
} else { } else {
self.canonicalize_ty_var( self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Float), t)
CanonicalVarKind::Ty(CanonicalTyVarKind::Float),
t,
)
} }
} }
TyKind::Infer(InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_)) => { TyKind::Infer(
InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_),
) => {
panic!("encountered a fresh type during canonicalization") panic!("encountered a fresh type during canonicalization")
} }
@ -410,10 +419,7 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> {
if !self.canonicalize_mode.preserve_universes() { if !self.canonicalize_mode.preserve_universes() {
placeholder.universe = UniverseIndex::ROOT; placeholder.universe = UniverseIndex::ROOT;
} }
self.canonicalize_ty_var( self.canonicalize_ty_var(CanonicalVarKind::PlaceholderTy(placeholder), t)
CanonicalVarKind::PlaceholderTy(placeholder),
t,
)
} }
TyKind::Bound(debruijn, _) => { TyKind::Bound(debruijn, _) => {
@ -465,14 +471,14 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> {
// We need to canonicalize the *root* of our const var. // We need to canonicalize the *root* of our const var.
// This is so that our canonical response correctly reflects // This is so that our canonical response correctly reflects
// any equated inference vars correctly! // any equated inference vars correctly!
let root_vid = self.infcx.unwrap().root_const_var(vid); let root_vid = self.infcx.root_const_var(vid);
if root_vid != vid { if root_vid != vid {
ct = Const::new_var(self.tcx, root_vid); ct = Const::new_var(self.tcx, root_vid);
vid = root_vid; vid = root_vid;
} }
debug!("canonical: const var found with vid {:?}", vid); debug!("canonical: const var found with vid {:?}", vid);
match self.infcx.unwrap().probe_const_var(vid) { match self.infcx.probe_const_var(vid) {
Ok(c) => { Ok(c) => {
debug!("(resolved to {:?})", c); debug!("(resolved to {:?})", c);
return self.fold_const(c); return self.fold_const(c);
@ -485,10 +491,7 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> {
// FIXME: perf problem described in #55921. // FIXME: perf problem described in #55921.
ui = UniverseIndex::ROOT; ui = UniverseIndex::ROOT;
} }
return self.canonicalize_const_var( return self.canonicalize_const_var(CanonicalVarKind::Const(ui), ct);
CanonicalVarKind::Const(ui),
ct,
);
} }
} }
} }
@ -503,10 +506,8 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> {
} }
} }
ConstKind::Placeholder(placeholder) => { ConstKind::Placeholder(placeholder) => {
return self.canonicalize_const_var( return self
CanonicalVarKind::PlaceholderConst(placeholder), .canonicalize_const_var(CanonicalVarKind::PlaceholderConst(placeholder), ct);
ct,
);
} }
_ => {} _ => {}
} }
@ -524,7 +525,7 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
/// `canonicalize_query` and `canonicalize_response`. /// `canonicalize_query` and `canonicalize_response`.
fn canonicalize<V>( fn canonicalize<V>(
value: V, value: V,
infcx: Option<&InferCtxt<'db>>, infcx: &InferCtxt<'db>,
tcx: DbInterner<'db>, tcx: DbInterner<'db>,
canonicalize_region_mode: &dyn CanonicalizeMode, canonicalize_region_mode: &dyn CanonicalizeMode,
query_state: &mut OriginalQueryValues<'db>, query_state: &mut OriginalQueryValues<'db>,
@ -551,7 +552,7 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
fn canonicalize_with_base<U, V>( fn canonicalize_with_base<U, V>(
base: Canonical<'db, U>, base: Canonical<'db, U>,
value: V, value: V,
infcx: Option<&InferCtxt<'db>>, infcx: &InferCtxt<'db>,
tcx: DbInterner<'db>, tcx: DbInterner<'db>,
canonicalize_region_mode: &dyn CanonicalizeMode, canonicalize_region_mode: &dyn CanonicalizeMode,
query_state: &mut OriginalQueryValues<'db>, query_state: &mut OriginalQueryValues<'db>,
@ -596,7 +597,8 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
// anymore. // anymore.
debug_assert!(!out_value.has_infer() && !out_value.has_placeholders()); debug_assert!(!out_value.has_infer() && !out_value.has_placeholders());
let canonical_variables = CanonicalVars::new_from_iter(tcx, canonicalizer.universe_canonicalized_variables()); let canonical_variables =
CanonicalVars::new_from_iter(tcx, canonicalizer.universe_canonicalized_variables());
let max_universe = canonical_variables let max_universe = canonical_variables
.iter() .iter()
@ -690,15 +692,11 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
self.variables self.variables
.iter() .iter()
.map(|v| match *v { .map(|v| match *v {
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => { CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => *v,
return *v;
}
CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => { CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {
CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u])) CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u]))
} }
CanonicalVarKind::Region(u) => { CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]),
CanonicalVarKind::Region(reverse_universe_map[&u])
}
CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]), CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
CanonicalVarKind::PlaceholderTy(placeholder) => { CanonicalVarKind::PlaceholderTy(placeholder) => {
CanonicalVarKind::PlaceholderTy(Placeholder { CanonicalVarKind::PlaceholderTy(Placeholder {
@ -735,14 +733,8 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
/// ///
/// (This works because unification never fails -- and hence trait /// (This works because unification never fails -- and hence trait
/// selection is never affected -- due to a universe mismatch.) /// selection is never affected -- due to a universe mismatch.)
fn canonical_var_for_region_in_root_universe( fn canonical_var_for_region_in_root_universe(&mut self, r: Region<'db>) -> Region<'db> {
&mut self, self.canonical_var_for_region(CanonicalVarKind::Region(UniverseIndex::ROOT), r)
r: Region<'db>,
) -> Region<'db> {
self.canonical_var_for_region(
CanonicalVarKind::Region(UniverseIndex::ROOT),
r,
)
} }
/// Creates a canonical variable (with the given `info`) /// Creates a canonical variable (with the given `info`)
@ -762,9 +754,13 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
/// *that*. Otherwise, create a new canonical variable for /// *that*. Otherwise, create a new canonical variable for
/// `ty_var`. /// `ty_var`.
fn canonicalize_ty_var(&mut self, info: CanonicalVarKind<'db>, ty_var: Ty<'db>) -> Ty<'db> { fn canonicalize_ty_var(&mut self, info: CanonicalVarKind<'db>, ty_var: Ty<'db>) -> Ty<'db> {
debug_assert!(!self.infcx.is_some_and(|infcx| ty_var != infcx.shallow_resolve(ty_var))); debug_assert_eq!(ty_var, self.infcx.shallow_resolve(ty_var));
let var = self.canonical_var(info, ty_var.into()); let var = self.canonical_var(info, ty_var.into());
Ty::new_bound(self.tcx, self.binder_index, BoundTy { kind: crate::next_solver::BoundTyKind::Anon, var }) Ty::new_bound(
self.tcx,
self.binder_index,
BoundTy { kind: crate::next_solver::BoundTyKind::Anon, var },
)
} }
/// Given a type variable `const_var` of the given kind, first check /// Given a type variable `const_var` of the given kind, first check
@ -776,10 +772,8 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
info: CanonicalVarKind<'db>, info: CanonicalVarKind<'db>,
const_var: Const<'db>, const_var: Const<'db>,
) -> Const<'db> { ) -> Const<'db> {
debug_assert!( debug_assert_eq!(const_var, self.infcx.shallow_resolve_const(const_var));
!self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve_const(const_var))
);
let var = self.canonical_var(info, const_var.into()); let var = self.canonical_var(info, const_var.into());
Const::new_bound(self.tcx, self.binder_index, var) Const::new_bound(self.tcx, self.binder_index, BoundConst { var })
} }
} }

View file

@ -503,7 +503,10 @@ impl<'db> InferCtxt<'db> {
} }
pub fn next_ty_vid(&self) -> TyVid { pub fn next_ty_vid(&self) -> TyVid {
self.inner.borrow_mut().type_variables().new_var(self.universe(), TypeVariableOrigin { param_def_id: None }) self.inner
.borrow_mut()
.type_variables()
.new_var(self.universe(), TypeVariableOrigin { param_def_id: None })
} }
pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'db> { pub fn next_ty_var_with_origin(&self, origin: TypeVariableOrigin) -> Ty<'db> {
@ -526,11 +529,13 @@ impl<'db> InferCtxt<'db> {
} }
pub fn next_const_vid(&self) -> ConstVid { pub fn next_const_vid(&self) -> ConstVid {
self self.inner
.inner
.borrow_mut() .borrow_mut()
.const_unification_table() .const_unification_table()
.new_key(ConstVariableValue::Unknown { origin: ConstVariableOrigin { param_def_id: None }, universe: self.universe() }) .new_key(ConstVariableValue::Unknown {
origin: ConstVariableOrigin { param_def_id: None },
universe: self.universe(),
})
.vid .vid
} }
@ -566,9 +571,7 @@ impl<'db> InferCtxt<'db> {
} }
pub fn next_float_var(&self) -> Ty<'db> { pub fn next_float_var(&self) -> Ty<'db> {
let next_float_var_id = Ty::new_float_var(self.interner, self.next_float_vid())
self.inner.borrow_mut().float_unification_table().new_key(FloatVarValue::Unknown);
Ty::new_float_var(self.interner, next_float_var_id)
} }
pub fn next_float_vid(&self) -> FloatVid { pub fn next_float_vid(&self) -> FloatVid {
@ -815,9 +818,7 @@ impl<'db> InferCtxt<'db> {
match value { match value {
IntVarValue::IntType(ty) => Some(Ty::new_int(self.interner, ty)), IntVarValue::IntType(ty) => Some(Ty::new_int(self.interner, ty)),
IntVarValue::UintType(ty) => Some(Ty::new_uint(self.interner, ty)), IntVarValue::UintType(ty) => Some(Ty::new_uint(self.interner, ty)),
IntVarValue::Unknown => { IntVarValue::Unknown => None,
None
}
} }
} }
@ -839,9 +840,7 @@ impl<'db> InferCtxt<'db> {
let value = inner.float_unification_table().probe_value(vid); let value = inner.float_unification_table().probe_value(vid);
match value { match value {
FloatVarValue::Known(ty) => Some(Ty::new_float(self.interner, ty)), FloatVarValue::Known(ty) => Some(Ty::new_float(self.interner, ty)),
FloatVarValue::Unknown => { FloatVarValue::Unknown => None,
None
}
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -9,12 +9,12 @@ use rustc_type_ir::{
solve::{Certainty, NoSolution}, solve::{Certainty, NoSolution},
}; };
use crate::next_solver::mapping::NextSolverToChalk;
use crate::{ use crate::{
TraitRefExt, TraitRefExt,
db::HirDatabase, db::HirDatabase,
next_solver::{ next_solver::{
ClauseKind, CoercePredicate, PredicateKind, SubtypePredicate, ClauseKind, CoercePredicate, PredicateKind, SubtypePredicate, mapping::ChalkToNextSolver,
mapping::ChalkToNextSolver,
util::sizedness_fast_path, util::sizedness_fast_path,
}, },
}; };
@ -200,7 +200,7 @@ impl<'db> SolverDelegate for SolverContext<'db> {
SolverDefId::StaticId(c) => GeneralConstId::StaticId(c), SolverDefId::StaticId(c) => GeneralConstId::StaticId(c),
_ => unreachable!(), _ => unreachable!(),
}; };
let subst = ChalkToNextSolver::from_nextsolver(uv.args, self.interner); let subst = uv.args.to_chalk(self.interner);
let ec = self.cx().db.const_eval(c, subst, None).ok()?; let ec = self.cx().db.const_eval(c, subst, None).ok()?;
Some(ec.to_nextsolver(self.interner)) Some(ec.to_nextsolver(self.interner))
} }

View file

@ -49,7 +49,7 @@ fn let_stmt_coerce() {
//- minicore: coerce_unsized //- minicore: coerce_unsized
fn test() { fn test() {
let x: &[isize] = &[1]; let x: &[isize] = &[1];
// ^^^^ adjustments: Deref(None), Borrow(Ref('?2, Not)), Pointer(Unsize) // ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize)
let x: *const [isize] = &[1]; let x: *const [isize] = &[1];
// ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize) // ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize)
} }
@ -96,7 +96,7 @@ fn foo<T>(x: &[T]) -> &[T] { x }
fn test() { fn test() {
let x = if true { let x = if true {
foo(&[1]) foo(&[1])
// ^^^^ adjustments: Deref(None), Borrow(Ref('?11, Not)), Pointer(Unsize) // ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize)
} else { } else {
&[1] &[1]
}; };
@ -148,7 +148,7 @@ fn foo<T>(x: &[T]) -> &[T] { x }
fn test(i: i32) { fn test(i: i32) {
let x = match i { let x = match i {
2 => foo(&[2]), 2 => foo(&[2]),
// ^^^^ adjustments: Deref(None), Borrow(Ref('?11, Not)), Pointer(Unsize) // ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize)
1 => &[1], 1 => &[1],
_ => &[3], _ => &[3],
}; };
@ -881,7 +881,7 @@ fn adjust_index() {
fn test() { fn test() {
let x = [1, 2, 3]; let x = [1, 2, 3];
x[2] = 6; x[2] = 6;
// ^ adjustments: Borrow(Ref('?8, Mut)) // ^ adjustments: Borrow(Ref('?0, Mut))
} }
", ",
); );
@ -906,11 +906,11 @@ impl core::ops::IndexMut<usize> for StructMut {
} }
fn test() { fn test() {
Struct[0]; Struct[0];
// ^^^^^^ adjustments: Borrow(Ref('?2, Not)) // ^^^^^^ adjustments: Borrow(Ref('?0, Not))
StructMut[0]; StructMut[0];
// ^^^^^^^^^ adjustments: Borrow(Ref('?5, Not)) // ^^^^^^^^^ adjustments: Borrow(Ref('?1, Not))
&mut StructMut[0]; &mut StructMut[0];
// ^^^^^^^^^ adjustments: Borrow(Ref('?8, Mut)) // ^^^^^^^^^ adjustments: Borrow(Ref('?2, Mut))
}", }",
); );
} }

View file

@ -589,6 +589,7 @@ fn main() {
"attrs_shim", "attrs_shim",
"attrs_shim", "attrs_shim",
"return_type_impl_traits_shim", "return_type_impl_traits_shim",
"generic_predicates_ns_shim",
"infer_shim", "infer_shim",
"function_signature_shim", "function_signature_shim",
"function_signature_with_source_map_shim", "function_signature_with_source_map_shim",
@ -605,8 +606,6 @@ fn main() {
"impl_signature_shim", "impl_signature_shim",
"impl_signature_with_source_map_shim", "impl_signature_with_source_map_shim",
"callable_item_signature_shim", "callable_item_signature_shim",
"adt_variance_shim",
"variances_of_shim",
"trait_impls_in_deps_shim", "trait_impls_in_deps_shim",
"trait_impls_in_crate_shim", "trait_impls_in_crate_shim",
"impl_trait_with_diagnostics_shim", "impl_trait_with_diagnostics_shim",
@ -615,7 +614,6 @@ fn main() {
"impl_trait_with_diagnostics_ns_shim", "impl_trait_with_diagnostics_ns_shim",
"impl_self_ty_with_diagnostics_ns_shim", "impl_self_ty_with_diagnostics_ns_shim",
"generic_predicates_ns_shim", "generic_predicates_ns_shim",
"generic_predicates_ns_shim",
"value_ty_shim", "value_ty_shim",
"generic_predicates_shim", "generic_predicates_shim",
"lang_item", "lang_item",
@ -691,6 +689,7 @@ fn main() {
"attrs_shim", "attrs_shim",
"attrs_shim", "attrs_shim",
"return_type_impl_traits_shim", "return_type_impl_traits_shim",
"generic_predicates_ns_shim",
"infer_shim", "infer_shim",
"function_signature_with_source_map_shim", "function_signature_with_source_map_shim",
"expr_scopes_shim", "expr_scopes_shim",
@ -706,7 +705,6 @@ fn main() {
"impl_trait_with_diagnostics_ns_shim", "impl_trait_with_diagnostics_ns_shim",
"impl_self_ty_with_diagnostics_ns_shim", "impl_self_ty_with_diagnostics_ns_shim",
"generic_predicates_ns_shim", "generic_predicates_ns_shim",
"generic_predicates_ns_shim",
"generic_predicates_shim", "generic_predicates_shim",
] ]
"#]], "#]],

View file

@ -202,7 +202,7 @@ fn expr_macro_def_expanded_in_various_places() {
100..119 'for _ ...!() {}': {unknown} 100..119 'for _ ...!() {}': {unknown}
100..119 'for _ ...!() {}': &'? mut {unknown} 100..119 'for _ ...!() {}': &'? mut {unknown}
100..119 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 100..119 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
100..119 'for _ ...!() {}': Option<{unknown}> 100..119 'for _ ...!() {}': Option<<{unknown} as Iterator>::Item>
100..119 'for _ ...!() {}': () 100..119 'for _ ...!() {}': ()
100..119 'for _ ...!() {}': () 100..119 'for _ ...!() {}': ()
100..119 'for _ ...!() {}': () 100..119 'for _ ...!() {}': ()
@ -296,7 +296,7 @@ fn expr_macro_rules_expanded_in_various_places() {
114..133 'for _ ...!() {}': {unknown} 114..133 'for _ ...!() {}': {unknown}
114..133 'for _ ...!() {}': &'? mut {unknown} 114..133 'for _ ...!() {}': &'? mut {unknown}
114..133 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 114..133 'for _ ...!() {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
114..133 'for _ ...!() {}': Option<{unknown}> 114..133 'for _ ...!() {}': Option<<{unknown} as Iterator>::Item>
114..133 'for _ ...!() {}': () 114..133 'for _ ...!() {}': ()
114..133 'for _ ...!() {}': () 114..133 'for _ ...!() {}': ()
114..133 'for _ ...!() {}': () 114..133 'for _ ...!() {}': ()

View file

@ -1876,9 +1876,9 @@ impl Foo {
} }
fn test() { fn test() {
Foo.foo(); Foo.foo();
//^^^ adjustments: Borrow(Ref('?1, Not)) //^^^ adjustments: Borrow(Ref('?0, Not))
(&Foo).foo(); (&Foo).foo();
// ^^^^ adjustments: Deref(None), Borrow(Ref('?3, Not)) // ^^^^ adjustments: Deref(None), Borrow(Ref('?2, Not))
} }
"#, "#,
); );
@ -1892,7 +1892,7 @@ fn receiver_adjustment_unsize_array() {
fn test() { fn test() {
let a = [1, 2, 3]; let a = [1, 2, 3];
a.len(); a.len();
} //^ adjustments: Borrow(Ref('?7, Not)), Pointer(Unsize) } //^ adjustments: Borrow(Ref('?0, Not)), Pointer(Unsize)
"#, "#,
); );
} }
@ -2105,7 +2105,7 @@ impl Foo {
} }
fn test() { fn test() {
Box::new(Foo).foo(); Box::new(Foo).foo();
//^^^^^^^^^^^^^ adjustments: Deref(None), Borrow(Ref('?5, Not)) //^^^^^^^^^^^^^ adjustments: Deref(None), Borrow(Ref('?0, Not))
} }
"#, "#,
); );
@ -2123,7 +2123,7 @@ impl Foo {
use core::mem::ManuallyDrop; use core::mem::ManuallyDrop;
fn test() { fn test() {
ManuallyDrop::new(Foo).foo(); ManuallyDrop::new(Foo).foo();
//^^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('?6, Not)) //^^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('?0, Not))
} }
"#, "#,
); );

View file

@ -362,12 +362,12 @@ fn diverging_expression_3_break() {
140..141 'x': u32 140..141 'x': u32
149..175 '{ for ...; }; }': u32 149..175 '{ for ...; }; }': u32
151..172 'for a ...eak; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter 151..172 'for a ...eak; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
151..172 'for a ...eak; }': {unknown} 151..172 'for a ...eak; }': <{unknown} as IntoIterator>::IntoIter
151..172 'for a ...eak; }': ! 151..172 'for a ...eak; }': !
151..172 'for a ...eak; }': {unknown} 151..172 'for a ...eak; }': <{unknown} as IntoIterator>::IntoIter
151..172 'for a ...eak; }': &'? mut {unknown} 151..172 'for a ...eak; }': &'? mut <{unknown} as IntoIterator>::IntoIter
151..172 'for a ...eak; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 151..172 'for a ...eak; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
151..172 'for a ...eak; }': Option<{unknown}> 151..172 'for a ...eak; }': Option<<{unknown} as Iterator>::Item>
151..172 'for a ...eak; }': () 151..172 'for a ...eak; }': ()
151..172 'for a ...eak; }': () 151..172 'for a ...eak; }': ()
151..172 'for a ...eak; }': () 151..172 'for a ...eak; }': ()
@ -379,12 +379,12 @@ fn diverging_expression_3_break() {
226..227 'x': u32 226..227 'x': u32
235..253 '{ for ... {}; }': u32 235..253 '{ for ... {}; }': u32
237..250 'for a in b {}': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter 237..250 'for a in b {}': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
237..250 'for a in b {}': {unknown} 237..250 'for a in b {}': <{unknown} as IntoIterator>::IntoIter
237..250 'for a in b {}': ! 237..250 'for a in b {}': !
237..250 'for a in b {}': {unknown} 237..250 'for a in b {}': <{unknown} as IntoIterator>::IntoIter
237..250 'for a in b {}': &'? mut {unknown} 237..250 'for a in b {}': &'? mut <{unknown} as IntoIterator>::IntoIter
237..250 'for a in b {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 237..250 'for a in b {}': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
237..250 'for a in b {}': Option<{unknown}> 237..250 'for a in b {}': Option<<{unknown} as Iterator>::Item>
237..250 'for a in b {}': () 237..250 'for a in b {}': ()
237..250 'for a in b {}': () 237..250 'for a in b {}': ()
237..250 'for a in b {}': () 237..250 'for a in b {}': ()
@ -395,12 +395,12 @@ fn diverging_expression_3_break() {
304..305 'x': u32 304..305 'x': u32
313..340 '{ for ...; }; }': u32 313..340 '{ for ...; }; }': u32
315..337 'for a ...urn; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter 315..337 'for a ...urn; }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
315..337 'for a ...urn; }': {unknown} 315..337 'for a ...urn; }': <{unknown} as IntoIterator>::IntoIter
315..337 'for a ...urn; }': ! 315..337 'for a ...urn; }': !
315..337 'for a ...urn; }': {unknown} 315..337 'for a ...urn; }': <{unknown} as IntoIterator>::IntoIter
315..337 'for a ...urn; }': &'? mut {unknown} 315..337 'for a ...urn; }': &'? mut <{unknown} as IntoIterator>::IntoIter
315..337 'for a ...urn; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 315..337 'for a ...urn; }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
315..337 'for a ...urn; }': Option<{unknown}> 315..337 'for a ...urn; }': Option<<{unknown} as Iterator>::Item>
315..337 'for a ...urn; }': () 315..337 'for a ...urn; }': ()
315..337 'for a ...urn; }': () 315..337 'for a ...urn; }': ()
315..337 'for a ...urn; }': () 315..337 'for a ...urn; }': ()

View file

@ -134,6 +134,9 @@ static ALIAS: AliasTy = {
"#, "#,
); );
// FIXME(next-solver): This should emit type mismatch error but leaving it for now
// as we should fully migrate into next-solver without chalk-ir and TAIT should be
// reworked on r-a to handle `#[define_opaque(T)]`
check_infer_with_mismatches( check_infer_with_mismatches(
r#" r#"
trait Trait {} trait Trait {}
@ -155,7 +158,6 @@ static ALIAS: i32 = {
191..193 '_a': impl Trait + ?Sized 191..193 '_a': impl Trait + ?Sized
205..211 'Struct': Struct 205..211 'Struct': Struct
217..218 '5': i32 217..218 '5': i32
205..211: expected impl Trait + ?Sized, got Struct
"#]], "#]],
) )
} }

View file

@ -48,12 +48,12 @@ fn infer_pattern() {
83..84 '1': i32 83..84 '1': i32
86..93 '"hello"': &'static str 86..93 '"hello"': &'static str
101..151 'for (e... }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter 101..151 'for (e... }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
101..151 'for (e... }': {unknown} 101..151 'for (e... }': <{unknown} as IntoIterator>::IntoIter
101..151 'for (e... }': ! 101..151 'for (e... }': !
101..151 'for (e... }': {unknown} 101..151 'for (e... }': <{unknown} as IntoIterator>::IntoIter
101..151 'for (e... }': &'? mut {unknown} 101..151 'for (e... }': &'? mut <{unknown} as IntoIterator>::IntoIter
101..151 'for (e... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 101..151 'for (e... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
101..151 'for (e... }': Option<({unknown}, {unknown})> 101..151 'for (e... }': Option<<{unknown} as Iterator>::Item>
101..151 'for (e... }': () 101..151 'for (e... }': ()
101..151 'for (e... }': () 101..151 'for (e... }': ()
101..151 'for (e... }': () 101..151 'for (e... }': ()
@ -719,28 +719,28 @@ fn test() {
51..58 'loop {}': ! 51..58 'loop {}': !
56..58 '{}': () 56..58 '{}': ()
72..171 '{ ... x); }': () 72..171 '{ ... x); }': ()
78..81 'foo': fn foo<&'? (i32, &'? str), i32, impl FnOnce(&'? (i32, &'? str)) -> i32>(&'? (i32, &'? str), impl FnOnce(&'? (i32, &'? str)) -> i32) -> i32 78..81 'foo': fn foo<&'? (i32, &'static str), i32, impl FnOnce(&'? (i32, &'static str)) -> i32>(&'? (i32, &'static str), impl FnOnce(&'? (i32, &'static str)) -> i32) -> i32
78..105 'foo(&(...y)| x)': i32 78..105 'foo(&(...y)| x)': i32
82..91 '&(1, "a")': &'? (i32, &'static str) 82..91 '&(1, "a")': &'? (i32, &'static str)
83..91 '(1, "a")': (i32, &'static str) 83..91 '(1, "a")': (i32, &'static str)
84..85 '1': i32 84..85 '1': i32
87..90 '"a"': &'static str 87..90 '"a"': &'static str
93..104 '|&(x, y)| x': impl FnOnce(&'? (i32, &'? str)) -> i32 93..104 '|&(x, y)| x': impl FnOnce(&'? (i32, &'static str)) -> i32
94..101 '&(x, y)': &'? (i32, &'? str) 94..101 '&(x, y)': &'? (i32, &'static str)
95..101 '(x, y)': (i32, &'? str) 95..101 '(x, y)': (i32, &'static str)
96..97 'x': i32 96..97 'x': i32
99..100 'y': &'? str 99..100 'y': &'static str
103..104 'x': i32 103..104 'x': i32
142..145 'foo': fn foo<&'? (i32, &'? str), &'? i32, impl FnOnce(&'? (i32, &'? str)) -> &'? i32>(&'? (i32, &'? str), impl FnOnce(&'? (i32, &'? str)) -> &'? i32) -> &'? i32 142..145 'foo': fn foo<&'? (i32, &'static str), &'? i32, impl FnOnce(&'? (i32, &'static str)) -> &'? i32>(&'? (i32, &'static str), impl FnOnce(&'? (i32, &'static str)) -> &'? i32) -> &'? i32
142..168 'foo(&(...y)| x)': &'? i32 142..168 'foo(&(...y)| x)': &'? i32
146..155 '&(1, "a")': &'? (i32, &'static str) 146..155 '&(1, "a")': &'? (i32, &'static str)
147..155 '(1, "a")': (i32, &'static str) 147..155 '(1, "a")': (i32, &'static str)
148..149 '1': i32 148..149 '1': i32
151..154 '"a"': &'static str 151..154 '"a"': &'static str
157..167 '|(x, y)| x': impl FnOnce(&'? (i32, &'? str)) -> &'? i32 157..167 '|(x, y)| x': impl FnOnce(&'? (i32, &'static str)) -> &'? i32
158..164 '(x, y)': (i32, &'? str) 158..164 '(x, y)': (i32, &'static str)
159..160 'x': &'? i32 159..160 'x': &'? i32
162..163 'y': &'? &'? str 162..163 'y': &'? &'static str
166..167 'x': &'? i32 166..167 'x': &'? i32
"#]], "#]],
); );

View file

@ -268,12 +268,12 @@ fn infer_std_crash_5() {
expect![[r#" expect![[r#"
26..322 '{ ... } }': () 26..322 '{ ... } }': ()
32..320 'for co... }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter 32..320 'for co... }': fn into_iter<{unknown}>({unknown}) -> <{unknown} as IntoIterator>::IntoIter
32..320 'for co... }': {unknown} 32..320 'for co... }': <{unknown} as IntoIterator>::IntoIter
32..320 'for co... }': ! 32..320 'for co... }': !
32..320 'for co... }': {unknown} 32..320 'for co... }': <{unknown} as IntoIterator>::IntoIter
32..320 'for co... }': &'? mut {unknown} 32..320 'for co... }': &'? mut <{unknown} as IntoIterator>::IntoIter
32..320 'for co... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 32..320 'for co... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
32..320 'for co... }': Option<{unknown}> 32..320 'for co... }': Option<<{unknown} as Iterator>::Item>
32..320 'for co... }': () 32..320 'for co... }': ()
32..320 'for co... }': () 32..320 'for co... }': ()
32..320 'for co... }': () 32..320 'for co... }': ()
@ -628,7 +628,7 @@ fn issue_4053_diesel_where_clauses() {
65..69 'self': Self 65..69 'self': Self
267..271 'self': Self 267..271 'self': Self
466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> 466..470 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
488..522 '{ ... }': () 488..522 '{ ... }': <SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> as BoxedDsl<DB>>::Output
498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}> 498..502 'self': SelectStatement<F, S, D, W, O, LOf, {unknown}, {unknown}>
498..508 'self.order': O 498..508 'self.order': O
498..515 'self.o...into()': dyn QueryFragment<DB> + '? 498..515 'self.o...into()': dyn QueryFragment<DB> + '?
@ -1248,7 +1248,7 @@ fn test() {
16..66 'for _ ... }': {unknown} 16..66 'for _ ... }': {unknown}
16..66 'for _ ... }': &'? mut {unknown} 16..66 'for _ ... }': &'? mut {unknown}
16..66 'for _ ... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item> 16..66 'for _ ... }': fn next<{unknown}>(&'? mut {unknown}) -> Option<<{unknown} as Iterator>::Item>
16..66 'for _ ... }': Option<{unknown}> 16..66 'for _ ... }': Option<<{unknown} as Iterator>::Item>
16..66 'for _ ... }': () 16..66 'for _ ... }': ()
16..66 'for _ ... }': () 16..66 'for _ ... }': ()
16..66 'for _ ... }': () 16..66 'for _ ... }': ()

View file

@ -20,7 +20,7 @@ impl<'a> IntoIterator for &'a Grid {
"#, "#,
expect![[r#" expect![[r#"
150..154 'self': &'a Grid 150..154 'self': &'a Grid
174..181 '{ }': impl Iterator<Item = &'a ()> 174..181 '{ }': impl Iterator<Item = &'? ()>
"#]], "#]],
); );
} }

View file

@ -1954,6 +1954,8 @@ fn closure_return_inferred() {
); );
} }
// FIXME(next-solver): `&'? str` in 231..262 seems suspicious.
// Should revisit this once we fully migrated into next-solver without chalk-ir.
#[test] #[test]
fn coroutine_types_inferred() { fn coroutine_types_inferred() {
check_infer( check_infer(
@ -1998,7 +2000,7 @@ fn test() {
225..360 'match ... }': () 225..360 'match ... }': ()
231..239 'Pin::new': fn new<&'? mut |usize| yields i64 -> &'static str>(&'? mut |usize| yields i64 -> &'static str) -> Pin<&'? mut |usize| yields i64 -> &'static str> 231..239 'Pin::new': fn new<&'? mut |usize| yields i64 -> &'static str>(&'? mut |usize| yields i64 -> &'static str) -> Pin<&'? mut |usize| yields i64 -> &'static str>
231..247 'Pin::n...mut g)': Pin<&'? mut |usize| yields i64 -> &'static str> 231..247 'Pin::n...mut g)': Pin<&'? mut |usize| yields i64 -> &'static str>
231..262 'Pin::n...usize)': CoroutineState<i64, &'static str> 231..262 'Pin::n...usize)': CoroutineState<i64, &'? str>
240..246 '&mut g': &'? mut |usize| yields i64 -> &'static str 240..246 '&mut g': &'? mut |usize| yields i64 -> &'static str
245..246 'g': |usize| yields i64 -> &'static str 245..246 'g': |usize| yields i64 -> &'static str
255..261 '0usize': usize 255..261 '0usize': usize

View file

@ -1,6 +1,8 @@
use cov_mark::check; use cov_mark::check;
use expect_test::expect; use expect_test::expect;
use crate::tests::infer_with_mismatches;
use super::{check, check_infer, check_infer_with_mismatches, check_no_mismatches, check_types}; use super::{check, check_infer, check_infer_with_mismatches, check_no_mismatches, check_types};
#[test] #[test]
@ -2460,7 +2462,7 @@ use core::ops::Index;
type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key;
pub trait UnificationStoreBase: Index<Output = Key<Self>> { pub trait UnificationStoreBase: Index<usize, Output = Key<Self>> {
type Key; type Key;
fn len(&self) -> usize; fn len(&self) -> usize;
@ -3634,8 +3636,7 @@ fn minimized() {
#[test] #[test]
fn no_builtin_binop_expectation_for_general_ty_var() { fn no_builtin_binop_expectation_for_general_ty_var() {
// FIXME: Ideally type mismatch should be reported on `take_u32(42 - p)`. infer_with_mismatches(
check_types(
r#" r#"
//- minicore: add //- minicore: add
use core::ops::Add; use core::ops::Add;
@ -3659,6 +3660,7 @@ fn minimized() {
take_u32(42 + p); take_u32(42 + p);
} }
"#, "#,
true,
); );
} }
@ -4188,6 +4190,8 @@ fn g<P: PointerFamily>(p: <P as PointerFamily>::Pointer<i32>) {
); );
} }
// FIXME(next-solver): Was `&'a T` but now getting error lifetime.
// This might be fixed once we migrate into next-solver fully without chalk-ir in lowering.
#[test] #[test]
fn gats_with_impl_trait() { fn gats_with_impl_trait() {
// FIXME: the last function (`fn i()`) is not valid Rust as of this writing because you cannot // FIXME: the last function (`fn i()`) is not valid Rust as of this writing because you cannot
@ -4211,21 +4215,21 @@ fn f<T>(v: impl Trait) {
} }
fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) { fn g<'a, T: 'a>(v: impl Trait<Assoc<T> = &'a T>) {
let a = v.get::<T>(); let a = v.get::<T>();
//^ &'a T //^ &'? T
let a = v.get::<()>(); let a = v.get::<()>();
//^ <impl Trait<Assoc<T> = &'a T> as Trait>::Assoc<()> //^ <impl Trait<Assoc<T> = &'a T> as Trait>::Assoc<()>
} }
fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) { fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) {
let a = v.get::<i32>(); let a = v.get::<i32>();
//^ &'a i32 //^ &'? i32
let a = v.get::<i64>(); let a = v.get::<i64>();
//^ &'a i64 //^ &'? i64
} }
fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) { fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) {
let a = v.get::<i32>(); let a = v.get::<i32>();
//^ &'a i32 //^ &'? i32
let a = v.get::<i64>(); let a = v.get::<i64>();
//^ &'a i64 //^ &'? i64
} }
"#, "#,
); );
@ -4255,8 +4259,8 @@ fn f<'a>(v: &dyn Trait<Assoc<i32> = &'a i32>) {
127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?) 127..128 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?)
164..195 '{ ...f(); }': () 164..195 '{ ...f(); }': ()
170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?) 170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?)
170..184 'v.get::<i32>()': {unknown} 170..184 'v.get::<i32>()': <dyn Trait<Assoc<i32> = &'a i32> + '? as Trait>::Assoc<i32>
170..192 'v.get:...eref()': &'? {unknown} 170..192 'v.get:...eref()': {unknown}
"#]], "#]],
); );
} }
@ -4931,6 +4935,8 @@ fn main() {
); );
} }
// FIXME(next-solver): Was `<D as Deserializer<'de>>::Error` but now getting error lifetime.
// This might be fixed once we migrate into next-solver fully without chalk-ir in lowering.
#[test] #[test]
fn new_solver_crash_1() { fn new_solver_crash_1() {
check_infer( check_infer(
@ -4947,7 +4953,7 @@ where
"#, "#,
expect![[r#" expect![[r#"
84..86 'de': D 84..86 'de': D
135..138 '{ }': <D as Deserializer<'de>>::Error 135..138 '{ }': <D as Deserializer<'?>>::Error
"#]], "#]],
); );
} }

View file

@ -21,9 +21,17 @@ use stdx::never;
use triomphe::Arc; use triomphe::Arc;
use crate::{ use crate::{
db::HirDatabase, infer::unify::InferenceTable, next_solver::{ AliasEq, AliasTy, Canonical, DomainGoal, Goal, InEnvironment, Interner, ProjectionTy,
infer::{DbInternerInferExt, InferCtxt}, mapping::{convert_canonical_args_for_result, ChalkToNextSolver}, util::mini_canonicalize, DbInterner, GenericArg, Predicate, SolverContext, Span ProjectionTyExt, TraitRefExt, Ty, TyKind, TypeFlags, WhereClause,
}, utils::UnevaluatedConstEvaluatorFolder, AliasEq, AliasTy, Canonical, DomainGoal, Goal, InEnvironment, Interner, ProjectionTy, ProjectionTyExt, TraitRefExt, Ty, TyKind, TypeFlags, WhereClause db::HirDatabase,
infer::unify::InferenceTable,
next_solver::{
DbInterner, GenericArg, Predicate, SolverContext, Span,
infer::{DbInternerInferExt, InferCtxt},
mapping::{ChalkToNextSolver, convert_canonical_args_for_result},
util::mini_canonicalize,
},
utils::UnevaluatedConstEvaluatorFolder,
}; };
/// A set of clauses that we assume to be true. E.g. if we are inside this function: /// A set of clauses that we assume to be true. E.g. if we are inside this function:
@ -282,30 +290,18 @@ pub fn next_trait_solve(
} }
} }
pub fn next_trait_solve_canonical<'db>( pub fn next_trait_solve_canonical_in_ctxt<'db>(
db: &'db dyn HirDatabase, infer_ctxt: &InferCtxt<'db>,
krate: Crate,
block: Option<BlockId>,
goal: crate::next_solver::Canonical<'db, crate::next_solver::Goal<'db, Predicate<'db>>>, goal: crate::next_solver::Canonical<'db, crate::next_solver::Goal<'db, Predicate<'db>>>,
) -> NextTraitSolveResult { ) -> NextTraitSolveResult {
// FIXME: should use analysis_in_body, but that needs GenericDefId::Block let context = SolverContext(infer_ctxt.clone());
let context = SolverContext(
DbInterner::new_with(db, Some(krate), block)
.infer_ctxt()
.build(TypingMode::non_body_analysis()),
);
tracing::info!(?goal); tracing::info!(?goal);
let (goal, var_values) = let (goal, var_values) = context.instantiate_canonical(&goal);
context.instantiate_canonical(&goal);
tracing::info!(?var_values); tracing::info!(?var_values);
let res = context.evaluate_root_goal( let res = context.evaluate_root_goal(goal, Span::dummy(), None);
goal.clone(),
Span::dummy(),
None
);
let vars = let vars =
var_values.var_values.iter().map(|g| context.0.resolve_vars_if_possible(g)).collect(); var_values.var_values.iter().map(|g| context.0.resolve_vars_if_possible(g)).collect();
@ -318,13 +314,10 @@ pub fn next_trait_solve_canonical<'db>(
match res { match res {
Err(_) => NextTraitSolveResult::NoSolution, Err(_) => NextTraitSolveResult::NoSolution,
Ok((_, Certainty::Yes, args)) => NextTraitSolveResult::Certain( Ok((_, Certainty::Yes, args)) => NextTraitSolveResult::Certain(
convert_canonical_args_for_result(DbInterner::new_with(db, Some(krate), block), args) convert_canonical_args_for_result(infer_ctxt.interner, args),
), ),
Ok((_, Certainty::Maybe(_), args)) => { Ok((_, Certainty::Maybe(_), args)) => {
let subst = convert_canonical_args_for_result( let subst = convert_canonical_args_for_result(infer_ctxt.interner, args);
DbInterner::new_with(db, Some(krate), block),
args,
);
NextTraitSolveResult::Uncertain(chalk_ir::Canonical { NextTraitSolveResult::Uncertain(chalk_ir::Canonical {
binders: subst.binders, binders: subst.binders,
value: subst.value.subst, value: subst.value.subst,

View file

@ -14,7 +14,11 @@ use hir_expand::{
mod_path::{ModPath, PathKind}, mod_path::{ModPath, PathKind},
name::Name, name::Name,
}; };
use hir_ty::{db::HirDatabase, method_resolution, next_solver::{mapping::ChalkToNextSolver, DbInterner}}; use hir_ty::{
db::HirDatabase,
method_resolution,
next_solver::{DbInterner, mapping::ChalkToNextSolver},
};
use crate::{ use crate::{
Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl, Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, DocLinkDef, Enum, ExternCrateDecl,
@ -271,7 +275,11 @@ fn resolve_impl_trait_item<'db>(
// //
// FIXME: resolve type aliases (which are not yielded by iterate_path_candidates) // FIXME: resolve type aliases (which are not yielded by iterate_path_candidates)
_ = method_resolution::iterate_path_candidates( _ = method_resolution::iterate_path_candidates(
&canonical.to_nextsolver(DbInterner::new_with(db, Some(environment.krate), environment.block)), &canonical.to_nextsolver(DbInterner::new_with(
db,
Some(environment.krate),
environment.block,
)),
db, db,
environment, environment,
&traits_in_scope, &traits_in_scope,

View file

@ -10,7 +10,8 @@ use crate::{
fn check_expected_type_and_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) { fn check_expected_type_and_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
let (db, pos) = position(ra_fixture); let (db, pos) = position(ra_fixture);
let config = TEST_CONFIG; let config = TEST_CONFIG;
let (completion_context, _analysis) = CompletionContext::new(&db, pos, &config).unwrap(); let (completion_context, _analysis) =
salsa::attach(&db, || CompletionContext::new(&db, pos, &config).unwrap());
let ty = completion_context let ty = completion_context
.expected_type .expected_type

View file

@ -526,8 +526,7 @@ fn main() {
fn run(_t: Rate<5>) { fn run(_t: Rate<5>) {
} }
fn main() { fn main() {
run(f()) // FIXME: remove this error run(f())
//^^^ error: expected Rate<5>, found Rate<_>
} }
"#, "#,
); );

View file

@ -2,7 +2,10 @@ use expect_test::{Expect, expect};
use hir::{FilePosition, FileRange}; use hir::{FilePosition, FileRange};
use ide_db::{ use ide_db::{
EditionedFileId, FxHashSet, EditionedFileId, FxHashSet,
base_db::{SourceDatabase, salsa::Durability}, base_db::{
SourceDatabase,
salsa::{self, Durability},
},
}; };
use test_utils::RangeOrOffset; use test_utils::RangeOrOffset;
use triomphe::Arc; use triomphe::Arc;
@ -116,7 +119,7 @@ fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) {
let rule: SsrRule = rule.parse().unwrap(); let rule: SsrRule = rule.parse().unwrap();
match_finder.add_rule(rule).unwrap(); match_finder.add_rule(rule).unwrap();
} }
let edits = match_finder.edits(); let edits = salsa::attach(&db, || match_finder.edits());
if edits.is_empty() { if edits.is_empty() {
panic!("No edits were made"); panic!("No edits were made");
} }
@ -155,8 +158,12 @@ fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
) )
.unwrap(); .unwrap();
match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap(); match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
let matched_strings: Vec<String> = let matched_strings: Vec<String> = salsa::attach(&db, || match_finder.matches())
match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect(); .flattened()
.matches
.iter()
.map(|m| m.matched_text())
.collect();
if matched_strings != expected && !expected.is_empty() { if matched_strings != expected && !expected.is_empty() {
print_match_debug_info(&match_finder, position.file_id, expected[0]); print_match_debug_info(&match_finder, position.file_id, expected[0]);
} }

View file

@ -47,7 +47,8 @@ fn check_rewrite(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect
let (analysis, position) = fixture::position(ra_fixture); let (analysis, position) = fixture::position(ra_fixture);
let sema = &Semantics::new(&analysis.db); let sema = &Semantics::new(&analysis.db);
let (cursor_def, docs, range) = def_under_cursor(sema, &position); let (cursor_def, docs, range) = def_under_cursor(sema, &position);
let res = rewrite_links(sema.db, docs.as_str(), cursor_def, Some(range)); let res =
salsa::attach(sema.db, || rewrite_links(sema.db, docs.as_str(), cursor_def, Some(range)));
expect.assert_eq(&res) expect.assert_eq(&res)
} }