Skip to content

Commit c5be0ce

Browse files
Merge #2463
2463: More correct method resolution r=flodiebold a=flodiebold This should fix the order in which candidates for method resolution are considered, i.e. `(&Foo).clone()` should now be of type `Foo` instead of `&Foo`. It also checks for inherent candidates that the self type unifies properly with the self type in the impl (i.e. `impl Foo<u32>` methods will only be considered for `Foo<u32>`). To be able to get the correct receiver type to check in the method resolution, I needed the unification logic, so I extracted it to the `unify.rs` module. Should fix #2435. Co-authored-by: Florian Diebold <flodiebold@gmail.com>
2 parents 3376c08 + 18f25ac commit c5be0ce

File tree

9 files changed

+570
-340
lines changed

9 files changed

+570
-340
lines changed

crates/ra_hir_ty/src/infer.rs

Lines changed: 25 additions & 234 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use std::mem;
1818
use std::ops::Index;
1919
use std::sync::Arc;
2020

21-
use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
2221
use rustc_hash::FxHashMap;
2322

2423
use hir_def::{
@@ -33,16 +32,17 @@ use hir_def::{
3332
use hir_expand::{diagnostics::DiagnosticSink, name};
3433
use ra_arena::map::ArenaMap;
3534
use ra_prof::profile;
36-
use test_utils::tested_by;
3735

3836
use super::{
3937
primitive::{FloatTy, IntTy},
4038
traits::{Guidance, Obligation, ProjectionPredicate, Solution},
41-
ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor,
42-
TypeWalk, Uncertain,
39+
ApplicationTy, InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeCtor, TypeWalk,
40+
Uncertain,
4341
};
4442
use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic};
4543

44+
pub(crate) use unify::unify;
45+
4646
macro_rules! ty_app {
4747
($ctor:pat, $param:pat) => {
4848
crate::Ty::Apply(crate::ApplicationTy { ctor: $ctor, parameters: $param })
@@ -191,7 +191,7 @@ struct InferenceContext<'a, D: HirDatabase> {
191191
owner: DefWithBodyId,
192192
body: Arc<Body>,
193193
resolver: Resolver,
194-
var_unification_table: InPlaceUnificationTable<TypeVarId>,
194+
table: unify::InferenceTable,
195195
trait_env: Arc<TraitEnvironment>,
196196
obligations: Vec<Obligation>,
197197
result: InferenceResult,
@@ -209,7 +209,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
209209
fn new(db: &'a D, owner: DefWithBodyId, resolver: Resolver) -> Self {
210210
InferenceContext {
211211
result: InferenceResult::default(),
212-
var_unification_table: InPlaceUnificationTable::new(),
212+
table: unify::InferenceTable::new(),
213213
obligations: Vec::default(),
214214
return_ty: Ty::Unknown, // set in collect_fn_signature
215215
trait_env: TraitEnvironment::lower(db, &resolver),
@@ -224,13 +224,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
224224
fn resolve_all(mut self) -> InferenceResult {
225225
// FIXME resolve obligations as well (use Guidance if necessary)
226226
let mut result = mem::replace(&mut self.result, InferenceResult::default());
227-
let mut tv_stack = Vec::new();
228227
for ty in result.type_of_expr.values_mut() {
229-
let resolved = self.resolve_ty_completely(&mut tv_stack, mem::replace(ty, Ty::Unknown));
228+
let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown));
230229
*ty = resolved;
231230
}
232231
for ty in result.type_of_pat.values_mut() {
233-
let resolved = self.resolve_ty_completely(&mut tv_stack, mem::replace(ty, Ty::Unknown));
232+
let resolved = self.table.resolve_ty_completely(mem::replace(ty, Ty::Unknown));
234233
*ty = resolved;
235234
}
236235
result
@@ -275,96 +274,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
275274
self.normalize_associated_types_in(ty)
276275
}
277276

278-
fn unify_substs(&mut self, substs1: &Substs, substs2: &Substs, depth: usize) -> bool {
279-
substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| self.unify_inner(t1, t2, depth))
280-
}
281-
282-
fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
283-
self.unify_inner(ty1, ty2, 0)
284-
}
285-
286-
fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool {
287-
if depth > 1000 {
288-
// prevent stackoverflows
289-
panic!("infinite recursion in unification");
290-
}
291-
if ty1 == ty2 {
292-
return true;
293-
}
294-
// try to resolve type vars first
295-
let ty1 = self.resolve_ty_shallow(ty1);
296-
let ty2 = self.resolve_ty_shallow(ty2);
297-
match (&*ty1, &*ty2) {
298-
(Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => {
299-
self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1)
300-
}
301-
_ => self.unify_inner_trivial(&ty1, &ty2),
302-
}
303-
}
304-
305-
fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
306-
match (ty1, ty2) {
307-
(Ty::Unknown, _) | (_, Ty::Unknown) => true,
308-
309-
(Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
310-
| (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
311-
| (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2)))
312-
| (
313-
Ty::Infer(InferTy::MaybeNeverTypeVar(tv1)),
314-
Ty::Infer(InferTy::MaybeNeverTypeVar(tv2)),
315-
) => {
316-
// both type vars are unknown since we tried to resolve them
317-
self.var_unification_table.union(*tv1, *tv2);
318-
true
319-
}
320-
321-
// The order of MaybeNeverTypeVar matters here.
322-
// Unifying MaybeNeverTypeVar and TypeVar will let the latter become MaybeNeverTypeVar.
323-
// Unifying MaybeNeverTypeVar and other concrete type will let the former become it.
324-
(Ty::Infer(InferTy::TypeVar(tv)), other)
325-
| (other, Ty::Infer(InferTy::TypeVar(tv)))
326-
| (Ty::Infer(InferTy::MaybeNeverTypeVar(tv)), other)
327-
| (other, Ty::Infer(InferTy::MaybeNeverTypeVar(tv)))
328-
| (Ty::Infer(InferTy::IntVar(tv)), other @ ty_app!(TypeCtor::Int(_)))
329-
| (other @ ty_app!(TypeCtor::Int(_)), Ty::Infer(InferTy::IntVar(tv)))
330-
| (Ty::Infer(InferTy::FloatVar(tv)), other @ ty_app!(TypeCtor::Float(_)))
331-
| (other @ ty_app!(TypeCtor::Float(_)), Ty::Infer(InferTy::FloatVar(tv))) => {
332-
// the type var is unknown since we tried to resolve it
333-
self.var_unification_table.union_value(*tv, TypeVarValue::Known(other.clone()));
334-
true
335-
}
336-
337-
_ => false,
338-
}
339-
}
340-
341-
fn new_type_var(&mut self) -> Ty {
342-
Ty::Infer(InferTy::TypeVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
343-
}
344-
345-
fn new_integer_var(&mut self) -> Ty {
346-
Ty::Infer(InferTy::IntVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
347-
}
348-
349-
fn new_float_var(&mut self) -> Ty {
350-
Ty::Infer(InferTy::FloatVar(self.var_unification_table.new_key(TypeVarValue::Unknown)))
351-
}
352-
353-
fn new_maybe_never_type_var(&mut self) -> Ty {
354-
Ty::Infer(InferTy::MaybeNeverTypeVar(
355-
self.var_unification_table.new_key(TypeVarValue::Unknown),
356-
))
357-
}
358-
359277
/// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
360278
fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
361279
match ty {
362-
Ty::Unknown => self.new_type_var(),
280+
Ty::Unknown => self.table.new_type_var(),
363281
Ty::Apply(ApplicationTy { ctor: TypeCtor::Int(Uncertain::Unknown), .. }) => {
364-
self.new_integer_var()
282+
self.table.new_integer_var()
365283
}
366284
Ty::Apply(ApplicationTy { ctor: TypeCtor::Float(Uncertain::Unknown), .. }) => {
367-
self.new_float_var()
285+
self.table.new_float_var()
368286
}
369287
_ => ty,
370288
}
@@ -402,64 +320,22 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
402320
}
403321
}
404322

323+
fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
324+
self.table.unify(ty1, ty2)
325+
}
326+
405327
/// Resolves the type as far as currently possible, replacing type variables
406328
/// by their known types. All types returned by the infer_* functions should
407329
/// be resolved as far as possible, i.e. contain no type variables with
408330
/// known type.
409-
fn resolve_ty_as_possible(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
331+
fn resolve_ty_as_possible(&mut self, ty: Ty) -> Ty {
410332
self.resolve_obligations_as_possible();
411333

412-
ty.fold(&mut |ty| match ty {
413-
Ty::Infer(tv) => {
414-
let inner = tv.to_inner();
415-
if tv_stack.contains(&inner) {
416-
tested_by!(type_var_cycles_resolve_as_possible);
417-
// recursive type
418-
return tv.fallback_value();
419-
}
420-
if let Some(known_ty) =
421-
self.var_unification_table.inlined_probe_value(inner).known()
422-
{
423-
// known_ty may contain other variables that are known by now
424-
tv_stack.push(inner);
425-
let result = self.resolve_ty_as_possible(tv_stack, known_ty.clone());
426-
tv_stack.pop();
427-
result
428-
} else {
429-
ty
430-
}
431-
}
432-
_ => ty,
433-
})
334+
self.table.resolve_ty_as_possible(ty)
434335
}
435336

436-
/// If `ty` is a type variable with known type, returns that type;
437-
/// otherwise, return ty.
438337
fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
439-
let mut ty = Cow::Borrowed(ty);
440-
// The type variable could resolve to a int/float variable. Hence try
441-
// resolving up to three times; each type of variable shouldn't occur
442-
// more than once
443-
for i in 0..3 {
444-
if i > 0 {
445-
tested_by!(type_var_resolves_to_int_var);
446-
}
447-
match &*ty {
448-
Ty::Infer(tv) => {
449-
let inner = tv.to_inner();
450-
match self.var_unification_table.inlined_probe_value(inner).known() {
451-
Some(known_ty) => {
452-
// The known_ty can't be a type var itself
453-
ty = Cow::Owned(known_ty.clone());
454-
}
455-
_ => return ty,
456-
}
457-
}
458-
_ => return ty,
459-
}
460-
}
461-
log::error!("Inference variable still not resolved: {:?}", ty);
462-
ty
338+
self.table.resolve_ty_shallow(ty)
463339
}
464340

465341
/// Recurses through the given type, normalizing associated types mentioned
@@ -469,48 +345,21 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
469345
/// call). `make_ty` handles this already, but e.g. for field types we need
470346
/// to do it as well.
471347
fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
472-
let ty = self.resolve_ty_as_possible(&mut vec![], ty);
348+
let ty = self.resolve_ty_as_possible(ty);
473349
ty.fold(&mut |ty| match ty {
474350
Ty::Projection(proj_ty) => self.normalize_projection_ty(proj_ty),
475351
_ => ty,
476352
})
477353
}
478354

479355
fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
480-
let var = self.new_type_var();
356+
let var = self.table.new_type_var();
481357
let predicate = ProjectionPredicate { projection_ty: proj_ty, ty: var.clone() };
482358
let obligation = Obligation::Projection(predicate);
483359
self.obligations.push(obligation);
484360
var
485361
}
486362

487-
/// Resolves the type completely; type variables without known type are
488-
/// replaced by Ty::Unknown.
489-
fn resolve_ty_completely(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
490-
ty.fold(&mut |ty| match ty {
491-
Ty::Infer(tv) => {
492-
let inner = tv.to_inner();
493-
if tv_stack.contains(&inner) {
494-
tested_by!(type_var_cycles_resolve_completely);
495-
// recursive type
496-
return tv.fallback_value();
497-
}
498-
if let Some(known_ty) =
499-
self.var_unification_table.inlined_probe_value(inner).known()
500-
{
501-
// known_ty may contain other variables that are known by now
502-
tv_stack.push(inner);
503-
let result = self.resolve_ty_completely(tv_stack, known_ty.clone());
504-
tv_stack.pop();
505-
result
506-
} else {
507-
tv.fallback_value()
508-
}
509-
}
510-
_ => ty,
511-
})
512-
}
513-
514363
fn resolve_variant(&mut self, path: Option<&Path>) -> (Ty, Option<VariantId>) {
515364
let path = match path {
516365
Some(path) => path,
@@ -615,78 +464,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
615464
}
616465
}
617466

618-
/// The ID of a type variable.
619-
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
620-
pub struct TypeVarId(pub(super) u32);
621-
622-
impl UnifyKey for TypeVarId {
623-
type Value = TypeVarValue;
624-
625-
fn index(&self) -> u32 {
626-
self.0
627-
}
628-
629-
fn from_index(i: u32) -> Self {
630-
TypeVarId(i)
631-
}
632-
633-
fn tag() -> &'static str {
634-
"TypeVarId"
635-
}
636-
}
637-
638-
/// The value of a type variable: either we already know the type, or we don't
639-
/// know it yet.
640-
#[derive(Clone, PartialEq, Eq, Debug)]
641-
pub enum TypeVarValue {
642-
Known(Ty),
643-
Unknown,
644-
}
645-
646-
impl TypeVarValue {
647-
fn known(&self) -> Option<&Ty> {
648-
match self {
649-
TypeVarValue::Known(ty) => Some(ty),
650-
TypeVarValue::Unknown => None,
651-
}
652-
}
653-
}
654-
655-
impl UnifyValue for TypeVarValue {
656-
type Error = NoError;
657-
658-
fn unify_values(value1: &Self, value2: &Self) -> Result<Self, NoError> {
659-
match (value1, value2) {
660-
// We should never equate two type variables, both of which have
661-
// known types. Instead, we recursively equate those types.
662-
(TypeVarValue::Known(t1), TypeVarValue::Known(t2)) => panic!(
663-
"equating two type variables, both of which have known types: {:?} and {:?}",
664-
t1, t2
665-
),
666-
667-
// If one side is known, prefer that one.
668-
(TypeVarValue::Known(..), TypeVarValue::Unknown) => Ok(value1.clone()),
669-
(TypeVarValue::Unknown, TypeVarValue::Known(..)) => Ok(value2.clone()),
670-
671-
(TypeVarValue::Unknown, TypeVarValue::Unknown) => Ok(TypeVarValue::Unknown),
672-
}
673-
}
674-
}
675-
676467
/// The kinds of placeholders we need during type inference. There's separate
677468
/// values for general types, and for integer and float variables. The latter
678469
/// two are used for inference of literal values (e.g. `100` could be one of
679470
/// several integer types).
680471
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
681472
pub enum InferTy {
682-
TypeVar(TypeVarId),
683-
IntVar(TypeVarId),
684-
FloatVar(TypeVarId),
685-
MaybeNeverTypeVar(TypeVarId),
473+
TypeVar(unify::TypeVarId),
474+
IntVar(unify::TypeVarId),
475+
FloatVar(unify::TypeVarId),
476+
MaybeNeverTypeVar(unify::TypeVarId),
686477
}
687478

688479
impl InferTy {
689-
fn to_inner(self) -> TypeVarId {
480+
fn to_inner(self) -> unify::TypeVarId {
690481
match self {
691482
InferTy::TypeVar(ty)
692483
| InferTy::IntVar(ty)

0 commit comments

Comments
 (0)