From 3ca3dca63f93e5bf81782605a26052af5c17db22 Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Fri, 29 Mar 2024 10:29:09 +0530 Subject: [PATCH] Remove note about iteration count in coerce and replace it with a simple note suggesting returning a value. The type mismatch error was never due to how many times the loop iterates. It is more because of the peculiar structure of what the for loop desugars to. So the note talking about iteration count didn't make sense --- compiler/rustc_hir_typeck/src/coercion.rs | 172 ++++-------- library/stdarch | 2 +- src/tools/cargo | 2 +- tests/ui/coercion/coerce-loop-issue-122561.rs | 94 +++++++ .../coercion/coerce-loop-issue-122561.stderr | 249 ++++++++++++++++++ tests/ui/did_you_mean/compatible-variants.rs | 3 + .../did_you_mean/compatible-variants.stderr | 38 ++- .../break-while-condition.stderr | 16 +- tests/ui/issues/issue-27042.stderr | 6 + tests/ui/issues/issue-50585.stderr | 5 + tests/ui/typeck/issue-100285.rs | 4 +- tests/ui/typeck/issue-100285.stderr | 38 +-- tests/ui/typeck/issue-98982.rs | 4 +- tests/ui/typeck/issue-98982.stderr | 17 +- 14 files changed, 450 insertions(+), 200 deletions(-) create mode 100644 tests/ui/coercion/coerce-loop-issue-122561.rs create mode 100644 tests/ui/coercion/coerce-loop-issue-122561.stderr diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 44b19318d5d19..d5ef102e1d959 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -37,11 +37,9 @@ use crate::errors::SuggestBoxingForReturnImplTrait; use crate::FnCtxt; -use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan}; +use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::Expr; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult}; @@ -95,22 +93,6 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> { type CoerceResult<'tcx> = InferResult<'tcx, (Vec>, Ty<'tcx>)>; -struct CollectRetsVisitor<'tcx> { - ret_exprs: Vec<&'tcx hir::Expr<'tcx>>, -} - -impl<'tcx> Visitor<'tcx> for CollectRetsVisitor<'tcx> { - fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - match expr.kind { - hir::ExprKind::Ret(_) => self.ret_exprs.push(expr), - // `return` in closures does not return from the outer function - hir::ExprKind::Closure(_) => return, - _ => {} - } - intravisit::walk_expr(self, expr); - } -} - /// Coercing a mutable reference to an immutable works, while /// coercing `&T` to `&mut T` should be forbidden. fn coerce_mutbls<'tcx>( @@ -1593,7 +1575,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { let mut err; let mut unsized_return = false; - let mut visitor = CollectRetsVisitor { ret_exprs: vec![] }; match *cause.code() { ObligationCauseCode::ReturnNoExpression => { err = struct_span_code_err!( @@ -1619,11 +1600,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { if !fcx.tcx.features().unsized_locals { unsized_return = self.is_return_ty_definitely_unsized(fcx); } - if let Some(expression) = expression - && let hir::ExprKind::Loop(loop_blk, ..) = expression.kind - { - intravisit::walk_block(&mut visitor, loop_blk); - } } ObligationCauseCode::ReturnValue(id) => { err = self.report_return_mismatched_types( @@ -1732,15 +1708,8 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { None, Some(coercion_error), ); - if visitor.ret_exprs.len() > 0 { - self.note_unreachable_loop_return( - &mut err, - fcx.tcx, - &expr, - &visitor.ret_exprs, - expected, - ); - } + + self.note_unreachable_loop_return(&mut err, fcx.tcx, &expr, expected); } let reported = err.emit_unless(unsized_return); @@ -1819,102 +1788,61 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> { err: &mut Diag<'_>, tcx: TyCtxt<'tcx>, expr: &hir::Expr<'tcx>, - ret_exprs: &Vec<&'tcx hir::Expr<'tcx>>, ty: Ty<'tcx>, ) { - let hir::ExprKind::Loop(_, _, _, loop_span) = expr.kind else { + let hir::ExprKind::Loop(_, _, _, _) = 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"); - 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", - ); - } - err.span_note( - 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 - )); - } + let hir = tcx.hir(); - let item = hir.get_parent_item(expr.hir_id); - let ret_msg = "return a value for the case when the loop has zero elements to iterate on"; - let ret_ty_msg = - "otherwise consider changing the return type to account for that possibility"; - let node = tcx.hir_node(item.into()); - if let Some(body_id) = node.body_id() - && let Some(sig) = node.fn_sig() - && let hir::ExprKind::Block(block, _) = hir.body(body_id).value.kind - && !ty.is_never() - { - let indentation = if let None = block.expr - && let [.., last] = &block.stmts - { - tcx.sess.source_map().indentation_before(last.span).unwrap_or_else(String::new) - } else if let Some(expr) = block.expr { - tcx.sess.source_map().indentation_before(expr.span).unwrap_or_else(String::new) + let body_def_id = hir.enclosing_body_owner(expr.hir_id); + let body_id = hir.body_owned_by(body_def_id); + let body = hir.body(body_id); + + let span = match body.value.kind { + // Regular block as in a function body + hir::ExprKind::Block(block, _) => { + if let None = block.expr + && let [.., last] = &block.stmts + { + Some(last.span) + } else if let Some(expr) = block.expr { + Some(expr.span) + } else { + None + } + } + // Anon const body (there's no enclosing block in this case) + hir::ExprKind::DropTemps(expr) => Some(expr.span), + _ => None, + }; + + if let Some(span) = span { + let (msg, suggestion) = if ty.is_never() { + ( + "consider adding a diverging expression here", + "`loop {}` or `panic!(\"...\")`".to_string(), + ) } else { - String::new() + ("consider returning a value here", format!("`{ty}` value")) }; - if let None = block.expr - && let [.., last] = &block.stmts - { - err.span_suggestion_verbose( - last.span.shrink_to_hi(), - ret_msg, - format!("\n{indentation}/* `{ty}` value */"), - Applicability::MaybeIncorrect, - ); - } else if let Some(expr) = block.expr { - err.span_suggestion_verbose( - expr.span.shrink_to_hi(), - ret_msg, - format!("\n{indentation}/* `{ty}` value */"), - Applicability::MaybeIncorrect, - ); - } - let mut sugg = match sig.decl.output { - hir::FnRetTy::DefaultReturn(span) => { - vec![(span, " -> Option<()>".to_string())] - } - hir::FnRetTy::Return(ty) => { - vec![ - (ty.span.shrink_to_lo(), "Option<".to_string()), - (ty.span.shrink_to_hi(), ">".to_string()), - ] - } + + let src_map = tcx.sess.source_map(); + let suggestion = if src_map.is_multiline(expr.span) { + let indentation = src_map.indentation_before(span).unwrap_or_else(String::new); + format!("\n{indentation}/* {suggestion} */") + } else { + // If the entire expr is on a single line + // put the suggestion also on the same line + format!(" /* {suggestion} */") }; - for ret_expr in ret_exprs { - match ret_expr.kind { - hir::ExprKind::Ret(Some(expr)) => { - sugg.push((expr.span.shrink_to_lo(), "Some(".to_string())); - sugg.push((expr.span.shrink_to_hi(), ")".to_string())); - } - hir::ExprKind::Ret(None) => { - sugg.push((ret_expr.span.shrink_to_hi(), " Some(())".to_string())); - } - _ => {} - } - } - if let None = block.expr - && let [.., last] = &block.stmts - { - sugg.push((last.span.shrink_to_hi(), format!("\n{indentation}None"))); - } else if let Some(expr) = block.expr { - sugg.push((expr.span.shrink_to_hi(), format!("\n{indentation}None"))); - } - err.multipart_suggestion(ret_ty_msg, sugg, Applicability::MaybeIncorrect); - } else { - err.help(format!("{ret_msg}, {ret_ty_msg}")); + + err.span_suggestion_verbose( + span.shrink_to_hi(), + msg, + suggestion, + Applicability::MaybeIncorrect, + ); } } diff --git a/library/stdarch b/library/stdarch index 967e7afd87cbe..56087ea170d87 160000 --- a/library/stdarch +++ b/library/stdarch @@ -1 +1 @@ -Subproject commit 967e7afd87cbea3232581a4a55031134ab88f595 +Subproject commit 56087ea170d878a7a57b3a5725e0c00f5f5cad70 diff --git a/src/tools/cargo b/src/tools/cargo index 499a61ce7a0fc..d438c80c45c24 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 499a61ce7a0fc6a72040084862a68b2603e770e8 +Subproject commit d438c80c45c24be676ef5867edc79d0a14910efe diff --git a/tests/ui/coercion/coerce-loop-issue-122561.rs b/tests/ui/coercion/coerce-loop-issue-122561.rs new file mode 100644 index 0000000000000..4e9871f02d321 --- /dev/null +++ b/tests/ui/coercion/coerce-loop-issue-122561.rs @@ -0,0 +1,94 @@ +// Regression test for #122561 + +fn for_infinite() -> bool { + for i in 0.. { + //~^ ERROR mismatched types + return false; + } +} + +fn for_finite() -> String { + for i in 0..5 { + //~^ ERROR mismatched types + return String::from("test"); + } +} + +fn for_never_type() -> ! { + for i in 0..0 { + //~^ ERROR mismatched types + } +} + +// Entire function on a single line. +// Tests that we format the suggestion +// correctly in this case +fn for_single_line() -> bool { for i in 0.. { return false; } } +//~^ ERROR mismatched types + +// Loop in an anon const in function args +// Tests that we: +// a. deal properly with this complex case +// b. format the suggestion correctly so +// that it's readable +fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool { +//~^ ERROR `for` is not allowed in a `const` +//~| ERROR mismatched types + true +} + +fn while_true() -> bool { + while true { + //~^ ERROR mismatched types + //~| WARN denote infinite loops with `loop { ... }` [while_true] + return true; + } +} + +fn while_false() -> bool { + while false { + //~^ ERROR mismatched types + return true; + } +} + +fn while_true_never_type() -> ! { + while true { + //~^ ERROR mismatched types + //~| WARN denote infinite loops with `loop { ... }` [while_true] + } +} + +// No type mismatch error in this case +fn loop_() -> bool { + loop { + return true; + } +} + +const C: i32 = { + for i in 0.. { + //~^ ERROR `for` is not allowed in a `const` + //~| ERROR mismatched types + } +}; + +fn main() { + let _ = [10; { + for i in 0..5 { + //~^ ERROR `for` is not allowed in a `const` + //~| ERROR mismatched types + } + }]; + + let _ = [10; { + while false { + //~^ ERROR mismatched types + } + }]; + + + let _ = |a: &[(); for x in 0..2 {}]| {}; + //~^ ERROR `for` is not allowed in a `const` + //~| ERROR mismatched types +} diff --git a/tests/ui/coercion/coerce-loop-issue-122561.stderr b/tests/ui/coercion/coerce-loop-issue-122561.stderr new file mode 100644 index 0000000000000..d297141a48f92 --- /dev/null +++ b/tests/ui/coercion/coerce-loop-issue-122561.stderr @@ -0,0 +1,249 @@ +warning: denote infinite loops with `loop { ... }` + --> $DIR/coerce-loop-issue-122561.rs:41:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + | + = note: `#[warn(while_true)]` on by default + +warning: denote infinite loops with `loop { ... }` + --> $DIR/coerce-loop-issue-122561.rs:56:5 + | +LL | while true { + | ^^^^^^^^^^ help: use `loop` + +error[E0658]: `for` is not allowed in a `const` + --> $DIR/coerce-loop-issue-122561.rs:34:24 + | +LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool { + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #87575 for more information + = help: add `#![feature(const_for)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `for` is not allowed in a `const` + --> $DIR/coerce-loop-issue-122561.rs:70:5 + | +LL | / for i in 0.. { +LL | | +LL | | +LL | | } + | |_____^ + | + = note: see issue #87575 for more information + = help: add `#![feature(const_for)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `for` is not allowed in a `const` + --> $DIR/coerce-loop-issue-122561.rs:78:9 + | +LL | / for i in 0..5 { +LL | | +LL | | +LL | | } + | |_________^ + | + = note: see issue #87575 for more information + = help: add `#![feature(const_for)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: `for` is not allowed in a `const` + --> $DIR/coerce-loop-issue-122561.rs:91:23 + | +LL | let _ = |a: &[(); for x in 0..2 {}]| {}; + | ^^^^^^^^^^^^^^^^ + | + = note: see issue #87575 for more information + = help: add `#![feature(const_for)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0308]: mismatched types + --> $DIR/coerce-loop-issue-122561.rs:34:24 + | +LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool { + | ^^^^^^^^^^^^^^^^ expected `usize`, found `()` + | +help: consider returning a value here + | +LL | fn for_in_arg(a: &[(); for x in 0..2 {} /* `usize` value */]) -> bool { + | +++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/coerce-loop-issue-122561.rs:70:5 + | +LL | / for i in 0.. { +LL | | +LL | | +LL | | } + | |_____^ expected `i32`, found `()` + | +help: consider returning a value here + | +LL ~ } +LL + /* `i32` value */ + | + +error[E0308]: mismatched types + --> $DIR/coerce-loop-issue-122561.rs:4:5 + | +LL | fn for_infinite() -> bool { + | ---- expected `bool` because of return type +LL | / for i in 0.. { +LL | | +LL | | return false; +LL | | } + | |_____^ expected `bool`, found `()` + | +help: consider returning a value here + | +LL ~ } +LL + /* `bool` value */ + | + +error[E0308]: mismatched types + --> $DIR/coerce-loop-issue-122561.rs:11:5 + | +LL | fn for_finite() -> String { + | ------ expected `String` because of return type +LL | / for i in 0..5 { +LL | | +LL | | return String::from("test"); +LL | | } + | |_____^ expected `String`, found `()` + | +help: consider returning a value here + | +LL ~ } +LL + /* `String` value */ + | + +error[E0308]: mismatched types + --> $DIR/coerce-loop-issue-122561.rs:18:5 + | +LL | fn for_never_type() -> ! { + | - expected `!` because of return type +LL | / for i in 0..0 { +LL | | +LL | | } + | |_____^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` +help: consider adding a diverging expression here + | +LL ~ } +LL + /* `loop {}` or `panic!("...")` */ + | + +error[E0308]: mismatched types + --> $DIR/coerce-loop-issue-122561.rs:26:32 + | +LL | fn for_single_line() -> bool { for i in 0.. { return false; } } + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()` + | | + | expected `bool` because of return type + | +help: consider returning a value here + | +LL | fn for_single_line() -> bool { for i in 0.. { return false; } /* `bool` value */ } + | ++++++++++++++++++ + +error[E0308]: mismatched types + --> $DIR/coerce-loop-issue-122561.rs:41:5 + | +LL | fn while_true() -> bool { + | ---- expected `bool` because of return type +LL | / while true { +LL | | +LL | | +LL | | return true; +LL | | } + | |_____^ expected `bool`, found `()` + | +help: consider returning a value here + | +LL ~ } +LL + /* `bool` value */ + | + +error[E0308]: mismatched types + --> $DIR/coerce-loop-issue-122561.rs:49:5 + | +LL | fn while_false() -> bool { + | ---- expected `bool` because of return type +LL | / while false { +LL | | +LL | | return true; +LL | | } + | |_____^ expected `bool`, found `()` + | +help: consider returning a value here + | +LL ~ } +LL + /* `bool` value */ + | + +error[E0308]: mismatched types + --> $DIR/coerce-loop-issue-122561.rs:56:5 + | +LL | fn while_true_never_type() -> ! { + | - expected `!` because of return type +LL | / while true { +LL | | +LL | | +LL | | } + | |_____^ expected `!`, found `()` + | + = note: expected type `!` + found unit type `()` +help: consider adding a diverging expression here + | +LL ~ } +LL + /* `loop {}` or `panic!("...")` */ + | + +error[E0308]: mismatched types + --> $DIR/coerce-loop-issue-122561.rs:78:9 + | +LL | / for i in 0..5 { +LL | | +LL | | +LL | | } + | |_________^ expected `usize`, found `()` + | +help: consider returning a value here + | +LL ~ } +LL + /* `usize` value */ + | + +error[E0308]: mismatched types + --> $DIR/coerce-loop-issue-122561.rs:85:9 + | +LL | / while false { +LL | | +LL | | } + | |_________^ expected `usize`, found `()` + | +help: consider returning a value here + | +LL ~ } +LL + /* `usize` value */ + | + +error[E0308]: mismatched types + --> $DIR/coerce-loop-issue-122561.rs:91:23 + | +LL | let _ = |a: &[(); for x in 0..2 {}]| {}; + | ^^^^^^^^^^^^^^^^ expected `usize`, found `()` + | +help: consider returning a value here + | +LL | let _ = |a: &[(); for x in 0..2 {} /* `usize` value */]| {}; + | +++++++++++++++++++ + +error: aborting due to 16 previous errors; 2 warnings emitted + +Some errors have detailed explanations: E0308, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/did_you_mean/compatible-variants.rs b/tests/ui/did_you_mean/compatible-variants.rs index b1c7dc2a7f672..f62784d7b9161 100644 --- a/tests/ui/did_you_mean/compatible-variants.rs +++ b/tests/ui/did_you_mean/compatible-variants.rs @@ -15,6 +15,7 @@ fn a() -> Option<()> { f(); } //~^ HELP try adding an expression + //~| HELP consider returning a value here } fn b() -> Result<(), ()> { @@ -29,6 +30,7 @@ fn c() -> Option<()> { f(); } //~^ HELP try adding an expression + //~| HELP consider returning a value here } fn d() -> Option<()> { @@ -63,6 +65,7 @@ fn main() { let _ = Foo { bar }; //~^ ERROR mismatched types //~| HELP try wrapping + //~| HELP consider returning a value here } enum A { diff --git a/tests/ui/did_you_mean/compatible-variants.stderr b/tests/ui/did_you_mean/compatible-variants.stderr index f2bbd8ced8f24..5b2250e2d7667 100644 --- a/tests/ui/did_you_mean/compatible-variants.stderr +++ b/tests/ui/did_you_mean/compatible-variants.stderr @@ -19,9 +19,14 @@ LL + None LL ~ } LL + Some(()) | +help: consider returning a value here + | +LL ~ } +LL + /* `Option<()>` value */ + | error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:21:5 + --> $DIR/compatible-variants.rs:22:5 | LL | fn b() -> Result<(), ()> { | -------------- expected `Result<(), ()>` because of return type @@ -37,7 +42,7 @@ LL + Ok(()) | error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:27:5 + --> $DIR/compatible-variants.rs:28:5 | LL | fn c() -> Option<()> { | ---------- expected `Option<()>` because of return type @@ -57,9 +62,14 @@ LL + None LL ~ } LL + Some(()) | +help: consider returning a value here + | +LL ~ } +LL + /* `Option<()>` value */ + | error[E0308]: `?` operator has incompatible types - --> $DIR/compatible-variants.rs:35:5 + --> $DIR/compatible-variants.rs:37:5 | LL | fn d() -> Option<()> { | ---------- expected `Option<()>` because of return type @@ -84,7 +94,7 @@ LL + Some(()) | error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:42:25 + --> $DIR/compatible-variants.rs:44:25 | LL | let _: Option<()> = while false {}; | ---------- ^^^^^^^^^^^^^^ expected `Option<()>`, found `()` @@ -99,7 +109,7 @@ LL | let _: Option<()> = Some(while false {}); | +++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:46:9 + --> $DIR/compatible-variants.rs:48:9 | LL | while false {} | ^^^^^^^^^^^^^^ expected `Option<()>`, found `()` @@ -114,9 +124,13 @@ LL + None LL ~ while false {} LL + Some(()) | +help: consider returning a value here + | +LL | let _ = Foo { bar }; /* `Option<()>` value */ + | ++++++++++++++++++++++++ error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:50:31 + --> $DIR/compatible-variants.rs:52:31 | LL | let _: Result = 1; | ---------------- ^ expected `Result`, found integer @@ -133,7 +147,7 @@ LL | let _: Result = Err(1); | ++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:53:26 + --> $DIR/compatible-variants.rs:55:26 | LL | let _: Option = 1; | ----------- ^ expected `Option`, found integer @@ -148,7 +162,7 @@ LL | let _: Option = Some(1); | +++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:56:28 + --> $DIR/compatible-variants.rs:58:28 | LL | let _: Hey = 1; | ------------- ^ expected `Hey`, found integer @@ -165,7 +179,7 @@ LL | let _: Hey = Hey::B(1); | +++++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:59:29 + --> $DIR/compatible-variants.rs:61:29 | LL | let _: Hey = false; | -------------- ^^^^^ expected `Hey`, found `bool` @@ -180,7 +194,7 @@ LL | let _: Hey = Hey::B(false); | +++++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:63:19 + --> $DIR/compatible-variants.rs:65:19 | LL | let _ = Foo { bar }; | ^^^ expected `Option`, found `i32` @@ -193,7 +207,7 @@ LL | let _ = Foo { bar: Some(bar) }; | ++++++++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:80:16 + --> $DIR/compatible-variants.rs:83:16 | LL | let a: A = B::Fst; | - ^^^^^^ expected `A`, found `B` @@ -206,7 +220,7 @@ LL | let a: A = A::B { b: B::Fst }; | +++++++++ + error[E0308]: mismatched types - --> $DIR/compatible-variants.rs:86:17 + --> $DIR/compatible-variants.rs:89:17 | LL | let a: A2 = B::Fst; | -- ^^^^^^ expected `A2`, found `B` diff --git a/tests/ui/for-loop-while/break-while-condition.stderr b/tests/ui/for-loop-while/break-while-condition.stderr index 48b29f44fa106..96d672cf9a092 100644 --- a/tests/ui/for-loop-while/break-while-condition.stderr +++ b/tests/ui/for-loop-while/break-while-condition.stderr @@ -20,6 +20,11 @@ LL | | } | = note: expected type `!` found unit type `()` +help: consider adding a diverging expression here + | +LL ~ } +LL + /* `loop {}` or `panic!("...")` */ + | error[E0308]: mismatched types --> $DIR/break-while-condition.rs:24:13 @@ -31,14 +36,11 @@ LL | | } | = note: expected type `!` found unit type `()` -note: the function expects a value to always be returned, but loops might run zero times - --> $DIR/break-while-condition.rs:24:13 +help: consider adding a diverging expression here + | +LL ~ } +LL + /* `loop {}` or `panic!("...")` */ | -LL | while false { - | ^^^^^^^^^^^ this might have zero elements to iterate on -LL | return - | ------ if the loop doesn't execute, this value would never get returned - = help: return a value for the case when the loop has zero elements to iterate on, otherwise consider changing the return type to account for that possibility error: aborting due to 3 previous errors diff --git a/tests/ui/issues/issue-27042.stderr b/tests/ui/issues/issue-27042.stderr index 01532de999e3b..279c1aa5997ba 100644 --- a/tests/ui/issues/issue-27042.stderr +++ b/tests/ui/issues/issue-27042.stderr @@ -40,6 +40,12 @@ error[E0308]: mismatched types LL | / 'c: LL | | for _ in None { break }; // but here we cite the whole loop | |_______________________________^ expected `i32`, found `()` + | +help: consider returning a value here + | +LL ~ while let Some(_) = None { break }; +LL + /* `i32` value */ + | error[E0308]: mismatched types --> $DIR/issue-27042.rs:15:9 diff --git a/tests/ui/issues/issue-50585.stderr b/tests/ui/issues/issue-50585.stderr index 13181f1cf7fe4..5e1030f0db914 100644 --- a/tests/ui/issues/issue-50585.stderr +++ b/tests/ui/issues/issue-50585.stderr @@ -13,6 +13,11 @@ error[E0308]: mismatched types | LL | |y: Vec<[(); for x in 0..2 {}]>| {}; | ^^^^^^^^^^^^^^^^ expected `usize`, found `()` + | +help: consider returning a value here + | +LL | |y: Vec<[(); for x in 0..2 {} /* `usize` value */]>| {}; + | +++++++++++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/typeck/issue-100285.rs b/tests/ui/typeck/issue-100285.rs index 460e0457105f5..bea4b2bc2bbe7 100644 --- a/tests/ui/typeck/issue-100285.rs +++ b/tests/ui/typeck/issue-100285.rs @@ -1,4 +1,4 @@ -fn foo(n: i32) -> i32 { //~ HELP otherwise consider changing the return type to account for that possibility +fn foo(n: i32) -> i32 { for i in 0..0 { //~ ERROR mismatched types [E0308] if n < 0 { return i; @@ -14,7 +14,7 @@ fn foo(n: i32) -> i32 { //~ HELP otherwise consider changing the return type to return 5; } - } //~ HELP return a value for the case when the loop has zero elements to iterate on + } //~ HELP consider returning a value here } fn main() {} diff --git a/tests/ui/typeck/issue-100285.stderr b/tests/ui/typeck/issue-100285.stderr index 9c8685a77127b..6e85a3bcc94a0 100644 --- a/tests/ui/typeck/issue-100285.stderr +++ b/tests/ui/typeck/issue-100285.stderr @@ -12,47 +12,11 @@ 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 | if n < 0 { -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 +help: consider returning a value here | LL ~ } LL ~ /* `i32` value */ | -help: otherwise consider changing the return type to account for that possibility - | -LL ~ fn foo(n: i32) -> Option { -LL | for i in 0..0 { -LL | if n < 0 { -LL ~ return Some(i); -LL | } else if n < 10 { -LL ~ return Some(1); -LL | } else if n < 20 { -LL ~ return Some(2); -LL | } else if n < 30 { -LL ~ return Some(3); -LL | } else if n < 40 { -LL ~ return Some(4); -LL | } else { -LL ~ return Some(5); -LL | } -LL | -LL ~ } -LL ~ None - | error: aborting due to 1 previous error diff --git a/tests/ui/typeck/issue-98982.rs b/tests/ui/typeck/issue-98982.rs index f875d20fa4c53..3eff9fbe360b7 100644 --- a/tests/ui/typeck/issue-98982.rs +++ b/tests/ui/typeck/issue-98982.rs @@ -1,7 +1,7 @@ -fn foo() -> i32 { //~ HELP otherwise consider changing the return type to account for that possibility +fn foo() -> i32 { for i in 0..0 { //~ ERROR mismatched types [E0308] return i; - } //~ HELP return a value for the case when the loop has zero elements to iterate on + } //~ HELP consider returning a value here } fn main() {} diff --git a/tests/ui/typeck/issue-98982.stderr b/tests/ui/typeck/issue-98982.stderr index d8d5a86b157f2..7759f359a0c96 100644 --- a/tests/ui/typeck/issue-98982.stderr +++ b/tests/ui/typeck/issue-98982.stderr @@ -8,26 +8,11 @@ LL | | return i; LL | | } | |_____^ expected `i32`, found `()` | -note: the function expects a value to always be returned, but loops might run zero times - --> $DIR/issue-98982.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 -help: return a value for the case when the loop has zero elements to iterate on +help: consider returning a value here | LL ~ } LL ~ /* `i32` value */ | -help: otherwise consider changing the return type to account for that possibility - | -LL ~ fn foo() -> Option { -LL | for i in 0..0 { -LL ~ return Some(i); -LL ~ } -LL ~ None - | error: aborting due to 1 previous error