2019-04-20 05:34:36 -05:00
|
|
|
//! Unification and canonicalization logic.
|
|
|
|
|
2023-01-09 12:36:22 -06:00
|
|
|
use std::{fmt, iter, mem, sync::Arc};
|
2019-12-01 13:30:28 -06:00
|
|
|
|
2021-04-03 10:49:29 -05:00
|
|
|
use chalk_ir::{
|
2022-07-03 02:22:10 -05:00
|
|
|
cast::Cast, fold::TypeFoldable, interner::HasInterner, zip::Zip, CanonicalVarKind, FloatTy,
|
2022-10-18 01:12:49 -05:00
|
|
|
IntTy, TyVariableKind, UniverseIndex,
|
2021-04-03 10:49:29 -05:00
|
|
|
};
|
2021-04-11 04:20:45 -05:00
|
|
|
use chalk_solve::infer::ParameterEnaVariableExt;
|
|
|
|
use ena::unify::UnifyKey;
|
2023-02-13 05:55:14 -06:00
|
|
|
use hir_def::{FunctionId, TraitId};
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
use hir_expand::name;
|
2022-03-09 12:50:24 -06:00
|
|
|
use stdx::never;
|
2019-12-01 13:30:28 -06:00
|
|
|
|
2021-05-01 14:53:10 -05:00
|
|
|
use super::{InferOk, InferResult, InferenceContext, TypeError};
|
2020-04-05 11:24:18 -05:00
|
|
|
use crate::{
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
db::HirDatabase, fold_tys, static_lifetime, traits::FnTrait, AliasEq, AliasTy, BoundVar,
|
2022-03-09 12:50:24 -06:00
|
|
|
Canonical, Const, DebruijnIndex, GenericArg, GenericArgData, Goal, Guidance, InEnvironment,
|
|
|
|
InferenceVar, Interner, Lifetime, ParamKind, ProjectionTy, ProjectionTyExt, Scalar, Solution,
|
|
|
|
Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind, VariableKind,
|
2020-04-05 11:24:18 -05:00
|
|
|
};
|
2019-04-20 05:34:36 -05:00
|
|
|
|
2020-03-13 10:05:46 -05:00
|
|
|
impl<'a> InferenceContext<'a> {
|
2022-07-03 02:22:10 -05:00
|
|
|
pub(super) fn canonicalize<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>(
|
2021-04-11 04:20:45 -05:00
|
|
|
&mut self,
|
|
|
|
t: T,
|
2022-07-03 02:22:10 -05:00
|
|
|
) -> Canonicalized<T>
|
2019-04-20 05:34:36 -05:00
|
|
|
where
|
2022-07-03 02:22:10 -05:00
|
|
|
T: HasInterner<Interner = Interner>,
|
2019-04-20 05:34:36 -05:00
|
|
|
{
|
2021-05-16 08:50:28 -05:00
|
|
|
self.table.canonicalize(t)
|
2019-04-20 05:34:36 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-16 08:50:28 -05:00
|
|
|
#[derive(Debug, Clone)]
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
pub(crate) struct Canonicalized<T>
|
2021-04-03 10:49:29 -05:00
|
|
|
where
|
|
|
|
T: HasInterner<Interner = Interner>,
|
|
|
|
{
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
pub(crate) value: Canonical<T>,
|
2021-04-11 04:20:45 -05:00
|
|
|
free_vars: Vec<GenericArg>,
|
2019-05-04 08:42:00 -05:00
|
|
|
}
|
|
|
|
|
2021-04-03 10:49:29 -05:00
|
|
|
impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
|
2020-11-02 06:13:32 -06:00
|
|
|
pub(super) fn apply_solution(
|
|
|
|
&self,
|
2022-07-20 08:02:08 -05:00
|
|
|
ctx: &mut InferenceTable<'_>,
|
2021-03-15 15:02:34 -05:00
|
|
|
solution: Canonical<Substitution>,
|
2020-11-02 06:13:32 -06:00
|
|
|
) {
|
2019-04-20 05:34:36 -05:00
|
|
|
// the solution may contain new variables, which we need to convert to new inference vars
|
2021-04-01 14:04:02 -05:00
|
|
|
let new_vars = Substitution::from_iter(
|
2021-12-19 10:58:39 -06:00
|
|
|
Interner,
|
2022-03-09 12:50:24 -06:00
|
|
|
solution.binders.iter(Interner).map(|k| match &k.kind {
|
2021-12-19 10:58:39 -06:00
|
|
|
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),
|
2021-04-08 06:58:03 -05:00
|
|
|
// Chalk can sometimes return new lifetime variables. We just use the static lifetime everywhere
|
2021-12-19 10:58:39 -06:00
|
|
|
VariableKind::Lifetime => static_lifetime().cast(Interner),
|
2022-03-09 12:50:24 -06:00
|
|
|
VariableKind::Const(ty) => ctx.new_const_var(ty.clone()).cast(Interner),
|
2021-04-01 14:04:02 -05:00
|
|
|
}),
|
2020-06-28 14:17:27 -05:00
|
|
|
);
|
2021-12-19 10:58:39 -06:00
|
|
|
for (i, v) in solution.value.iter(Interner).enumerate() {
|
2021-05-01 14:53:10 -05:00
|
|
|
let var = self.free_vars[i].clone();
|
2021-12-19 10:58:39 -06:00
|
|
|
if let Some(ty) = v.ty(Interner) {
|
2021-05-15 16:09:18 -05:00
|
|
|
// eagerly replace projections in the type; we may be getting types
|
|
|
|
// e.g. from where clauses where this hasn't happened yet
|
2021-12-19 10:58:39 -06:00
|
|
|
let ty = ctx.normalize_associated_types_in(new_vars.apply(ty.clone(), Interner));
|
|
|
|
ctx.unify(var.assert_ty_ref(Interner), &ty);
|
2021-05-15 16:09:18 -05:00
|
|
|
} else {
|
2021-12-19 10:58:39 -06:00
|
|
|
let _ = ctx.try_unify(&var, &new_vars.apply(v.clone(), Interner));
|
2021-05-15 16:09:18 -05:00
|
|
|
}
|
2019-12-01 13:30:28 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-15 13:28:07 -05:00
|
|
|
pub fn could_unify(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
env: Arc<TraitEnvironment>,
|
|
|
|
tys: &Canonical<(Ty, Ty)>,
|
|
|
|
) -> bool {
|
|
|
|
unify(db, env, tys).is_some()
|
2021-03-16 10:45:46 -05:00
|
|
|
}
|
|
|
|
|
2021-04-11 04:20:45 -05:00
|
|
|
pub(crate) fn unify(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
env: Arc<TraitEnvironment>,
|
|
|
|
tys: &Canonical<(Ty, Ty)>,
|
|
|
|
) -> Option<Substitution> {
|
|
|
|
let mut table = InferenceTable::new(db, env);
|
2021-04-01 14:04:02 -05:00
|
|
|
let vars = Substitution::from_iter(
|
2021-12-19 10:58:39 -06:00
|
|
|
Interner,
|
2022-03-09 12:50:24 -06:00
|
|
|
tys.binders.iter(Interner).map(|x| match &x.kind {
|
|
|
|
chalk_ir::VariableKind::Ty(_) => {
|
|
|
|
GenericArgData::Ty(table.new_type_var()).intern(Interner)
|
|
|
|
}
|
|
|
|
chalk_ir::VariableKind::Lifetime => {
|
|
|
|
GenericArgData::Ty(table.new_type_var()).intern(Interner)
|
|
|
|
} // FIXME: maybe wrong?
|
|
|
|
chalk_ir::VariableKind::Const(ty) => {
|
|
|
|
GenericArgData::Const(table.new_const_var(ty.clone())).intern(Interner)
|
|
|
|
}
|
|
|
|
}),
|
2020-06-28 14:17:27 -05:00
|
|
|
);
|
2021-12-19 10:58:39 -06:00
|
|
|
let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner);
|
|
|
|
let ty2_with_vars = vars.apply(tys.value.1.clone(), Interner);
|
2020-03-01 07:31:35 -06:00
|
|
|
if !table.unify(&ty1_with_vars, &ty2_with_vars) {
|
2019-12-01 15:14:28 -06:00
|
|
|
return None;
|
|
|
|
}
|
2020-03-01 07:31:35 -06:00
|
|
|
// default any type vars that weren't unified back to their original bound vars
|
|
|
|
// (kind of hacky)
|
2021-05-09 13:06:24 -05:00
|
|
|
let find_var = |iv| {
|
2021-12-19 10:58:39 -06:00
|
|
|
vars.iter(Interner).position(|v| match v.interned() {
|
|
|
|
chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner),
|
|
|
|
chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
|
|
|
|
chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner),
|
2021-05-09 13:06:24 -05:00
|
|
|
} == Some(iv))
|
|
|
|
};
|
2021-05-13 12:44:29 -05:00
|
|
|
let fallback = |iv, kind, default, binder| match kind {
|
|
|
|
chalk_ir::VariableKind::Ty(_ty_kind) => find_var(iv)
|
2021-12-19 10:58:39 -06:00
|
|
|
.map_or(default, |i| BoundVar::new(binder, i).to_ty(Interner).cast(Interner)),
|
2021-05-13 12:44:29 -05:00
|
|
|
chalk_ir::VariableKind::Lifetime => find_var(iv)
|
2021-12-19 10:58:39 -06:00
|
|
|
.map_or(default, |i| BoundVar::new(binder, i).to_lifetime(Interner).cast(Interner)),
|
2021-05-13 12:44:29 -05:00
|
|
|
chalk_ir::VariableKind::Const(ty) => find_var(iv)
|
2021-12-19 10:58:39 -06:00
|
|
|
.map_or(default, |i| BoundVar::new(binder, i).to_const(Interner, ty).cast(Interner)),
|
2021-05-09 13:06:24 -05:00
|
|
|
};
|
2021-04-04 05:48:10 -05:00
|
|
|
Some(Substitution::from_iter(
|
2021-12-19 10:58:39 -06:00
|
|
|
Interner,
|
2022-03-09 12:50:24 -06:00
|
|
|
vars.iter(Interner).map(|v| table.resolve_with_fallback(v.clone(), &fallback)),
|
2021-04-04 05:48:10 -05:00
|
|
|
))
|
2019-12-01 13:30:28 -06:00
|
|
|
}
|
|
|
|
|
2023-01-09 12:36:22 -06:00
|
|
|
bitflags::bitflags! {
|
|
|
|
#[derive(Default)]
|
|
|
|
pub(crate) struct TypeVariableFlags: u8 {
|
|
|
|
const DIVERGING = 1 << 0;
|
|
|
|
const INTEGER = 1 << 1;
|
|
|
|
const FLOAT = 1 << 2;
|
|
|
|
}
|
2021-03-01 05:35:11 -06:00
|
|
|
}
|
|
|
|
|
2021-04-11 04:20:45 -05:00
|
|
|
type ChalkInferenceTable = chalk_solve::infer::InferenceTable<Interner>;
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub(crate) struct InferenceTable<'a> {
|
2021-05-21 12:50:18 -05:00
|
|
|
pub(crate) db: &'a dyn HirDatabase,
|
|
|
|
pub(crate) trait_env: Arc<TraitEnvironment>,
|
|
|
|
var_unification_table: ChalkInferenceTable,
|
2023-01-09 12:36:22 -06:00
|
|
|
type_variable_table: Vec<TypeVariableFlags>,
|
2021-05-16 08:50:28 -05:00
|
|
|
pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
|
2019-12-01 13:30:28 -06:00
|
|
|
}
|
|
|
|
|
2021-07-15 13:02:58 -05:00
|
|
|
pub(crate) struct InferenceTableSnapshot {
|
|
|
|
var_table_snapshot: chalk_solve::infer::InferenceSnapshot<Interner>,
|
2022-03-17 08:29:39 -05:00
|
|
|
pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
|
2023-01-09 12:36:22 -06:00
|
|
|
type_variable_table_snapshot: Vec<TypeVariableFlags>,
|
2021-07-15 13:02:58 -05:00
|
|
|
}
|
|
|
|
|
2021-04-11 04:20:45 -05:00
|
|
|
impl<'a> InferenceTable<'a> {
|
|
|
|
pub(crate) fn new(db: &'a dyn HirDatabase, trait_env: Arc<TraitEnvironment>) -> Self {
|
2021-03-01 05:35:11 -06:00
|
|
|
InferenceTable {
|
2021-04-11 04:20:45 -05:00
|
|
|
db,
|
|
|
|
trait_env,
|
|
|
|
var_unification_table: ChalkInferenceTable::new(),
|
2021-05-16 13:04:00 -05:00
|
|
|
type_variable_table: Vec::new(),
|
2021-05-16 08:50:28 -05:00
|
|
|
pending_obligations: Vec::new(),
|
2021-03-01 05:35:11 -06:00
|
|
|
}
|
2019-12-01 13:30:28 -06:00
|
|
|
}
|
|
|
|
|
2021-05-15 12:28:58 -05:00
|
|
|
/// Chalk doesn't know about the `diverging` flag, so when it unifies two
|
|
|
|
/// type variables of which one is diverging, the chosen root might not be
|
|
|
|
/// diverging and we have no way of marking it as such at that time. This
|
|
|
|
/// function goes through all type variables and make sure their root is
|
|
|
|
/// marked as diverging if necessary, so that resolving them gives the right
|
|
|
|
/// result.
|
|
|
|
pub(super) fn propagate_diverging_flag(&mut self) {
|
2021-05-16 13:04:00 -05:00
|
|
|
for i in 0..self.type_variable_table.len() {
|
2023-01-09 12:36:22 -06:00
|
|
|
if !self.type_variable_table[i].contains(TypeVariableFlags::DIVERGING) {
|
2021-05-15 12:28:58 -05:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let v = InferenceVar::from(i as u32);
|
|
|
|
let root = self.var_unification_table.inference_var_root(v);
|
2021-05-16 13:04:00 -05:00
|
|
|
if let Some(data) = self.type_variable_table.get_mut(root.index() as usize) {
|
2023-01-09 12:36:22 -06:00
|
|
|
*data |= TypeVariableFlags::DIVERGING;
|
2021-05-15 12:28:58 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-05-16 13:04:00 -05:00
|
|
|
pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
|
2023-01-09 12:36:22 -06:00
|
|
|
self.type_variable_table[iv.index() as usize].set(TypeVariableFlags::DIVERGING, diverging);
|
2021-05-16 13:04:00 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
|
|
|
|
match kind {
|
|
|
|
_ if self
|
|
|
|
.type_variable_table
|
|
|
|
.get(iv.index() as usize)
|
2023-01-09 12:36:22 -06:00
|
|
|
.map_or(false, |data| data.contains(TypeVariableFlags::DIVERGING)) =>
|
2021-05-16 13:04:00 -05:00
|
|
|
{
|
|
|
|
TyKind::Never
|
|
|
|
}
|
|
|
|
TyVariableKind::General => TyKind::Error,
|
|
|
|
TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
|
|
|
|
TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
|
|
|
|
}
|
2021-12-19 10:58:39 -06:00
|
|
|
.intern(Interner)
|
2021-05-16 13:04:00 -05:00
|
|
|
}
|
|
|
|
|
2022-07-03 02:22:10 -05:00
|
|
|
pub(crate) fn canonicalize<T: TypeFoldable<Interner> + HasInterner<Interner = Interner>>(
|
2021-05-16 08:50:28 -05:00
|
|
|
&mut self,
|
|
|
|
t: T,
|
2022-07-03 02:22:10 -05:00
|
|
|
) -> Canonicalized<T>
|
2021-05-16 08:50:28 -05:00
|
|
|
where
|
2022-07-03 02:22:10 -05:00
|
|
|
T: HasInterner<Interner = Interner>,
|
2021-05-16 08:50:28 -05:00
|
|
|
{
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
// try to resolve obligations before canonicalizing, since this might
|
|
|
|
// result in new knowledge about variables
|
|
|
|
self.resolve_obligations_as_possible();
|
2021-12-19 10:58:39 -06:00
|
|
|
let result = self.var_unification_table.canonicalize(Interner, t);
|
2021-05-16 08:50:28 -05:00
|
|
|
let free_vars = result
|
|
|
|
.free_vars
|
|
|
|
.into_iter()
|
2021-12-19 10:58:39 -06:00
|
|
|
.map(|free_var| free_var.to_generic_arg(Interner))
|
2021-05-16 08:50:28 -05:00
|
|
|
.collect();
|
|
|
|
Canonicalized { value: result.quantified, free_vars }
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Recurses through the given type, normalizing associated types mentioned
|
|
|
|
/// in it by replacing them by type variables and registering obligations to
|
|
|
|
/// resolve later. This should be done once for every type we get from some
|
|
|
|
/// type annotation (e.g. from a let type annotation, field type or function
|
|
|
|
/// call). `make_ty` handles this already, but e.g. for field types we need
|
|
|
|
/// to do it as well.
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
pub(crate) fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
|
2021-05-16 08:50:28 -05:00
|
|
|
fold_tys(
|
|
|
|
ty,
|
2021-12-19 10:58:39 -06:00
|
|
|
|ty, _| match ty.kind(Interner) {
|
2021-05-16 08:50:28 -05:00
|
|
|
TyKind::Alias(AliasTy::Projection(proj_ty)) => {
|
|
|
|
self.normalize_projection_ty(proj_ty.clone())
|
|
|
|
}
|
|
|
|
_ => ty,
|
|
|
|
},
|
|
|
|
DebruijnIndex::INNERMOST,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
pub(crate) fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
|
2021-05-16 08:50:28 -05:00
|
|
|
let var = self.new_type_var();
|
|
|
|
let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
|
2021-12-19 10:58:39 -06:00
|
|
|
let obligation = alias_eq.cast(Interner);
|
2021-05-16 08:50:28 -05:00
|
|
|
self.register_obligation(obligation);
|
|
|
|
var
|
|
|
|
}
|
|
|
|
|
2021-05-16 13:04:00 -05:00
|
|
|
fn extend_type_variable_table(&mut self, to_index: usize) {
|
2023-01-09 12:36:22 -06:00
|
|
|
let count = to_index - self.type_variable_table.len() + 1;
|
|
|
|
self.type_variable_table.extend(iter::repeat(TypeVariableFlags::default()).take(count));
|
2021-05-16 13:04:00 -05:00
|
|
|
}
|
|
|
|
|
2021-03-01 06:54:17 -06:00
|
|
|
fn new_var(&mut self, kind: TyVariableKind, diverging: bool) -> Ty {
|
2021-04-11 04:20:45 -05:00
|
|
|
let var = self.var_unification_table.new_variable(UniverseIndex::ROOT);
|
2021-05-15 12:28:58 -05:00
|
|
|
// Chalk might have created some type variables for its own purposes that we don't know about...
|
2021-05-16 13:04:00 -05:00
|
|
|
self.extend_type_variable_table(var.index() as usize);
|
|
|
|
assert_eq!(var.index() as usize, self.type_variable_table.len() - 1);
|
2023-01-09 12:36:22 -06:00
|
|
|
let flags = self.type_variable_table.get_mut(var.index() as usize).unwrap();
|
|
|
|
if diverging {
|
|
|
|
*flags |= TypeVariableFlags::DIVERGING;
|
|
|
|
}
|
|
|
|
if matches!(kind, TyVariableKind::Integer) {
|
|
|
|
*flags |= TypeVariableFlags::INTEGER;
|
|
|
|
} else if matches!(kind, TyVariableKind::Float) {
|
|
|
|
*flags |= TypeVariableFlags::FLOAT;
|
|
|
|
}
|
2021-12-19 10:58:39 -06:00
|
|
|
var.to_ty_with_kind(Interner, kind)
|
2021-03-01 06:54:17 -06:00
|
|
|
}
|
|
|
|
|
2020-11-02 06:13:32 -06:00
|
|
|
pub(crate) fn new_type_var(&mut self) -> Ty {
|
2021-03-01 06:54:17 -06:00
|
|
|
self.new_var(TyVariableKind::General, false)
|
2019-12-01 13:30:28 -06:00
|
|
|
}
|
|
|
|
|
2020-11-02 06:13:32 -06:00
|
|
|
pub(crate) fn new_integer_var(&mut self) -> Ty {
|
2021-03-01 06:54:17 -06:00
|
|
|
self.new_var(TyVariableKind::Integer, false)
|
2019-12-01 13:30:28 -06:00
|
|
|
}
|
|
|
|
|
2020-11-02 06:13:32 -06:00
|
|
|
pub(crate) fn new_float_var(&mut self) -> Ty {
|
2021-03-01 06:54:17 -06:00
|
|
|
self.new_var(TyVariableKind::Float, false)
|
2019-12-01 13:30:28 -06:00
|
|
|
}
|
|
|
|
|
2021-03-01 05:35:11 -06:00
|
|
|
pub(crate) fn new_maybe_never_var(&mut self) -> Ty {
|
2021-03-01 06:54:17 -06:00
|
|
|
self.new_var(TyVariableKind::General, true)
|
2019-12-01 13:30:28 -06:00
|
|
|
}
|
|
|
|
|
2021-08-21 12:47:06 -05:00
|
|
|
pub(crate) fn new_const_var(&mut self, ty: Ty) -> Const {
|
|
|
|
let var = self.var_unification_table.new_variable(UniverseIndex::ROOT);
|
2021-12-19 10:58:39 -06:00
|
|
|
var.to_const(Interner, ty)
|
2021-08-21 12:47:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn new_lifetime_var(&mut self) -> Lifetime {
|
|
|
|
let var = self.var_unification_table.new_variable(UniverseIndex::ROOT);
|
2021-12-19 10:58:39 -06:00
|
|
|
var.to_lifetime(Interner)
|
2021-08-21 12:47:06 -05:00
|
|
|
}
|
|
|
|
|
2021-05-09 13:06:24 -05:00
|
|
|
pub(crate) fn resolve_with_fallback<T>(
|
|
|
|
&mut self,
|
|
|
|
t: T,
|
2021-10-20 12:20:17 -05:00
|
|
|
fallback: &dyn Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
|
2022-07-03 02:22:10 -05:00
|
|
|
) -> T
|
2021-05-09 13:06:24 -05:00
|
|
|
where
|
2022-07-03 02:22:10 -05:00
|
|
|
T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
|
2021-05-09 13:06:24 -05:00
|
|
|
{
|
|
|
|
self.resolve_with_fallback_inner(&mut Vec::new(), t, &fallback)
|
|
|
|
}
|
|
|
|
|
2022-03-20 18:08:12 -05:00
|
|
|
pub(crate) fn fresh_subst(&mut self, binders: &[CanonicalVarKind<Interner>]) -> Substitution {
|
2022-03-20 10:19:02 -05:00
|
|
|
Substitution::from_iter(
|
|
|
|
Interner,
|
|
|
|
binders.iter().map(|kind| {
|
2022-03-20 18:08:12 -05:00
|
|
|
let param_infer_var =
|
|
|
|
kind.map_ref(|&ui| self.var_unification_table.new_variable(ui));
|
2022-03-20 10:19:02 -05:00
|
|
|
param_infer_var.to_generic_arg(Interner)
|
|
|
|
}),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-07-03 02:22:10 -05:00
|
|
|
pub(crate) fn instantiate_canonical<T>(&mut self, canonical: Canonical<T>) -> T
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
where
|
2022-07-03 02:22:10 -05:00
|
|
|
T: HasInterner<Interner = Interner> + TypeFoldable<Interner> + std::fmt::Debug,
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
{
|
2022-03-20 10:19:02 -05:00
|
|
|
let subst = self.fresh_subst(canonical.binders.as_slice(Interner));
|
|
|
|
subst.apply(canonical.value, Interner)
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
}
|
|
|
|
|
2021-05-09 13:06:24 -05:00
|
|
|
fn resolve_with_fallback_inner<T>(
|
|
|
|
&mut self,
|
|
|
|
var_stack: &mut Vec<InferenceVar>,
|
|
|
|
t: T,
|
2021-10-20 12:20:17 -05:00
|
|
|
fallback: &dyn Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
|
2022-07-03 02:22:10 -05:00
|
|
|
) -> T
|
2021-05-09 13:06:24 -05:00
|
|
|
where
|
2022-07-03 02:22:10 -05:00
|
|
|
T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
|
2021-05-09 13:06:24 -05:00
|
|
|
{
|
2021-05-13 12:44:29 -05:00
|
|
|
t.fold_with(
|
2021-05-16 13:04:00 -05:00
|
|
|
&mut resolve::Resolver { table: self, var_stack, fallback },
|
2021-05-09 13:06:24 -05:00
|
|
|
DebruijnIndex::INNERMOST,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-07-03 02:22:10 -05:00
|
|
|
pub(crate) fn resolve_completely<T>(&mut self, t: T) -> T
|
2021-05-23 09:59:23 -05:00
|
|
|
where
|
2022-07-03 02:22:10 -05:00
|
|
|
T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
|
2021-05-23 09:59:23 -05:00
|
|
|
{
|
2021-10-20 12:20:17 -05:00
|
|
|
self.resolve_with_fallback(t, &|_, _, d, _| d)
|
2019-12-01 13:30:28 -06:00
|
|
|
}
|
|
|
|
|
2023-01-09 12:36:22 -06:00
|
|
|
/// Apply a fallback to unresolved scalar types. Integer type variables and float type
|
|
|
|
/// variables are replaced with i32 and f64, respectively.
|
|
|
|
///
|
|
|
|
/// This method is only intended to be called just before returning inference results (i.e. in
|
|
|
|
/// `InferenceContext::resolve_all()`).
|
|
|
|
///
|
|
|
|
/// FIXME: This method currently doesn't apply fallback to unconstrained general type variables
|
|
|
|
/// whereas rustc replaces them with `()` or `!`.
|
|
|
|
pub(super) fn fallback_if_possible(&mut self) {
|
|
|
|
let int_fallback = TyKind::Scalar(Scalar::Int(IntTy::I32)).intern(Interner);
|
|
|
|
let float_fallback = TyKind::Scalar(Scalar::Float(FloatTy::F64)).intern(Interner);
|
|
|
|
|
|
|
|
let scalar_vars: Vec<_> = self
|
|
|
|
.type_variable_table
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.filter_map(|(index, flags)| {
|
|
|
|
let kind = if flags.contains(TypeVariableFlags::INTEGER) {
|
|
|
|
TyVariableKind::Integer
|
|
|
|
} else if flags.contains(TypeVariableFlags::FLOAT) {
|
|
|
|
TyVariableKind::Float
|
|
|
|
} else {
|
|
|
|
return None;
|
|
|
|
};
|
|
|
|
|
|
|
|
// FIXME: This is not really the nicest way to get `InferenceVar`s. Can we get them
|
|
|
|
// without directly constructing them from `index`?
|
|
|
|
let var = InferenceVar::from(index as u32).to_ty(Interner, kind);
|
|
|
|
Some(var)
|
|
|
|
})
|
|
|
|
.collect();
|
|
|
|
|
|
|
|
for var in scalar_vars {
|
|
|
|
let maybe_resolved = self.resolve_ty_shallow(&var);
|
|
|
|
if let TyKind::InferenceVar(_, kind) = maybe_resolved.kind(Interner) {
|
|
|
|
let fallback = match kind {
|
|
|
|
TyVariableKind::Integer => &int_fallback,
|
|
|
|
TyVariableKind::Float => &float_fallback,
|
|
|
|
TyVariableKind::General => unreachable!(),
|
|
|
|
};
|
|
|
|
self.unify(&var, fallback);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-01 04:31:31 -05:00
|
|
|
/// Unify two relatable values (e.g. `Ty`) and register new trait goals that arise from that.
|
|
|
|
pub(crate) fn unify<T: ?Sized + Zip<Interner>>(&mut self, ty1: &T, ty2: &T) -> bool {
|
2021-10-03 07:53:01 -05:00
|
|
|
let result = match self.try_unify(ty1, ty2) {
|
|
|
|
Ok(r) => r,
|
|
|
|
Err(_) => return false,
|
2021-04-11 04:20:45 -05:00
|
|
|
};
|
2021-05-16 11:27:17 -05:00
|
|
|
self.register_infer_ok(result);
|
2021-04-11 04:20:45 -05:00
|
|
|
true
|
2020-04-17 12:41:37 -05:00
|
|
|
}
|
|
|
|
|
2022-11-01 04:31:31 -05:00
|
|
|
/// Unify two relatable values (e.g. `Ty`) and return new trait goals arising from it, so the
|
2021-05-01 14:53:10 -05:00
|
|
|
/// caller needs to deal with them.
|
2022-11-01 04:31:31 -05:00
|
|
|
pub(crate) fn try_unify<T: ?Sized + Zip<Interner>>(
|
|
|
|
&mut self,
|
|
|
|
t1: &T,
|
|
|
|
t2: &T,
|
|
|
|
) -> InferResult<()> {
|
2021-05-01 14:53:10 -05:00
|
|
|
match self.var_unification_table.relate(
|
2021-12-19 10:58:39 -06:00
|
|
|
Interner,
|
2021-05-01 14:53:10 -05:00
|
|
|
&self.db,
|
|
|
|
&self.trait_env.env,
|
|
|
|
chalk_ir::Variance::Invariant,
|
2021-05-15 16:09:18 -05:00
|
|
|
t1,
|
|
|
|
t2,
|
2021-05-01 14:53:10 -05:00
|
|
|
) {
|
2021-07-06 11:05:40 -05:00
|
|
|
Ok(result) => Ok(InferOk { goals: result.goals, value: () }),
|
2021-05-02 09:20:37 -05:00
|
|
|
Err(chalk_ir::NoSolution) => Err(TypeError),
|
2021-05-01 14:53:10 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 13:30:28 -06:00
|
|
|
/// If `ty` is a type variable with known type, returns that type;
|
|
|
|
/// otherwise, return ty.
|
2021-05-16 08:56:27 -05:00
|
|
|
pub(crate) fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
self.resolve_obligations_as_possible();
|
2021-12-19 10:58:39 -06:00
|
|
|
self.var_unification_table.normalize_ty_shallow(Interner, ty).unwrap_or_else(|| ty.clone())
|
2019-12-01 13:30:28 -06:00
|
|
|
}
|
|
|
|
|
2021-07-15 13:02:58 -05:00
|
|
|
pub(crate) fn snapshot(&mut self) -> InferenceTableSnapshot {
|
2022-03-05 03:59:28 -06:00
|
|
|
let var_table_snapshot = self.var_unification_table.snapshot();
|
|
|
|
let type_variable_table_snapshot = self.type_variable_table.clone();
|
2022-03-17 08:29:39 -05:00
|
|
|
let pending_obligations = self.pending_obligations.clone();
|
|
|
|
InferenceTableSnapshot {
|
|
|
|
var_table_snapshot,
|
|
|
|
pending_obligations,
|
|
|
|
type_variable_table_snapshot,
|
|
|
|
}
|
2021-07-15 13:02:58 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn rollback_to(&mut self, snapshot: InferenceTableSnapshot) {
|
|
|
|
self.var_unification_table.rollback_to(snapshot.var_table_snapshot);
|
2022-03-05 03:59:28 -06:00
|
|
|
self.type_variable_table = snapshot.type_variable_table_snapshot;
|
2022-03-17 08:29:39 -05:00
|
|
|
self.pending_obligations = snapshot.pending_obligations;
|
2021-07-15 13:02:58 -05:00
|
|
|
}
|
|
|
|
|
2022-07-20 08:02:08 -05:00
|
|
|
pub(crate) fn run_in_snapshot<T>(&mut self, f: impl FnOnce(&mut InferenceTable<'_>) -> T) -> T {
|
2022-03-17 11:02:58 -05:00
|
|
|
let snapshot = self.snapshot();
|
|
|
|
let result = f(self);
|
|
|
|
self.rollback_to(snapshot);
|
|
|
|
result
|
|
|
|
}
|
|
|
|
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
/// Checks an obligation without registering it. Useful mostly to check
|
|
|
|
/// whether a trait *might* be implemented before deciding to 'lock in' the
|
|
|
|
/// choice (during e.g. method resolution or deref).
|
|
|
|
pub(crate) fn try_obligation(&mut self, goal: Goal) -> Option<Solution> {
|
|
|
|
let in_env = InEnvironment::new(&self.trait_env.env, goal);
|
|
|
|
let canonicalized = self.canonicalize(in_env);
|
|
|
|
let solution = self.db.trait_solve(self.trait_env.krate, canonicalized.value);
|
|
|
|
solution
|
|
|
|
}
|
|
|
|
|
2021-05-21 12:50:18 -05:00
|
|
|
pub(crate) fn register_obligation(&mut self, goal: Goal) {
|
2021-05-16 08:50:28 -05:00
|
|
|
let in_env = InEnvironment::new(&self.trait_env.env, goal);
|
|
|
|
self.register_obligation_in_env(in_env)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn register_obligation_in_env(&mut self, goal: InEnvironment<Goal>) {
|
|
|
|
let canonicalized = self.canonicalize(goal);
|
|
|
|
if !self.try_resolve_obligation(&canonicalized) {
|
|
|
|
self.pending_obligations.push(canonicalized);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-06 11:05:40 -05:00
|
|
|
pub(crate) fn register_infer_ok<T>(&mut self, infer_ok: InferOk<T>) {
|
2021-05-16 11:27:17 -05:00
|
|
|
infer_ok.goals.into_iter().for_each(|goal| self.register_obligation_in_env(goal));
|
|
|
|
}
|
|
|
|
|
2021-05-21 12:50:18 -05:00
|
|
|
pub(crate) fn resolve_obligations_as_possible(&mut self) {
|
2021-05-16 08:50:28 -05:00
|
|
|
let _span = profile::span("resolve_obligations_as_possible");
|
|
|
|
let mut changed = true;
|
|
|
|
let mut obligations = Vec::new();
|
|
|
|
while changed {
|
|
|
|
changed = false;
|
|
|
|
mem::swap(&mut self.pending_obligations, &mut obligations);
|
|
|
|
for canonicalized in obligations.drain(..) {
|
|
|
|
if !self.check_changed(&canonicalized) {
|
|
|
|
self.pending_obligations.push(canonicalized);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
changed = true;
|
|
|
|
let uncanonical = chalk_ir::Substitute::apply(
|
|
|
|
&canonicalized.free_vars,
|
|
|
|
canonicalized.value.value,
|
2021-12-19 10:58:39 -06:00
|
|
|
Interner,
|
2021-05-16 08:50:28 -05:00
|
|
|
);
|
|
|
|
self.register_obligation_in_env(uncanonical);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-03 02:22:10 -05:00
|
|
|
pub(crate) fn fudge_inference<T: TypeFoldable<Interner>>(
|
2021-08-21 12:47:06 -05:00
|
|
|
&mut self,
|
|
|
|
f: impl FnOnce(&mut Self) -> T,
|
2022-07-03 02:22:10 -05:00
|
|
|
) -> T {
|
|
|
|
use chalk_ir::fold::TypeFolder;
|
2022-10-18 01:12:49 -05:00
|
|
|
|
|
|
|
#[derive(chalk_derive::FallibleTypeFolder)]
|
|
|
|
#[has_interner(Interner)]
|
2021-08-21 12:47:06 -05:00
|
|
|
struct VarFudger<'a, 'b> {
|
|
|
|
table: &'a mut InferenceTable<'b>,
|
|
|
|
highest_known_var: InferenceVar,
|
|
|
|
}
|
2022-07-03 02:22:10 -05:00
|
|
|
impl<'a, 'b> TypeFolder<Interner> for VarFudger<'a, 'b> {
|
|
|
|
fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
|
2021-08-21 12:47:06 -05:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-12-19 10:58:39 -06:00
|
|
|
fn interner(&self) -> Interner {
|
|
|
|
Interner
|
2021-08-21 12:47:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_inference_ty(
|
|
|
|
&mut self,
|
|
|
|
var: chalk_ir::InferenceVar,
|
|
|
|
kind: TyVariableKind,
|
|
|
|
_outer_binder: chalk_ir::DebruijnIndex,
|
2022-10-18 01:12:49 -05:00
|
|
|
) -> chalk_ir::Ty<Interner> {
|
|
|
|
if var < self.highest_known_var {
|
2021-12-19 10:58:39 -06:00
|
|
|
var.to_ty(Interner, kind)
|
2021-08-21 12:47:06 -05:00
|
|
|
} else {
|
|
|
|
self.table.new_type_var()
|
2022-10-18 01:12:49 -05:00
|
|
|
}
|
2021-08-21 12:47:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_inference_lifetime(
|
|
|
|
&mut self,
|
|
|
|
var: chalk_ir::InferenceVar,
|
|
|
|
_outer_binder: chalk_ir::DebruijnIndex,
|
2022-10-18 01:12:49 -05:00
|
|
|
) -> chalk_ir::Lifetime<Interner> {
|
|
|
|
if var < self.highest_known_var {
|
2021-12-19 10:58:39 -06:00
|
|
|
var.to_lifetime(Interner)
|
2021-08-21 12:47:06 -05:00
|
|
|
} else {
|
|
|
|
self.table.new_lifetime_var()
|
2022-10-18 01:12:49 -05:00
|
|
|
}
|
2021-08-21 12:47:06 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_inference_const(
|
|
|
|
&mut self,
|
|
|
|
ty: chalk_ir::Ty<Interner>,
|
|
|
|
var: chalk_ir::InferenceVar,
|
|
|
|
_outer_binder: chalk_ir::DebruijnIndex,
|
2022-10-18 01:12:49 -05:00
|
|
|
) -> chalk_ir::Const<Interner> {
|
|
|
|
if var < self.highest_known_var {
|
2021-12-19 10:58:39 -06:00
|
|
|
var.to_const(Interner, ty)
|
2021-08-21 12:47:06 -05:00
|
|
|
} else {
|
|
|
|
self.table.new_const_var(ty)
|
2022-10-18 01:12:49 -05:00
|
|
|
}
|
2021-08-21 12:47:06 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
let snapshot = self.snapshot();
|
2021-12-19 10:58:39 -06:00
|
|
|
let highest_known_var = self.new_type_var().inference_var(Interner).expect("inference_var");
|
2021-08-21 12:47:06 -05:00
|
|
|
let result = f(self);
|
|
|
|
self.rollback_to(snapshot);
|
|
|
|
result
|
2021-09-03 09:00:50 -05:00
|
|
|
.fold_with(&mut VarFudger { table: self, highest_known_var }, DebruijnIndex::INNERMOST)
|
2021-08-21 12:47:06 -05:00
|
|
|
}
|
|
|
|
|
2021-05-16 08:50:28 -05:00
|
|
|
/// This checks whether any of the free variables in the `canonicalized`
|
|
|
|
/// have changed (either been unified with another variable, or with a
|
|
|
|
/// value). If this is not the case, we don't need to try to solve the goal
|
|
|
|
/// again -- it'll give the same result as last time.
|
|
|
|
fn check_changed(&mut self, canonicalized: &Canonicalized<InEnvironment<Goal>>) -> bool {
|
|
|
|
canonicalized.free_vars.iter().any(|var| {
|
2021-12-19 10:58:39 -06:00
|
|
|
let iv = match var.data(Interner) {
|
|
|
|
chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner),
|
|
|
|
chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
|
|
|
|
chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner),
|
2021-05-16 08:50:28 -05:00
|
|
|
}
|
|
|
|
.expect("free var is not inference var");
|
|
|
|
if self.var_unification_table.probe_var(iv).is_some() {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
let root = self.var_unification_table.inference_var_root(iv);
|
|
|
|
iv != root
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
fn try_resolve_obligation(
|
|
|
|
&mut self,
|
|
|
|
canonicalized: &Canonicalized<InEnvironment<Goal>>,
|
|
|
|
) -> bool {
|
|
|
|
let solution = self.db.trait_solve(self.trait_env.krate, canonicalized.value.clone());
|
|
|
|
|
|
|
|
match solution {
|
|
|
|
Some(Solution::Unique(canonical_subst)) => {
|
|
|
|
canonicalized.apply_solution(
|
|
|
|
self,
|
|
|
|
Canonical {
|
|
|
|
binders: canonical_subst.binders,
|
|
|
|
// FIXME: handle constraints
|
|
|
|
value: canonical_subst.value.subst,
|
|
|
|
},
|
|
|
|
);
|
|
|
|
true
|
|
|
|
}
|
|
|
|
Some(Solution::Ambig(Guidance::Definite(substs))) => {
|
|
|
|
canonicalized.apply_solution(self, substs);
|
|
|
|
false
|
|
|
|
}
|
|
|
|
Some(_) => {
|
|
|
|
// FIXME use this when trying to resolve everything at the end
|
|
|
|
false
|
|
|
|
}
|
|
|
|
None => {
|
|
|
|
// FIXME obligation cannot be fulfilled => diagnostic
|
|
|
|
true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
|
2023-02-13 05:55:14 -06:00
|
|
|
pub(crate) fn callable_sig(
|
|
|
|
&mut self,
|
|
|
|
ty: &Ty,
|
|
|
|
num_args: usize,
|
|
|
|
) -> Option<(Option<(TraitId, FunctionId)>, Vec<Ty>, Ty)> {
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
match ty.callable_sig(self.db) {
|
2023-02-13 05:55:14 -06:00
|
|
|
Some(sig) => Some((None, sig.params().to_vec(), sig.ret().clone())),
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
None => self.callable_sig_from_fn_trait(ty, num_args),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-13 05:55:14 -06:00
|
|
|
fn callable_sig_from_fn_trait(
|
|
|
|
&mut self,
|
|
|
|
ty: &Ty,
|
|
|
|
num_args: usize,
|
|
|
|
) -> Option<(Option<(TraitId, FunctionId)>, Vec<Ty>, Ty)> {
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
let krate = self.trait_env.krate;
|
|
|
|
let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
|
2023-02-13 05:55:14 -06:00
|
|
|
let trait_data = self.db.trait_data(fn_once_trait);
|
|
|
|
let output_assoc_type = trait_data.associated_type_by_name(&name![Output])?;
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
|
|
|
|
let mut arg_tys = vec![];
|
|
|
|
let arg_ty = TyBuilder::tuple(num_args)
|
2022-03-09 12:50:24 -06:00
|
|
|
.fill(|x| {
|
|
|
|
let arg = match x {
|
|
|
|
ParamKind::Type => self.new_type_var(),
|
|
|
|
ParamKind::Const(ty) => {
|
|
|
|
never!("Tuple with const parameter");
|
|
|
|
return GenericArgData::Const(self.new_const_var(ty.clone()))
|
|
|
|
.intern(Interner);
|
|
|
|
}
|
|
|
|
};
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
arg_tys.push(arg.clone());
|
2022-03-09 12:50:24 -06:00
|
|
|
GenericArgData::Ty(arg).intern(Interner)
|
|
|
|
})
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
.build();
|
|
|
|
|
|
|
|
let projection = {
|
2022-10-11 02:37:35 -05:00
|
|
|
let b = TyBuilder::subst_for_def(self.db, fn_once_trait, None);
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
if b.remaining() != 2 {
|
|
|
|
return None;
|
|
|
|
}
|
2022-10-11 02:37:35 -05:00
|
|
|
let fn_once_subst = b.push(ty.clone()).push(arg_ty).build();
|
|
|
|
|
|
|
|
TyBuilder::assoc_type_projection(self.db, output_assoc_type, Some(fn_once_subst))
|
|
|
|
.build()
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
};
|
|
|
|
|
|
|
|
let trait_env = self.trait_env.env.clone();
|
|
|
|
let obligation = InEnvironment {
|
|
|
|
goal: projection.trait_ref(self.db).cast(Interner),
|
|
|
|
environment: trait_env,
|
|
|
|
};
|
|
|
|
let canonical = self.canonicalize(obligation.clone());
|
|
|
|
if self.db.trait_solve(krate, canonical.value.cast(Interner)).is_some() {
|
|
|
|
self.register_obligation(obligation.goal);
|
|
|
|
let return_ty = self.normalize_projection_ty(projection);
|
2023-02-13 05:55:14 -06:00
|
|
|
Some((
|
|
|
|
Some(fn_once_trait).zip(trait_data.method_by_name(&name!(call_once))),
|
|
|
|
arg_tys,
|
|
|
|
return_ty,
|
|
|
|
))
|
Refactor autoderef and method resolution
- don't return the receiver type from method resolution; instead just
return the autorefs/autoderefs that happened and repeat them. This
ensures all the effects like trait obligations and whatever we learned
about type variables from derefing them are actually applied. Also, it
allows us to get rid of `decanonicalize_ty`, which was just wrong in
principle.
- Autoderef itself now directly works with an inference table. Sadly
this has the effect of making it harder to use as an iterator, often
requiring manual `while let` loops. (rustc works around this by using
inner mutability in the inference context, so that things like unifying
types don't require a unique reference.)
- We now record the adjustments (autoref/deref) for method receivers
and index expressions, which we didn't before.
- Removed the redundant crate parameter from method resolution, since
the trait_env contains the crate as well.
- in the HIR API, the methods now take a scope to determine the trait env.
`Type` carries a trait env, but I think that's probably a bad decision
because it's easy to create it with the wrong env, e.g. by using
`Adt::ty`. This mostly didn't matter so far because
`iterate_method_candidates` took a crate parameter and ignored
`self.krate`, but the trait env would still have been wrong in those
cases, which I think would give some wrong results in some edge cases.
Fixes #10058.
2022-02-16 10:44:03 -06:00
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2019-12-01 13:30:28 -06:00
|
|
|
}
|
|
|
|
|
2021-04-11 04:20:45 -05:00
|
|
|
impl<'a> fmt::Debug for InferenceTable<'a> {
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2021-05-16 13:04:00 -05:00
|
|
|
f.debug_struct("InferenceTable").field("num_vars", &self.type_variable_table.len()).finish()
|
2019-04-20 05:34:36 -05:00
|
|
|
}
|
|
|
|
}
|
2021-05-13 12:44:29 -05:00
|
|
|
|
|
|
|
mod resolve {
|
2021-05-16 13:04:00 -05:00
|
|
|
use super::InferenceTable;
|
2021-05-13 12:44:29 -05:00
|
|
|
use crate::{
|
|
|
|
ConcreteConst, Const, ConstData, ConstValue, DebruijnIndex, GenericArg, InferenceVar,
|
2021-05-22 07:25:58 -05:00
|
|
|
Interner, Lifetime, Ty, TyVariableKind, VariableKind,
|
2021-05-13 12:44:29 -05:00
|
|
|
};
|
|
|
|
use chalk_ir::{
|
|
|
|
cast::Cast,
|
2022-07-03 02:22:10 -05:00
|
|
|
fold::{TypeFoldable, TypeFolder},
|
2021-05-13 12:44:29 -05:00
|
|
|
};
|
|
|
|
use hir_def::type_ref::ConstScalar;
|
|
|
|
|
2022-10-18 01:12:49 -05:00
|
|
|
#[derive(chalk_derive::FallibleTypeFolder)]
|
|
|
|
#[has_interner(Interner)]
|
|
|
|
pub(super) struct Resolver<
|
|
|
|
'a,
|
|
|
|
'b,
|
|
|
|
F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
|
|
|
|
> {
|
2021-05-21 12:50:18 -05:00
|
|
|
pub(super) table: &'a mut InferenceTable<'b>,
|
|
|
|
pub(super) var_stack: &'a mut Vec<InferenceVar>,
|
|
|
|
pub(super) fallback: F,
|
2021-05-13 12:44:29 -05:00
|
|
|
}
|
2022-10-18 01:12:49 -05:00
|
|
|
impl<'a, 'b, F> TypeFolder<Interner> for Resolver<'a, 'b, F>
|
2021-05-13 12:44:29 -05:00
|
|
|
where
|
2022-10-18 01:12:49 -05:00
|
|
|
F: Fn(InferenceVar, VariableKind, GenericArg, DebruijnIndex) -> GenericArg,
|
2021-05-13 12:44:29 -05:00
|
|
|
{
|
2022-07-03 02:22:10 -05:00
|
|
|
fn as_dyn(&mut self) -> &mut dyn TypeFolder<Interner, Error = Self::Error> {
|
2021-05-13 12:44:29 -05:00
|
|
|
self
|
|
|
|
}
|
|
|
|
|
2021-12-19 10:58:39 -06:00
|
|
|
fn interner(&self) -> Interner {
|
|
|
|
Interner
|
2021-05-13 12:44:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_inference_ty(
|
|
|
|
&mut self,
|
|
|
|
var: InferenceVar,
|
|
|
|
kind: TyVariableKind,
|
|
|
|
outer_binder: DebruijnIndex,
|
2022-10-18 01:12:49 -05:00
|
|
|
) -> Ty {
|
2021-05-16 13:04:00 -05:00
|
|
|
let var = self.table.var_unification_table.inference_var_root(var);
|
2021-05-13 12:44:29 -05:00
|
|
|
if self.var_stack.contains(&var) {
|
|
|
|
// recursive type
|
2021-12-19 10:58:39 -06:00
|
|
|
let default = self.table.fallback_value(var, kind).cast(Interner);
|
2022-10-18 01:12:49 -05:00
|
|
|
return (self.fallback)(var, VariableKind::Ty(kind), default, outer_binder)
|
2021-12-19 10:58:39 -06:00
|
|
|
.assert_ty_ref(Interner)
|
2022-10-18 01:12:49 -05:00
|
|
|
.clone();
|
2021-05-13 12:44:29 -05:00
|
|
|
}
|
2021-05-16 13:04:00 -05:00
|
|
|
let result = if let Some(known_ty) = self.table.var_unification_table.probe_var(var) {
|
2021-05-13 12:44:29 -05:00
|
|
|
// known_ty may contain other variables that are known by now
|
|
|
|
self.var_stack.push(var);
|
2022-10-18 01:12:49 -05:00
|
|
|
let result = known_ty.fold_with(self, outer_binder);
|
2021-05-13 12:44:29 -05:00
|
|
|
self.var_stack.pop();
|
2021-12-19 10:58:39 -06:00
|
|
|
result.assert_ty_ref(Interner).clone()
|
2021-05-13 12:44:29 -05:00
|
|
|
} else {
|
2021-12-19 10:58:39 -06:00
|
|
|
let default = self.table.fallback_value(var, kind).cast(Interner);
|
2021-05-13 12:44:29 -05:00
|
|
|
(self.fallback)(var, VariableKind::Ty(kind), default, outer_binder)
|
2021-12-19 10:58:39 -06:00
|
|
|
.assert_ty_ref(Interner)
|
2021-05-13 12:44:29 -05:00
|
|
|
.clone()
|
|
|
|
};
|
2022-10-18 01:12:49 -05:00
|
|
|
result
|
2021-05-13 12:44:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn fold_inference_const(
|
|
|
|
&mut self,
|
|
|
|
ty: Ty,
|
|
|
|
var: InferenceVar,
|
|
|
|
outer_binder: DebruijnIndex,
|
2022-10-18 01:12:49 -05:00
|
|
|
) -> Const {
|
2021-05-16 13:04:00 -05:00
|
|
|
let var = self.table.var_unification_table.inference_var_root(var);
|
2021-05-13 12:44:29 -05:00
|
|
|
let default = ConstData {
|
|
|
|
ty: ty.clone(),
|
|
|
|
value: ConstValue::Concrete(ConcreteConst { interned: ConstScalar::Unknown }),
|
|
|
|
}
|
2021-12-19 10:58:39 -06:00
|
|
|
.intern(Interner)
|
|
|
|
.cast(Interner);
|
2021-05-13 12:44:29 -05:00
|
|
|
if self.var_stack.contains(&var) {
|
|
|
|
// recursive
|
2022-10-18 01:12:49 -05:00
|
|
|
return (self.fallback)(var, VariableKind::Const(ty), default, outer_binder)
|
2021-12-19 10:58:39 -06:00
|
|
|
.assert_const_ref(Interner)
|
2022-10-18 01:12:49 -05:00
|
|
|
.clone();
|
2021-05-13 12:44:29 -05:00
|
|
|
}
|
2022-10-18 01:12:49 -05:00
|
|
|
if let Some(known_ty) = self.table.var_unification_table.probe_var(var) {
|
2021-05-13 12:44:29 -05:00
|
|
|
// known_ty may contain other variables that are known by now
|
|
|
|
self.var_stack.push(var);
|
2022-10-18 01:12:49 -05:00
|
|
|
let result = known_ty.fold_with(self, outer_binder);
|
2021-05-13 12:44:29 -05:00
|
|
|
self.var_stack.pop();
|
2021-12-19 10:58:39 -06:00
|
|
|
result.assert_const_ref(Interner).clone()
|
2021-05-13 12:44:29 -05:00
|
|
|
} else {
|
|
|
|
(self.fallback)(var, VariableKind::Const(ty), default, outer_binder)
|
2021-12-19 10:58:39 -06:00
|
|
|
.assert_const_ref(Interner)
|
2021-05-13 12:44:29 -05:00
|
|
|
.clone()
|
2022-10-18 01:12:49 -05:00
|
|
|
}
|
2021-05-13 12:44:29 -05:00
|
|
|
}
|
2021-05-22 07:25:58 -05:00
|
|
|
|
|
|
|
fn fold_inference_lifetime(
|
|
|
|
&mut self,
|
|
|
|
_var: InferenceVar,
|
|
|
|
_outer_binder: DebruijnIndex,
|
2022-10-18 01:12:49 -05:00
|
|
|
) -> Lifetime {
|
2021-05-22 07:25:58 -05:00
|
|
|
// fall back all lifetimes to 'static -- currently we don't deal
|
|
|
|
// with any lifetimes, but we can sometimes get some lifetime
|
|
|
|
// variables through Chalk's unification, and this at least makes
|
|
|
|
// sure we don't leak them outside of inference
|
2022-10-18 01:12:49 -05:00
|
|
|
crate::static_lifetime()
|
2021-05-22 07:25:58 -05:00
|
|
|
}
|
2021-05-13 12:44:29 -05:00
|
|
|
}
|
|
|
|
}
|