Skip to content

Commit

Permalink
when there are 3 or more return statements in the loop
Browse files Browse the repository at this point in the history
emit the first 3 errors and duplicated diagnostic information
using take of iterator for the first third return
	modified:   compiler/rustc_typeck/src/check/coercion.rs
	new file:   src/test/ui/typeck/issue-100285.rs
	new file:   src/test/ui/typeck/issue-100285.stderr
  • Loading branch information
Yiming Lei committed Aug 15, 2022
1 parent 6d3f1be commit 0471e27
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 1 deletion.
10 changes: 9 additions & 1 deletion compiler/rustc_typeck/src/check/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1590,7 +1590,9 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
let hir::ExprKind::Loop(_, _, _, loop_span) = expr.kind else { return;};
let mut span: MultiSpan = vec![loop_span].into();
span.push_span_label(loop_span, "this might have zero elements to iterate on");
for ret_expr in ret_exprs {
const MAXITER: usize = 3;
let iter = ret_exprs.iter().take(MAXITER);
for ret_expr in iter {
span.push_span_label(
ret_expr.span,
"if the loop doesn't execute, this value would never get returned",
Expand All @@ -1600,6 +1602,12 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
span,
"the function expects a value to always be returned, but loops might run zero times",
);
if MAXITER < ret_exprs.len() {
err.note(&format!(
"if the loop doesn't execute, {} other values would never get returned",
ret_exprs.len() - MAXITER
));
}
err.help(
"return a value for the case when the loop has zero elements to iterate on, or \
consider changing the return type to account for that possibility",
Expand Down
22 changes: 22 additions & 0 deletions src/test/ui/typeck/issue-100285.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
fn foo(n: i32) -> i32 {
for i in 0..0 {
//~^ ERROR: mismatched types [E0308]
if n < 0 {
return i;
} else if n < 10 {
return 1;
} else if n < 20 {
return 2;
} else if n < 30 {
return 3;
} else if n < 40 {
return 4;
} else {
return 5;
}

}
//~| help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility
}

fn main() {}
34 changes: 34 additions & 0 deletions src/test/ui/typeck/issue-100285.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
error[E0308]: mismatched types
--> $DIR/issue-100285.rs:2:5
|
LL | fn foo(n: i32) -> i32 {
| --- expected `i32` because of return type
LL | / for i in 0..0 {
LL | |
LL | | if n < 0 {
LL | | return i;
... |
LL | |
LL | | }
| |_____^ expected `i32`, found `()`
|
note: the function expects a value to always be returned, but loops might run zero times
--> $DIR/issue-100285.rs:2:5
|
LL | for i in 0..0 {
| ^^^^^^^^^^^^^ this might have zero elements to iterate on
...
LL | return i;
| -------- if the loop doesn't execute, this value would never get returned
LL | } else if n < 10 {
LL | return 1;
| -------- if the loop doesn't execute, this value would never get returned
LL | } else if n < 20 {
LL | return 2;
| -------- if the loop doesn't execute, this value would never get returned
= note: if the loop doesn't execute, 3 other values would never get returned
= help: return a value for the case when the loop has zero elements to iterate on, or consider changing the return type to account for that possibility

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.

0 comments on commit 0471e27

Please sign in to comment.