mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-29 10:58:02 +00:00
Fix failing tests and fill-in missing details
This commit is contained in:
parent
d24e8c1d38
commit
4a8bc8db38
36 changed files with 917 additions and 1431 deletions
|
|
@ -13,7 +13,7 @@ use triomphe::Arc;
|
|||
|
||||
use crate::{
|
||||
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;
|
||||
|
|
@ -98,7 +98,7 @@ impl<'table, 'db> Autoderef<'table, 'db> {
|
|||
explicit: bool,
|
||||
use_receiver_trait: bool,
|
||||
) -> 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 }
|
||||
}
|
||||
|
||||
|
|
@ -114,7 +114,7 @@ impl<'table, 'db> Autoderef<'table, 'db, usize> {
|
|||
explicit: bool,
|
||||
use_receiver_trait: bool,
|
||||
) -> 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 }
|
||||
}
|
||||
}
|
||||
|
|
@ -160,7 +160,7 @@ pub(crate) fn autoderef_step(
|
|||
use_receiver_trait: bool,
|
||||
) -> Option<(AutoderefKind, Ty)> {
|
||||
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 {
|
||||
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,
|
||||
) -> Option<Ty> {
|
||||
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
|
||||
return None;
|
||||
}
|
||||
|
|
@ -229,8 +229,8 @@ pub(crate) fn deref_by_trait(
|
|||
return None;
|
||||
}
|
||||
|
||||
table.register_obligation(implements_goal);
|
||||
table.register_obligation(implements_goal.to_nextsolver(table.interner));
|
||||
|
||||
let result = table.normalize_projection_ty(projection);
|
||||
Some(table.resolve_ty_shallow(&result))
|
||||
Some(table.structurally_resolve_type(&result))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -245,10 +245,7 @@ impl TyExt for Ty {
|
|||
}
|
||||
|
||||
fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
|
||||
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) => {
|
||||
let handle_async_block_type_impl_trait = |def: DefWithBodyId| {
|
||||
let krate = def.module(db).krate();
|
||||
if let Some(future_trait) = LangItem::Future.resolve_trait(db, krate) {
|
||||
// This is only used by type walking.
|
||||
|
|
@ -265,6 +262,13 @@ impl TyExt for Ty {
|
|||
} else {
|
||||
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) => {
|
||||
db.return_type_impl_traits(func).map(|it| {
|
||||
|
|
@ -299,8 +303,9 @@ impl TyExt for Ty {
|
|||
data.substitute(Interner, &opaque_ty.substitution)
|
||||
})
|
||||
}
|
||||
// It always has an parameter for Future::Output type.
|
||||
ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
|
||||
ImplTraitId::AsyncBlockTypeImplTrait(def, _) => {
|
||||
return handle_async_block_type_impl_trait(def);
|
||||
}
|
||||
};
|
||||
|
||||
predicates.map(|it| it.into_value_and_skipped_binders().0)
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ use crate::{
|
|||
next_solver::{
|
||||
Const, ConstBytes, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
|
||||
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),
|
||||
_ => 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);
|
||||
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),
|
||||
_ => 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);
|
||||
try_const_isize(db, &ec)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,10 +55,9 @@ use stdx::{always, never};
|
|||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, Goal, ImplTraitId,
|
||||
ImplTraitIdx, InEnvironment, IncorrectGenericsLenKind, Interner, Lifetime, OpaqueTyId,
|
||||
ParamLoweringMode, PathLoweringDiagnostic, ProjectionTy, Substitution, TraitEnvironment, Ty,
|
||||
TyBuilder, TyExt,
|
||||
AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, ImplTraitId, ImplTraitIdx,
|
||||
IncorrectGenericsLenKind, Interner, Lifetime, OpaqueTyId, ParamLoweringMode,
|
||||
PathLoweringDiagnostic, ProjectionTy, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt,
|
||||
db::HirDatabase,
|
||||
fold_tys,
|
||||
generics::Generics,
|
||||
|
|
@ -70,6 +69,7 @@ use crate::{
|
|||
},
|
||||
lower::{ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic},
|
||||
mir::MirSpan,
|
||||
next_solver::{self, mapping::ChalkToNextSolver},
|
||||
static_lifetime, to_assoc_type_id,
|
||||
traits::FnTrait,
|
||||
utils::UnevaluatedConstEvaluatorFolder,
|
||||
|
|
@ -182,13 +182,13 @@ impl BindingMode {
|
|||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct InferOk<T> {
|
||||
pub(crate) struct InferOk<'db, T> {
|
||||
value: T,
|
||||
goals: Vec<InEnvironment<Goal>>,
|
||||
goals: Vec<next_solver::Goal<'db, next_solver::Predicate<'db>>>,
|
||||
}
|
||||
|
||||
impl<T> InferOk<T> {
|
||||
fn map<U>(self, f: impl FnOnce(T) -> U) -> InferOk<U> {
|
||||
impl<'db, T> InferOk<'db, T> {
|
||||
fn map<U>(self, f: impl FnOnce(T) -> U) -> InferOk<'db, U> {
|
||||
InferOk { value: f(self.value), goals: self.goals }
|
||||
}
|
||||
}
|
||||
|
|
@ -203,7 +203,7 @@ pub enum InferenceTyDiagnosticSource {
|
|||
|
||||
#[derive(Debug)]
|
||||
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)]
|
||||
pub enum InferenceDiagnostic {
|
||||
|
|
@ -832,6 +832,7 @@ impl<'db> InferenceContext<'db> {
|
|||
coercion_casts,
|
||||
diagnostics: _,
|
||||
} = &mut result;
|
||||
table.resolve_obligations_as_possible();
|
||||
table.fallback_if_possible();
|
||||
|
||||
// Comment from rustc:
|
||||
|
|
@ -1480,7 +1481,8 @@ impl<'db> InferenceContext<'db> {
|
|||
}
|
||||
|
||||
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 {
|
||||
|
|
@ -1746,7 +1748,7 @@ impl<'db> InferenceContext<'db> {
|
|||
|
||||
ty = self.table.insert_type_vars(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() {
|
||||
return (self.err_ty(), None);
|
||||
}
|
||||
|
|
@ -1817,7 +1819,7 @@ impl<'db> InferenceContext<'db> {
|
|||
let ty = match ty.kind(Interner) {
|
||||
TyKind::Alias(AliasTy::Projection(proj_ty)) => {
|
||||
let ty = self.table.normalize_projection_ty(proj_ty.clone());
|
||||
self.table.resolve_ty_shallow(&ty)
|
||||
self.table.structurally_resolve_type(&ty)
|
||||
}
|
||||
_ => ty,
|
||||
};
|
||||
|
|
@ -2047,7 +2049,7 @@ impl Expectation {
|
|||
fn adjust_for_branches(&self, table: &mut unify::InferenceTable<'_>) -> Expectation {
|
||||
match self {
|
||||
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) }
|
||||
}
|
||||
Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()),
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ use crate::{
|
|||
infer::{BreakableKind, CoerceMany, Diverges, coerce::CoerceNever},
|
||||
make_binders,
|
||||
mir::{BorrowKind, MirSpan, MutBorrowKind, ProjectionElem},
|
||||
next_solver::mapping::ChalkToNextSolver,
|
||||
to_assoc_type_id,
|
||||
traits::FnTrait,
|
||||
utils::{self, elaborate_clause_supertraits},
|
||||
|
|
@ -437,10 +438,10 @@ impl InferenceContext<'_> {
|
|||
associated_ty_id: to_assoc_type_id(future_output),
|
||||
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() }
|
||||
.cast(Interner),
|
||||
);
|
||||
.cast(Interner);
|
||||
self.table.register_obligation(goal.to_nextsolver(self.table.interner));
|
||||
|
||||
Some(FnSubst(Substitution::from_iter(
|
||||
Interner,
|
||||
|
|
@ -568,7 +569,10 @@ impl InferenceContext<'_> {
|
|||
let supplied_sig = self.supplied_sig_of_closure(body, ret_type, arg_types, closure_kind);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,24 +8,27 @@
|
|||
use std::iter;
|
||||
|
||||
use chalk_ir::{BoundVar, Mutability, TyKind, TyVariableKind, cast::Cast};
|
||||
use hir_def::{
|
||||
hir::ExprId,
|
||||
lang_item::LangItem,
|
||||
};
|
||||
use hir_def::{hir::ExprId, lang_item::LangItem};
|
||||
use rustc_type_ir::solve::Certainty;
|
||||
use stdx::always;
|
||||
use triomphe::Arc;
|
||||
|
||||
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,
|
||||
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;
|
||||
|
||||
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`.
|
||||
fn identity(_: Ty) -> Vec<Adjustment> {
|
||||
|
|
@ -37,11 +40,11 @@ fn simple(kind: Adjust) -> impl FnOnce(Ty) -> Vec<Adjustment> {
|
|||
}
|
||||
|
||||
/// This always returns `Ok(...)`.
|
||||
fn success(
|
||||
fn success<'db>(
|
||||
adj: Vec<Adjustment>,
|
||||
target: Ty,
|
||||
goals: Vec<InEnvironment<Goal>>,
|
||||
) -> CoerceResult {
|
||||
goals: Vec<next_solver::Goal<'db, next_solver::Predicate<'db>>>,
|
||||
) -> CoerceResult<'db> {
|
||||
Ok(InferOk { goals, value: (adj, target) })
|
||||
}
|
||||
|
||||
|
|
@ -107,9 +110,9 @@ impl CoerceMany {
|
|||
/// coerce both to function pointers;
|
||||
/// - if we were concerned with lifetime subtyping, we'd need to look for a
|
||||
/// least upper bound.
|
||||
pub(super) fn coerce(
|
||||
pub(super) fn coerce<'db>(
|
||||
&mut self,
|
||||
ctx: &mut InferenceContext<'_>,
|
||||
ctx: &mut InferenceContext<'db>,
|
||||
expr: Option<ExprId>,
|
||||
expr_ty: &Ty,
|
||||
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
|
||||
/// using "implicit coercion rules" if needed.
|
||||
pub(crate) fn coerce(
|
||||
|
|
@ -285,8 +288,8 @@ impl InferenceTable<'_> {
|
|||
to_ty: &Ty,
|
||||
coerce_never: CoerceNever,
|
||||
) -> Result<(Vec<Adjustment>, Ty), TypeError> {
|
||||
let from_ty = self.resolve_ty_shallow(from_ty);
|
||||
let to_ty = self.resolve_ty_shallow(to_ty);
|
||||
let from_ty = self.structurally_resolve_type(from_ty);
|
||||
let to_ty = self.structurally_resolve_type(to_ty);
|
||||
match self.coerce_inner(from_ty, &to_ty, coerce_never) {
|
||||
Ok(InferOk { value: (adjustments, ty), 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 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 {
|
||||
// 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.
|
||||
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
|
||||
F: FnOnce(Ty) -> Vec<Adjustment>,
|
||||
{
|
||||
|
|
@ -378,7 +386,7 @@ impl InferenceTable<'_> {
|
|||
.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) {
|
||||
TyKind::Ref(mt, _, ty) => (true, mt, ty),
|
||||
TyKind::Raw(mt, ty) => (false, mt, ty),
|
||||
|
|
@ -420,7 +428,7 @@ impl InferenceTable<'_> {
|
|||
to_ty: &Ty,
|
||||
to_mt: Mutability,
|
||||
to_lt: &Lifetime,
|
||||
) -> CoerceResult {
|
||||
) -> CoerceResult<'db> {
|
||||
let (_from_lt, from_mt) = match from_ty.kind(Interner) {
|
||||
TyKind::Ref(mt, lt, _) => {
|
||||
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.
|
||||
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) {
|
||||
TyKind::Function(_) => {
|
||||
let from_sig = from_ty.callable_sig(self.db).expect("FnDef had no sig");
|
||||
|
|
@ -566,7 +574,7 @@ impl InferenceTable<'_> {
|
|||
from_ty: Ty,
|
||||
from_f: &FnPointer,
|
||||
to_ty: &Ty,
|
||||
) -> CoerceResult {
|
||||
) -> CoerceResult<'db> {
|
||||
self.coerce_from_safe_fn(
|
||||
from_ty,
|
||||
from_f,
|
||||
|
|
@ -583,7 +591,7 @@ impl InferenceTable<'_> {
|
|||
to_ty: &Ty,
|
||||
to_unsafe: F,
|
||||
normal: G,
|
||||
) -> CoerceResult
|
||||
) -> CoerceResult<'db>
|
||||
where
|
||||
F: FnOnce(Ty) -> Vec<Adjustment>,
|
||||
G: FnOnce(Ty) -> Vec<Adjustment>,
|
||||
|
|
@ -606,7 +614,7 @@ impl InferenceTable<'_> {
|
|||
from_ty: Ty,
|
||||
from_substs: &Substitution,
|
||||
to_ty: &Ty,
|
||||
) -> CoerceResult {
|
||||
) -> CoerceResult<'db> {
|
||||
match to_ty.kind(Interner) {
|
||||
// if from_substs is non-capturing (FIXME)
|
||||
TyKind::Function(fn_ty) => {
|
||||
|
|
@ -631,7 +639,7 @@ impl InferenceTable<'_> {
|
|||
/// Coerce a type using `from_ty: CoerceUnsized<ty_ty>`
|
||||
///
|
||||
/// 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.
|
||||
// The `CoerceUnsized` trait is special - it is only
|
||||
// possible to write `impl CoerceUnsized<B> for A` where
|
||||
|
|
@ -707,12 +715,9 @@ impl InferenceTable<'_> {
|
|||
|
||||
let goal: Goal = coerce_unsized_tref.cast(Interner);
|
||||
|
||||
self.commit_if_ok(|table| {
|
||||
match table.solve_obligation(goal) {
|
||||
self.commit_if_ok(|table| match table.solve_obligation(goal) {
|
||||
Ok(Certainty::Yes) => Ok(()),
|
||||
Ok(Certainty::Maybe(_)) => Ok(()),
|
||||
Err(_) => Err(TypeError),
|
||||
}
|
||||
_ => Err(TypeError),
|
||||
})?;
|
||||
|
||||
let unsize =
|
||||
|
|
|
|||
|
|
@ -23,9 +23,29 @@ use stdx::always;
|
|||
use syntax::ast::RangeOp;
|
||||
|
||||
use crate::{
|
||||
autoderef::{builtin_deref, deref_by_trait, Autoderef}, consteval, generics::generics, infer::{
|
||||
coerce::{CoerceMany, CoerceNever, CoercionCause}, find_continuable, pat::contains_explicit_ref_binding, BreakableKind
|
||||
}, 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
|
||||
Adjust, Adjustment, AdtId, AutoBorrow, Binders, CallableDefId, CallableSig, DeclContext,
|
||||
DeclOrigin, IncorrectGenericsLenKind, Interner, LifetimeElisionKind, Rawness, Scalar,
|
||||
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::{
|
||||
|
|
@ -383,7 +403,7 @@ impl InferenceContext<'_> {
|
|||
let matchee_diverges = mem::replace(&mut self.diverges, Diverges::Maybe);
|
||||
let mut all_arms_diverge = Diverges::Always;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
@ -633,7 +653,7 @@ impl InferenceContext<'_> {
|
|||
&Expr::Box { expr } => self.infer_expr_box(expr, expected),
|
||||
Expr::UnaryOp { expr, op } => {
|
||||
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
|
||||
match op {
|
||||
UnaryOp::Deref => {
|
||||
|
|
@ -651,7 +671,7 @@ impl InferenceContext<'_> {
|
|||
);
|
||||
}
|
||||
if let Some(derefed) = builtin_deref(self.table.db, &inner_ty, true) {
|
||||
self.resolve_ty_shallow(derefed)
|
||||
self.table.structurally_resolve_type(derefed)
|
||||
} else {
|
||||
deref_by_trait(&mut self.table, inner_ty, false)
|
||||
.unwrap_or_else(|| self.err_ty())
|
||||
|
|
@ -807,10 +827,10 @@ impl InferenceContext<'_> {
|
|||
let index_ty = self.infer_expr(*index, &Expectation::none(), ExprIsRead::Yes);
|
||||
|
||||
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(
|
||||
self.db,
|
||||
self.table.trait_env.clone(),
|
||||
&mut self.table,
|
||||
canonicalized,
|
||||
index_trait,
|
||||
);
|
||||
|
|
@ -983,7 +1003,7 @@ impl InferenceContext<'_> {
|
|||
// allows them to be inferred based on how they are used later in the
|
||||
// function.
|
||||
if is_input {
|
||||
let ty = this.resolve_ty_shallow(&ty);
|
||||
let ty = this.table.structurally_resolve_type(&ty);
|
||||
match ty.kind(Interner) {
|
||||
TyKind::FnDef(def, parameters) => {
|
||||
let fnptr_ty = TyKind::Function(
|
||||
|
|
@ -1405,10 +1425,11 @@ impl InferenceContext<'_> {
|
|||
// 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);
|
||||
self.unify(&builtin_ret, &ret_ty);
|
||||
}
|
||||
|
||||
builtin_ret
|
||||
} else {
|
||||
ret_ty
|
||||
}
|
||||
}
|
||||
|
||||
fn infer_block(
|
||||
&mut self,
|
||||
|
|
@ -1660,7 +1681,8 @@ impl InferenceContext<'_> {
|
|||
None => {
|
||||
// no field found, lets attempt to resolve it like a function so that IDE things
|
||||
// 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(
|
||||
self.db,
|
||||
&canonicalized_receiver,
|
||||
|
|
@ -1806,7 +1828,8 @@ impl InferenceContext<'_> {
|
|||
expected: &Expectation,
|
||||
) -> Ty {
|
||||
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(
|
||||
self.db,
|
||||
|
|
@ -2216,7 +2239,7 @@ impl InferenceContext<'_> {
|
|||
}
|
||||
|
||||
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) {
|
||||
let def: CallableDefId = from_chalk(self.db, *fn_def);
|
||||
let generic_predicates =
|
||||
|
|
@ -2305,9 +2328,9 @@ impl InferenceContext<'_> {
|
|||
|
||||
/// Dereferences a single level of immutable referencing.
|
||||
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) {
|
||||
TyKind::Ref(Mutability::Not, _, inner) => self.resolve_ty_shallow(inner),
|
||||
TyKind::Ref(Mutability::Not, _, inner) => self.table.structurally_resolve_type(inner),
|
||||
_ => ty,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -190,7 +190,7 @@ impl InferenceContext<'_> {
|
|||
subs: &[PatId],
|
||||
decl: Option<DeclContext>,
|
||||
) -> Ty {
|
||||
let expected = self.resolve_ty_shallow(expected);
|
||||
let expected = self.table.structurally_resolve_type(expected);
|
||||
let expectations = match expected.as_tuple() {
|
||||
Some(parameters) => parameters.as_slice(Interner),
|
||||
_ => &[],
|
||||
|
|
@ -238,7 +238,7 @@ impl InferenceContext<'_> {
|
|||
mut default_bm: BindingMode,
|
||||
decl: Option<DeclContext>,
|
||||
) -> 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 {
|
||||
cov_mark::hit!(match_ergonomics_ref);
|
||||
|
|
@ -251,7 +251,7 @@ impl InferenceContext<'_> {
|
|||
let mut pat_adjustments = Vec::new();
|
||||
while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
|
||||
pat_adjustments.push(expected.clone());
|
||||
expected = self.resolve_ty_shallow(inner);
|
||||
expected = self.table.structurally_resolve_type(inner);
|
||||
default_bm = match default_bm {
|
||||
BindingMode::Move => BindingMode::Ref(mutability),
|
||||
BindingMode::Ref(Mutability::Not) => BindingMode::Ref(Mutability::Not),
|
||||
|
|
@ -494,7 +494,7 @@ impl InferenceContext<'_> {
|
|||
default_bm: BindingMode,
|
||||
decl: Option<DeclContext>,
|
||||
) -> 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
|
||||
// allows it. See issue #16609
|
||||
|
|
@ -506,7 +506,7 @@ impl InferenceContext<'_> {
|
|||
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) {
|
||||
TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
|
||||
_ => self.err_ty(),
|
||||
|
|
@ -542,7 +542,7 @@ impl InferenceContext<'_> {
|
|||
if let Expr::Literal(Literal::ByteString(_)) = self.body[expr]
|
||||
&& 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(_)) {
|
||||
let elem_ty = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(Interner);
|
||||
let slice_ty = TyKind::Slice(elem_ty).intern(Interner);
|
||||
|
|
|
|||
|
|
@ -10,7 +10,15 @@ use hir_expand::name::Name;
|
|||
use stdx::never;
|
||||
|
||||
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};
|
||||
|
|
@ -384,7 +392,7 @@ impl InferenceContext<'_> {
|
|||
name: &Name,
|
||||
id: ExprOrPatId,
|
||||
) -> 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() {
|
||||
Some((AdtId::EnumId(e), subst)) => (e, subst),
|
||||
_ => return None,
|
||||
|
|
|
|||
|
|
@ -3,7 +3,8 @@
|
|||
use std::{fmt, mem};
|
||||
|
||||
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 hir_def::{AdtId, lang_item::LangItem};
|
||||
|
|
@ -11,13 +12,36 @@ use hir_expand::name::Name;
|
|||
use intern::sym;
|
||||
use rustc_hash::{FxHashMap, FxHashSet};
|
||||
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 triomphe::Arc;
|
||||
|
||||
use super::{InferOk, InferResult, InferenceContext, TypeError};
|
||||
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> {
|
||||
|
|
@ -38,7 +62,7 @@ impl<'db> InferenceContext<'db> {
|
|||
let pending_obligations = mem::take(&mut self.table.pending_obligations);
|
||||
let obligations = pending_obligations
|
||||
.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)) => {
|
||||
let ty = match clause {
|
||||
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.
|
||||
///
|
||||
/// 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)]
|
||||
pub(crate) struct InferenceTable<'a> {
|
||||
pub(crate) db: &'a dyn HirDatabase,
|
||||
pub(crate) interner: DbInterner<'a>,
|
||||
pub(crate) trait_env: Arc<TraitEnvironment>,
|
||||
pub(crate) tait_coercion_table: Option<FxHashMap<OpaqueTyId, Ty>>,
|
||||
infer_ctxt: InferCtxt<'a>,
|
||||
pub(crate) infer_ctxt: InferCtxt<'a>,
|
||||
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,
|
||||
diverging_tys: FxHashSet<Ty>,
|
||||
pending_obligations: Vec<InEnvironment<Goal>>,
|
||||
pending_obligations: Vec<next_solver::Goal<'a, next_solver::Predicate<'a>>>,
|
||||
}
|
||||
|
||||
impl<'a> InferenceTable<'a> {
|
||||
|
|
@ -234,7 +211,9 @@ impl<'a> InferenceTable<'a> {
|
|||
interner,
|
||||
trait_env,
|
||||
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(),
|
||||
pending_obligations: Vec::new(),
|
||||
}
|
||||
|
|
@ -250,40 +229,55 @@ impl<'a> InferenceTable<'a> {
|
|||
let mut new_tys = FxHashSet::default();
|
||||
for ty in self.diverging_tys.iter() {
|
||||
match ty.kind(Interner) {
|
||||
TyKind::InferenceVar(var, kind) => {
|
||||
match kind {
|
||||
TyKind::InferenceVar(var, kind) => match kind {
|
||||
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() {
|
||||
new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner));
|
||||
}
|
||||
}
|
||||
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() {
|
||||
new_tys.insert(TyKind::InferenceVar(root, *kind).intern(Interner));
|
||||
}
|
||||
}
|
||||
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() {
|
||||
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));
|
||||
}
|
||||
|
||||
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 {
|
||||
return TyKind::Never.intern(Interner);
|
||||
}
|
||||
|
|
@ -295,19 +289,6 @@ impl<'a> InferenceTable<'a> {
|
|||
.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>
|
||||
where
|
||||
T: rustc_type_ir::TypeFoldable<DbInterner<'a>>,
|
||||
|
|
@ -341,7 +322,7 @@ impl<'a> InferenceTable<'a> {
|
|||
self.resolve_ty_shallow(&ty)
|
||||
}
|
||||
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(
|
||||
chalk_ir::TypeFlags::HAS_TY_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 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 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)
|
||||
};
|
||||
let canonical_goal = rustc_type_ir::Canonical {
|
||||
max_universe: canonical_goal.max_universe,
|
||||
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(
|
||||
self.db,
|
||||
self.trait_env.krate,
|
||||
self.trait_env.block,
|
||||
canonical_goal.clone(),
|
||||
let solution = next_trait_solve_canonical_in_ctxt(
|
||||
&self.infer_ctxt,
|
||||
canonical_goal,
|
||||
);
|
||||
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.
|
||||
if canonical_subst.value.subst.len(Interner) != 1 {
|
||||
let subst = self.instantiate_canonical(canonical_subst).subst;
|
||||
if subst.len(Interner) != orig_values.var_values.len() {
|
||||
ty
|
||||
} else {
|
||||
let normalized = canonical_subst.value.subst.as_slice(Interner)
|
||||
[0]
|
||||
.assert_ty_ref(Interner);
|
||||
match normalized.kind(Interner) {
|
||||
TyKind::Alias(AliasTy::Projection(proj_ty)) => {
|
||||
if id == &proj_ty.associated_ty_id
|
||||
&& subst == &proj_ty.substitution
|
||||
{
|
||||
ty
|
||||
let target_ty = var.to_nextsolver(self.interner);
|
||||
subst
|
||||
.iter(Interner)
|
||||
.zip(orig_values.var_values.iter())
|
||||
.find_map(|(new, orig)| {
|
||||
if orig.ty() == Some(target_ty) {
|
||||
Some(new.assert_ty_ref(Interner).clone())
|
||||
} else {
|
||||
normalized.clone()
|
||||
}
|
||||
}
|
||||
TyKind::AssociatedType(new_id, new_subst) => {
|
||||
if new_id == id && new_subst == subst {
|
||||
ty
|
||||
} else {
|
||||
normalized.clone()
|
||||
}
|
||||
}
|
||||
_ => normalized.clone(),
|
||||
None
|
||||
}
|
||||
})
|
||||
.unwrap_or(ty)
|
||||
}
|
||||
} else {
|
||||
ty
|
||||
|
|
@ -504,8 +478,8 @@ impl<'a> InferenceTable<'a> {
|
|||
pub(crate) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
|
||||
let var = self.new_type_var();
|
||||
let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
|
||||
let obligation = alias_eq.cast(Interner);
|
||||
self.register_obligation(obligation);
|
||||
let obligation: Goal = alias_eq.cast(Interner);
|
||||
self.register_obligation(obligation.to_nextsolver(self.interner));
|
||||
var
|
||||
}
|
||||
|
||||
|
|
@ -575,7 +549,9 @@ impl<'a> InferenceTable<'a> {
|
|||
Substitution::from_iter(
|
||||
Interner,
|
||||
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::Const(ty) => self.new_const_var(ty.clone()).cast(Interner),
|
||||
}),
|
||||
|
|
@ -590,7 +566,10 @@ impl<'a> InferenceTable<'a> {
|
|||
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
|
||||
T: rustc_type_ir::TypeFoldable<DbInterner<'a>>,
|
||||
{
|
||||
|
|
@ -605,7 +584,7 @@ impl<'a> InferenceTable<'a> {
|
|||
where
|
||||
T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
|
||||
{
|
||||
let mut var_stack = &mut vec![];
|
||||
let var_stack = &mut vec![];
|
||||
t.fold_with(
|
||||
&mut resolve::Resolver { table: self, var_stack, fallback },
|
||||
DebruijnIndex::INNERMOST,
|
||||
|
|
@ -618,6 +597,7 @@ impl<'a> InferenceTable<'a> {
|
|||
{
|
||||
let t = self.resolve_with_fallback(t, &|_, _, d, _| d);
|
||||
let t = self.normalize_associated_types_in(t);
|
||||
// let t = self.resolve_opaque_tys_in(t);
|
||||
// Resolve again, because maybe normalization inserted infer vars.
|
||||
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();
|
||||
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);
|
||||
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
|
||||
|
|
@ -665,7 +645,11 @@ impl<'a> InferenceTable<'a> {
|
|||
}
|
||||
|
||||
/// 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) {
|
||||
Ok(r) => r,
|
||||
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
|
||||
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) {
|
||||
Ok(r) => r,
|
||||
Err(_) => return false,
|
||||
};
|
||||
result.goals.iter().all(|goal| {
|
||||
let goal = goal.to_nextsolver(self.interner);
|
||||
match next_trait_solve_in_ctxt(&self.infer_ctxt, goal) {
|
||||
Ok((_, Certainty::Yes)) => true,
|
||||
_ => false,
|
||||
}
|
||||
result.goals.into_iter().all(|goal| {
|
||||
matches!(next_trait_solve_in_ctxt(&self.infer_ctxt, goal), Ok((_, Certainty::Yes)))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -695,20 +679,15 @@ impl<'a> InferenceTable<'a> {
|
|||
&mut self,
|
||||
t1: &T,
|
||||
t2: &T,
|
||||
) -> InferResult<()> {
|
||||
) -> InferResult<'a, ()> {
|
||||
let param_env = self.trait_env.env.to_nextsolver(self.interner);
|
||||
let lhs = t1.to_nextsolver(self.interner);
|
||||
let rhs = t2.to_nextsolver(self.interner);
|
||||
let variance = rustc_type_ir::Variance::Invariant;
|
||||
let span = crate::next_solver::Span::dummy();
|
||||
match self.infer_ctxt.relate(param_env, lhs, variance, rhs, span) {
|
||||
Ok(res) => {
|
||||
let goals = res.into_iter().map(|g| ChalkToNextSolver::from_nextsolver(g, self.interner)).collect();
|
||||
Ok(InferOk { goals, value: () })
|
||||
}
|
||||
Err(_) => {
|
||||
Err(TypeError)
|
||||
}
|
||||
Ok(goals) => Ok(InferOk { goals, value: () }),
|
||||
Err(_) => Err(TypeError),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -719,11 +698,67 @@ impl<'a> InferenceTable<'a> {
|
|||
if !ty.data(Interner).flags.intersects(chalk_ir::TypeFlags::HAS_FREE_LOCAL_NAMES) {
|
||||
return ty.clone();
|
||||
}
|
||||
self.resolve_obligations_as_possible();
|
||||
ChalkToNextSolver::from_nextsolver(self.infer_ctxt.resolve_vars_if_possible(ty.to_nextsolver(self.interner)), self.interner)
|
||||
self.infer_ctxt
|
||||
.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 diverging_tys = self.diverging_tys.clone();
|
||||
let pending_obligations = self.pending_obligations.clone();
|
||||
|
|
@ -731,7 +766,7 @@ impl<'a> InferenceTable<'a> {
|
|||
}
|
||||
|
||||
#[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.diverging_tys = snapshot.diverging_tys;
|
||||
self.pending_obligations = snapshot.pending_obligations;
|
||||
|
|
@ -745,7 +780,10 @@ impl<'a> InferenceTable<'a> {
|
|||
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 result = f(self);
|
||||
match result {
|
||||
|
|
@ -765,59 +803,31 @@ impl<'a> InferenceTable<'a> {
|
|||
let in_env = InEnvironment::new(&self.trait_env.env, goal);
|
||||
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))]
|
||||
pub(crate) fn solve_obligation(&mut self, goal: Goal) -> Result<Certainty, NoSolution> {
|
||||
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 result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal);
|
||||
result.map(|m| m.1)
|
||||
}
|
||||
|
||||
pub(crate) fn register_obligation(&mut self, goal: Goal) {
|
||||
let in_env = InEnvironment::new(&self.trait_env.env, goal);
|
||||
self.register_obligation_in_env(in_env)
|
||||
}
|
||||
|
||||
// If this goal is an `AliasEq` for an opaque type, just unify instead of trying to solve (since the next-solver is lazy)
|
||||
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)
|
||||
pub(crate) fn register_obligation(&mut self, predicate: Predicate<'a>) {
|
||||
let goal = next_solver::Goal {
|
||||
param_env: self.trait_env.env.to_nextsolver(self.interner),
|
||||
predicate,
|
||||
};
|
||||
self.register_obligation_in_env(goal)
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self))]
|
||||
fn register_obligation_in_env(&mut self, goal: InEnvironment<Goal>) {
|
||||
let Some(goal) = self.unify_opaque_instead_of_solve(goal) else { return };
|
||||
let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal.to_nextsolver(self.interner));
|
||||
fn register_obligation_in_env(
|
||||
&mut self,
|
||||
goal: next_solver::Goal<'a, next_solver::Predicate<'a>>,
|
||||
) {
|
||||
let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal);
|
||||
tracing::debug!(?result);
|
||||
match result {
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
@ -841,12 +851,7 @@ impl<'a> InferenceTable<'a> {
|
|||
for goal in obligations.drain(..) {
|
||||
tracing::debug!(obligation = ?goal);
|
||||
|
||||
let Some(goal) = self.unify_opaque_instead_of_solve(goal) else {
|
||||
changed = true;
|
||||
continue;
|
||||
};
|
||||
|
||||
let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal.to_nextsolver(self.interner));
|
||||
let result = next_trait_solve_in_ctxt(&self.infer_ctxt, goal);
|
||||
let (has_changed, certainty) = match result {
|
||||
Ok(result) => result,
|
||||
Err(_) => {
|
||||
|
|
@ -934,40 +939,6 @@ impl<'a> InferenceTable<'a> {
|
|||
.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(
|
||||
&mut self,
|
||||
ty: &Ty,
|
||||
|
|
@ -1027,7 +998,7 @@ impl<'a> InferenceTable<'a> {
|
|||
|
||||
let goal: Goal = trait_ref.clone().cast(Interner);
|
||||
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);
|
||||
for &fn_x in subtraits {
|
||||
let fn_x_trait = fn_x.get_id(self.db, krate)?;
|
||||
|
|
@ -1067,7 +1038,7 @@ impl<'a> InferenceTable<'a> {
|
|||
match ty.kind(Interner) {
|
||||
TyKind::Error => self.new_type_var(),
|
||||
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 }
|
||||
}
|
||||
_ => ty,
|
||||
|
|
@ -1165,7 +1136,9 @@ impl fmt::Debug for InferenceTable<'_> {
|
|||
mod resolve {
|
||||
use super::InferenceTable;
|
||||
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::{
|
||||
cast::Cast,
|
||||
|
|
@ -1220,7 +1193,7 @@ mod resolve {
|
|||
.clone();
|
||||
}
|
||||
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
|
||||
self.var_stack.push((var, VarKind::Ty(kind)));
|
||||
let result = known_ty.fold_with(self, outer_binder);
|
||||
|
|
@ -1234,7 +1207,13 @@ mod resolve {
|
|||
}
|
||||
}
|
||||
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());
|
||||
if self.var_stack.contains(&(var, VarKind::Ty(kind))) {
|
||||
// recursive type
|
||||
|
|
@ -1244,7 +1223,7 @@ mod resolve {
|
|||
.clone();
|
||||
}
|
||||
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
|
||||
self.var_stack.push((var, VarKind::Ty(kind)));
|
||||
let result = known_ty.fold_with(self, outer_binder);
|
||||
|
|
@ -1258,7 +1237,13 @@ mod resolve {
|
|||
}
|
||||
}
|
||||
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());
|
||||
if self.var_stack.contains(&(var, VarKind::Ty(kind))) {
|
||||
// recursive type
|
||||
|
|
@ -1268,7 +1253,7 @@ mod resolve {
|
|||
.clone();
|
||||
}
|
||||
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
|
||||
self.var_stack.push((var, VarKind::Ty(kind)));
|
||||
let result = known_ty.fold_with(self, outer_binder);
|
||||
|
|
@ -1290,7 +1275,10 @@ mod resolve {
|
|||
var: InferenceVar,
|
||||
outer_binder: DebruijnIndex,
|
||||
) -> 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 default = ConstData {
|
||||
ty: ty.clone(),
|
||||
|
|
@ -1305,7 +1293,7 @@ mod resolve {
|
|||
.clone();
|
||||
}
|
||||
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
|
||||
self.var_stack.push((var, VarKind::Const));
|
||||
let result = known_const.fold_with(self, outer_binder);
|
||||
|
|
|
|||
|
|
@ -101,7 +101,10 @@ use crate::{
|
|||
display::{DisplayTarget, HirDisplay},
|
||||
generics::Generics,
|
||||
infer::unify::InferenceTable,
|
||||
next_solver::{DbInterner, mapping::convert_ty_for_result},
|
||||
next_solver::{
|
||||
DbInterner,
|
||||
mapping::{ChalkToNextSolver, convert_ty_for_result},
|
||||
},
|
||||
};
|
||||
|
||||
pub use autoderef::autoderef;
|
||||
|
|
@ -957,8 +960,10 @@ pub fn callable_sig_from_fn_trait(
|
|||
)
|
||||
.build();
|
||||
|
||||
if !table.try_obligation(trait_ref.clone().cast(Interner)).no_solution() {
|
||||
table.register_obligation(trait_ref.clone().cast(Interner));
|
||||
let goal: Goal = 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);
|
||||
for fn_x in [FnTrait::Fn, FnTrait::FnMut, FnTrait::FnOnce] {
|
||||
let fn_x_trait = fn_x.get_id(db, krate)?;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,25 @@ use stdx::never;
|
|||
use triomphe::Arc;
|
||||
|
||||
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.
|
||||
|
|
@ -89,6 +107,7 @@ impl TyFingerprint {
|
|||
}
|
||||
TyKind::AssociatedType(_, _)
|
||||
| TyKind::OpaqueType(_, _)
|
||||
| TyKind::Alias(AliasTy::Opaque(_))
|
||||
| TyKind::FnDef(_, _)
|
||||
| TyKind::Closure(_, _)
|
||||
| TyKind::Coroutine(..)
|
||||
|
|
@ -106,7 +125,7 @@ impl TyFingerprint {
|
|||
}
|
||||
|
||||
/// 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;
|
||||
let fp = match (*ty).kind() {
|
||||
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.
|
||||
pub(crate) fn lookup_method<'db>(
|
||||
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>,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
visible_from_module: VisibleFromModule,
|
||||
|
|
@ -605,7 +624,7 @@ pub struct ReceiverAdjustments {
|
|||
|
||||
impl ReceiverAdjustments {
|
||||
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();
|
||||
for _ in 0..self.autoderefs {
|
||||
match autoderef::autoderef_step(table, ty.clone(), true, false) {
|
||||
|
|
@ -686,7 +705,7 @@ impl ReceiverAdjustments {
|
|||
// lifetime problems, because we need to borrow temp `CrateImplDefs`.
|
||||
// FIXME add a context type here?
|
||||
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,
|
||||
env: Arc<TraitEnvironment>,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
|
|
@ -887,7 +906,7 @@ fn find_matching_impl(
|
|||
if table.try_obligation(goal.clone()).no_solution() {
|
||||
return None;
|
||||
}
|
||||
table.register_obligation(goal);
|
||||
table.register_obligation(goal.to_nextsolver(table.interner));
|
||||
}
|
||||
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>(
|
||||
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,
|
||||
env: Arc<TraitEnvironment>,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
|
|
@ -1057,7 +1076,7 @@ pub fn iterate_path_candidates<'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,
|
||||
env: Arc<TraitEnvironment>,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
|
|
@ -1096,7 +1115,7 @@ pub fn iterate_method_candidates_dyn<'db>(
|
|||
// types*.
|
||||
|
||||
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);
|
||||
|
||||
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))]
|
||||
fn iterate_method_candidates_with_autoref<'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,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
visible_from_module: VisibleFromModule,
|
||||
name: Option<&Name>,
|
||||
callback: &mut dyn MethodCandidateCallback,
|
||||
) -> 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 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;
|
||||
}
|
||||
|
||||
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,
|
||||
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(
|
||||
|
|
@ -1179,10 +1198,15 @@ fn iterate_method_candidates_with_autoref<'db>(
|
|||
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,
|
||||
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(
|
||||
|
|
@ -1190,10 +1214,12 @@ fn iterate_method_candidates_with_autoref<'db>(
|
|||
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 {
|
||||
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,
|
||||
};
|
||||
iterate_method_candidates_by_receiver(
|
||||
|
|
@ -1247,7 +1273,7 @@ where
|
|||
#[tracing::instrument(skip_all, fields(name = ?name))]
|
||||
fn iterate_method_candidates_by_receiver<'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,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
visible_from_module: VisibleFromModule,
|
||||
|
|
@ -1255,7 +1281,7 @@ fn iterate_method_candidates_by_receiver<'db>(
|
|||
callback: &mut dyn MethodCandidateCallback,
|
||||
) -> ControlFlow<()> {
|
||||
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
|
||||
// be found in any of the derefs of receiver_ty, so we have to go through
|
||||
// that, including raw derefs.
|
||||
|
|
@ -1270,6 +1296,7 @@ fn iterate_method_candidates_by_receiver<'db>(
|
|||
Some(&receiver_ty),
|
||||
Some(receiver_adjustments.clone()),
|
||||
visible_from_module,
|
||||
LookupMode::MethodCall,
|
||||
&mut |adjustments, item, is_visible| {
|
||||
callback.on_inherent_method(adjustments, item, is_visible)
|
||||
},
|
||||
|
|
@ -1293,6 +1320,7 @@ fn iterate_method_candidates_by_receiver<'db>(
|
|||
name,
|
||||
Some(&receiver_ty),
|
||||
Some(receiver_adjustments.clone()),
|
||||
LookupMode::MethodCall,
|
||||
&mut |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))]
|
||||
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,
|
||||
env: Arc<TraitEnvironment>,
|
||||
traits_in_scope: &FxHashSet<TraitId>,
|
||||
|
|
@ -1313,7 +1341,7 @@ fn iterate_method_candidates_for_self_ty<'db>(
|
|||
callback: &mut dyn MethodCandidateCallback,
|
||||
) -> ControlFlow<()> {
|
||||
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(
|
||||
&self_ty,
|
||||
&mut table,
|
||||
|
|
@ -1321,6 +1349,7 @@ fn iterate_method_candidates_for_self_ty<'db>(
|
|||
None,
|
||||
None,
|
||||
visible_from_module,
|
||||
LookupMode::Path,
|
||||
&mut |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,
|
||||
None,
|
||||
None,
|
||||
LookupMode::Path,
|
||||
&mut |adjustments, item, is_visible| {
|
||||
callback.on_trait_method(adjustments, item, is_visible)
|
||||
},
|
||||
|
|
@ -1346,12 +1376,13 @@ fn iterate_trait_method_candidates(
|
|||
name: Option<&Name>,
|
||||
receiver_ty: Option<&Ty>,
|
||||
receiver_adjustments: Option<ReceiverAdjustments>,
|
||||
mode: LookupMode,
|
||||
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
|
||||
) -> ControlFlow<()> {
|
||||
let db = table.db;
|
||||
|
||||
let canonical_self_ty = ChalkToNextSolver::from_nextsolver(table.canonicalize(self_ty.clone().to_nextsolver(table.interner)), table.interner);
|
||||
let TraitEnvironment { krate, block, .. } = *table.trait_env;
|
||||
let canonical_self_ty = table.canonicalize(self_ty.clone().to_nextsolver(table.interner));
|
||||
let TraitEnvironment { krate, .. } = *table.trait_env;
|
||||
|
||||
'traits: for &t in traits_in_scope {
|
||||
let data = db.trait_signature(t);
|
||||
|
|
@ -1391,15 +1422,22 @@ fn iterate_trait_method_candidates(
|
|||
for &(_, item) in t.trait_items(db).items.iter() {
|
||||
// Don't pass a `visible_from_module` down to `is_valid_candidate`,
|
||||
// since only inherent methods should be included into visibility checking.
|
||||
let visible =
|
||||
match is_valid_trait_method_candidate(table, t, name, receiver_ty, item, self_ty) {
|
||||
let visible = match is_valid_trait_method_candidate(
|
||||
table,
|
||||
t,
|
||||
name,
|
||||
receiver_ty,
|
||||
item,
|
||||
self_ty,
|
||||
mode,
|
||||
) {
|
||||
IsValidCandidate::Yes => true,
|
||||
IsValidCandidate::NotVisible => false,
|
||||
IsValidCandidate::No => continue,
|
||||
};
|
||||
if !known_implemented {
|
||||
let goal = generic_implements_goal(db, &table.trait_env, t, &canonical_self_ty);
|
||||
if db.trait_solve(krate, block, goal.cast(Interner)).no_solution() {
|
||||
let goal = generic_implements_goal_ns(table, t, canonical_self_ty);
|
||||
if next_trait_solve_canonical_in_ctxt(&table.infer_ctxt, goal).no_solution() {
|
||||
continue 'traits;
|
||||
}
|
||||
}
|
||||
|
|
@ -1418,6 +1456,7 @@ fn iterate_inherent_methods(
|
|||
receiver_ty: Option<&Ty>,
|
||||
receiver_adjustments: Option<ReceiverAdjustments>,
|
||||
visible_from_module: VisibleFromModule,
|
||||
mode: LookupMode,
|
||||
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
|
||||
) -> ControlFlow<()> {
|
||||
let db = table.db;
|
||||
|
|
@ -1441,6 +1480,7 @@ fn iterate_inherent_methods(
|
|||
receiver_adjustments.clone(),
|
||||
callback,
|
||||
traits,
|
||||
mode,
|
||||
)?;
|
||||
}
|
||||
TyKind::Dyn(_) => {
|
||||
|
|
@ -1454,6 +1494,7 @@ fn iterate_inherent_methods(
|
|||
receiver_adjustments.clone(),
|
||||
callback,
|
||||
traits.into_iter(),
|
||||
mode,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
|
@ -1512,6 +1553,7 @@ fn iterate_inherent_methods(
|
|||
receiver_adjustments: Option<ReceiverAdjustments>,
|
||||
callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId, bool) -> ControlFlow<()>,
|
||||
traits: impl Iterator<Item = TraitId>,
|
||||
mode: LookupMode,
|
||||
) -> ControlFlow<()> {
|
||||
let db = table.db;
|
||||
for t in traits {
|
||||
|
|
@ -1525,6 +1567,7 @@ fn iterate_inherent_methods(
|
|||
receiver_ty,
|
||||
item,
|
||||
self_ty,
|
||||
mode,
|
||||
) {
|
||||
IsValidCandidate::Yes => true,
|
||||
IsValidCandidate::NotVisible => false,
|
||||
|
|
@ -1571,22 +1614,17 @@ fn iterate_inherent_methods(
|
|||
}
|
||||
|
||||
/// Returns the receiver type for the index trait call.
|
||||
pub(crate) fn resolve_indexing_op(
|
||||
db: &dyn HirDatabase,
|
||||
env: Arc<TraitEnvironment>,
|
||||
ty: Canonical<Ty>,
|
||||
pub(crate) fn resolve_indexing_op<'db>(
|
||||
table: &mut InferenceTable<'db>,
|
||||
ty: next_solver::Canonical<'db, next_solver::Ty<'db>>,
|
||||
index_trait: TraitId,
|
||||
) -> Option<ReceiverAdjustments> {
|
||||
let mut table = InferenceTable::new(db, env);
|
||||
let ty = table.instantiate_canonical(ty);
|
||||
let interner = table.interner;
|
||||
let deref_chain = autoderef_method_receiver(&mut table, ty.to_nextsolver(interner));
|
||||
let ty = table.instantiate_canonical_ns(ty);
|
||||
let deref_chain = autoderef_method_receiver(table, ty);
|
||||
for (ty, adj) in deref_chain {
|
||||
//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: chalk_ir::Canonical<chalk_ir::InEnvironment<chalk_ir::Goal<Interner>>> = goal.cast(Interner);
|
||||
let goal = goal.to_nextsolver(interner);
|
||||
if !next_trait_solve_canonical(db, table.trait_env.krate, table.trait_env.block, goal).no_solution() {
|
||||
let goal = generic_implements_goal_ns(table, index_trait, ty);
|
||||
if !next_trait_solve_canonical_in_ctxt(&table.infer_ctxt, goal).no_solution() {
|
||||
return Some(adj);
|
||||
}
|
||||
}
|
||||
|
|
@ -1666,6 +1704,7 @@ fn is_valid_trait_method_candidate(
|
|||
receiver_ty: Option<&Ty>,
|
||||
item: AssocItemId,
|
||||
self_ty: &Ty,
|
||||
mode: LookupMode,
|
||||
) -> IsValidCandidate {
|
||||
let db = table.db;
|
||||
match item {
|
||||
|
|
@ -1693,6 +1732,35 @@ fn is_valid_trait_method_candidate(
|
|||
let expected_receiver =
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
@ -1839,53 +1907,36 @@ fn generic_implements_goal(
|
|||
Canonical { binders, value }
|
||||
}
|
||||
|
||||
/*
|
||||
/// 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.
|
||||
#[tracing::instrument(skip_all)]
|
||||
fn generic_implements_goal_ns<'db>(
|
||||
db: &'db dyn HirDatabase,
|
||||
interner: DbInterner<'db>,
|
||||
env: &TraitEnvironment,
|
||||
table: &mut InferenceTable<'db>,
|
||||
trait_: TraitId,
|
||||
self_ty: &crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
|
||||
) -> crate::next_solver::Canonical<'db, crate::next_solver::Goal<'db, crate::next_solver::Predicate<'db>>> {
|
||||
let variables = self_ty.variables;
|
||||
let trait_ref = TyBuilder::trait_ref(db, trait_)
|
||||
.push(ChalkToNextSolver::from_nextsolver(self_ty.value, interner))
|
||||
.fill_with_bound_vars(DebruijnIndex::INNERMOST, variables.len())
|
||||
.build();
|
||||
self_ty: next_solver::Canonical<'db, crate::next_solver::Ty<'db>>,
|
||||
) -> next_solver::Canonical<'db, next_solver::Goal<'db, crate::next_solver::Predicate<'db>>> {
|
||||
let args = table.infer_ctxt.fresh_args_for_item(SolverDefId::TraitId(trait_));
|
||||
let self_ty = table.instantiate_canonical_ns(self_ty);
|
||||
let trait_ref =
|
||||
rustc_type_ir::TraitRef::new_from_args(table.infer_ctxt.interner, trait_.into(), args)
|
||||
.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());
|
||||
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 }
|
||||
table.canonicalize(goal)
|
||||
}
|
||||
*/
|
||||
|
||||
fn autoderef_method_receiver<'db>(
|
||||
table: &mut InferenceTable<'db>,
|
||||
ty: crate::next_solver::Ty<'db>,
|
||||
) -> Vec<(crate::next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ReceiverAdjustments)> {
|
||||
ty: next_solver::Ty<'db>,
|
||||
) -> Vec<(next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ReceiverAdjustments)> {
|
||||
let interner = table.interner;
|
||||
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() {
|
||||
deref_chain.push((
|
||||
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!)
|
||||
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((
|
||||
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() },
|
||||
));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,8 +34,7 @@ pub use eval::{
|
|||
};
|
||||
pub use lower::{MirLowerError, lower_to_mir, mir_body_for_closure_query, mir_body_query};
|
||||
pub use monomorphization::{
|
||||
monomorphize_mir_body_bad, monomorphized_mir_body_for_closure_query,
|
||||
monomorphized_mir_body_query,
|
||||
monomorphized_mir_body_for_closure_query, monomorphized_mir_body_query,
|
||||
};
|
||||
use rustc_hash::FxHashMap;
|
||||
use smallvec::{SmallVec, smallvec};
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ struct Filler<'a> {
|
|||
trait_env: Arc<TraitEnvironment>,
|
||||
subst: &'a Substitution,
|
||||
generics: Option<Generics>,
|
||||
owner: DefWithBodyId,
|
||||
}
|
||||
impl FallibleTypeFolder<Interner> for Filler<'_> {
|
||||
type Error = MirLowerError;
|
||||
|
|
@ -66,7 +65,11 @@ impl FallibleTypeFolder<Interner> for Filler<'_> {
|
|||
}))
|
||||
.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 subst = subst.clone().try_fold_with(self.as_dyn(), outer_binder)?;
|
||||
match impl_trait_id {
|
||||
|
|
@ -74,7 +77,6 @@ impl FallibleTypeFolder<Interner> for Filler<'_> {
|
|||
let infer = self.db.infer(func.into());
|
||||
let filler = &mut Filler {
|
||||
db: self.db,
|
||||
owner: self.owner,
|
||||
trait_env: self.trait_env.clone(),
|
||||
subst: &subst,
|
||||
generics: Some(generics(self.db, func.into())),
|
||||
|
|
@ -306,7 +308,7 @@ pub fn monomorphized_mir_body_query(
|
|||
trait_env: Arc<crate::TraitEnvironment>,
|
||||
) -> Result<Arc<MirBody>, MirLowerError> {
|
||||
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 mut body = (*body).clone();
|
||||
filler.fill_body(&mut body)?;
|
||||
|
|
@ -330,23 +332,9 @@ pub fn monomorphized_mir_body_for_closure_query(
|
|||
) -> Result<Arc<MirBody>, MirLowerError> {
|
||||
let InternedClosure(owner, _) = db.lookup_intern_closure(closure);
|
||||
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 mut body = (*body).clone();
|
||||
filler.fill_body(&mut 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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,11 +5,10 @@ pub mod abi;
|
|||
mod consts;
|
||||
mod def_id;
|
||||
pub mod fold;
|
||||
mod fulfill;
|
||||
pub mod fulfill;
|
||||
mod generic_arg;
|
||||
pub mod generics;
|
||||
pub mod infer;
|
||||
//mod infer_new;
|
||||
pub mod interner;
|
||||
mod ir_print;
|
||||
pub mod mapping;
|
||||
|
|
@ -24,7 +23,6 @@ pub mod util;
|
|||
pub use consts::*;
|
||||
pub use def_id::*;
|
||||
pub use generic_arg::*;
|
||||
//pub use infer_new::*;
|
||||
pub use interner::*;
|
||||
pub use opaques::*;
|
||||
pub use predicate::*;
|
||||
|
|
|
|||
|
|
@ -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_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::{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 tracing::debug;
|
||||
|
||||
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
|
||||
/// 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.
|
||||
let canonical_param_env = Canonicalizer::canonicalize(
|
||||
param_env,
|
||||
None,
|
||||
self,
|
||||
self.interner,
|
||||
&CanonicalizeFreeRegionsOtherThanStatic,
|
||||
query_state,
|
||||
|
|
@ -74,7 +88,7 @@ impl<'db> InferCtxt<'db> {
|
|||
let canonical = Canonicalizer::canonicalize_with_base(
|
||||
canonical_param_env,
|
||||
value,
|
||||
Some(self),
|
||||
self,
|
||||
self.interner,
|
||||
&CanonicalizeAllFreeRegions,
|
||||
query_state,
|
||||
|
|
@ -115,7 +129,7 @@ impl<'db> InferCtxt<'db> {
|
|||
let mut query_state = OriginalQueryValues::default();
|
||||
Canonicalizer::canonicalize(
|
||||
value,
|
||||
Some(self),
|
||||
self,
|
||||
self.interner,
|
||||
&CanonicalizeQueryResponse,
|
||||
&mut query_state,
|
||||
|
|
@ -129,7 +143,7 @@ impl<'db> InferCtxt<'db> {
|
|||
let mut query_state = OriginalQueryValues::default();
|
||||
Canonicalizer::canonicalize(
|
||||
value,
|
||||
Some(self),
|
||||
self,
|
||||
self.interner,
|
||||
&CanonicalizeUserTypeAnnotation,
|
||||
&mut query_state,
|
||||
|
|
@ -165,7 +179,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
|
|||
canonicalizer: &mut Canonicalizer<'_, 'db>,
|
||||
mut r: Region<'db>,
|
||||
) -> Region<'db> {
|
||||
let infcx = canonicalizer.infcx.unwrap();
|
||||
let infcx = canonicalizer.infcx;
|
||||
|
||||
if let RegionKind::ReVar(vid) = r.kind() {
|
||||
r = infcx
|
||||
|
|
@ -180,12 +194,14 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
|
|||
};
|
||||
|
||||
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(
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder),
|
||||
r,
|
||||
),
|
||||
RegionKind::RePlaceholder(placeholder) => canonicalizer
|
||||
.canonical_var_for_region(CanonicalVarKind::PlaceholderRegion(placeholder), r),
|
||||
|
||||
RegionKind::ReVar(vid) => {
|
||||
let universe = infcx
|
||||
|
|
@ -194,10 +210,7 @@ impl CanonicalizeMode for CanonicalizeQueryResponse {
|
|||
.unwrap_region_constraints()
|
||||
.probe_value(vid)
|
||||
.unwrap_err();
|
||||
canonicalizer.canonical_var_for_region(
|
||||
CanonicalVarKind::Region(universe),
|
||||
r,
|
||||
)
|
||||
canonicalizer.canonical_var_for_region(CanonicalVarKind::Region(universe), r)
|
||||
}
|
||||
|
||||
_ => {
|
||||
|
|
@ -240,7 +253,7 @@ impl CanonicalizeMode for CanonicalizeUserTypeAnnotation {
|
|||
RegionKind::ReVar(_) => canonicalizer.canonical_var_for_region_in_root_universe(r),
|
||||
RegionKind::RePlaceholder(..) | RegionKind::ReBound(..) => {
|
||||
// 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> {
|
||||
/// Set to `None` to disable the resolution of inference variables.
|
||||
infcx: Option<&'cx InferCtxt<'db>>,
|
||||
infcx: &'cx InferCtxt<'db>,
|
||||
tcx: DbInterner<'db>,
|
||||
variables: SmallVec<[CanonicalVarKind<'db>; 8]>,
|
||||
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.
|
||||
// This is so that our canonical response correctly reflects
|
||||
// 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 {
|
||||
t = Ty::new_var(self.tcx, root_vid);
|
||||
vid = root_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.
|
||||
Ok(t) => {
|
||||
debug!("(resolved to {:?})", t);
|
||||
|
|
@ -380,29 +393,25 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> {
|
|||
}
|
||||
|
||||
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 {
|
||||
return self.fold_ty(nt);
|
||||
self.fold_ty(nt)
|
||||
} else {
|
||||
self.canonicalize_ty_var(
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int),
|
||||
t,
|
||||
)
|
||||
self.canonicalize_ty_var(CanonicalVarKind::Ty(CanonicalTyVarKind::Int), t)
|
||||
}
|
||||
}
|
||||
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 {
|
||||
return self.fold_ty(nt);
|
||||
self.fold_ty(nt)
|
||||
} else {
|
||||
self.canonicalize_ty_var(
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Float),
|
||||
t,
|
||||
)
|
||||
self.canonicalize_ty_var(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")
|
||||
}
|
||||
|
||||
|
|
@ -410,10 +419,7 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> {
|
|||
if !self.canonicalize_mode.preserve_universes() {
|
||||
placeholder.universe = UniverseIndex::ROOT;
|
||||
}
|
||||
self.canonicalize_ty_var(
|
||||
CanonicalVarKind::PlaceholderTy(placeholder),
|
||||
t,
|
||||
)
|
||||
self.canonicalize_ty_var(CanonicalVarKind::PlaceholderTy(placeholder), t)
|
||||
}
|
||||
|
||||
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.
|
||||
// This is so that our canonical response correctly reflects
|
||||
// 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 {
|
||||
ct = Const::new_var(self.tcx, root_vid);
|
||||
vid = root_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) => {
|
||||
debug!("(resolved to {:?})", 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.
|
||||
ui = UniverseIndex::ROOT;
|
||||
}
|
||||
return self.canonicalize_const_var(
|
||||
CanonicalVarKind::Const(ui),
|
||||
ct,
|
||||
);
|
||||
return self.canonicalize_const_var(CanonicalVarKind::Const(ui), ct);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -503,10 +506,8 @@ impl<'cx, 'db> TypeFolder<DbInterner<'db>> for Canonicalizer<'cx, 'db> {
|
|||
}
|
||||
}
|
||||
ConstKind::Placeholder(placeholder) => {
|
||||
return self.canonicalize_const_var(
|
||||
CanonicalVarKind::PlaceholderConst(placeholder),
|
||||
ct,
|
||||
);
|
||||
return self
|
||||
.canonicalize_const_var(CanonicalVarKind::PlaceholderConst(placeholder), ct);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -524,7 +525,7 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
|
|||
/// `canonicalize_query` and `canonicalize_response`.
|
||||
fn canonicalize<V>(
|
||||
value: V,
|
||||
infcx: Option<&InferCtxt<'db>>,
|
||||
infcx: &InferCtxt<'db>,
|
||||
tcx: DbInterner<'db>,
|
||||
canonicalize_region_mode: &dyn CanonicalizeMode,
|
||||
query_state: &mut OriginalQueryValues<'db>,
|
||||
|
|
@ -551,7 +552,7 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
|
|||
fn canonicalize_with_base<U, V>(
|
||||
base: Canonical<'db, U>,
|
||||
value: V,
|
||||
infcx: Option<&InferCtxt<'db>>,
|
||||
infcx: &InferCtxt<'db>,
|
||||
tcx: DbInterner<'db>,
|
||||
canonicalize_region_mode: &dyn CanonicalizeMode,
|
||||
query_state: &mut OriginalQueryValues<'db>,
|
||||
|
|
@ -596,7 +597,8 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
|
|||
// anymore.
|
||||
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
|
||||
.iter()
|
||||
|
|
@ -690,15 +692,11 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
|
|||
self.variables
|
||||
.iter()
|
||||
.map(|v| match *v {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => {
|
||||
return *v;
|
||||
}
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) => *v,
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(u)) => {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(reverse_universe_map[&u]))
|
||||
}
|
||||
CanonicalVarKind::Region(u) => {
|
||||
CanonicalVarKind::Region(reverse_universe_map[&u])
|
||||
}
|
||||
CanonicalVarKind::Region(u) => CanonicalVarKind::Region(reverse_universe_map[&u]),
|
||||
CanonicalVarKind::Const(u) => CanonicalVarKind::Const(reverse_universe_map[&u]),
|
||||
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
|
||||
/// selection is never affected -- due to a universe mismatch.)
|
||||
fn canonical_var_for_region_in_root_universe(
|
||||
&mut self,
|
||||
r: Region<'db>,
|
||||
) -> Region<'db> {
|
||||
self.canonical_var_for_region(
|
||||
CanonicalVarKind::Region(UniverseIndex::ROOT),
|
||||
r,
|
||||
)
|
||||
fn canonical_var_for_region_in_root_universe(&mut self, r: Region<'db>) -> Region<'db> {
|
||||
self.canonical_var_for_region(CanonicalVarKind::Region(UniverseIndex::ROOT), r)
|
||||
}
|
||||
|
||||
/// 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
|
||||
/// `ty_var`.
|
||||
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());
|
||||
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
|
||||
|
|
@ -776,10 +772,8 @@ impl<'cx, 'db> Canonicalizer<'cx, 'db> {
|
|||
info: CanonicalVarKind<'db>,
|
||||
const_var: Const<'db>,
|
||||
) -> Const<'db> {
|
||||
debug_assert!(
|
||||
!self.infcx.is_some_and(|infcx| const_var != infcx.shallow_resolve_const(const_var))
|
||||
);
|
||||
debug_assert_eq!(const_var, self.infcx.shallow_resolve_const(const_var));
|
||||
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 })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -503,7 +503,10 @@ impl<'db> InferCtxt<'db> {
|
|||
}
|
||||
|
||||
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> {
|
||||
|
|
@ -526,11 +529,13 @@ impl<'db> InferCtxt<'db> {
|
|||
}
|
||||
|
||||
pub fn next_const_vid(&self) -> ConstVid {
|
||||
self
|
||||
.inner
|
||||
self.inner
|
||||
.borrow_mut()
|
||||
.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
|
||||
}
|
||||
|
||||
|
|
@ -566,9 +571,7 @@ impl<'db> InferCtxt<'db> {
|
|||
}
|
||||
|
||||
pub fn next_float_var(&self) -> Ty<'db> {
|
||||
let next_float_var_id =
|
||||
self.inner.borrow_mut().float_unification_table().new_key(FloatVarValue::Unknown);
|
||||
Ty::new_float_var(self.interner, next_float_var_id)
|
||||
Ty::new_float_var(self.interner, self.next_float_vid())
|
||||
}
|
||||
|
||||
pub fn next_float_vid(&self) -> FloatVid {
|
||||
|
|
@ -815,9 +818,7 @@ impl<'db> InferCtxt<'db> {
|
|||
match value {
|
||||
IntVarValue::IntType(ty) => Some(Ty::new_int(self.interner, ty)),
|
||||
IntVarValue::UintType(ty) => Some(Ty::new_uint(self.interner, ty)),
|
||||
IntVarValue::Unknown => {
|
||||
None
|
||||
}
|
||||
IntVarValue::Unknown => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -839,9 +840,7 @@ impl<'db> InferCtxt<'db> {
|
|||
let value = inner.float_unification_table().probe_value(vid);
|
||||
match value {
|
||||
FloatVarValue::Known(ty) => Some(Ty::new_float(self.interner, ty)),
|
||||
FloatVarValue::Unknown => {
|
||||
None
|
||||
}
|
||||
FloatVarValue::Unknown => None,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -9,12 +9,12 @@ use rustc_type_ir::{
|
|||
solve::{Certainty, NoSolution},
|
||||
};
|
||||
|
||||
use crate::next_solver::mapping::NextSolverToChalk;
|
||||
use crate::{
|
||||
TraitRefExt,
|
||||
db::HirDatabase,
|
||||
next_solver::{
|
||||
ClauseKind, CoercePredicate, PredicateKind, SubtypePredicate,
|
||||
mapping::ChalkToNextSolver,
|
||||
ClauseKind, CoercePredicate, PredicateKind, SubtypePredicate, mapping::ChalkToNextSolver,
|
||||
util::sizedness_fast_path,
|
||||
},
|
||||
};
|
||||
|
|
@ -200,7 +200,7 @@ impl<'db> SolverDelegate for SolverContext<'db> {
|
|||
SolverDefId::StaticId(c) => GeneralConstId::StaticId(c),
|
||||
_ => 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()?;
|
||||
Some(ec.to_nextsolver(self.interner))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ fn let_stmt_coerce() {
|
|||
//- minicore: coerce_unsized
|
||||
fn test() {
|
||||
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];
|
||||
// ^^^^ adjustments: Deref(None), Borrow(RawPtr(Not)), Pointer(Unsize)
|
||||
}
|
||||
|
|
@ -96,7 +96,7 @@ fn foo<T>(x: &[T]) -> &[T] { x }
|
|||
fn test() {
|
||||
let x = if true {
|
||||
foo(&[1])
|
||||
// ^^^^ adjustments: Deref(None), Borrow(Ref('?11, Not)), Pointer(Unsize)
|
||||
// ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize)
|
||||
} else {
|
||||
&[1]
|
||||
};
|
||||
|
|
@ -148,7 +148,7 @@ fn foo<T>(x: &[T]) -> &[T] { x }
|
|||
fn test(i: i32) {
|
||||
let x = match i {
|
||||
2 => foo(&[2]),
|
||||
// ^^^^ adjustments: Deref(None), Borrow(Ref('?11, Not)), Pointer(Unsize)
|
||||
// ^^^^ adjustments: Deref(None), Borrow(Ref('?1, Not)), Pointer(Unsize)
|
||||
1 => &[1],
|
||||
_ => &[3],
|
||||
};
|
||||
|
|
@ -881,7 +881,7 @@ fn adjust_index() {
|
|||
fn test() {
|
||||
let x = [1, 2, 3];
|
||||
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() {
|
||||
Struct[0];
|
||||
// ^^^^^^ adjustments: Borrow(Ref('?2, Not))
|
||||
// ^^^^^^ adjustments: Borrow(Ref('?0, Not))
|
||||
StructMut[0];
|
||||
// ^^^^^^^^^ adjustments: Borrow(Ref('?5, Not))
|
||||
// ^^^^^^^^^ adjustments: Borrow(Ref('?1, Not))
|
||||
&mut StructMut[0];
|
||||
// ^^^^^^^^^ adjustments: Borrow(Ref('?8, Mut))
|
||||
// ^^^^^^^^^ adjustments: Borrow(Ref('?2, Mut))
|
||||
}",
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -589,6 +589,7 @@ fn main() {
|
|||
"attrs_shim",
|
||||
"attrs_shim",
|
||||
"return_type_impl_traits_shim",
|
||||
"generic_predicates_ns_shim",
|
||||
"infer_shim",
|
||||
"function_signature_shim",
|
||||
"function_signature_with_source_map_shim",
|
||||
|
|
@ -605,8 +606,6 @@ fn main() {
|
|||
"impl_signature_shim",
|
||||
"impl_signature_with_source_map_shim",
|
||||
"callable_item_signature_shim",
|
||||
"adt_variance_shim",
|
||||
"variances_of_shim",
|
||||
"trait_impls_in_deps_shim",
|
||||
"trait_impls_in_crate_shim",
|
||||
"impl_trait_with_diagnostics_shim",
|
||||
|
|
@ -615,7 +614,6 @@ fn main() {
|
|||
"impl_trait_with_diagnostics_ns_shim",
|
||||
"impl_self_ty_with_diagnostics_ns_shim",
|
||||
"generic_predicates_ns_shim",
|
||||
"generic_predicates_ns_shim",
|
||||
"value_ty_shim",
|
||||
"generic_predicates_shim",
|
||||
"lang_item",
|
||||
|
|
@ -691,6 +689,7 @@ fn main() {
|
|||
"attrs_shim",
|
||||
"attrs_shim",
|
||||
"return_type_impl_traits_shim",
|
||||
"generic_predicates_ns_shim",
|
||||
"infer_shim",
|
||||
"function_signature_with_source_map_shim",
|
||||
"expr_scopes_shim",
|
||||
|
|
@ -706,7 +705,6 @@ fn main() {
|
|||
"impl_trait_with_diagnostics_ns_shim",
|
||||
"impl_self_ty_with_diagnostics_ns_shim",
|
||||
"generic_predicates_ns_shim",
|
||||
"generic_predicates_ns_shim",
|
||||
"generic_predicates_shim",
|
||||
]
|
||||
"#]],
|
||||
|
|
|
|||
|
|
@ -202,7 +202,7 @@ fn expr_macro_def_expanded_in_various_places() {
|
|||
100..119 'for _ ...!() {}': {unknown}
|
||||
100..119 'for _ ...!() {}': &'? mut {unknown}
|
||||
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 _ ...!() {}': ()
|
||||
|
|
@ -296,7 +296,7 @@ fn expr_macro_rules_expanded_in_various_places() {
|
|||
114..133 'for _ ...!() {}': {unknown}
|
||||
114..133 'for _ ...!() {}': &'? mut {unknown}
|
||||
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 _ ...!() {}': ()
|
||||
|
|
|
|||
|
|
@ -1876,9 +1876,9 @@ impl Foo {
|
|||
}
|
||||
fn test() {
|
||||
Foo.foo();
|
||||
//^^^ adjustments: Borrow(Ref('?1, Not))
|
||||
//^^^ adjustments: Borrow(Ref('?0, Not))
|
||||
(&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() {
|
||||
let a = [1, 2, 3];
|
||||
a.len();
|
||||
} //^ adjustments: Borrow(Ref('?7, Not)), Pointer(Unsize)
|
||||
} //^ adjustments: Borrow(Ref('?0, Not)), Pointer(Unsize)
|
||||
"#,
|
||||
);
|
||||
}
|
||||
|
|
@ -2105,7 +2105,7 @@ impl Foo {
|
|||
}
|
||||
fn test() {
|
||||
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;
|
||||
fn test() {
|
||||
ManuallyDrop::new(Foo).foo();
|
||||
//^^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('?6, Not))
|
||||
//^^^^^^^^^^^^^^^^^^^^^^ adjustments: Deref(Some(OverloadedDeref(Some(Not)))), Borrow(Ref('?0, Not))
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -362,12 +362,12 @@ fn diverging_expression_3_break() {
|
|||
140..141 'x': u32
|
||||
149..175 '{ for ...; }; }': u32
|
||||
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; }': {unknown}
|
||||
151..172 'for a ...eak; }': &'? mut {unknown}
|
||||
151..172 'for a ...eak; }': <{unknown} as IntoIterator>::IntoIter
|
||||
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; }': 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; }': ()
|
||||
|
|
@ -379,12 +379,12 @@ fn diverging_expression_3_break() {
|
|||
226..227 'x': 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 {}': {unknown}
|
||||
237..250 'for a in b {}': <{unknown} as IntoIterator>::IntoIter
|
||||
237..250 'for a in b {}': !
|
||||
237..250 'for a in b {}': {unknown}
|
||||
237..250 'for a in b {}': &'? mut {unknown}
|
||||
237..250 'for a in b {}': <{unknown} as IntoIterator>::IntoIter
|
||||
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 {}': 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 {}': ()
|
||||
|
|
@ -395,12 +395,12 @@ fn diverging_expression_3_break() {
|
|||
304..305 'x': u32
|
||||
313..340 '{ for ...; }; }': u32
|
||||
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; }': {unknown}
|
||||
315..337 'for a ...urn; }': &'? mut {unknown}
|
||||
315..337 'for a ...urn; }': <{unknown} as IntoIterator>::IntoIter
|
||||
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; }': 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; }': ()
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
r#"
|
||||
trait Trait {}
|
||||
|
|
@ -155,7 +158,6 @@ static ALIAS: i32 = {
|
|||
191..193 '_a': impl Trait + ?Sized
|
||||
205..211 'Struct': Struct
|
||||
217..218 '5': i32
|
||||
205..211: expected impl Trait + ?Sized, got Struct
|
||||
"#]],
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,12 +48,12 @@ fn infer_pattern() {
|
|||
83..84 '1': i32
|
||||
86..93 '"hello"': &'static str
|
||||
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... }': {unknown}
|
||||
101..151 'for (e... }': &'? mut {unknown}
|
||||
101..151 'for (e... }': <{unknown} as IntoIterator>::IntoIter
|
||||
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... }': Option<({unknown}, {unknown})>
|
||||
101..151 'for (e... }': Option<<{unknown} as Iterator>::Item>
|
||||
101..151 'for (e... }': ()
|
||||
101..151 'for (e... }': ()
|
||||
101..151 'for (e... }': ()
|
||||
|
|
@ -719,28 +719,28 @@ fn test() {
|
|||
51..58 'loop {}': !
|
||||
56..58 '{}': ()
|
||||
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
|
||||
82..91 '&(1, "a")': &'? (i32, &'static str)
|
||||
83..91 '(1, "a")': (i32, &'static str)
|
||||
84..85 '1': i32
|
||||
87..90 '"a"': &'static str
|
||||
93..104 '|&(x, y)| x': impl FnOnce(&'? (i32, &'? str)) -> i32
|
||||
94..101 '&(x, y)': &'? (i32, &'? str)
|
||||
95..101 '(x, y)': (i32, &'? str)
|
||||
93..104 '|&(x, y)| x': impl FnOnce(&'? (i32, &'static str)) -> i32
|
||||
94..101 '&(x, y)': &'? (i32, &'static str)
|
||||
95..101 '(x, y)': (i32, &'static str)
|
||||
96..97 'x': i32
|
||||
99..100 'y': &'? str
|
||||
99..100 'y': &'static str
|
||||
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
|
||||
146..155 '&(1, "a")': &'? (i32, &'static str)
|
||||
147..155 '(1, "a")': (i32, &'static str)
|
||||
148..149 '1': i32
|
||||
151..154 '"a"': &'static str
|
||||
157..167 '|(x, y)| x': impl FnOnce(&'? (i32, &'? str)) -> &'? i32
|
||||
158..164 '(x, y)': (i32, &'? str)
|
||||
157..167 '|(x, y)| x': impl FnOnce(&'? (i32, &'static str)) -> &'? i32
|
||||
158..164 '(x, y)': (i32, &'static str)
|
||||
159..160 'x': &'? i32
|
||||
162..163 'y': &'? &'? str
|
||||
162..163 'y': &'? &'static str
|
||||
166..167 'x': &'? i32
|
||||
"#]],
|
||||
);
|
||||
|
|
|
|||
|
|
@ -268,12 +268,12 @@ fn infer_std_crash_5() {
|
|||
expect![[r#"
|
||||
26..322 '{ ... } }': ()
|
||||
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... }': {unknown}
|
||||
32..320 'for co... }': &'? mut {unknown}
|
||||
32..320 'for co... }': <{unknown} as IntoIterator>::IntoIter
|
||||
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... }': Option<{unknown}>
|
||||
32..320 'for co... }': Option<<{unknown} as Iterator>::Item>
|
||||
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
|
||||
267..271 'self': Self
|
||||
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..508 'self.order': O
|
||||
498..515 'self.o...into()': dyn QueryFragment<DB> + '?
|
||||
|
|
@ -1248,7 +1248,7 @@ fn test() {
|
|||
16..66 'for _ ... }': {unknown}
|
||||
16..66 'for _ ... }': &'? mut {unknown}
|
||||
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 _ ... }': ()
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ impl<'a> IntoIterator for &'a Grid {
|
|||
"#,
|
||||
expect![[r#"
|
||||
150..154 'self': &'a Grid
|
||||
174..181 '{ }': impl Iterator<Item = &'a ()>
|
||||
174..181 '{ }': impl Iterator<Item = &'? ()>
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
fn coroutine_types_inferred() {
|
||||
check_infer(
|
||||
|
|
@ -1998,7 +2000,7 @@ fn test() {
|
|||
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..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
|
||||
245..246 'g': |usize| yields i64 -> &'static str
|
||||
255..261 '0usize': usize
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
use cov_mark::check;
|
||||
use expect_test::expect;
|
||||
|
||||
use crate::tests::infer_with_mismatches;
|
||||
|
||||
use super::{check, check_infer, check_infer_with_mismatches, check_no_mismatches, check_types};
|
||||
|
||||
#[test]
|
||||
|
|
@ -2460,7 +2462,7 @@ use core::ops::Index;
|
|||
|
||||
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;
|
||||
|
||||
fn len(&self) -> usize;
|
||||
|
|
@ -3634,8 +3636,7 @@ fn minimized() {
|
|||
|
||||
#[test]
|
||||
fn no_builtin_binop_expectation_for_general_ty_var() {
|
||||
// FIXME: Ideally type mismatch should be reported on `take_u32(42 - p)`.
|
||||
check_types(
|
||||
infer_with_mismatches(
|
||||
r#"
|
||||
//- minicore: add
|
||||
use core::ops::Add;
|
||||
|
|
@ -3659,6 +3660,7 @@ fn minimized() {
|
|||
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]
|
||||
fn gats_with_impl_trait() {
|
||||
// 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>) {
|
||||
let a = v.get::<T>();
|
||||
//^ &'a T
|
||||
//^ &'? T
|
||||
let a = v.get::<()>();
|
||||
//^ <impl Trait<Assoc<T> = &'a T> as Trait>::Assoc<()>
|
||||
}
|
||||
fn h<'a>(v: impl Trait<Assoc<i32> = &'a i32> + Trait<Assoc<i64> = &'a i64>) {
|
||||
let a = v.get::<i32>();
|
||||
//^ &'a i32
|
||||
//^ &'? i32
|
||||
let a = v.get::<i64>();
|
||||
//^ &'a i64
|
||||
//^ &'? i64
|
||||
}
|
||||
fn i<'a>(v: impl Trait<Assoc<i32> = &'a i32, Assoc<i64> = &'a i64>) {
|
||||
let a = v.get::<i32>();
|
||||
//^ &'a i32
|
||||
//^ &'? i32
|
||||
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> + '?)
|
||||
164..195 '{ ...f(); }': ()
|
||||
170..171 'v': &'? (dyn Trait<Assoc<i32> = &'a i32> + '?)
|
||||
170..184 'v.get::<i32>()': {unknown}
|
||||
170..192 'v.get:...eref()': &'? {unknown}
|
||||
170..184 'v.get::<i32>()': <dyn Trait<Assoc<i32> = &'a i32> + '? as Trait>::Assoc<i32>
|
||||
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]
|
||||
fn new_solver_crash_1() {
|
||||
check_infer(
|
||||
|
|
@ -4947,7 +4953,7 @@ where
|
|||
"#,
|
||||
expect![[r#"
|
||||
84..86 'de': D
|
||||
135..138 '{ }': <D as Deserializer<'de>>::Error
|
||||
135..138 '{ }': <D as Deserializer<'?>>::Error
|
||||
"#]],
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,9 +21,17 @@ use stdx::never;
|
|||
use triomphe::Arc;
|
||||
|
||||
use crate::{
|
||||
db::HirDatabase, infer::unify::InferenceTable, next_solver::{
|
||||
infer::{DbInternerInferExt, InferCtxt}, mapping::{convert_canonical_args_for_result, ChalkToNextSolver}, util::mini_canonicalize, DbInterner, GenericArg, Predicate, SolverContext, Span
|
||||
}, utils::UnevaluatedConstEvaluatorFolder, AliasEq, AliasTy, Canonical, DomainGoal, Goal, InEnvironment, Interner, ProjectionTy, ProjectionTyExt, TraitRefExt, Ty, TyKind, TypeFlags, WhereClause
|
||||
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:
|
||||
|
|
@ -282,30 +290,18 @@ pub fn next_trait_solve(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn next_trait_solve_canonical<'db>(
|
||||
db: &'db dyn HirDatabase,
|
||||
krate: Crate,
|
||||
block: Option<BlockId>,
|
||||
pub fn next_trait_solve_canonical_in_ctxt<'db>(
|
||||
infer_ctxt: &InferCtxt<'db>,
|
||||
goal: crate::next_solver::Canonical<'db, crate::next_solver::Goal<'db, Predicate<'db>>>,
|
||||
) -> NextTraitSolveResult {
|
||||
// FIXME: should use analysis_in_body, but that needs GenericDefId::Block
|
||||
let context = SolverContext(
|
||||
DbInterner::new_with(db, Some(krate), block)
|
||||
.infer_ctxt()
|
||||
.build(TypingMode::non_body_analysis()),
|
||||
);
|
||||
let context = SolverContext(infer_ctxt.clone());
|
||||
|
||||
tracing::info!(?goal);
|
||||
|
||||
let (goal, var_values) =
|
||||
context.instantiate_canonical(&goal);
|
||||
let (goal, var_values) = context.instantiate_canonical(&goal);
|
||||
tracing::info!(?var_values);
|
||||
|
||||
let res = context.evaluate_root_goal(
|
||||
goal.clone(),
|
||||
Span::dummy(),
|
||||
None
|
||||
);
|
||||
let res = context.evaluate_root_goal(goal, Span::dummy(), None);
|
||||
|
||||
let vars =
|
||||
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 {
|
||||
Err(_) => NextTraitSolveResult::NoSolution,
|
||||
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)) => {
|
||||
let subst = convert_canonical_args_for_result(
|
||||
DbInterner::new_with(db, Some(krate), block),
|
||||
args,
|
||||
);
|
||||
let subst = convert_canonical_args_for_result(infer_ctxt.interner, args);
|
||||
NextTraitSolveResult::Uncertain(chalk_ir::Canonical {
|
||||
binders: subst.binders,
|
||||
value: subst.value.subst,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,11 @@ use hir_expand::{
|
|||
mod_path::{ModPath, PathKind},
|
||||
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::{
|
||||
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)
|
||||
_ = 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,
|
||||
environment,
|
||||
&traits_in_scope,
|
||||
|
|
|
|||
|
|
@ -10,7 +10,8 @@ use crate::{
|
|||
fn check_expected_type_and_name(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect) {
|
||||
let (db, pos) = position(ra_fixture);
|
||||
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
|
||||
.expected_type
|
||||
|
|
|
|||
|
|
@ -526,8 +526,7 @@ fn main() {
|
|||
fn run(_t: Rate<5>) {
|
||||
}
|
||||
fn main() {
|
||||
run(f()) // FIXME: remove this error
|
||||
//^^^ error: expected Rate<5>, found Rate<_>
|
||||
run(f())
|
||||
}
|
||||
"#,
|
||||
);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ use expect_test::{Expect, expect};
|
|||
use hir::{FilePosition, FileRange};
|
||||
use ide_db::{
|
||||
EditionedFileId, FxHashSet,
|
||||
base_db::{SourceDatabase, salsa::Durability},
|
||||
base_db::{
|
||||
SourceDatabase,
|
||||
salsa::{self, Durability},
|
||||
},
|
||||
};
|
||||
use test_utils::RangeOrOffset;
|
||||
use triomphe::Arc;
|
||||
|
|
@ -116,7 +119,7 @@ fn assert_ssr_transforms(rules: &[&str], input: &str, expected: Expect) {
|
|||
let rule: SsrRule = rule.parse().unwrap();
|
||||
match_finder.add_rule(rule).unwrap();
|
||||
}
|
||||
let edits = match_finder.edits();
|
||||
let edits = salsa::attach(&db, || match_finder.edits());
|
||||
if edits.is_empty() {
|
||||
panic!("No edits were made");
|
||||
}
|
||||
|
|
@ -155,8 +158,12 @@ fn assert_matches(pattern: &str, code: &str, expected: &[&str]) {
|
|||
)
|
||||
.unwrap();
|
||||
match_finder.add_search_pattern(pattern.parse().unwrap()).unwrap();
|
||||
let matched_strings: Vec<String> =
|
||||
match_finder.matches().flattened().matches.iter().map(|m| m.matched_text()).collect();
|
||||
let matched_strings: Vec<String> = salsa::attach(&db, || match_finder.matches())
|
||||
.flattened()
|
||||
.matches
|
||||
.iter()
|
||||
.map(|m| m.matched_text())
|
||||
.collect();
|
||||
if matched_strings != expected && !expected.is_empty() {
|
||||
print_match_debug_info(&match_finder, position.file_id, expected[0]);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,7 +47,8 @@ fn check_rewrite(#[rust_analyzer::rust_fixture] ra_fixture: &str, expect: Expect
|
|||
let (analysis, position) = fixture::position(ra_fixture);
|
||||
let sema = &Semantics::new(&analysis.db);
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue