Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/method_resolution.rs')
-rw-r--r--crates/hir-ty/src/method_resolution.rs47
1 files changed, 29 insertions, 18 deletions
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index ac85bf7950..a4427517a1 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -24,7 +24,7 @@ use triomphe::Arc;
use crate::{
AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, GenericArgData,
Goal, InEnvironment, Interner, Mutability, Scalar, Substitution, TraitEnvironment, TraitRef,
- TraitRefExt, Ty, TyBuilder, TyExt, TyKind, TyVariableKind, VariableKind, WhereClause,
+ TraitRefExt, Ty, TyBuilder, TyExt, TyKind, VariableKind, WhereClause,
autoderef::{self, AutoderefKind},
db::HirDatabase,
from_chalk_trait_id, from_foreign_def_id,
@@ -622,18 +622,23 @@ pub struct ReceiverAdjustments {
}
impl ReceiverAdjustments {
- pub(crate) fn apply(&self, table: &mut InferenceTable<'_>, ty: Ty) -> (Ty, Vec<Adjustment>) {
- let mut ty = table.structurally_resolve_type(&ty);
+ pub(crate) fn apply(
+ &self,
+ table: &mut InferenceTable<'_>,
+ mut ty: Ty,
+ ) -> (Ty, Vec<Adjustment>) {
let mut adjust = Vec::new();
+ let mut autoderef = table.autoderef(ty.to_nextsolver(table.interner));
+ autoderef.next();
for _ in 0..self.autoderefs {
- match autoderef::autoderef_step(table, ty.clone(), true, false) {
+ match autoderef.next() {
None => {
never!("autoderef not possible for {:?}", ty);
ty = TyKind::Error.intern(Interner);
break;
}
- Some((kind, new_ty)) => {
- ty = new_ty.clone();
+ Some((new_ty, _)) => {
+ ty = new_ty.to_chalk(autoderef.table.interner);
let mutbl = match self.autoref {
Some(AutorefOrPtrAdjustment::Autoref(m)) => Some(m),
Some(AutorefOrPtrAdjustment::ToConstPtr) => Some(Mutability::Not),
@@ -641,11 +646,11 @@ impl ReceiverAdjustments {
None => None,
};
adjust.push(Adjustment {
- kind: Adjust::Deref(match kind {
+ kind: Adjust::Deref(match autoderef.steps().last().unwrap().1 {
AutoderefKind::Overloaded => Some(OverloadedDeref(mutbl)),
AutoderefKind::Builtin => None,
}),
- target: new_ty,
+ target: ty.clone(),
});
}
}
@@ -1282,17 +1287,20 @@ fn iterate_method_candidates_by_receiver<'db>(
name: Option<&Name>,
callback: &mut dyn MethodCandidateCallback,
) -> ControlFlow<()> {
+ let interner = table.interner;
let receiver_ty = table.instantiate_canonical_ns(receiver_ty);
- let receiver_ty: crate::Ty = receiver_ty.to_chalk(table.interner);
+ let receiver_ty: crate::Ty = receiver_ty.to_chalk(interner);
// We're looking for methods with *receiver* type receiver_ty. These could
// be found in any of the derefs of receiver_ty, so we have to go through
// that, including raw derefs.
table.run_in_snapshot(|table| {
let mut autoderef =
- autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true, true);
+ autoderef::Autoderef::new_no_tracking(table, receiver_ty.to_nextsolver(interner))
+ .include_raw_pointers()
+ .use_receiver_trait();
while let Some((self_ty, _)) = autoderef.next() {
iterate_inherent_methods(
- &self_ty,
+ &self_ty.to_chalk(interner),
autoderef.table,
name,
Some(&receiver_ty),
@@ -1308,15 +1316,18 @@ fn iterate_method_candidates_by_receiver<'db>(
})?;
table.run_in_snapshot(|table| {
let mut autoderef =
- autoderef::Autoderef::new_no_tracking(table, receiver_ty.clone(), true, true);
+ autoderef::Autoderef::new_no_tracking(table, receiver_ty.to_nextsolver(interner))
+ .include_raw_pointers()
+ .use_receiver_trait();
while let Some((self_ty, _)) = autoderef.next() {
- if matches!(self_ty.kind(Interner), TyKind::InferenceVar(_, TyVariableKind::General)) {
+ if matches!(self_ty.kind(), crate::next_solver::TyKind::Infer(rustc_type_ir::TyVar(_)))
+ {
// don't try to resolve methods on unknown types
return ControlFlow::Continue(());
}
iterate_trait_method_candidates(
- &self_ty,
+ &self_ty.to_chalk(interner),
autoderef.table,
traits_in_scope,
name,
@@ -1760,7 +1771,8 @@ fn is_valid_trait_method_candidate(
for pred in infer_ok.into_obligations() {
ctxt.register_predicate_obligation(&table.infer_ctxt, pred);
}
- check_that!(ctxt.select_all_or_error(&table.infer_ctxt).is_empty());
+ // FIXME: Are we doing this correctly? Probably better to follow rustc more closely.
+ check_that!(ctxt.select_where_possible(&table.infer_ctxt).is_empty());
}
check_that!(table.unify(receiver_ty, &expected_receiver));
@@ -1937,11 +1949,10 @@ fn autoderef_method_receiver<'db>(
) -> Vec<(next_solver::Canonical<'db, crate::next_solver::Ty<'db>>, ReceiverAdjustments)> {
let interner = table.interner;
let mut deref_chain = Vec::new();
- let mut autoderef =
- autoderef::Autoderef::new_no_tracking(table, ty.to_chalk(interner), false, true);
+ let mut autoderef = autoderef::Autoderef::new_no_tracking(table, ty).use_receiver_trait();
while let Some((ty, derefs)) = autoderef.next() {
deref_chain.push((
- autoderef.table.canonicalize(ty.to_nextsolver(interner)),
+ autoderef.table.canonicalize(ty),
ReceiverAdjustments { autoref: None, autoderefs: derefs, unsize_array: false },
));
}