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 std::sync::Arc;
|
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-01-21 10:29:07 -06: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;
|
2019-01-06 12:51:42 -06:00
|
|
|
|
2019-12-07 04:50:36 -06: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, infer::unify::InferenceTable, Canonical, Goal, Interner, ProjectionTyExt,
|
|
|
|
TraitEnvironment, Ty, TyBuilder, TyKind,
|
2019-11-25 03:45:45 -06:00
|
|
|
};
|
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
|
|
|
|
2021-07-09 12:12:56 -05:00
|
|
|
pub(crate) enum AutoderefKind {
|
|
|
|
Builtin,
|
|
|
|
Overloaded,
|
|
|
|
}
|
|
|
|
|
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 Autoderef<'a, 'db> {
|
2022-02-25 05:09:49 -06:00
|
|
|
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)>,
|
|
|
|
}
|
|
|
|
|
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> {
|
|
|
|
pub(crate) fn new(table: &'a mut InferenceTable<'db>, ty: Ty) -> Self {
|
|
|
|
let ty = table.resolve_ty_shallow(&ty);
|
|
|
|
Autoderef { table, ty, at_start: true, steps: Vec::new() }
|
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
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
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 (kind, new_ty) = autoderef_step(self.table, 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
|
|
|
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,
|
|
|
|
) -> Option<(AutoderefKind, 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
|
|
|
if let Some(derefed) = builtin_deref(&ty) {
|
|
|
|
Some((AutoderefKind::Builtin, table.resolve_ty_shallow(derefed)))
|
|
|
|
} else {
|
|
|
|
Some((AutoderefKind::Overloaded, deref_by_trait(table, ty)?))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-07-09 12:12:56 -05:00
|
|
|
// FIXME: replace uses of this with Autoderef above
|
2022-12-30 03:00:42 -06:00
|
|
|
pub fn autoderef(
|
|
|
|
db: &dyn HirDatabase,
|
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
|
|
|
env: Arc<TraitEnvironment>,
|
|
|
|
ty: Canonical<Ty>,
|
2022-12-30 03:00:42 -06:00
|
|
|
) -> impl Iterator<Item = Canonical<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 mut table = InferenceTable::new(db, env);
|
|
|
|
let ty = table.instantiate_canonical(ty);
|
|
|
|
let mut autoderef = Autoderef::new(&mut table, ty);
|
|
|
|
let mut v = Vec::new();
|
|
|
|
while let Some((ty, _steps)) = autoderef.next() {
|
|
|
|
v.push(autoderef.table.canonicalize(ty).value);
|
|
|
|
}
|
|
|
|
v.into_iter()
|
2019-05-12 11:33:47 -05:00
|
|
|
}
|
|
|
|
|
2022-07-20 08:02:08 -05:00
|
|
|
pub(crate) fn deref(table: &mut InferenceTable<'_>, ty: Ty) -> Option<Ty> {
|
2021-04-14 09:15:37 -05:00
|
|
|
let _p = profile::span("deref");
|
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
|
|
|
autoderef_step(table, ty).map(|(_, ty)| ty)
|
2019-05-12 11:33:47 -05:00
|
|
|
}
|
|
|
|
|
2021-12-10 13:01:24 -06:00
|
|
|
fn builtin_deref(ty: &Ty) -> Option<&Ty> {
|
2021-12-19 10:58:39 -06:00
|
|
|
match ty.kind(Interner) {
|
2022-09-06 13:20:49 -05:00
|
|
|
TyKind::Ref(.., ty) | TyKind::Raw(.., ty) => Some(ty),
|
2021-04-07 06:06:48 -05:00
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-20 08:02:08 -05:00
|
|
|
fn deref_by_trait(table: &mut InferenceTable<'_>, ty: Ty) -> Option<Ty> {
|
2021-04-14 08:59:08 -05:00
|
|
|
let _p = profile::span("deref_by_trait");
|
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;
|
|
|
|
}
|
|
|
|
|
|
|
|
let db = table.db;
|
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
|
|
|
}
|