Skip to content

Commit 9eb7553

Browse files
Merge #11842
11842: Fix duplicate type mismatches with blocks r=flodiebold a=flodiebold E.g. when there's a type mismatch on the return value of a function. To fix this, we have to return the expected type as the type of the block when there's a mismatch. That meant some IDE code that expected otherwise had to be adapted, in particular the "add return type" assist. For the "wrap in Ok/Some" quickfix, this sadly means it usually can't be applied in all branches of an if expression at the same time anymore, because there's a type mismatch for each branch that has the wrong type. Co-authored-by: Florian Diebold <flodiebold@gmail.com>
2 parents 89d495e + 0c4bdd2 commit 9eb7553

File tree

12 files changed

+212
-83
lines changed

12 files changed

+212
-83
lines changed

crates/hir_ty/src/infer/expr.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -69,12 +69,11 @@ impl<'a> InferenceContext<'a> {
6969
match self.coerce(Some(expr), &ty, &target) {
7070
Ok(res) => res,
7171
Err(_) => {
72-
self.result
73-
.type_mismatches
74-
.insert(expr.into(), TypeMismatch { expected: target, actual: ty.clone() });
75-
// Return actual type when type mismatch.
76-
// This is needed for diagnostic when return type mismatch.
77-
ty
72+
self.result.type_mismatches.insert(
73+
expr.into(),
74+
TypeMismatch { expected: target.clone(), actual: ty.clone() },
75+
);
76+
target
7877
}
7978
}
8079
} else {
@@ -914,9 +913,16 @@ impl<'a> InferenceContext<'a> {
914913
self.table.new_maybe_never_var()
915914
} else {
916915
if let Some(t) = expected.only_has_type(&mut self.table) {
917-
let _ = self.coerce(Some(expr), &TyBuilder::unit(), &t);
916+
if self.coerce(Some(expr), &TyBuilder::unit(), &t).is_err() {
917+
self.result.type_mismatches.insert(
918+
expr.into(),
919+
TypeMismatch { expected: t.clone(), actual: TyBuilder::unit() },
920+
);
921+
}
922+
t
923+
} else {
924+
TyBuilder::unit()
918925
}
919-
TyBuilder::unit()
920926
}
921927
}
922928
}

crates/hir_ty/src/tests.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ mod method_resolution;
88
mod macros;
99
mod display_source_code;
1010
mod incremental;
11+
mod diagnostics;
1112

1213
use std::{collections::HashMap, env, sync::Arc};
1314

crates/hir_ty/src/tests/coercion.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@ use super::{check, check_no_mismatches, check_types};
22

33
#[test]
44
fn block_expr_type_mismatch() {
5-
// FIXME fix double type mismatch
65
check(
76
r"
87
fn test() {
98
let a: i32 = { 1i64 };
10-
// ^^^^^^^^ expected i32, got i64
119
// ^^^^ expected i32, got i64
1210
}
1311
",
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
use super::check;
2+
3+
#[test]
4+
fn function_return_type_mismatch_1() {
5+
check(
6+
r#"
7+
fn test() -> &'static str {
8+
5
9+
//^ expected &str, got i32
10+
}
11+
"#,
12+
);
13+
}
14+
15+
#[test]
16+
fn function_return_type_mismatch_2() {
17+
check(
18+
r#"
19+
fn test(x: bool) -> &'static str {
20+
if x {
21+
return 1;
22+
//^ expected &str, got i32
23+
}
24+
"ok"
25+
}
26+
"#,
27+
);
28+
}
29+
30+
#[test]
31+
fn function_return_type_mismatch_3() {
32+
check(
33+
r#"
34+
fn test(x: bool) -> &'static str {
35+
if x {
36+
return "ok";
37+
}
38+
1
39+
//^ expected &str, got i32
40+
}
41+
"#,
42+
);
43+
}
44+
45+
#[test]
46+
fn function_return_type_mismatch_4() {
47+
check(
48+
r#"
49+
fn test(x: bool) -> &'static str {
50+
if x {
51+
"ok"
52+
} else {
53+
1
54+
//^ expected &str, got i32
55+
}
56+
}
57+
"#,
58+
);
59+
}
60+
61+
#[test]
62+
fn function_return_type_mismatch_5() {
63+
check(
64+
r#"
65+
fn test(x: bool) -> &'static str {
66+
if x {
67+
1
68+
//^ expected &str, got i32
69+
} else {
70+
"ok"
71+
}
72+
}
73+
"#,
74+
);
75+
}

crates/hir_ty/src/tests/never_type.rs

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -314,11 +314,10 @@ fn diverging_expression_2() {
314314
expect![[r#"
315315
11..84 '{ ..." }; }': ()
316316
54..55 'x': u32
317-
63..81 '{ loop...foo" }': &str
317+
63..81 '{ loop...foo" }': u32
318318
65..72 'loop {}': !
319319
70..72 '{}': ()
320320
74..79 '"foo"': &str
321-
63..81: expected u32, got &str
322321
74..79: expected u32, got &str
323322
"#]],
324323
);
@@ -350,31 +349,30 @@ fn diverging_expression_3_break() {
350349
let x: u32 = { while true { return; }; };
351350
}
352351
",
353-
expect![[r"
352+
expect![[r#"
354353
11..85 '{ ...} }; }': ()
355354
54..55 'x': u32
356-
63..82 '{ loop...k; } }': ()
355+
63..82 '{ loop...k; } }': u32
357356
65..80 'loop { break; }': ()
358357
70..80 '{ break; }': ()
359358
72..77 'break': !
360-
63..82: expected u32, got ()
361359
65..80: expected u32, got ()
362360
97..343 '{ ...; }; }': ()
363361
140..141 'x': u32
364-
149..175 '{ for ...; }; }': ()
362+
149..175 '{ for ...; }; }': u32
365363
151..172 'for a ...eak; }': ()
366364
155..156 'a': {unknown}
367365
160..161 'b': {unknown}
368366
162..172 '{ break; }': ()
369367
164..169 'break': !
370368
226..227 'x': u32
371-
235..253 '{ for ... {}; }': ()
369+
235..253 '{ for ... {}; }': u32
372370
237..250 'for a in b {}': ()
373371
241..242 'a': {unknown}
374372
246..247 'b': {unknown}
375373
248..250 '{}': ()
376374
304..305 'x': u32
377-
313..340 '{ for ...; }; }': ()
375+
313..340 '{ for ...; }; }': u32
378376
315..337 'for a ...urn; }': ()
379377
319..320 'a': {unknown}
380378
324..325 'b': {unknown}
@@ -385,26 +383,26 @@ fn diverging_expression_3_break() {
385383
313..340: expected u32, got ()
386384
355..654 '{ ...; }; }': ()
387385
398..399 'x': u32
388-
407..433 '{ whil...; }; }': ()
386+
407..433 '{ whil...; }; }': u32
389387
409..430 'while ...eak; }': ()
390388
415..419 'true': bool
391389
420..430 '{ break; }': ()
392390
422..427 'break': !
393391
537..538 'x': u32
394-
546..564 '{ whil... {}; }': ()
392+
546..564 '{ whil... {}; }': u32
395393
548..561 'while true {}': ()
396394
554..558 'true': bool
397395
559..561 '{}': ()
398396
615..616 'x': u32
399-
624..651 '{ whil...; }; }': ()
397+
624..651 '{ whil...; }; }': u32
400398
626..648 'while ...urn; }': ()
401399
632..636 'true': bool
402400
637..648 '{ return; }': ()
403401
639..645 'return': !
404402
407..433: expected u32, got ()
405403
546..564: expected u32, got ()
406404
624..651: expected u32, got ()
407-
"]],
405+
"#]],
408406
);
409407
}
410408

@@ -438,7 +436,7 @@ fn let_else_must_diverge() {
438436
17..18 '1': i32
439437
17..18 '1': i32
440438
21..22 '2': i32
441-
28..30 '{}': ()
439+
28..30 '{}': !
442440
28..30: expected !, got ()
443441
"#]],
444442
);

crates/hir_ty/src/tests/regression.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ fn bug_1030() {
367367
}
368368
"#,
369369
expect![[r#"
370-
143..145 '{}': ()
370+
143..145 '{}': HashSet<T, H>
371371
168..197 '{ ...t(); }': ()
372372
174..192 'FxHash...efault': fn default<{unknown}, FxHasher>() -> HashSet<{unknown}, FxHasher>
373373
174..194 'FxHash...ault()': HashSet<{unknown}, FxHasher>
@@ -831,7 +831,7 @@ fn issue_4966() {
831831
"#,
832832
expect![[r#"
833833
225..229 'iter': T
834-
244..246 '{}': ()
834+
244..246 '{}': Vec<A>
835835
258..402 '{ ...r(); }': ()
836836
268..273 'inner': Map<|&f64| -> f64>
837837
276..300 'Map { ... 0.0 }': Map<|&f64| -> f64>
@@ -914,7 +914,7 @@ fn flush(&self) {
914914
"#,
915915
expect![[r#"
916916
123..127 'self': &Mutex<T>
917-
150..152 '{}': ()
917+
150..152 '{}': MutexGuard<T>
918918
234..238 'self': &{unknown}
919919
240..290 '{ ...()); }': ()
920920
250..251 'w': &Mutex<BufWriter>
@@ -1039,18 +1039,18 @@ fn cfg_tail() {
10391039
}
10401040
"#,
10411041
expect![[r#"
1042-
14..53 '{ ...)] 9 }': &str
1043-
20..31 '{ "first" }': &str
1042+
14..53 '{ ...)] 9 }': ()
1043+
20..31 '{ "first" }': ()
10441044
22..29 '"first"': &str
1045-
72..190 '{ ...] 13 }': &str
1045+
72..190 '{ ...] 13 }': ()
10461046
78..88 '{ "fake" }': &str
10471047
80..86 '"fake"': &str
10481048
93..103 '{ "fake" }': &str
10491049
95..101 '"fake"': &str
1050-
108..120 '{ "second" }': &str
1050+
108..120 '{ "second" }': ()
10511051
110..118 '"second"': &str
1052-
210..273 '{ ... 15; }': &str
1053-
216..227 '{ "third" }': &str
1052+
210..273 '{ ... 15; }': ()
1053+
216..227 '{ "third" }': ()
10541054
218..225 '"third"': &str
10551055
293..357 '{ ...] 15 }': ()
10561056
299..311 '{ "fourth" }': &str

crates/hir_ty/src/tests/simple.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -996,9 +996,9 @@ fn main(foo: Foo) {
996996
50..106 'if tru... }': ()
997997
53..57 'true': bool
998998
58..66 '{ }': ()
999-
72..106 'if fal... }': i32
999+
72..106 'if fal... }': ()
10001000
75..80 'false': bool
1001-
81..106 '{ ... }': i32
1001+
81..106 '{ ... }': ()
10021002
91..94 'foo': Foo
10031003
91..100 'foo.field': i32
10041004
"#]],
@@ -1094,10 +1094,10 @@ fn infer_inherent_method() {
10941094
expect![[r#"
10951095
31..35 'self': A
10961096
37..38 'x': u32
1097-
52..54 '{}': ()
1097+
52..54 '{}': i32
10981098
106..110 'self': &A
10991099
112..113 'x': u64
1100-
127..129 '{}': ()
1100+
127..129 '{}': i64
11011101
147..148 'a': A
11021102
153..201 '{ ...(1); }': ()
11031103
159..160 'a': A
@@ -1129,7 +1129,7 @@ fn infer_inherent_method_str() {
11291129
"#,
11301130
expect![[r#"
11311131
39..43 'self': &str
1132-
52..54 '{}': ()
1132+
52..54 '{}': i32
11331133
68..88 '{ ...o(); }': ()
11341134
74..79 '"foo"': &str
11351135
74..85 '"foo".foo()': i32
@@ -1419,7 +1419,7 @@ fn infer_impl_generics_basic() {
14191419
206..210 'self': A<X, Y>
14201420
206..212 'self.y': Y
14211421
214..215 't': T
1422-
244..341 '{ ...(1); }': ()
1422+
244..341 '{ ...(1); }': i128
14231423
254..255 'a': A<u64, i64>
14241424
258..280 'A { x:...1i64 }': A<u64, i64>
14251425
265..269 '1u64': u64
@@ -1456,7 +1456,7 @@ fn infer_impl_generics_with_autoderef() {
14561456
"#,
14571457
expect![[r#"
14581458
77..81 'self': &Option<T>
1459-
97..99 '{}': ()
1459+
97..99 '{}': Option<&T>
14601460
110..111 'o': Option<u32>
14611461
126..164 '{ ...f(); }': ()
14621462
132..145 '(&o).as_ref()': Option<&u32>
@@ -1852,7 +1852,7 @@ fn closure_return() {
18521852
}
18531853
"#,
18541854
expect![[r#"
1855-
16..58 '{ ...; }; }': ()
1855+
16..58 '{ ...; }; }': u32
18561856
26..27 'x': || -> usize
18571857
30..55 '|| -> ...n 1; }': || -> usize
18581858
42..55 '{ return 1; }': usize
@@ -1871,7 +1871,7 @@ fn closure_return_unit() {
18711871
}
18721872
"#,
18731873
expect![[r#"
1874-
16..47 '{ ...; }; }': ()
1874+
16..47 '{ ...; }; }': u32
18751875
26..27 'x': || -> ()
18761876
30..44 '|| { return; }': || -> ()
18771877
33..44 '{ return; }': ()
@@ -1889,7 +1889,7 @@ fn closure_return_inferred() {
18891889
}
18901890
"#,
18911891
expect![[r#"
1892-
16..46 '{ ..." }; }': ()
1892+
16..46 '{ ..." }; }': u32
18931893
26..27 'x': || -> &str
18941894
30..43 '|| { "test" }': || -> &str
18951895
33..43 '{ "test" }': &str
@@ -2628,11 +2628,11 @@ fn main() {
26282628
expect![[r#"
26292629
104..108 'self': &Box<T>
26302630
188..192 'self': &Box<Foo<T>>
2631-
218..220 '{}': ()
2631+
218..220 '{}': &T
26322632
242..246 'self': &Box<Foo<T>>
2633-
275..277 '{}': ()
2633+
275..277 '{}': &Foo<T>
26342634
297..301 'self': Box<Foo<T>>
2635-
322..324 '{}': ()
2635+
322..324 '{}': Foo<T>
26362636
338..559 '{ ...r(); }': ()
26372637
348..353 'boxed': Box<Foo<i32>>
26382638
356..359 'Box': Box<Foo<i32>>(Foo<i32>) -> Box<Foo<i32>>

0 commit comments

Comments
 (0)