Push resolver further up

This commit is contained in:
Aleksey Kladov 2020-01-14 14:20:33 +01:00
parent 7ec62ea5e6
commit 21c5fd8b1b
4 changed files with 60 additions and 27 deletions

View File

@ -358,10 +358,17 @@ impl SourceAnalyzer {
// FIXME check that?
// FIXME replace Unknown by bound vars here
let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 };
let env = TraitEnvironment::lower(db, &self.resolver);
let krate = self.resolver.krate()?;
let traits_in_scope = self.resolver.traits_in_scope(db);
method_resolution::iterate_method_candidates(
&canonical,
db,
&self.resolver,
env,
krate,
&traits_in_scope,
name,
method_resolution::LookupMode::MethodCall,
|ty, it| match it {
@ -382,10 +389,17 @@ impl SourceAnalyzer {
// FIXME check that?
// FIXME replace Unknown by bound vars here
let canonical = Canonical { value: ty.ty.value.clone(), num_vars: 0 };
let env = TraitEnvironment::lower(db, &self.resolver);
let krate = self.resolver.krate()?;
let traits_in_scope = self.resolver.traits_in_scope(db);
method_resolution::iterate_method_candidates(
&canonical,
db,
&self.resolver,
env,
krate,
&traits_in_scope,
name,
method_resolution::LookupMode::Path,
|ty, it| callback(ty, it.into()),

View File

@ -569,12 +569,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
) -> Ty {
let receiver_ty = self.infer_expr(receiver, &Expectation::none());
let canonicalized_receiver = self.canonicalizer().canonicalize_ty(receiver_ty.clone());
let resolved = method_resolution::lookup_method(
&canonicalized_receiver.value,
self.db,
method_name,
&self.resolver,
);
let traits_in_scope = self.resolver.traits_in_scope(self.db);
let resolved = self.resolver.krate().and_then(|krate| {
method_resolution::lookup_method(
&canonicalized_receiver.value,
self.db,
self.trait_env.clone(),
krate,
&traits_in_scope,
method_name,
)
});
let (derefed_receiver_ty, method_ty, def_generics) = match resolved {
Some((ty, func)) => {
let ty = canonicalized_receiver.decanonicalize_ty(ty);

View File

@ -11,7 +11,7 @@ use hir_expand::name::Name;
use crate::{db::HirDatabase, method_resolution, Substs, Ty, TypeWalk, ValueTyDefId};
use super::{ExprOrPatId, InferenceContext, TraitRef};
use super::{ExprOrPatId, InferenceContext, TraitEnvironment, TraitRef};
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
pub(super) fn infer_path(
@ -193,11 +193,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
}
let canonical_ty = self.canonicalizer().canonicalize_ty(ty.clone());
let env = TraitEnvironment::lower(self.db, &self.resolver);
let krate = self.resolver.krate()?;
let traits_in_scope = self.resolver.traits_in_scope(self.db);
method_resolution::iterate_method_candidates(
&canonical_ty.value,
self.db,
&self.resolver.clone(),
env,
krate,
&traits_in_scope,
Some(name),
method_resolution::LookupMode::Path,
move |_ty, item| {

View File

@ -6,8 +6,8 @@ use std::sync::Arc;
use arrayvec::ArrayVec;
use hir_def::{
lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocContainerId,
AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId,
lang_item::LangItemTarget, type_ref::Mutability, AssocContainerId, AssocItemId, FunctionId,
HasModule, ImplId, Lookup, TraitId,
};
use hir_expand::name::Name;
use ra_db::CrateId;
@ -144,14 +144,24 @@ impl Ty {
pub(crate) fn lookup_method(
ty: &Canonical<Ty>,
db: &impl HirDatabase,
env: Arc<TraitEnvironment>,
krate: CrateId,
traits_in_scope: &FxHashSet<TraitId>,
name: &Name,
resolver: &Resolver,
) -> Option<(Ty, FunctionId)> {
iterate_method_candidates(ty, db, resolver, Some(name), LookupMode::MethodCall, |ty, f| match f
{
AssocItemId::FunctionId(f) => Some((ty.clone(), f)),
_ => None,
})
iterate_method_candidates(
ty,
db,
env,
krate,
&traits_in_scope,
Some(name),
LookupMode::MethodCall,
|ty, f| match f {
AssocItemId::FunctionId(f) => Some((ty.clone(), f)),
_ => None,
},
)
}
/// Whether we're looking up a dotted method call (like `v.len()`) or a path
@ -172,14 +182,13 @@ pub enum LookupMode {
pub fn iterate_method_candidates<T>(
ty: &Canonical<Ty>,
db: &impl HirDatabase,
resolver: &Resolver,
env: Arc<TraitEnvironment>,
krate: CrateId,
traits_in_scope: &FxHashSet<TraitId>,
name: Option<&Name>,
mode: LookupMode,
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
) -> Option<T> {
let traits_in_scope = resolver.traits_in_scope(db);
let krate = resolver.krate()?;
let env = TraitEnvironment::lower(db, resolver);
match mode {
LookupMode::MethodCall => {
// For method calls, rust first does any number of autoderef, and then one
@ -190,9 +199,7 @@ pub fn iterate_method_candidates<T>(
// Also note that when we've got a receiver like &S, even if the method we
// find in the end takes &self, we still do the autoderef step (just as
// rustc does an autoderef and then autoref again).
let environment = TraitEnvironment::lower(db, resolver);
let ty = InEnvironment { value: ty.clone(), environment };
let krate = resolver.krate()?;
let ty = InEnvironment { value: ty.clone(), environment: env.clone() };
// We have to be careful about the order we're looking at candidates
// in here. Consider the case where we're resolving `x.clone()`
@ -214,7 +221,7 @@ pub fn iterate_method_candidates<T>(
db,
env.clone(),
krate,
&traits_in_scope,
traits_in_scope,
name,
&mut callback,
) {
@ -230,7 +237,7 @@ pub fn iterate_method_candidates<T>(
db,
env,
krate,
&traits_in_scope,
traits_in_scope,
name,
&mut callback,
)