mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-29 10:13:54 +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::{
|
||||
primitive::{FloatTy, IntTy},
|
||||
traits::{Guidance, Obligation, ProjectionPredicate, Solution},
|
||||
ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor,
|
||||
TypeWalk, Uncertain,
|
||||
ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
|
||||
Uncertain,
|
||||
};
|
||||
use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
|
||||
|
||||
pub use unify::unify;
|
||||
|
||||
macro_rules! ty_app {
|
||||
($ctor:pat, $param:pat) => {
|
||||
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 super::{InEnvironment, InferTy, InferenceContext, unify::TypeVarValue};
|
||||
use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext};
|
||||
|
||||
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
|
||||
/// 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 vars = Substs::builder(ty1.num_vars)
|
||||
.fill(std::iter::repeat_with(|| table.new_type_var())).build();
|
||||
let vars =
|
||||
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);
|
||||
table.unify(&ty_with_vars, ty2);
|
||||
Substs::builder(ty1.num_vars).fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))).build()
|
||||
if !table.unify(&ty_with_vars, ty2) {
|
||||
return None;
|
||||
}
|
||||
Some(
|
||||
Substs::builder(ty1.num_vars)
|
||||
.fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone())))
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -183,9 +189,7 @@ pub(crate) struct InferenceTable {
|
||||
|
||||
impl InferenceTable {
|
||||
pub fn new() -> Self {
|
||||
InferenceTable {
|
||||
var_unification_table: InPlaceUnificationTable::new(),
|
||||
}
|
||||
InferenceTable { var_unification_table: InPlaceUnificationTable::new() }
|
||||
}
|
||||
|
||||
pub fn new_type_var(&mut self) -> Ty {
|
||||
|
@ -7,19 +7,20 @@ use std::sync::Arc;
|
||||
use arrayvec::ArrayVec;
|
||||
use hir_def::{
|
||||
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 ra_db::CrateId;
|
||||
use ra_prof::profile;
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use super::Substs;
|
||||
use crate::{
|
||||
autoderef,
|
||||
db::HirDatabase,
|
||||
primitive::{FloatBitness, Uncertain},
|
||||
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.
|
||||
@ -231,21 +232,42 @@ fn iterate_method_candidates_autoref<T>(
|
||||
name: Option<&Name>,
|
||||
mut callback: impl FnMut(&Ty, AssocItemId) -> 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);
|
||||
}
|
||||
let refed = Canonical {
|
||||
num_vars: deref_chain[0].num_vars,
|
||||
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);
|
||||
}
|
||||
let ref_muted = Canonical {
|
||||
num_vars: deref_chain[0].num_vars,
|
||||
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);
|
||||
}
|
||||
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
|
||||
// that.
|
||||
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);
|
||||
}
|
||||
}
|
||||
@ -280,7 +309,9 @@ fn iterate_method_candidates_inner<T>(
|
||||
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
|
||||
) -> Option<T> {
|
||||
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);
|
||||
}
|
||||
if let Some(result) =
|
||||
@ -381,7 +412,31 @@ fn is_valid_candidate(
|
||||
if !data.has_self_param {
|
||||
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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user