aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-04-17 18:41:37 +0100
committerFlorian Diebold <[email protected]>2020-04-17 18:42:36 +0100
commit6a7fc76b89dca4d1b4e3e50047183535aee98627 (patch)
tree54d7d20ef4dc585bf85d176173f6d59273699681 /crates
parentf11236e511ec8470276180fa728f4e00c17ee3fb (diff)
Fix type equality for dyn Trait
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...)
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_ty/src/infer/coerce.rs4
-rw-r--r--crates/ra_hir_ty/src/infer/unify.rs42
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs24
3 files changed, 65 insertions, 5 deletions
diff --git a/crates/ra_hir_ty/src/infer/coerce.rs b/crates/ra_hir_ty/src/infer/coerce.rs
index 959b1e212..89200255a 100644
--- a/crates/ra_hir_ty/src/infer/coerce.rs
+++ b/crates/ra_hir_ty/src/infer/coerce.rs
@@ -51,7 +51,7 @@ impl<'a> InferenceContext<'a> {
51 // Trivial cases, this should go after `never` check to 51 // Trivial cases, this should go after `never` check to
52 // avoid infer result type to be never 52 // avoid infer result type to be never
53 _ => { 53 _ => {
54 if self.table.unify_inner_trivial(&from_ty, &to_ty) { 54 if self.table.unify_inner_trivial(&from_ty, &to_ty, 0) {
55 return true; 55 return true;
56 } 56 }
57 } 57 }
@@ -175,7 +175,7 @@ impl<'a> InferenceContext<'a> {
175 return self.table.unify_substs(st1, st2, 0); 175 return self.table.unify_substs(st1, st2, 0);
176 } 176 }
177 _ => { 177 _ => {
178 if self.table.unify_inner_trivial(&derefed_ty, &to_ty) { 178 if self.table.unify_inner_trivial(&derefed_ty, &to_ty, 0) {
179 return true; 179 return true;
180 } 180 }
181 } 181 }
diff --git a/crates/ra_hir_ty/src/infer/unify.rs b/crates/ra_hir_ty/src/infer/unify.rs
index 5f6cea8d3..ab0bc8b70 100644
--- a/crates/ra_hir_ty/src/infer/unify.rs
+++ b/crates/ra_hir_ty/src/infer/unify.rs
@@ -8,7 +8,8 @@ use test_utils::tested_by;
8 8
9use super::{InferenceContext, Obligation}; 9use super::{InferenceContext, Obligation};
10use crate::{ 10use crate::{
11 BoundVar, Canonical, DebruijnIndex, InEnvironment, InferTy, Substs, Ty, TypeCtor, TypeWalk, 11 BoundVar, Canonical, DebruijnIndex, GenericPredicate, InEnvironment, InferTy, Substs, Ty,
12 TypeCtor, TypeWalk,
12}; 13};
13 14
14impl<'a> InferenceContext<'a> { 15impl<'a> InferenceContext<'a> {
@@ -226,16 +227,26 @@ impl InferenceTable {
226 (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => { 227 (Ty::Apply(a_ty1), Ty::Apply(a_ty2)) if a_ty1.ctor == a_ty2.ctor => {
227 self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1) 228 self.unify_substs(&a_ty1.parameters, &a_ty2.parameters, depth + 1)
228 } 229 }
229 _ => self.unify_inner_trivial(&ty1, &ty2), 230
231 _ => self.unify_inner_trivial(&ty1, &ty2, depth),
230 } 232 }
231 } 233 }
232 234
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 {
234 match (ty1, ty2) { 236 match (ty1, ty2) {
235 (Ty::Unknown, _) | (_, Ty::Unknown) => true, 237 (Ty::Unknown, _) | (_, Ty::Unknown) => true,
236 238
237 (Ty::Placeholder(p1), Ty::Placeholder(p2)) if *p1 == *p2 => true, 239 (Ty::Placeholder(p1), Ty::Placeholder(p2)) if *p1 == *p2 => true,
238 240
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
239 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2))) 250 (Ty::Infer(InferTy::TypeVar(tv1)), Ty::Infer(InferTy::TypeVar(tv2)))
240 | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2))) 251 | (Ty::Infer(InferTy::IntVar(tv1)), Ty::Infer(InferTy::IntVar(tv2)))
241 | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2))) 252 | (Ty::Infer(InferTy::FloatVar(tv1)), Ty::Infer(InferTy::FloatVar(tv2)))
@@ -268,6 +279,31 @@ impl InferenceTable {
268 } 279 }
269 } 280 }
270 281
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
271 /// If `ty` is a type variable with known type, returns that type; 307 /// If `ty` is a type variable with known type, returns that type;
272 /// otherwise, return ty. 308 /// otherwise, return ty.
273 pub fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> { 309 pub fn resolve_ty_shallow<'b>(&mut self, ty: &'b Ty) -> Cow<'b, Ty> {
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index dc517fc4a..f6e3e07cd 100644
--- a/crates/ra_hir_ty/src/tests/traits.rs
+++ b/crates/ra_hir_ty/src/tests/traits.rs
@@ -2378,3 +2378,27 @@ fn main() {
2378 ); 2378 );
2379 assert_eq!(t, "Foo"); 2379 assert_eq!(t, "Foo");
2380} 2380}
2381
2382#[test]
2383fn trait_object_no_coercion() {
2384 assert_snapshot!(
2385 infer_with_mismatches(r#"
2386trait Foo {}
2387
2388fn foo(x: &dyn Foo) {}
2389
2390fn 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}