Skip to content

Commit 456d52f

Browse files
committed
Check receiver type properly
1 parent 599dab5 commit 456d52f

File tree

4 files changed

+80
-19
lines changed

4 files changed

+80
-19
lines changed

crates/ra_hir_ty/src/infer.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,13 @@ use ra_prof::profile;
3636
use super::{
3737
primitive::{FloatTy, IntTy},
3838
traits::{Guidance, Obligation, ProjectionPredicate, Solution},
39-
ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor,
40-
TypeWalk, Uncertain,
39+
ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
40+
Uncertain,
4141
};
4242
use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
4343

44+
pub use unify::unify;
45+
4446
macro_rules! ty_app {
4547
($ctor:pat, $param:pat) => {
4648
crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param })

crates/ra_hir_ty/src/infer/coerce.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use test_utils::tested_by;
1010

1111
use crate::{autoderef, db::HirDatabase, Substs, Ty, TypeCtor, TypeWalk};
1212

13-
use super::{InEnvironment, InferTy, InferenceContext, unify::TypeVarValue};
13+
use super::{unify::TypeVarValue, InEnvironment, InferTy, InferenceContext};
1414

1515
impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1616
/// Unify two types, but may coerce the first one to the second one

crates/ra_hir_ty/src/infer/unify.rs

+12-8
Original file line numberDiff line numberDiff line change
@@ -167,13 +167,19 @@ impl<T> Canonicalized<T> {
167167
}
168168
}
169169

170-
pub fn unify(ty1: Canonical<&Ty>, ty2: &Ty) -> Substs {
170+
pub fn unify(ty1: Canonical<&Ty>, ty2: &Ty) -> Option<Substs> {
171171
let mut table = InferenceTable::new();
172-
let vars = Substs::builder(ty1.num_vars)
173-
.fill(std::iter::repeat_with(|| table.new_type_var())).build();
172+
let vars =
173+
Substs::builder(ty1.num_vars).fill(std::iter::repeat_with(|| table.new_type_var())).build();
174174
let ty_with_vars = ty1.value.clone().subst_bound_vars(&vars);
175-
table.unify(&ty_with_vars, ty2);
176-
Substs::builder(ty1.num_vars).fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))).build()
175+
if !table.unify(&ty_with_vars, ty2) {
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+
)
177183
}
178184

179185
#[derive(Clone, Debug)]
@@ -183,9 +189,7 @@ pub(crate) struct InferenceTable {
183189

184190
impl InferenceTable {
185191
pub fn new() -> Self {
186-
InferenceTable {
187-
var_unification_table: InPlaceUnificationTable::new(),
188-
}
192+
InferenceTable { var_unification_table: InPlaceUnificationTable::new() }
189193
}
190194

191195
pub fn new_type_var(&mut self) -> Ty {

crates/ra_hir_ty/src/method_resolution.rs

+63-8
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,20 @@ use std::sync::Arc;
77
use arrayvec::ArrayVec;
88
use hir_def::{
99
lang_item::LangItemTarget, resolver::Resolver, type_ref::Mutability, AssocItemId, AstItemDef,
10-
FunctionId, HasModule, ImplId, TraitId,
10+
FunctionId, HasModule, ImplId, Lookup, TraitId,
1111
};
1212
use hir_expand::name::Name;
1313
use ra_db::CrateId;
1414
use ra_prof::profile;
1515
use rustc_hash::FxHashMap;
1616

17+
use super::Substs;
1718
use crate::{
1819
autoderef,
1920
db::HirDatabase,
2021
primitive::{FloatBitness, Uncertain},
2122
utils::all_super_traits,
22-
Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor,
23+
Canonical, InEnvironment, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
2324
};
2425

2526
/// This is used as a key for indexing impls.
@@ -231,21 +232,42 @@ fn iterate_method_candidates_autoref<T>(
231232
name: Option<&Name>,
232233
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
233234
) -> 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+
) {
235243
return Some(result);
236244
}
237245
let refed = Canonical {
238246
num_vars: deref_chain[0].num_vars,
239247
value: Ty::apply_one(TypeCtor::Ref(Mutability::Shared), deref_chain[0].value.clone()),
240248
};
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+
) {
242257
return Some(result);
243258
}
244259
let ref_muted = Canonical {
245260
num_vars: deref_chain[0].num_vars,
246261
value: Ty::apply_one(TypeCtor::Ref(Mutability::Mut), deref_chain[0].value.clone()),
247262
};
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+
) {
249271
return Some(result);
250272
}
251273
None
@@ -264,7 +286,14 @@ fn iterate_method_candidates_by_receiver<T>(
264286
// be found in any of the derefs of receiver_ty, so we have to go through
265287
// that.
266288
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+
) {
268297
return Some(result);
269298
}
270299
}
@@ -280,7 +309,9 @@ fn iterate_method_candidates_inner<T>(
280309
mut callback: impl FnMut(&Ty, AssocItemId) -> Option<T>,
281310
) -> Option<T> {
282311
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+
{
284315
return Some(result);
285316
}
286317
if let Some(result) =
@@ -381,7 +412,31 @@ fn is_valid_candidate(
381412
if !data.has_self_param {
382413
return false;
383414
}
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+
}
385440
}
386441
true
387442
}

0 commit comments

Comments
 (0)