aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_ty
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-12-01 21:14:28 +0000
committerFlorian Diebold <[email protected]>2019-12-02 18:33:13 +0000
commit456d52fdfa8525af2a54e76ee5300f0a40ef582a (patch)
treee8cd093624ac3ccc9926856dc8db0d4daa0d0b8a /crates/ra_hir_ty
parent599dab59824b164b1c24e2e51adeae1ac1307964 (diff)
Check receiver type properly
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r--crates/ra_hir_ty/src/infer.rs6
-rw-r--r--crates/ra_hir_ty/src/infer/coerce.rs2
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs20
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs71
4 files changed, 80 insertions, 19 deletions
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index 81afbd2b4..0889a6bf9 100644
--- a/crates/ra_hir_ty/src/infer.rs
+++ b/crates/ra_hir_ty/src/infer.rs
@@ -36,11 +36,13 @@ use ra_prof::profile;
36use super::{ 36use super::{
37 primitive::{FloatTy, IntTy}, 37 primitive::{FloatTy, IntTy},
38 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 38 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
39 ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, 39 ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
40 TypeWalk, Uncertain, 40 Uncertain,
41}; 41};
42use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; 42use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
43 43
44pub use unify::unify;
45
44macro_rules! ty_app { 46macro_rules! ty_app {
45 ($ctor:pat, $param:pat) => { 47 ($ctor:pat, $param:pat) => {
46 crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param }) 48 crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param })
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index 9bfc701cd..9daa77cfa 100644
--- a/crates/ra_hir_ty/src/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -10,7 +10,7 @@ use test_utils::tested_by;
10 10
11use crate::{autoderef, db::HirDatabase, Substs, Ty, TypeCtor, TypeWalk}; 11use crate::{autoderef, db::HirDatabase, Substs, Ty, TypeCtor, TypeWalk};
12 12
13use super::{InEnvironment, InferTy, InferenceContext, unify::TypeVarValue}; 13use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext};
14 14
15impl<'a, D: HirDatabase> InferenceContext<'a, D> { 15impl<'a, D: HirDatabase> InferenceContext<'a, D> {
16 /// Unify two types, but may coerce the first one to the second one 16 /// Unify two types, but may coerce the first one to the second one
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index ff50138f5..8ed2a6090 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -167,13 +167,19 @@ impl<T> Canonicalized<T> {
167 } 167 }
168} 168}
169 169
170pub fn unify(ty1: Canonical<&Ty>, ty2: &Ty) -> Substs { 170pub fn unify(ty1: Canonical<&Ty>, ty2: &Ty) -> Option<Substs> {
171 let mut table = InferenceTable::new(); 171 let mut table = InferenceTable::new();
172 let vars = Substs::builder(ty1.num_vars) 172 let vars =
173 .fill(std::iter::repeat_with(|| table.new_type_var())).build(); 173 Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build();
174 let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars); 174 let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars);
175 table.unify(&ty_with_vars, ty2); 175 if !table.unify(&ty_with_vars, ty2) {
176 Substs::builder(ty1.num_vars).fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))).build() 176 return None;
177 }
178 Some(
179 Substs::builder(ty1.num_vars)
180 .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone())))
181 .build(),
182 )
177} 183}
178 184
179#[derive(Clone, Debug)] 185#[derive(Clone, Debug)]
@@ -183,9 +189,7 @@ pub(crate) struct InferenceTable {
183 189
184impl InferenceTable { 190impl InferenceTable {
185 pub fn new() -> Self { 191 pub fn new() -> Self {
186 InferenceTable { 192 InferenceTable { var_unification_table: InPlaceUnificationTable::new() }
187 var_unification_table: InPlaceUnificationTable::new(),
188 }
189 } 193 }
190 194
191 pub fn new_type_var(&mut self) -> Ty { 195 pub fn new_type_var(&mut self) -> Ty {
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index fbb932a3e..97281cf15 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -7,19 +7,20 @@ use std::sync::Arc;
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use hir_def::{ 8use hir_def::{
9 lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef, 9 lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef,
10 FunctionId, HasModule, ImplId, TraitId, 10 FunctionId, HasModule, ImplId, Lookup, TraitId,
11}; 11};
12use hir_expand::name::Name; 12use hir_expand::name::Name;
13use ra_db::CrateId; 13use ra_db::CrateId;
14use ra_prof::profile; 14use ra_prof::profile;
15use rustc_hash::FxHashMap; 15use rustc_hash::FxHashMap;
16 16
17use super::Substs;
17use crate::{ 18use crate::{
18 autoderef, 19 autoderef,
19 db::HirDatabase, 20 db::HirDatabase,
20 primitive::{FloatBitness, Uncertain}, 21 primitive::{FloatBitness, Uncertain},
21 utils::all_super_traits, 22 utils::all_super_traits,
22 Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, 23 Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
23}; 24};
24 25
25/// This is used as a key for indexing impls. 26/// This is used as a key for indexing impls.
@@ -231,21 +232,42 @@ fn iterate_method_candidates_autoref<T>(
231 name: Option<&Name>, 232 name: Option<&Name>,
232 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 233 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
233) -> Option<T> { 234) -> Option<T> {
234 if let Some(result) = iterate_method_candidates_by_receiver(&deref_chain[0], &deref_chain[1..], db, resolver, name, &mut callback) { 235 if let Some(result) = iterate_method_candidates_by_receiver(
236 &deref_chain[0],
237 &deref_chain[1..],
238 db,
239 resolver,
240 name,
241 &mut callback,
242 ) {
235 return Some(result); 243 return Some(result);
236 } 244 }
237 let refed = Canonical { 245 let refed = Canonical {
238 num_vars: deref_chain[0].num_vars, 246 num_vars: deref_chain[0].num_vars,
239 value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()), 247 value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()),
240 }; 248 };
241 if let Some(result) = iterate_method_candidates_by_receiver(&refed, deref_chain, db, resolver, name, &mut callback) { 249 if let Some(result) = iterate_method_candidates_by_receiver(
250 &refed,
251 deref_chain,
252 db,
253 resolver,
254 name,
255 &mut callback,
256 ) {
242 return Some(result); 257 return Some(result);
243 } 258 }
244 let ref_muted = Canonical { 259 let ref_muted = Canonical {
245 num_vars: deref_chain[0].num_vars, 260 num_vars: deref_chain[0].num_vars,
246 value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()), 261 value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()),
247 }; 262 };
248 if let Some(result) = iterate_method_candidates_by_receiver(&ref_muted, deref_chain, db, resolver, name, &mut callback) { 263 if let Some(result) = iterate_method_candidates_by_receiver(
264 &ref_muted,
265 deref_chain,
266 db,
267 resolver,
268 name,
269 &mut callback,
270 ) {
249 return Some(result); 271 return Some(result);
250 } 272 }
251 None 273 None
@@ -264,7 +286,14 @@ fn iterate_method_candidates_by_receiver<T>(
264 // be found in any of the derefs of receiver_ty, so we have to go through 286 // be found in any of the derefs of receiver_ty, so we have to go through
265 // that. 287 // that.
266 for self_ty in std::iter::once(receiver_ty).chain(deref_chain) { 288 for self_ty in std::iter::once(receiver_ty).chain(deref_chain) {
267 if let Some(result) = iterate_method_candidates_inner(self_ty, db, resolver, name, Some(receiver_ty), &mut callback) { 289 if let Some(result) = iterate_method_candidates_inner(
290 self_ty,
291 db,
292 resolver,
293 name,
294 Some(receiver_ty),
295 &mut callback,
296 ) {
268 return Some(result); 297 return Some(result);
269 } 298 }
270 } 299 }
@@ -280,7 +309,9 @@ fn iterate_method_candidates_inner<T>(
280 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>, 309 mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
281) -> Option<T> { 310) -> Option<T> {
282 let krate = resolver.krate()?; 311 let krate = resolver.krate()?;
283 if let Some(result) = iterate_inherent_methods(self_ty, db, name, receiver_ty, krate, &mut callback) { 312 if let Some(result) =
313 iterate_inherent_methods(self_ty, db, name, receiver_ty, krate, &mut callback)
314 {
284 return Some(result); 315 return Some(result);
285 } 316 }
286 if let Some(result) = 317 if let Some(result) =
@@ -381,7 +412,31 @@ fn is_valid_candidate(
381 if !data.has_self_param { 412 if !data.has_self_param {
382 return false; 413 return false;
383 } 414 }
384 // TODO compare receiver ty 415 let substs = match m.lookup(db).container {
416 hir_def::ContainerId::TraitId(_) => Substs::build_for_def(db, item)
417 .push(self_ty.value.clone())
418 .fill_with_unknown()
419 .build(),
420 hir_def::ContainerId::ImplId(impl_id) => {
421 let vars =
422 Substs::build_for_def(db, impl_id).fill_with_bound_vars(0).build();
423 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
424 let self_ty_with_vars =
425 Canonical { num_vars: vars.len(), value: &self_ty_with_vars };
426 if let Some(substs) = super::infer::unify(self_ty_with_vars, &self_ty.value)
427 {
428 substs
429 } else {
430 return false;
431 }
432 }
433 hir_def::ContainerId::ModuleId(_) => unreachable!(),
434 };
435 let sig = db.callable_item_signature(m.into());
436 let receiver = sig.params()[0].clone().subst(&substs);
437 if receiver != receiver_ty.value {
438 return false;
439 }
385 } 440 }
386 true 441 true
387 } 442 }