mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-01 19:23:50 +00:00
Check receiver type properly
This commit is contained in:
parent
599dab5982
commit
456d52fdfa
@ -36,11 +36,13 @@ use ra_prof::profile;
|
|||||||
use super::{
|
use super::{
|
||||||
primitive::{FloatTy, IntTy},
|
primitive::{FloatTy, IntTy},
|
||||||
traits::{Guidance, Obligation, ProjectionPredicate, Solution},
|
traits::{Guidance, Obligation, ProjectionPredicate, Solution},
|
||||||
ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor,
|
ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
|
||||||
TypeWalk, Uncertain,
|
Uncertain,
|
||||||
};
|
};
|
||||||
use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
|
use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
|
||||||
|
|
||||||
|
pub use unify::unify;
|
||||||
|
|
||||||
macro_rules! ty_app {
|
macro_rules! ty_app {
|
||||||
($ctor:pat, $param:pat) => {
|
($ctor:pat, $param:pat) => {
|
||||||
crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param })
|
crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param })
|
||||||
|
@ -10,7 +10,7 @@ use test_utils::tested_by;
|
|||||||
|
|
||||||
use crate::{autoderef, db::HirDatabase, Substs, Ty, TypeCtor, TypeWalk};
|
use crate::{autoderef, db::HirDatabase, Substs, Ty, TypeCtor, TypeWalk};
|
||||||
|
|
||||||
use super::{InEnvironment, InferTy, InferenceContext, unify::TypeVarValue};
|
use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext};
|
||||||
|
|
||||||
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||||
/// Unify two types, but may coerce the first one to the second one
|
/// Unify two types, but may coerce the first one to the second one
|
||||||
|
@ -167,13 +167,19 @@ impl<T> Canonicalized<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unify(ty1: Canonical<&Ty>, ty2: &Ty) -> Substs {
|
pub fn unify(ty1: Canonical<&Ty>, ty2: &Ty) -> Option<Substs> {
|
||||||
let mut table = InferenceTable::new();
|
let mut table = InferenceTable::new();
|
||||||
let vars = Substs::builder(ty1.num_vars)
|
let vars =
|
||||||
.fill(std::iter::repeat_with(|| table.new_type_var())).build();
|
Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build();
|
||||||
let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars);
|
let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars);
|
||||||
table.unify(&ty_with_vars, ty2);
|
if !table.unify(&ty_with_vars, ty2) {
|
||||||
Substs::builder(ty1.num_vars).fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))).build()
|
return None;
|
||||||
|
}
|
||||||
|
Some(
|
||||||
|
Substs::builder(ty1.num_vars)
|
||||||
|
.fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone())))
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -183,9 +189,7 @@ pub(crate) struct InferenceTable {
|
|||||||
|
|
||||||
impl InferenceTable {
|
impl InferenceTable {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
InferenceTable {
|
InferenceTable { var_unification_table: InPlaceUnificationTable::new() }
|
||||||
var_unification_table: InPlaceUnificationTable::new(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_type_var(&mut self) -> Ty {
|
pub fn new_type_var(&mut self) -> Ty {
|
||||||
|
@ -7,19 +7,20 @@ use std::sync::Arc;
|
|||||||
use arrayvec::ArrayVec;
|
use arrayvec::ArrayVec;
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef,
|
lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef,
|
||||||
FunctionId, HasModule, ImplId, TraitId,
|
FunctionId, HasModule, ImplId, Lookup, TraitId,
|
||||||
};
|
};
|
||||||
use hir_expand::name::Name;
|
use hir_expand::name::Name;
|
||||||
use ra_db::CrateId;
|
use ra_db::CrateId;
|
||||||
use ra_prof::profile;
|
use ra_prof::profile;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
|
|
||||||
|
use super::Substs;
|
||||||
use crate::{
|
use crate::{
|
||||||
autoderef,
|
autoderef,
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
primitive::{FloatBitness, Uncertain},
|
primitive::{FloatBitness, Uncertain},
|
||||||
utils::all_super_traits,
|
utils::all_super_traits,
|
||||||
Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor,
|
Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This is used as a key for indexing impls.
|
/// This is used as a key for indexing impls.
|
||||||
@ -231,21 +232,42 @@ fn iterate_method_candidates_autoref<T>(
|
|||||||
name: Option<&Name>,
|
name: Option<&Name>,
|
||||||
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
if let Some(result) = iterate_method_candidates_by_receiver(&deref_chain[0], &deref_chain[1..], db, resolver, name, &mut callback) {
|
if let Some(result) = iterate_method_candidates_by_receiver(
|
||||||
|
&deref_chain[0],
|
||||||
|
&deref_chain[1..],
|
||||||
|
db,
|
||||||
|
resolver,
|
||||||
|
name,
|
||||||
|
&mut callback,
|
||||||
|
) {
|
||||||
return Some(result);
|
return Some(result);
|
||||||
}
|
}
|
||||||
let refed = Canonical {
|
let refed = Canonical {
|
||||||
num_vars: deref_chain[0].num_vars,
|
num_vars: deref_chain[0].num_vars,
|
||||||
value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()),
|
value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()),
|
||||||
};
|
};
|
||||||
if let Some(result) = iterate_method_candidates_by_receiver(&refed, deref_chain, db, resolver, name, &mut callback) {
|
if let Some(result) = iterate_method_candidates_by_receiver(
|
||||||
|
&refed,
|
||||||
|
deref_chain,
|
||||||
|
db,
|
||||||
|
resolver,
|
||||||
|
name,
|
||||||
|
&mut callback,
|
||||||
|
) {
|
||||||
return Some(result);
|
return Some(result);
|
||||||
}
|
}
|
||||||
let ref_muted = Canonical {
|
let ref_muted = Canonical {
|
||||||
num_vars: deref_chain[0].num_vars,
|
num_vars: deref_chain[0].num_vars,
|
||||||
value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()),
|
value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()),
|
||||||
};
|
};
|
||||||
if let Some(result) = iterate_method_candidates_by_receiver(&ref_muted, deref_chain, db, resolver, name, &mut callback) {
|
if let Some(result) = iterate_method_candidates_by_receiver(
|
||||||
|
&ref_muted,
|
||||||
|
deref_chain,
|
||||||
|
db,
|
||||||
|
resolver,
|
||||||
|
name,
|
||||||
|
&mut callback,
|
||||||
|
) {
|
||||||
return Some(result);
|
return Some(result);
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@ -264,7 +286,14 @@ fn iterate_method_candidates_by_receiver<T>(
|
|||||||
// be found in any of the derefs of receiver_ty, so we have to go through
|
// be found in any of the derefs of receiver_ty, so we have to go through
|
||||||
// that.
|
// that.
|
||||||
for self_ty in std::iter::once(receiver_ty).chain(deref_chain) {
|
for self_ty in std::iter::once(receiver_ty).chain(deref_chain) {
|
||||||
if let Some(result) = iterate_method_candidates_inner(self_ty, db, resolver, name, Some(receiver_ty), &mut callback) {
|
if let Some(result) = iterate_method_candidates_inner(
|
||||||
|
self_ty,
|
||||||
|
db,
|
||||||
|
resolver,
|
||||||
|
name,
|
||||||
|
Some(receiver_ty),
|
||||||
|
&mut callback,
|
||||||
|
) {
|
||||||
return Some(result);
|
return Some(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -280,7 +309,9 @@ fn iterate_method_candidates_inner<T>(
|
|||||||
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
let krate = resolver.krate()?;
|
let krate = resolver.krate()?;
|
||||||
if let Some(result) = iterate_inherent_methods(self_ty, db, name, receiver_ty, krate, &mut callback) {
|
if let Some(result) =
|
||||||
|
iterate_inherent_methods(self_ty, db, name, receiver_ty, krate, &mut callback)
|
||||||
|
{
|
||||||
return Some(result);
|
return Some(result);
|
||||||
}
|
}
|
||||||
if let Some(result) =
|
if let Some(result) =
|
||||||
@ -381,7 +412,31 @@ fn is_valid_candidate(
|
|||||||
if !data.has_self_param {
|
if !data.has_self_param {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// TODO compare receiver ty
|
let substs = match m.lookup(db).container {
|
||||||
|
hir_def::ContainerId::TraitId(_) => Substs::build_for_def(db, item)
|
||||||
|
.push(self_ty.value.clone())
|
||||||
|
.fill_with_unknown()
|
||||||
|
.build(),
|
||||||
|
hir_def::ContainerId::ImplId(impl_id) => {
|
||||||
|
let vars =
|
||||||
|
Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build();
|
||||||
|
let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
|
||||||
|
let self_ty_with_vars =
|
||||||
|
Canonical { num_vars: vars.len(), value: &self_ty_with_vars };
|
||||||
|
if let Some(substs) = super::infer::unify(self_ty_with_vars, &self_ty.value)
|
||||||
|
{
|
||||||
|
substs
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hir_def::ContainerId::ModuleId(_) => unreachable!(),
|
||||||
|
};
|
||||||
|
let sig = db.callable_item_signature(m.into());
|
||||||
|
let receiver = sig.params()[0].clone().subst(&substs);
|
||||||
|
if receiver != receiver_ty.value {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user