From 287e9a870c90650f2779c25de498602782a0f683 Mon Sep 17 00:00:00 2001 From: Florian Diebold Date: Mon, 15 Mar 2021 18:22:25 +0100 Subject: [PATCH] Fix unification logic --- crates/hir_ty/src/infer/unify.rs | 2 +- crates/hir_ty/src/tests/traits.rs | 216 ++++++++++++++++-------------- 2 files changed, 117 insertions(+), 101 deletions(-) diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index 66f8fe8a320..7795f446f51 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs @@ -300,7 +300,7 @@ fn unify_inner(&mut self, ty1: &Ty, ty2: &Ty, depth: usize) -> bool { | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2)) | (TyKind::Array(ty1), TyKind::Array(ty2)) | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1), - _ => false, + _ => true, /* we checked equals_ctor already */ } } else { self.unify_inner_trivial(&ty1, &ty2, depth) diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index e185b1c0a16..93d3ad020a8 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs @@ -1699,7 +1699,7 @@ fn test() { #[test] fn fn_trait() { - check_infer( + check_infer_with_mismatches( r#" trait FnOnce { type Output; @@ -1727,7 +1727,7 @@ fn test u128>(f: F) { #[test] fn fn_ptr_and_item() { - check_infer( + check_infer_with_mismatches( r#" #[lang="fn_once"] trait FnOnce { @@ -1743,12 +1743,12 @@ trait Foo { struct Bar(T); impl R> Foo<(A1, R)> for Bar { - fn foo(&self) -> (A1, R) {} + fn foo(&self) -> (A1, R) { loop {} } } enum Opt { None, Some(T) } impl Opt { - fn map U>(self, f: F) -> Opt {} + fn map U>(self, f: F) -> Opt { loop {} } } fn test() { @@ -1765,19 +1765,23 @@ fn test() { 80..84 'args': Args 139..143 'self': &Self 243..247 'self': &Bar - 260..262 '{}': () - 346..350 'self': Opt - 352..353 'f': F - 368..370 '{}': () - 384..500 '{ ...(f); }': () - 394..397 'bar': Bar u32> - 423..426 'bar': Bar u32> - 423..432 'bar.foo()': (u8, u32) - 443..446 'opt': Opt - 465..466 'f': fn(u8) -> u32 - 487..490 'opt': Opt - 487..497 'opt.map(f)': Opt - 495..496 'f': fn(u8) -> u32 + 260..271 '{ loop {} }': (A1, R) + 262..269 'loop {}': ! + 267..269 '{}': () + 355..359 'self': Opt + 361..362 'f': F + 377..388 '{ loop {} }': Opt + 379..386 'loop {}': ! + 384..386 '{}': () + 402..518 '{ ...(f); }': () + 412..415 'bar': Bar u32> + 441..444 'bar': Bar u32> + 441..450 'bar.foo()': (u8, u32) + 461..464 'opt': Opt + 483..484 'f': fn(u8) -> u32 + 505..508 'opt': Opt + 505..515 'opt.map(f)': Opt + 513..514 'f': fn(u8) -> u32 "#]], ); } @@ -1859,7 +1863,7 @@ fn make_foo_fn() -> Foo {} #[test] fn closure_1() { - check_infer( + check_infer_with_mismatches( r#" #[lang = "fn_once"] trait FnOnce { @@ -1868,7 +1872,7 @@ trait FnOnce { enum Option { Some(T), None } impl Option { - fn map U>(self, f: F) -> Option {} + fn map U>(self, f: F) -> Option { loop {} } } fn test() { @@ -1881,37 +1885,39 @@ fn test() { expect![[r#" 147..151 'self': Option 153..154 'f': F - 172..174 '{}': () - 188..307 '{ ... 1); }': () - 198..199 'x': Option - 202..214 'Option::Some': Some(u32) -> Option - 202..220 'Option...(1u32)': Option - 215..219 '1u32': u32 - 226..227 'x': Option - 226..242 'x.map(...v + 1)': Option - 232..241 '|v| v + 1': |u32| -> u32 - 233..234 'v': u32 - 236..237 'v': u32 - 236..241 'v + 1': u32 - 240..241 '1': u32 - 248..249 'x': Option - 248..264 'x.map(... 1u64)': Option - 254..263 '|_v| 1u64': |u32| -> u64 - 255..257 '_v': u32 - 259..263 '1u64': u64 - 274..275 'y': Option - 291..292 'x': Option - 291..304 'x.map(|_v| 1)': Option - 297..303 '|_v| 1': |u32| -> i64 - 298..300 '_v': u32 - 302..303 '1': i64 + 172..183 '{ loop {} }': Option + 174..181 'loop {}': ! + 179..181 '{}': () + 197..316 '{ ... 1); }': () + 207..208 'x': Option + 211..223 'Option::Some': Some(u32) -> Option + 211..229 'Option...(1u32)': Option + 224..228 '1u32': u32 + 235..236 'x': Option + 235..251 'x.map(...v + 1)': Option + 241..250 '|v| v + 1': |u32| -> u32 + 242..243 'v': u32 + 245..246 'v': u32 + 245..250 'v + 1': u32 + 249..250 '1': u32 + 257..258 'x': Option + 257..273 'x.map(... 1u64)': Option + 263..272 '|_v| 1u64': |u32| -> u64 + 264..266 '_v': u32 + 268..272 '1u64': u64 + 283..284 'y': Option + 300..301 'x': Option + 300..313 'x.map(|_v| 1)': Option + 306..312 '|_v| 1': |u32| -> i64 + 307..309 '_v': u32 + 311..312 '1': i64 "#]], ); } #[test] fn closure_2() { - check_infer( + check_infer_with_mismatches( r#" trait FnOnce { type Output; @@ -1951,22 +1957,22 @@ fn test u64>(f: F) { #[test] fn closure_as_argument_inference_order() { - check_infer( + check_infer_with_mismatches( r#" #[lang = "fn_once"] trait FnOnce { type Output; } - fn foo1 U>(x: T, f: F) -> U {} - fn foo2 U>(f: F, x: T) -> U {} + fn foo1 U>(x: T, f: F) -> U { loop {} } + fn foo2 U>(f: F, x: T) -> U { loop {} } struct S; impl S { fn method(self) -> u64; - fn foo1 U>(self, x: T, f: F) -> U {} - fn foo2 U>(self, f: F, x: T) -> U {} + fn foo1 U>(self, x: T, f: F) -> U { loop {} } + fn foo2 U>(self, f: F, x: T) -> U { loop {} } } fn test() { @@ -1979,52 +1985,60 @@ fn test() { expect![[r#" 94..95 'x': T 100..101 'f': F - 111..113 '{}': () - 147..148 'f': F - 153..154 'x': T - 164..166 '{}': () - 201..205 'self': S - 253..257 'self': S - 259..260 'x': T - 265..266 'f': F - 276..278 '{}': () - 316..320 'self': S - 322..323 'f': F - 328..329 'x': T - 339..341 '{}': () - 355..514 '{ ... S); }': () - 365..367 'x1': u64 - 370..374 'foo1': fn foo1 u64>(S, |S| -> u64) -> u64 - 370..393 'foo1(S...hod())': u64 - 375..376 'S': S - 378..392 '|s| s.method()': |S| -> u64 - 379..380 's': S - 382..383 's': S - 382..392 's.method()': u64 - 403..405 'x2': u64 - 408..412 'foo2': fn foo2 u64>(|S| -> u64, S) -> u64 - 408..431 'foo2(|...(), S)': u64 - 413..427 '|s| s.method()': |S| -> u64 - 414..415 's': S - 417..418 's': S - 417..427 's.method()': u64 - 429..430 'S': S - 441..443 'x3': u64 - 446..447 'S': S - 446..471 'S.foo1...hod())': u64 - 453..454 'S': S - 456..470 '|s| s.method()': |S| -> u64 - 457..458 's': S - 460..461 's': S - 460..470 's.method()': u64 - 481..483 'x4': u64 - 486..487 'S': S - 486..511 'S.foo2...(), S)': u64 - 493..507 '|s| s.method()': |S| -> u64 - 494..495 's': S - 497..498 's': S - 497..507 's.method()': u64 - 509..510 'S': S + 111..122 '{ loop {} }': U + 113..120 'loop {}': ! + 118..120 '{}': () + 156..157 'f': F + 162..163 'x': T + 173..184 '{ loop {} }': U + 175..182 'loop {}': ! + 180..182 '{}': () + 219..223 'self': S + 271..275 'self': S + 277..278 'x': T + 283..284 'f': F + 294..305 '{ loop {} }': U + 296..303 'loop {}': ! + 301..303 '{}': () + 343..347 'self': S + 349..350 'f': F + 355..356 'x': T + 366..377 '{ loop {} }': U + 368..375 'loop {}': ! + 373..375 '{}': () + 391..550 '{ ... S); }': () + 401..403 'x1': u64 + 406..410 'foo1': fn foo1 u64>(S, |S| -> u64) -> u64 + 406..429 'foo1(S...hod())': u64 + 411..412 'S': S + 414..428 '|s| s.method()': |S| -> u64 + 415..416 's': S + 418..419 's': S + 418..428 's.method()': u64 + 439..441 'x2': u64 + 444..448 'foo2': fn foo2 u64>(|S| -> u64, S) -> u64 + 444..467 'foo2(|...(), S)': u64 + 449..463 '|s| s.method()': |S| -> u64 + 450..451 's': S + 453..454 's': S + 453..463 's.method()': u64 + 465..466 'S': S + 477..479 'x3': u64 + 482..483 'S': S + 482..507 'S.foo1...hod())': u64 + 489..490 'S': S + 492..506 '|s| s.method()': |S| -> u64 + 493..494 's': S + 496..497 's': S + 496..506 's.method()': u64 + 517..519 'x4': u64 + 522..523 'S': S + 522..547 'S.foo2...(), S)': u64 + 529..543 '|s| s.method()': |S| -> u64 + 530..531 's': S + 533..534 's': S + 533..543 's.method()': u64 + 545..546 'S': S "#]], ); } @@ -2536,7 +2550,7 @@ fn test() { #[test] fn iterator_chain() { - check_infer( + check_infer_with_mismatches( r#" //- /main.rs #[lang = "fn_once"] @@ -2939,7 +2953,7 @@ fn foo() { #[test] fn infer_fn_trait_arg() { - check_infer( + check_infer_with_mismatches( r#" //- /lib.rs deps:std @@ -2986,7 +3000,8 @@ fn foo(f: F) -> T #[test] fn infer_box_fn_arg() { - check_infer( + // The type mismatch is a bug + check_infer_with_mismatches( r#" //- /lib.rs deps:std @@ -3025,7 +3040,7 @@ enum Option { fn foo() { let s = Option::None; let f: Box)> = box (|ps| {}); - f(&s) + f(&s); } "#, expect![[r#" @@ -3037,7 +3052,7 @@ fn foo() { 406..417 '&self.inner': &*mut T 407..411 'self': &Box 407..417 'self.inner': *mut T - 478..575 '{ ...(&s) }': FnOnce::Output), (&Option,)> + 478..576 '{ ...&s); }': () 488..489 's': Option 492..504 'Option::None': Option 514..515 'f': Box)> @@ -3049,6 +3064,7 @@ fn foo() { 568..573 'f(&s)': FnOnce::Output), (&Option,)> 570..572 '&s': &Option 571..572 's': Option + 549..562: expected Box)>, got Box<|_| -> ()> "#]], ); }