Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit fa73e37

Browse files
committedApr 9, 2024
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
1 parent 2805aed commit fa73e37

File tree

13 files changed

+545
-205
lines changed

13 files changed

+545
-205
lines changed
 

‎compiler/rustc_hir_typeck/src/coercion.rs‎

Lines changed: 17 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -37,11 +37,9 @@
3737
3838
use crate::errors::SuggestBoxingForReturnImplTrait;
3939
use crate::FnCtxt;
40-
use rustc_errors::{codes::*, struct_span_code_err, Applicability, Diag, MultiSpan};
40+
use rustc_errors::{codes::*, struct_span_code_err, Diag};
4141
use rustc_hir as hir;
4242
use rustc_hir::def_id::{DefId, LocalDefId};
43-
use rustc_hir::intravisit::{self, Visitor};
44-
use rustc_hir::Expr;
4543
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
4644
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
4745
use rustc_infer::infer::{Coercion, DefineOpaqueTypes, InferOk, InferResult};
@@ -95,22 +93,6 @@ impl<'a, 'tcx> Deref for Coerce<'a, 'tcx> {
9593

9694
type CoerceResult<'tcx> = InferResult<'tcx, (Vec<Adjustment<'tcx>>, Ty<'tcx>)>;
9795

98-
struct CollectRetsVisitor<'tcx> {
99-
ret_exprs: Vec<&'tcx hir::Expr<'tcx>>,
100-
}
101-
102-
impl<'tcx> Visitor<'tcx> for CollectRetsVisitor<'tcx> {
103-
fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
104-
match expr.kind {
105-
hir::ExprKind::Ret(_) => self.ret_exprs.push(expr),
106-
// `return` in closures does not return from the outer function
107-
hir::ExprKind::Closure(_) => return,
108-
_ => {}
109-
}
110-
intravisit::walk_expr(self, expr);
111-
}
112-
}
113-
11496
/// Coercing a mutable reference to an immutable works, while
11597
/// coercing `&T` to `&mut T` should be forbidden.
11698
fn coerce_mutbls<'tcx>(
@@ -1607,7 +1589,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
16071589

16081590
let mut err;
16091591
let mut unsized_return = false;
1610-
let mut visitor = CollectRetsVisitor { ret_exprs: vec![] };
16111592
match *cause.code() {
16121593
ObligationCauseCode::ReturnNoExpression => {
16131594
err = struct_span_code_err!(
@@ -1633,11 +1614,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
16331614
if !fcx.tcx.features().unsized_locals {
16341615
unsized_return = self.is_return_ty_definitely_unsized(fcx);
16351616
}
1636-
if let Some(expression) = expression
1637-
&& let hir::ExprKind::Loop(loop_blk, ..) = expression.kind
1638-
{
1639-
intravisit::walk_block(&mut visitor, loop_blk);
1640-
}
16411617
}
16421618
ObligationCauseCode::ReturnValue(id) => {
16431619
err = self.report_return_mismatched_types(
@@ -1738,6 +1714,22 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17381714
augment_error(&mut err);
17391715

17401716
if let Some(expr) = expression {
1717+
if let hir::ExprKind::Loop(
1718+
_,
1719+
_,
1720+
loop_src @ (hir::LoopSource::While | hir::LoopSource::ForLoop),
1721+
_,
1722+
) = expr.kind
1723+
{
1724+
let loop_type = if loop_src == hir::LoopSource::While {
1725+
"`while` loops"
1726+
} else {
1727+
"`for` loops"
1728+
};
1729+
1730+
err.note(format!("{loop_type} evaluate to unit type `()`"));
1731+
}
1732+
17411733
fcx.emit_coerce_suggestions(
17421734
&mut err,
17431735
expr,
@@ -1746,15 +1738,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
17461738
None,
17471739
Some(coercion_error),
17481740
);
1749-
if visitor.ret_exprs.len() > 0 {
1750-
self.note_unreachable_loop_return(
1751-
&mut err,
1752-
fcx.tcx,
1753-
&expr,
1754-
&visitor.ret_exprs,
1755-
expected,
1756-
);
1757-
}
17581741
}
17591742

17601743
let reported = err.emit_unless(unsized_return);
@@ -1828,110 +1811,6 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
18281811
);
18291812
}
18301813

1831-
fn note_unreachable_loop_return(
1832-
&self,
1833-
err: &mut Diag<'_>,
1834-
tcx: TyCtxt<'tcx>,
1835-
expr: &hir::Expr<'tcx>,
1836-
ret_exprs: &Vec<&'tcx hir::Expr<'tcx>>,
1837-
ty: Ty<'tcx>,
1838-
) {
1839-
let hir::ExprKind::Loop(_, _, _, loop_span) = expr.kind else {
1840-
return;
1841-
};
1842-
let mut span: MultiSpan = vec![loop_span].into();
1843-
span.push_span_label(loop_span, "this might have zero elements to iterate on");
1844-
const MAXITER: usize = 3;
1845-
let iter = ret_exprs.iter().take(MAXITER);
1846-
for ret_expr in iter {
1847-
span.push_span_label(
1848-
ret_expr.span,
1849-
"if the loop doesn't execute, this value would never get returned",
1850-
);
1851-
}
1852-
err.span_note(
1853-
span,
1854-
"the function expects a value to always be returned, but loops might run zero times",
1855-
);
1856-
if MAXITER < ret_exprs.len() {
1857-
err.note(format!(
1858-
"if the loop doesn't execute, {} other values would never get returned",
1859-
ret_exprs.len() - MAXITER
1860-
));
1861-
}
1862-
let hir = tcx.hir();
1863-
let item = hir.get_parent_item(expr.hir_id);
1864-
let ret_msg = "return a value for the case when the loop has zero elements to iterate on";
1865-
let ret_ty_msg =
1866-
"otherwise consider changing the return type to account for that possibility";
1867-
let node = tcx.hir_node(item.into());
1868-
if let Some(body_id) = node.body_id()
1869-
&& let Some(sig) = node.fn_sig()
1870-
&& let hir::ExprKind::Block(block, _) = hir.body(body_id).value.kind
1871-
&& !ty.is_never()
1872-
{
1873-
let indentation = if let None = block.expr
1874-
&& let [.., last] = &block.stmts
1875-
{
1876-
tcx.sess.source_map().indentation_before(last.span).unwrap_or_else(String::new)
1877-
} else if let Some(expr) = block.expr {
1878-
tcx.sess.source_map().indentation_before(expr.span).unwrap_or_else(String::new)
1879-
} else {
1880-
String::new()
1881-
};
1882-
if let None = block.expr
1883-
&& let [.., last] = &block.stmts
1884-
{
1885-
err.span_suggestion_verbose(
1886-
last.span.shrink_to_hi(),
1887-
ret_msg,
1888-
format!("\n{indentation}/* `{ty}` value */"),
1889-
Applicability::MaybeIncorrect,
1890-
);
1891-
} else if let Some(expr) = block.expr {
1892-
err.span_suggestion_verbose(
1893-
expr.span.shrink_to_hi(),
1894-
ret_msg,
1895-
format!("\n{indentation}/* `{ty}` value */"),
1896-
Applicability::MaybeIncorrect,
1897-
);
1898-
}
1899-
let mut sugg = match sig.decl.output {
1900-
hir::FnRetTy::DefaultReturn(span) => {
1901-
vec![(span, " -> Option<()>".to_string())]
1902-
}
1903-
hir::FnRetTy::Return(ty) => {
1904-
vec![
1905-
(ty.span.shrink_to_lo(), "Option<".to_string()),
1906-
(ty.span.shrink_to_hi(), ">".to_string()),
1907-
]
1908-
}
1909-
};
1910-
for ret_expr in ret_exprs {
1911-
match ret_expr.kind {
1912-
hir::ExprKind::Ret(Some(expr)) => {
1913-
sugg.push((expr.span.shrink_to_lo(), "Some(".to_string()));
1914-
sugg.push((expr.span.shrink_to_hi(), ")".to_string()));
1915-
}
1916-
hir::ExprKind::Ret(None) => {
1917-
sugg.push((ret_expr.span.shrink_to_hi(), " Some(())".to_string()));
1918-
}
1919-
_ => {}
1920-
}
1921-
}
1922-
if let None = block.expr
1923-
&& let [.., last] = &block.stmts
1924-
{
1925-
sugg.push((last.span.shrink_to_hi(), format!("\n{indentation}None")));
1926-
} else if let Some(expr) = block.expr {
1927-
sugg.push((expr.span.shrink_to_hi(), format!("\n{indentation}None")));
1928-
}
1929-
err.multipart_suggestion(ret_ty_msg, sugg, Applicability::MaybeIncorrect);
1930-
} else {
1931-
err.help(format!("{ret_msg}, {ret_ty_msg}"));
1932-
}
1933-
}
1934-
19351814
fn report_return_mismatched_types<'a>(
19361815
&self,
19371816
cause: &ObligationCause<'tcx>,

‎compiler/rustc_hir_typeck/src/demand.rs‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
5757
|| self.suggest_into(err, expr, expr_ty, expected)
5858
|| self.suggest_floating_point_literal(err, expr, expected)
5959
|| self.suggest_null_ptr_for_literal_zero_given_to_ptr_arg(err, expr, expected)
60-
|| self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty);
60+
|| self.suggest_coercing_result_via_try_operator(err, expr, expected, expr_ty)
61+
|| self.suggest_returning_value_after_loop(err, expr, expected);
6162

6263
if !suggested {
6364
self.note_source_of_type_mismatch_constraint(

‎compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs‎

Lines changed: 87 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ use rustc_hir::def::Res;
1717
use rustc_hir::def::{CtorKind, CtorOf, DefKind};
1818
use rustc_hir::lang_items::LangItem;
1919
use rustc_hir::{
20-
CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId, Node,
21-
Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
20+
Arm, CoroutineDesugaring, CoroutineKind, CoroutineSource, Expr, ExprKind, GenericBound, HirId,
21+
Node, Path, QPath, Stmt, StmtKind, TyKind, WherePredicate,
2222
};
2323
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer;
2424
use rustc_infer::traits::{self};
@@ -1955,6 +1955,91 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
19551955
false
19561956
}
19571957

1958+
// If the expr is a while or for loop and is the tail expr of its
1959+
// enclosing body suggest returning a value right after it
1960+
pub fn suggest_returning_value_after_loop(
1961+
&self,
1962+
err: &mut Diag<'_>,
1963+
expr: &hir::Expr<'tcx>,
1964+
expected: Ty<'tcx>,
1965+
) -> bool {
1966+
let hir = self.tcx.hir();
1967+
let enclosing_scope =
1968+
hir.get_enclosing_scope(expr.hir_id).map(|hir_id| self.tcx.hir_node(hir_id));
1969+
1970+
// Get tail expr of the enclosing block or body
1971+
let tail_expr = if let Some(Node::Block(hir::Block { expr, .. })) = enclosing_scope
1972+
&& expr.is_some()
1973+
{
1974+
*expr
1975+
} else {
1976+
let body_def_id = hir.enclosing_body_owner(expr.hir_id);
1977+
let body_id = hir.body_owned_by(body_def_id);
1978+
let body = hir.body(body_id);
1979+
1980+
// Get tail expr of the body
1981+
match body.value.kind {
1982+
// Regular function body etc.
1983+
hir::ExprKind::Block(block, _) => block.expr,
1984+
// Anon const body (there's no block in this case)
1985+
hir::ExprKind::DropTemps(expr) => Some(expr),
1986+
_ => None,
1987+
}
1988+
};
1989+
1990+
let Some(tail_expr) = tail_expr else {
1991+
return false; // Body doesn't have a tail expr we can compare with
1992+
};
1993+
1994+
// Get the loop expr within the tail expr
1995+
let loop_expr_in_tail = match expr.kind {
1996+
hir::ExprKind::Loop(_, _, hir::LoopSource::While, _) => tail_expr,
1997+
hir::ExprKind::Loop(_, _, hir::LoopSource::ForLoop, _) => {
1998+
match tail_expr.peel_drop_temps() {
1999+
Expr { kind: ExprKind::Match(_, [Arm { body, .. }], _), .. } => body,
2000+
_ => return false, // Not really a for loop
2001+
}
2002+
}
2003+
_ => return false, // Not a while or a for loop
2004+
};
2005+
2006+
// If the expr is the loop expr in the tail
2007+
// then make the suggestion
2008+
if expr.hir_id == loop_expr_in_tail.hir_id {
2009+
let span = expr.span;
2010+
2011+
let (msg, suggestion) = if expected.is_never() {
2012+
(
2013+
"consider adding a diverging expression here",
2014+
"`loop {}` or `panic!(\"...\")`".to_string(),
2015+
)
2016+
} else {
2017+
("consider returning a value here", format!("`{expected}` value"))
2018+
};
2019+
2020+
let src_map = self.tcx.sess.source_map();
2021+
let suggestion = if src_map.is_multiline(expr.span) {
2022+
let indentation = src_map.indentation_before(span).unwrap_or_else(String::new);
2023+
format!("\n{indentation}/* {suggestion} */")
2024+
} else {
2025+
// If the entire expr is on a single line
2026+
// put the suggestion also on the same line
2027+
format!(" /* {suggestion} */")
2028+
};
2029+
2030+
err.span_suggestion_verbose(
2031+
span.shrink_to_hi(),
2032+
msg,
2033+
suggestion,
2034+
Applicability::MaybeIncorrect,
2035+
);
2036+
2037+
true
2038+
} else {
2039+
false
2040+
}
2041+
}
2042+
19582043
/// If the expected type is an enum (Issue #55250) with any variants whose
19592044
/// sole field is of the found type, suggest such variants. (Issue #42764)
19602045
pub(crate) fn suggest_compatible_variants(
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Regression test for #122561
2+
3+
fn for_infinite() -> bool {
4+
for i in 0.. {
5+
//~^ ERROR mismatched types
6+
return false;
7+
}
8+
}
9+
10+
fn for_finite() -> String {
11+
for i in 0..5 {
12+
//~^ ERROR mismatched types
13+
return String::from("test");
14+
}
15+
}
16+
17+
fn for_zero_times() -> bool {
18+
for i in 0..0 {
19+
//~^ ERROR mismatched types
20+
return true;
21+
}
22+
}
23+
24+
fn for_never_type() -> ! {
25+
for i in 0..5 {
26+
//~^ ERROR mismatched types
27+
}
28+
}
29+
30+
// Entire function on a single line.
31+
// Tests that we format the suggestion
32+
// correctly in this case
33+
fn for_single_line() -> bool { for i in 0.. { return false; } }
34+
//~^ ERROR mismatched types
35+
36+
// Loop in an anon const in function args
37+
// Tests that we:
38+
// a. deal properly with this complex case
39+
// b. format the suggestion correctly so
40+
// that it's readable
41+
fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool {
42+
//~^ ERROR `for` is not allowed in a `const`
43+
//~| ERROR mismatched types
44+
true
45+
}
46+
47+
fn while_inifinite() -> bool {
48+
while true {
49+
//~^ ERROR mismatched types
50+
//~| WARN denote infinite loops with `loop { ... }` [while_true]
51+
return true;
52+
}
53+
}
54+
55+
fn while_finite() -> bool {
56+
let mut i = 0;
57+
while i < 3 {
58+
//~^ ERROR mismatched types
59+
i += 1;
60+
return true;
61+
}
62+
}
63+
64+
fn while_zero_times() -> bool {
65+
while false {
66+
//~^ ERROR mismatched types
67+
return true;
68+
}
69+
}
70+
71+
fn while_never_type() -> ! {
72+
while true {
73+
//~^ ERROR mismatched types
74+
//~| WARN denote infinite loops with `loop { ... }` [while_true]
75+
}
76+
}
77+
78+
// No type mismatch error in this case
79+
fn loop_() -> bool {
80+
loop {
81+
return true;
82+
}
83+
}
84+
85+
const C: i32 = {
86+
for i in 0.. {
87+
//~^ ERROR `for` is not allowed in a `const`
88+
//~| ERROR mismatched types
89+
}
90+
};
91+
92+
fn main() {
93+
let _ = [10; {
94+
for i in 0..5 {
95+
//~^ ERROR `for` is not allowed in a `const`
96+
//~| ERROR mismatched types
97+
}
98+
}];
99+
100+
let _ = [10; {
101+
while false {
102+
//~^ ERROR mismatched types
103+
}
104+
}];
105+
106+
107+
let _ = |a: &[(); for x in 0..2 {}]| {};
108+
//~^ ERROR `for` is not allowed in a `const`
109+
//~| ERROR mismatched types
110+
}
Lines changed: 299 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,299 @@
1+
warning: denote infinite loops with `loop { ... }`
2+
--> $DIR/coerce-loop-issue-122561.rs:48:5
3+
|
4+
LL | while true {
5+
| ^^^^^^^^^^ help: use `loop`
6+
|
7+
= note: `#[warn(while_true)]` on by default
8+
9+
warning: denote infinite loops with `loop { ... }`
10+
--> $DIR/coerce-loop-issue-122561.rs:72:5
11+
|
12+
LL | while true {
13+
| ^^^^^^^^^^ help: use `loop`
14+
15+
error[E0658]: `for` is not allowed in a `const`
16+
--> $DIR/coerce-loop-issue-122561.rs:41:24
17+
|
18+
LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool {
19+
| ^^^^^^^^^^^^^^^^
20+
|
21+
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
22+
= help: add `#![feature(const_for)]` to the crate attributes to enable
23+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
24+
25+
error[E0658]: `for` is not allowed in a `const`
26+
--> $DIR/coerce-loop-issue-122561.rs:86:5
27+
|
28+
LL | / for i in 0.. {
29+
LL | |
30+
LL | |
31+
LL | | }
32+
| |_____^
33+
|
34+
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
35+
= help: add `#![feature(const_for)]` to the crate attributes to enable
36+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
37+
38+
error[E0658]: `for` is not allowed in a `const`
39+
--> $DIR/coerce-loop-issue-122561.rs:94:9
40+
|
41+
LL | / for i in 0..5 {
42+
LL | |
43+
LL | |
44+
LL | | }
45+
| |_________^
46+
|
47+
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
48+
= help: add `#![feature(const_for)]` to the crate attributes to enable
49+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
50+
51+
error[E0658]: `for` is not allowed in a `const`
52+
--> $DIR/coerce-loop-issue-122561.rs:107:23
53+
|
54+
LL | let _ = |a: &[(); for x in 0..2 {}]| {};
55+
| ^^^^^^^^^^^^^^^^
56+
|
57+
= note: see issue #87575 <https://github.com/rust-lang/rust/issues/87575> for more information
58+
= help: add `#![feature(const_for)]` to the crate attributes to enable
59+
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
60+
61+
error[E0308]: mismatched types
62+
--> $DIR/coerce-loop-issue-122561.rs:41:24
63+
|
64+
LL | fn for_in_arg(a: &[(); for x in 0..2 {}]) -> bool {
65+
| ^^^^^^^^^^^^^^^^ expected `usize`, found `()`
66+
|
67+
= note: `for` loops evaluate to unit type `()`
68+
help: consider returning a value here
69+
|
70+
LL | fn for_in_arg(a: &[(); for x in 0..2 {} /* `usize` value */]) -> bool {
71+
| +++++++++++++++++++
72+
73+
error[E0308]: mismatched types
74+
--> $DIR/coerce-loop-issue-122561.rs:86:5
75+
|
76+
LL | / for i in 0.. {
77+
LL | |
78+
LL | |
79+
LL | | }
80+
| |_____^ expected `i32`, found `()`
81+
|
82+
= note: `for` loops evaluate to unit type `()`
83+
help: consider returning a value here
84+
|
85+
LL ~ }
86+
LL + /* `i32` value */
87+
|
88+
89+
error[E0308]: mismatched types
90+
--> $DIR/coerce-loop-issue-122561.rs:4:5
91+
|
92+
LL | fn for_infinite() -> bool {
93+
| ---- expected `bool` because of return type
94+
LL | / for i in 0.. {
95+
LL | |
96+
LL | | return false;
97+
LL | | }
98+
| |_____^ expected `bool`, found `()`
99+
|
100+
= note: `for` loops evaluate to unit type `()`
101+
help: consider returning a value here
102+
|
103+
LL ~ }
104+
LL + /* `bool` value */
105+
|
106+
107+
error[E0308]: mismatched types
108+
--> $DIR/coerce-loop-issue-122561.rs:11:5
109+
|
110+
LL | fn for_finite() -> String {
111+
| ------ expected `String` because of return type
112+
LL | / for i in 0..5 {
113+
LL | |
114+
LL | | return String::from("test");
115+
LL | | }
116+
| |_____^ expected `String`, found `()`
117+
|
118+
= note: `for` loops evaluate to unit type `()`
119+
help: consider returning a value here
120+
|
121+
LL ~ }
122+
LL + /* `String` value */
123+
|
124+
125+
error[E0308]: mismatched types
126+
--> $DIR/coerce-loop-issue-122561.rs:18:5
127+
|
128+
LL | fn for_zero_times() -> bool {
129+
| ---- expected `bool` because of return type
130+
LL | / for i in 0..0 {
131+
LL | |
132+
LL | | return true;
133+
LL | | }
134+
| |_____^ expected `bool`, found `()`
135+
|
136+
= note: `for` loops evaluate to unit type `()`
137+
help: consider returning a value here
138+
|
139+
LL ~ }
140+
LL + /* `bool` value */
141+
|
142+
143+
error[E0308]: mismatched types
144+
--> $DIR/coerce-loop-issue-122561.rs:25:5
145+
|
146+
LL | fn for_never_type() -> ! {
147+
| - expected `!` because of return type
148+
LL | / for i in 0..5 {
149+
LL | |
150+
LL | | }
151+
| |_____^ expected `!`, found `()`
152+
|
153+
= note: expected type `!`
154+
found unit type `()`
155+
= note: `for` loops evaluate to unit type `()`
156+
help: consider adding a diverging expression here
157+
|
158+
LL ~ }
159+
LL + /* `loop {}` or `panic!("...")` */
160+
|
161+
162+
error[E0308]: mismatched types
163+
--> $DIR/coerce-loop-issue-122561.rs:33:32
164+
|
165+
LL | fn for_single_line() -> bool { for i in 0.. { return false; } }
166+
| ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
167+
| |
168+
| expected `bool` because of return type
169+
|
170+
= note: `for` loops evaluate to unit type `()`
171+
help: consider returning a value here
172+
|
173+
LL | fn for_single_line() -> bool { for i in 0.. { return false; } /* `bool` value */ }
174+
| ++++++++++++++++++
175+
176+
error[E0308]: mismatched types
177+
--> $DIR/coerce-loop-issue-122561.rs:48:5
178+
|
179+
LL | fn while_inifinite() -> bool {
180+
| ---- expected `bool` because of return type
181+
LL | / while true {
182+
LL | |
183+
LL | |
184+
LL | | return true;
185+
LL | | }
186+
| |_____^ expected `bool`, found `()`
187+
|
188+
= note: `while` loops evaluate to unit type `()`
189+
help: consider returning a value here
190+
|
191+
LL ~ }
192+
LL + /* `bool` value */
193+
|
194+
195+
error[E0308]: mismatched types
196+
--> $DIR/coerce-loop-issue-122561.rs:57:5
197+
|
198+
LL | fn while_finite() -> bool {
199+
| ---- expected `bool` because of return type
200+
LL | let mut i = 0;
201+
LL | / while i < 3 {
202+
LL | |
203+
LL | | i += 1;
204+
LL | | return true;
205+
LL | | }
206+
| |_____^ expected `bool`, found `()`
207+
|
208+
= note: `while` loops evaluate to unit type `()`
209+
help: consider returning a value here
210+
|
211+
LL ~ }
212+
LL + /* `bool` value */
213+
|
214+
215+
error[E0308]: mismatched types
216+
--> $DIR/coerce-loop-issue-122561.rs:65:5
217+
|
218+
LL | fn while_zero_times() -> bool {
219+
| ---- expected `bool` because of return type
220+
LL | / while false {
221+
LL | |
222+
LL | | return true;
223+
LL | | }
224+
| |_____^ expected `bool`, found `()`
225+
|
226+
= note: `while` loops evaluate to unit type `()`
227+
help: consider returning a value here
228+
|
229+
LL ~ }
230+
LL + /* `bool` value */
231+
|
232+
233+
error[E0308]: mismatched types
234+
--> $DIR/coerce-loop-issue-122561.rs:72:5
235+
|
236+
LL | fn while_never_type() -> ! {
237+
| - expected `!` because of return type
238+
LL | / while true {
239+
LL | |
240+
LL | |
241+
LL | | }
242+
| |_____^ expected `!`, found `()`
243+
|
244+
= note: expected type `!`
245+
found unit type `()`
246+
= note: `while` loops evaluate to unit type `()`
247+
help: consider adding a diverging expression here
248+
|
249+
LL ~ }
250+
LL + /* `loop {}` or `panic!("...")` */
251+
|
252+
253+
error[E0308]: mismatched types
254+
--> $DIR/coerce-loop-issue-122561.rs:94:9
255+
|
256+
LL | / for i in 0..5 {
257+
LL | |
258+
LL | |
259+
LL | | }
260+
| |_________^ expected `usize`, found `()`
261+
|
262+
= note: `for` loops evaluate to unit type `()`
263+
help: consider returning a value here
264+
|
265+
LL ~ }
266+
LL + /* `usize` value */
267+
|
268+
269+
error[E0308]: mismatched types
270+
--> $DIR/coerce-loop-issue-122561.rs:101:9
271+
|
272+
LL | / while false {
273+
LL | |
274+
LL | | }
275+
| |_________^ expected `usize`, found `()`
276+
|
277+
= note: `while` loops evaluate to unit type `()`
278+
help: consider returning a value here
279+
|
280+
LL ~ }
281+
LL + /* `usize` value */
282+
|
283+
284+
error[E0308]: mismatched types
285+
--> $DIR/coerce-loop-issue-122561.rs:107:23
286+
|
287+
LL | let _ = |a: &[(); for x in 0..2 {}]| {};
288+
| ^^^^^^^^^^^^^^^^ expected `usize`, found `()`
289+
|
290+
= note: `for` loops evaluate to unit type `()`
291+
help: consider returning a value here
292+
|
293+
LL | let _ = |a: &[(); for x in 0..2 {} /* `usize` value */]| {};
294+
| +++++++++++++++++++
295+
296+
error: aborting due to 18 previous errors; 2 warnings emitted
297+
298+
Some errors have detailed explanations: E0308, E0658.
299+
For more information about an error, try `rustc --explain E0308`.

‎tests/ui/did_you_mean/compatible-variants.stderr‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ LL | | }
1111
|
1212
= note: expected enum `Option<()>`
1313
found unit type `()`
14+
= note: `while` loops evaluate to unit type `()`
1415
help: try adding an expression at the end of the block
1516
|
1617
LL ~ }
@@ -49,6 +50,7 @@ LL | | }
4950
|
5051
= note: expected enum `Option<()>`
5152
found unit type `()`
53+
= note: `for` loops evaluate to unit type `()`
5254
help: try adding an expression at the end of the block
5355
|
5456
LL ~ }
@@ -106,6 +108,7 @@ LL | while false {}
106108
|
107109
= note: expected enum `Option<()>`
108110
found unit type `()`
111+
= note: `while` loops evaluate to unit type `()`
109112
help: try adding an expression at the end of the block
110113
|
111114
LL ~ while false {}

‎tests/ui/for-loop-while/break-while-condition.stderr‎

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,12 @@ LL | | }
2020
|
2121
= note: expected type `!`
2222
found unit type `()`
23+
= note: `while` loops evaluate to unit type `()`
24+
help: consider adding a diverging expression here
25+
|
26+
LL ~ }
27+
LL + /* `loop {}` or `panic!("...")` */
28+
|
2329

2430
error[E0308]: mismatched types
2531
--> $DIR/break-while-condition.rs:24:13
@@ -31,14 +37,12 @@ LL | | }
3137
|
3238
= note: expected type `!`
3339
found unit type `()`
34-
note: the function expects a value to always be returned, but loops might run zero times
35-
--> $DIR/break-while-condition.rs:24:13
40+
= note: `while` loops evaluate to unit type `()`
41+
help: consider adding a diverging expression here
42+
|
43+
LL ~ }
44+
LL + /* `loop {}` or `panic!("...")` */
3645
|
37-
LL | while false {
38-
| ^^^^^^^^^^^ this might have zero elements to iterate on
39-
LL | return
40-
| ------ if the loop doesn't execute, this value would never get returned
41-
= 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
4246

4347
error: aborting due to 3 previous errors
4448

‎tests/ui/issues/issue-27042.stderr‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ error[E0308]: mismatched types
4040
LL | / 'c:
4141
LL | | for _ in None { break }; // but here we cite the whole loop
4242
| |_______________________________^ expected `i32`, found `()`
43+
|
44+
= note: `for` loops evaluate to unit type `()`
4345

4446
error[E0308]: mismatched types
4547
--> $DIR/issue-27042.rs:15:9

‎tests/ui/issues/issue-50585.stderr‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,12 @@ error[E0308]: mismatched types
1313
|
1414
LL | |y: Vec<[(); for x in 0..2 {}]>| {};
1515
| ^^^^^^^^^^^^^^^^ expected `usize`, found `()`
16+
|
17+
= note: `for` loops evaluate to unit type `()`
18+
help: consider returning a value here
19+
|
20+
LL | |y: Vec<[(); for x in 0..2 {} /* `usize` value */]>| {};
21+
| +++++++++++++++++++
1622

1723
error: aborting due to 2 previous errors
1824

‎tests/ui/typeck/issue-100285.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
fn foo(n: i32) -> i32 { //~ HELP otherwise consider changing the return type to account for that possibility
1+
fn foo(n: i32) -> i32 {
22
for i in 0..0 { //~ ERROR mismatched types [E0308]
33
if n < 0 {
44
return i;
@@ -14,7 +14,7 @@ fn foo(n: i32) -> i32 { //~ HELP otherwise consider changing the return type to
1414
return 5;
1515
}
1616

17-
} //~ HELP return a value for the case when the loop has zero elements to iterate on
17+
} //~ HELP consider returning a value here
1818
}
1919

2020
fn main() {}

‎tests/ui/typeck/issue-100285.stderr‎

Lines changed: 2 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -12,47 +12,12 @@ LL | |
1212
LL | | }
1313
| |_____^ expected `i32`, found `()`
1414
|
15-
note: the function expects a value to always be returned, but loops might run zero times
16-
--> $DIR/issue-100285.rs:2:5
17-
|
18-
LL | for i in 0..0 {
19-
| ^^^^^^^^^^^^^ this might have zero elements to iterate on
20-
LL | if n < 0 {
21-
LL | return i;
22-
| -------- if the loop doesn't execute, this value would never get returned
23-
LL | } else if n < 10 {
24-
LL | return 1;
25-
| -------- if the loop doesn't execute, this value would never get returned
26-
LL | } else if n < 20 {
27-
LL | return 2;
28-
| -------- if the loop doesn't execute, this value would never get returned
29-
= note: if the loop doesn't execute, 3 other values would never get returned
30-
help: return a value for the case when the loop has zero elements to iterate on
15+
= note: `for` loops evaluate to unit type `()`
16+
help: consider returning a value here
3117
|
3218
LL ~ }
3319
LL ~ /* `i32` value */
3420
|
35-
help: otherwise consider changing the return type to account for that possibility
36-
|
37-
LL ~ fn foo(n: i32) -> Option<i32> {
38-
LL | for i in 0..0 {
39-
LL | if n < 0 {
40-
LL ~ return Some(i);
41-
LL | } else if n < 10 {
42-
LL ~ return Some(1);
43-
LL | } else if n < 20 {
44-
LL ~ return Some(2);
45-
LL | } else if n < 30 {
46-
LL ~ return Some(3);
47-
LL | } else if n < 40 {
48-
LL ~ return Some(4);
49-
LL | } else {
50-
LL ~ return Some(5);
51-
LL | }
52-
LL |
53-
LL ~ }
54-
LL ~ None
55-
|
5621

5722
error: aborting due to 1 previous error
5823

‎tests/ui/typeck/issue-98982.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
fn foo() -> i32 { //~ HELP otherwise consider changing the return type to account for that possibility
1+
fn foo() -> i32 {
22
for i in 0..0 { //~ ERROR mismatched types [E0308]
33
return i;
4-
} //~ HELP return a value for the case when the loop has zero elements to iterate on
4+
} //~ HELP consider returning a value here
55
}
66

77
fn main() {}

‎tests/ui/typeck/issue-98982.stderr‎

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,12 @@ LL | | return i;
88
LL | | }
99
| |_____^ expected `i32`, found `()`
1010
|
11-
note: the function expects a value to always be returned, but loops might run zero times
12-
--> $DIR/issue-98982.rs:2:5
13-
|
14-
LL | for i in 0..0 {
15-
| ^^^^^^^^^^^^^ this might have zero elements to iterate on
16-
LL | return i;
17-
| -------- if the loop doesn't execute, this value would never get returned
18-
help: return a value for the case when the loop has zero elements to iterate on
11+
= note: `for` loops evaluate to unit type `()`
12+
help: consider returning a value here
1913
|
2014
LL ~ }
2115
LL ~ /* `i32` value */
2216
|
23-
help: otherwise consider changing the return type to account for that possibility
24-
|
25-
LL ~ fn foo() -> Option<i32> {
26-
LL | for i in 0..0 {
27-
LL ~ return Some(i);
28-
LL ~ }
29-
LL ~ None
30-
|
3117

3218
error: aborting due to 1 previous error
3319

0 commit comments

Comments
 (0)
This repository has been archived.