Skip to content

Commit 8a4ceba

Browse files
Merge #4021
4021: Fix type equality for dyn Trait r=matklad a=flodiebold Fixes a lot of false type mismatches. (And as always when touching the unification code, I have to say I'm looking forward to replacing it by Chalk's...) Co-authored-by: Florian Diebold <[email protected]>
2 parents f11236e + 6a7fc76 commit 8a4ceba

File tree

3 files changed

+65
-5
lines changed

3 files changed

+65
-5
lines changed

crates/ra_hir_ty/src/infer/coerce.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ impl<'a> InferenceContext<'a> {
5151
// Trivial cases, this should go after `never` check to
5252
// avoid infer result type to be never
5353
_ => {
54-
if self.table.unify_inner_trivial(&from_ty, &to_ty) {
54+
if self.table.unify_inner_trivial(&from_ty, &to_ty, 0) {
5555
return true;
5656
}
5757
}
@@ -175,7 +175,7 @@ impl<'a> InferenceContext<'a> {
175175
return self.table.unify_substs(st1, st2, 0);
176176
}
177177
_ => {
178-
if self.table.unify_inner_trivial(&derefed_ty, &to_ty) {
178+
if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) {
179179
return true;
180180
}
181181
}

crates/ra_hir_ty/src/infer/unify.rs

+39-3
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ use test_utils::tested_by;
88

99
use super::{InferenceContext, Obligation};
1010
use crate::{
11-
BoundVar, Canonical, DebruijnIndex, InEnvironment, InferTy, Substs, Ty, TypeCtor, TypeWalk,
11+
BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferTy, Substs, Ty,
12+
TypeCtor, TypeWalk,
1213
};
1314

1415
impl<'a> InferenceContext<'a> {
@@ -226,16 +227,26 @@ impl InferenceTable {
226227
(Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => {
227228
self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1)
228229
}
229-
_ => self.unify_inner_trivial(&ty1, &ty2),
230+
231+
_ => self.unify_inner_trivial(&ty1, &ty2, depth),
230232
}
231233
}
232234

233-
pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
235+
pub(super) fn unify_inner_trivial(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool {
234236
match (ty1, ty2) {
235237
(Ty::Unknown, _) | (_, Ty::Unknown) => true,
236238

237239
(Ty::Placeholder(p1), Ty::Placeholder(p2)) if *p1 == *p2 => true,
238240

241+
(Ty::Dyn(dyn1), Ty::Dyn(dyn2)) if dyn1.len() == dyn2.len() => {
242+
for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) {
243+
if !self.unify_preds(pred1, pred2, depth + 1) {
244+
return false;
245+
}
246+
}
247+
true
248+
}
249+
239250
(Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
240251
| (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
241252
| (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2)))
@@ -268,6 +279,31 @@ impl InferenceTable {
268279
}
269280
}
270281

282+
fn unify_preds(
283+
&mut self,
284+
pred1: &GenericPredicate,
285+
pred2: &GenericPredicate,
286+
depth: usize,
287+
) -> bool {
288+
match (pred1, pred2) {
289+
(GenericPredicate::Implemented(tr1), GenericPredicate::Implemented(tr2))
290+
if tr1.trait_ == tr2.trait_ =>
291+
{
292+
self.unify_substs(&tr1.substs, &tr2.substs, depth + 1)
293+
}
294+
(GenericPredicate::Projection(proj1), GenericPredicate::Projection(proj2))
295+
if proj1.projection_ty.associated_ty == proj2.projection_ty.associated_ty =>
296+
{
297+
self.unify_substs(
298+
&proj1.projection_ty.parameters,
299+
&proj2.projection_ty.parameters,
300+
depth + 1,
301+
) && self.unify_inner(&proj1.ty, &proj2.ty, depth + 1)
302+
}
303+
_ => false,
304+
}
305+
}
306+
271307
/// If `ty` is a type variable with known type, returns that type;
272308
/// otherwise, return ty.
273309
pub fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {

crates/ra_hir_ty/src/tests/traits.rs

+24
Original file line numberDiff line numberDiff line change
@@ -2378,3 +2378,27 @@ fn main() {
23782378
);
23792379
assert_eq!(t, "Foo");
23802380
}
2381+
2382+
#[test]
2383+
fn trait_object_no_coercion() {
2384+
assert_snapshot!(
2385+
infer_with_mismatches(r#"
2386+
trait Foo {}
2387+
2388+
fn foo(x: &dyn Foo) {}
2389+
2390+
fn test(x: &dyn Foo) {
2391+
foo(x);
2392+
}
2393+
"#, true),
2394+
@r###"
2395+
[22; 23) 'x': &dyn Foo
2396+
[35; 37) '{}': ()
2397+
[47; 48) 'x': &dyn Foo
2398+
[60; 75) '{ foo(x); }': ()
2399+
[66; 69) 'foo': fn foo(&dyn Foo)
2400+
[66; 72) 'foo(x)': ()
2401+
[70; 71) 'x': &dyn Foo
2402+
"###
2403+
);
2404+
}

0 commit comments

Comments
 (0)