2019-01-08 17:47:12 -06:00
|
|
|
//! In certain situations, rust automatically inserts derefs as necessary: for
|
2019-01-06 12:51:42 -06:00
|
|
|
//! example, field accesses `foo.bar` still work when `foo` is actually a
|
|
|
|
//! reference to a type with the field `bar`. This is an approximation of the
|
2022-09-26 06:00:29 -05:00
|
|
|
//! logic in rustc (which lives in rustc_hir_analysis/check/autoderef.rs).
|
2019-01-06 12:51:42 -06: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
|
|
|
use chalk_ir::cast::Cast;
|
2023-03-30 02:37:52 -05:00
|
|
|
use hir_def::lang_item::LangItem;
|
2019-12-13 15:01:06 -06:00
|
|
|
use hir_expand::name::name;
|
2021-07-10 15:49:17 -05:00
|
|
|
use limit::Limit;
|
2023-05-02 09:12:22 -05:00
|
|
|
use triomphe::Arc;
|
2019-01-06 12:51:42 -06:00
|
|
|
|
2023-03-30 06:18:44 -05:00
|
|
|
use crate::{
|
|
|
|
db::HirDatabase, infer::unify::InferenceTable, Canonical, Goal, Interner, ProjectionTyExt,
|
|
|
|
TraitEnvironment, Ty, TyBuilder, TyKind,
|
|
|
|
};
|
2019-05-12 11:33:47 -05:00
|
|
|
|
2021-10-21 05:21:34 -05:00
|
|
|
static AUTODEREF_RECURSION_LIMIT: Limit = Limit::new(10);
|
2021-07-10 15:49:17 -05:00
|
|
|
|
2023-01-31 10:53:38 -06:00
|
|
|
#[derive(Debug)]
|
2021-07-09 12:12:56 -05:00
|
|
|
pub(crate) enum AutoderefKind {
|
|
|
|
Builtin,
|
|
|
|
Overloaded,
|
|
|
|
}
|
|
|
|
|
2023-06-11 05:12:02 -05:00
|
|
|
/// Returns types that `ty` transitively dereferences to. This function is only meant to be used
|
|
|
|
/// outside `hir-ty`.
|
|
|
|
///
|
|
|
|
/// It is guaranteed that:
|
|
|
|
/// - the yielded types don't contain inference variables (but may contain `TyKind::Error`).
|
|
|
|
/// - a type won't be yielded more than once; in other words, the returned iterator will stop if it
|
|
|
|
/// detects a cycle in the deref chain.
|
2023-03-30 06:18:44 -05:00
|
|
|
pub fn autoderef(
|
|
|
|
db: &dyn HirDatabase,
|
|
|
|
env: Arc<TraitEnvironment>,
|
|
|
|
ty: Canonical<Ty>,
|
2023-06-11 05:12:02 -05:00
|
|
|
) -> impl Iterator<Item = Ty> {
|
2023-03-30 06:18:44 -05:00
|
|
|
let mut table = InferenceTable::new(db, env);
|
|
|
|
let ty = table.instantiate_canonical(ty);
|
2023-06-23 08:35:41 -05:00
|
|
|
let mut autoderef = Autoderef::new(&mut table, ty, false);
|
2023-03-30 06:18:44 -05:00
|
|
|
let mut v = Vec::new();
|
|
|
|
while let Some((ty, _steps)) = autoderef.next() {
|
2023-06-11 05:12:02 -05:00
|
|
|
// `ty` may contain unresolved inference variables. Since there's no chance they would be
|
|
|
|
// resolved, just replace with fallback type.
|
|
|
|
let resolved = autoderef.table.resolve_completely(ty);
|
|
|
|
|
|
|
|
// If the deref chain contains a cycle (e.g. `A` derefs to `B` and `B` derefs to `A`), we
|
|
|
|
// would revisit some already visited types. Stop here to avoid duplication.
|
|
|
|
//
|
|
|
|
// XXX: The recursion limit for `Autoderef` is currently 10, so `Vec::contains()` shouldn't
|
|
|
|
// be too expensive. Replace this duplicate check with `FxHashSet` if it proves to be more
|
|
|
|
// performant.
|
|
|
|
if v.contains(&resolved) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
v.push(resolved);
|
2023-03-30 06:18:44 -05:00
|
|
|
}
|
|
|
|
v.into_iter()
|
|
|
|
}
|
|
|
|
|
2023-01-31 10:53:38 -06:00
|
|
|
#[derive(Debug)]
|
2023-03-30 06:18:44 -05:00
|
|
|
pub(crate) struct Autoderef<'a, 'db> {
|
|
|
|
pub(crate) table: &'a mut InferenceTable<'db>,
|
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
|
|
|
ty: Ty,
|
2021-07-09 12:12:56 -05:00
|
|
|
at_start: bool,
|
|
|
|
steps: Vec<(AutoderefKind, Ty)>,
|
2023-06-23 08:35:41 -05:00
|
|
|
explicit: bool,
|
2021-07-09 12:12:56 -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
|
|
|
impl<'a, 'db> Autoderef<'a, 'db> {
|
2023-06-23 08:35:41 -05:00
|
|
|
pub(crate) fn new(table: &'a mut InferenceTable<'db>, ty: Ty, explicit: bool) -> Self {
|
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 ty = table.resolve_ty_shallow(&ty);
|
2023-06-23 08:35:41 -05:00
|
|
|
Autoderef { table, ty, at_start: true, steps: Vec::new(), explicit }
|
2021-07-09 12:12:56 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn step_count(&self) -> usize {
|
|
|
|
self.steps.len()
|
|
|
|
}
|
|
|
|
|
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 steps(&self) -> &[(AutoderefKind, Ty)] {
|
2021-07-09 12:12:56 -05:00
|
|
|
&self.steps
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn final_ty(&self) -> 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.ty.clone()
|
2021-07-09 12:12:56 -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
|
|
|
impl Iterator for Autoderef<'_, '_> {
|
|
|
|
type Item = (Ty, usize);
|
2021-07-09 12:12:56 -05:00
|
|
|
|
2024-02-01 15:10:32 -06:00
|
|
|
#[tracing::instrument(skip_all)]
|
2021-07-09 12:12:56 -05:00
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
|
|
if self.at_start {
|
|
|
|
self.at_start = false;
|
|
|
|
return Some((self.ty.clone(), 0));
|
|
|
|
}
|
|
|
|
|
2021-07-10 15:49:17 -05:00
|
|
|
if AUTODEREF_RECURSION_LIMIT.check(self.steps.len() + 1).is_err() {
|
2021-07-09 12:12:56 -05:00
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2023-06-23 08:35:41 -05:00
|
|
|
let (kind, new_ty) = autoderef_step(self.table, self.ty.clone(), self.explicit)?;
|
2021-07-09 12:12:56 -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
|
|
|
self.steps.push((kind, self.ty.clone()));
|
2021-07-09 12:12:56 -05:00
|
|
|
self.ty = new_ty;
|
|
|
|
|
|
|
|
Some((self.ty.clone(), self.step_count()))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-20 08:06:15 -05:00
|
|
|
pub(crate) fn autoderef_step(
|
|
|
|
table: &mut InferenceTable<'_>,
|
|
|
|
ty: Ty,
|
2023-06-23 08:35:41 -05:00
|
|
|
explicit: bool,
|
2022-07-20 08:06:15 -05:00
|
|
|
) -> Option<(AutoderefKind, Ty)> {
|
2023-06-23 08:35:41 -05:00
|
|
|
if let Some(derefed) = builtin_deref(table, &ty, explicit) {
|
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
|
|
|
Some((AutoderefKind::Builtin, table.resolve_ty_shallow(derefed)))
|
|
|
|
} else {
|
|
|
|
Some((AutoderefKind::Overloaded, deref_by_trait(table, ty)?))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-29 14:38:32 -05:00
|
|
|
pub(crate) fn builtin_deref<'ty>(
|
|
|
|
table: &mut InferenceTable<'_>,
|
|
|
|
ty: &'ty Ty,
|
|
|
|
explicit: bool,
|
|
|
|
) -> Option<&'ty Ty> {
|
2021-12-19 10:58:39 -06:00
|
|
|
match ty.kind(Interner) {
|
2023-03-29 14:38:32 -05:00
|
|
|
TyKind::Ref(.., ty) => Some(ty),
|
|
|
|
TyKind::Raw(.., ty) if explicit => Some(ty),
|
2023-03-30 02:37:52 -05:00
|
|
|
&TyKind::Adt(chalk_ir::AdtId(adt), ref substs) => {
|
|
|
|
if crate::lang_items::is_box(table.db, adt) {
|
2023-03-29 14:38:32 -05:00
|
|
|
substs.at(Interner, 0).ty(Interner)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}
|
2021-04-07 06:06:48 -05:00
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-29 14:38:32 -05:00
|
|
|
pub(crate) fn deref_by_trait(
|
|
|
|
table @ &mut InferenceTable { db, .. }: &mut InferenceTable<'_>,
|
|
|
|
ty: Ty,
|
|
|
|
) -> Option<Ty> {
|
2024-01-17 20:27:38 -06:00
|
|
|
let _p = tracing::span!(tracing::Level::INFO, "deref_by_trait").entered();
|
2022-03-23 13:18:12 -05:00
|
|
|
if table.resolve_ty_shallow(&ty).inference_var(Interner).is_some() {
|
|
|
|
// don't try to deref unknown variables
|
|
|
|
return None;
|
|
|
|
}
|
|
|
|
|
2023-01-21 10:29:07 -06:00
|
|
|
let deref_trait =
|
|
|
|
db.lang_item(table.trait_env.krate, LangItem::Deref).and_then(|l| l.as_trait())?;
|
2019-12-13 15:01:06 -06:00
|
|
|
let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
|
2019-05-12 11:33:47 -05:00
|
|
|
|
2021-04-03 14:56:18 -05:00
|
|
|
let projection = {
|
2022-10-11 02:37:35 -05:00
|
|
|
let b = TyBuilder::subst_for_def(db, deref_trait, None);
|
2021-04-03 14:56:18 -05:00
|
|
|
if b.remaining() != 1 {
|
|
|
|
// the Target type + Deref trait should only have one generic parameter,
|
|
|
|
// namely Deref's Self type
|
|
|
|
return None;
|
|
|
|
}
|
2022-10-11 02:37:35 -05:00
|
|
|
let deref_subst = b.push(ty).build();
|
|
|
|
TyBuilder::assoc_type_projection(db, target, Some(deref_subst)).build()
|
2021-04-03 14:56:18 -05:00
|
|
|
};
|
2019-06-15 11:33:30 -05:00
|
|
|
|
2020-04-10 10:44:43 -05:00
|
|
|
// Check that the type implements Deref at all
|
2021-04-03 14:56:18 -05:00
|
|
|
let trait_ref = projection.trait_ref(db);
|
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 implements_goal: Goal = trait_ref.cast(Interner);
|
|
|
|
table.try_obligation(implements_goal.clone())?;
|
2020-04-10 10:44:43 -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
|
|
|
table.register_obligation(implements_goal);
|
2021-04-08 16:34:05 -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
|
|
|
let result = table.normalize_projection_ty(projection);
|
|
|
|
Some(table.resolve_ty_shallow(&result))
|
2021-04-08 16:34:05 -05:00
|
|
|
}
|