Skip to content

Commit 60624db

Browse files
authored
Unrolled build for rust-lang#132156
Rollup merge of rust-lang#132156 - estebank:closure-return, r=Nadrieril,compiler-errors When encountering unexpected closure return type, point at return type/expression ``` error[E0271]: expected `{[email protected]:18:40}` to be a closure that returns `()`, but it returns `!` --> $DIR/fallback-closure-wrap.rs:19:9 | LL | let error = Closure::wrap(Box::new(move || { | ------- LL | panic!("Can't connect to server."); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `!` | = note: expected unit type `()` found type `!` = note: required for the cast from `Box<{closure@$DIR/fallback-closure-wrap.rs:18:40: 18:47}>` to `Box<dyn FnMut()>` ``` ``` error[E0271]: expected `{[email protected]:6:10}` to be a closure that returns `bool`, but it returns `Option<()>` --> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:6:16 | LL | call(|| -> Option<()> { | ---- ------^^^^^^^^^^ | | | | | expected `bool`, found `Option<()>` | required by a bound introduced by this call | = note: expected type `bool` found enum `Option<()>` note: required by a bound in `call` --> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:3:25 | LL | fn call(_: impl Fn() -> bool) {} | ^^^^ required by this bound in `call` ``` ``` error[E0271]: expected `{[email protected]:28:13}` to be a closure that returns `Result<(), _>`, but it returns `!` --> f670.rs:28:20 | 28 | let c = |e| -> ! { | -------^ | | | expected `Result<(), _>`, found `!` ... 32 | f().or_else(c); | ------- required by a bound introduced by this call -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs:1433:28 | = note: expected enum `Result<(), _>` found type `!` note: required by a bound in `Result::<T, E>::or_else` --> /home/gh-estebank/rust/library/core/src/result.rs:1406:39 | 1406 | pub fn or_else<F, O: FnOnce(E) -> Result<T, F>>(self, op: O) -> Result<T, F> { | ^^^^^^^^^^^^ required by this bound in `Result::<T, E>::or_else` ``` CC rust-lang#111539.
2 parents 25a1657 + d116767 commit 60624db

File tree

13 files changed

+191
-67
lines changed

13 files changed

+191
-67
lines changed

Diff for: compiler/rustc_hir_analysis/src/check/compare_impl_item.rs

+3
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>(
653653
}))),
654654
terr,
655655
false,
656+
None,
656657
);
657658
return Err(diag.emit());
658659
}
@@ -1070,6 +1071,7 @@ fn report_trait_method_mismatch<'tcx>(
10701071
}))),
10711072
terr,
10721073
false,
1074+
None,
10731075
);
10741076

10751077
diag.emit()
@@ -1862,6 +1864,7 @@ fn compare_const_predicate_entailment<'tcx>(
18621864
}))),
18631865
terr,
18641866
false,
1867+
None,
18651868
);
18661869
return Err(diag.emit());
18671870
};

Diff for: compiler/rustc_hir_analysis/src/check/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -649,6 +649,7 @@ pub fn check_function_signature<'tcx>(
649649
}))),
650650
err,
651651
false,
652+
None,
652653
);
653654
return Err(diag.emit());
654655
}

Diff for: compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1147,6 +1147,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11471147
Some(self.param_env.and(trace.values)),
11481148
e,
11491149
true,
1150+
None,
11501151
);
11511152
}
11521153
}

Diff for: compiler/rustc_passes/src/check_attr.rs

+1
Original file line numberDiff line numberDiff line change
@@ -2471,6 +2471,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
24712471
}))),
24722472
terr,
24732473
false,
2474+
None,
24742475
);
24752476
diag.emit();
24762477
self.abort.set(true);

Diff for: compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs

+7-2
Original file line numberDiff line numberDiff line change
@@ -1392,9 +1392,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
13921392
mut values: Option<ty::ParamEnvAnd<'tcx, ValuePairs<'tcx>>>,
13931393
terr: TypeError<'tcx>,
13941394
prefer_label: bool,
1395+
override_span: Option<Span>,
13951396
) {
1396-
let span = cause.span;
1397-
1397+
// We use `override_span` when we want the error to point at a `Span` other than
1398+
// `cause.span`. This is used in E0271, when a closure is passed in where the return type
1399+
// isn't what was expected. We want to point at the closure's return type (or expression),
1400+
// instead of the expression where the closure is passed as call argument.
1401+
let span = override_span.unwrap_or(cause.span);
13981402
// For some types of errors, expected-found does not make
13991403
// sense, so just ignore the values we were given.
14001404
if let TypeError::CyclicTy(_) = terr {
@@ -2057,6 +2061,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
20572061
Some(param_env.and(trace.values)),
20582062
terr,
20592063
false,
2064+
None,
20602065
);
20612066
diag
20622067
}

Diff for: compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

+83-22
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
708708
None,
709709
TypeError::Sorts(ty::error::ExpectedFound::new(expected_ty, ct_ty)),
710710
false,
711+
None,
711712
);
712713
diag
713714
}
@@ -931,14 +932,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
931932
}
932933
}
933934
let hir_id = self.tcx.local_def_id_to_hir_id(obligation.cause.body_id);
934-
let body_id = match self.tcx.hir_node(hir_id) {
935-
hir::Node::Item(hir::Item {
936-
kind: hir::ItemKind::Fn { body: body_id, .. }, ..
937-
}) => body_id,
938-
_ => return false,
939-
};
940-
let ControlFlow::Break(expr) = (FindMethodSubexprOfTry { search_span: span })
941-
.visit_body(self.tcx.hir().body(*body_id))
935+
let Some(body_id) = self.tcx.hir_node(hir_id).body_id() else { return false };
936+
let ControlFlow::Break(expr) =
937+
(FindMethodSubexprOfTry { search_span: span }).visit_body(self.tcx.hir().body(body_id))
942938
else {
943939
return false;
944940
};
@@ -1385,22 +1381,54 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
13851381
_ => (None, error.err),
13861382
};
13871383

1388-
let msg = values
1384+
let (msg, span, closure_span) = values
13891385
.and_then(|(predicate, normalized_term, expected_term)| {
1390-
self.maybe_detailed_projection_msg(predicate, normalized_term, expected_term)
1386+
self.maybe_detailed_projection_msg(
1387+
obligation.cause.span,
1388+
predicate,
1389+
normalized_term,
1390+
expected_term,
1391+
)
13911392
})
13921393
.unwrap_or_else(|| {
13931394
let mut cx = FmtPrinter::new_with_limit(
13941395
self.tcx,
13951396
Namespace::TypeNS,
13961397
rustc_session::Limit(10),
13971398
);
1398-
with_forced_trimmed_paths!(format!("type mismatch resolving `{}`", {
1399-
self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap();
1400-
cx.into_buffer()
1401-
}))
1399+
(
1400+
with_forced_trimmed_paths!(format!("type mismatch resolving `{}`", {
1401+
self.resolve_vars_if_possible(predicate).print(&mut cx).unwrap();
1402+
cx.into_buffer()
1403+
})),
1404+
obligation.cause.span,
1405+
None,
1406+
)
14021407
});
1403-
let mut diag = struct_span_code_err!(self.dcx(), obligation.cause.span, E0271, "{msg}");
1408+
let mut diag = struct_span_code_err!(self.dcx(), span, E0271, "{msg}");
1409+
if let Some(span) = closure_span {
1410+
// Mark the closure decl so that it is seen even if we are pointing at the return
1411+
// type or expression.
1412+
//
1413+
// error[E0271]: expected `{[email protected]:41:16}` to be a closure that returns
1414+
// `Unit3`, but it returns `Unit4`
1415+
// --> $DIR/foo.rs:43:17
1416+
// |
1417+
// LL | let v = Unit2.m(
1418+
// | - required by a bound introduced by this call
1419+
// ...
1420+
// LL | f: |x| {
1421+
// | --- /* this span */
1422+
// LL | drop(x);
1423+
// LL | Unit4
1424+
// | ^^^^^ expected `Unit3`, found `Unit4`
1425+
// |
1426+
diag.span_label(span, "this closure");
1427+
if !span.overlaps(obligation.cause.span) {
1428+
// Point at the binding corresponding to the closure where it is used.
1429+
diag.span_label(obligation.cause.span, "closure used here");
1430+
}
1431+
}
14041432

14051433
let secondary_span = (|| {
14061434
let ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) =
@@ -1471,6 +1499,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
14711499
}),
14721500
err,
14731501
false,
1502+
Some(span),
14741503
);
14751504
self.note_obligation_cause(&mut diag, obligation);
14761505
diag.emit()
@@ -1479,34 +1508,66 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
14791508

14801509
fn maybe_detailed_projection_msg(
14811510
&self,
1511+
mut span: Span,
14821512
projection_term: ty::AliasTerm<'tcx>,
14831513
normalized_ty: ty::Term<'tcx>,
14841514
expected_ty: ty::Term<'tcx>,
1485-
) -> Option<String> {
1515+
) -> Option<(String, Span, Option<Span>)> {
14861516
let trait_def_id = projection_term.trait_def_id(self.tcx);
14871517
let self_ty = projection_term.self_ty();
14881518

14891519
with_forced_trimmed_paths! {
14901520
if self.tcx.is_lang_item(projection_term.def_id, LangItem::FnOnceOutput) {
14911521
let fn_kind = self_ty.prefix_string(self.tcx);
1522+
let (span, closure_span) = if let ty::Closure(def_id, _) = self_ty.kind() {
1523+
let def_span = self.tcx.def_span(def_id);
1524+
if let Some(local_def_id) = def_id.as_local()
1525+
&& let node = self.tcx.hir_node_by_def_id(local_def_id)
1526+
&& let Some(fn_decl) = node.fn_decl()
1527+
&& let Some(id) = node.body_id()
1528+
{
1529+
span = match fn_decl.output {
1530+
hir::FnRetTy::Return(ty) => ty.span,
1531+
hir::FnRetTy::DefaultReturn(_) => {
1532+
let body = self.tcx.hir().body(id);
1533+
match body.value.kind {
1534+
hir::ExprKind::Block(
1535+
hir::Block { expr: Some(expr), .. },
1536+
_,
1537+
) => expr.span,
1538+
hir::ExprKind::Block(
1539+
hir::Block {
1540+
expr: None, stmts: [.., last], ..
1541+
},
1542+
_,
1543+
) => last.span,
1544+
_ => body.value.span,
1545+
}
1546+
}
1547+
};
1548+
}
1549+
(span, Some(def_span))
1550+
} else {
1551+
(span, None)
1552+
};
14921553
let item = match self_ty.kind() {
14931554
ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
14941555
_ => self_ty.to_string(),
14951556
};
1496-
Some(format!(
1557+
Some((format!(
14971558
"expected `{item}` to be a {fn_kind} that returns `{expected_ty}`, but it \
14981559
returns `{normalized_ty}`",
1499-
))
1560+
), span, closure_span))
15001561
} else if self.tcx.is_lang_item(trait_def_id, LangItem::Future) {
1501-
Some(format!(
1562+
Some((format!(
15021563
"expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \
15031564
resolves to `{normalized_ty}`"
1504-
))
1565+
), span, None))
15051566
} else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
1506-
Some(format!(
1567+
Some((format!(
15071568
"expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \
15081569
yields `{normalized_ty}`"
1509-
))
1570+
), span, None))
15101571
} else {
15111572
None
15121573
}

Diff for: tests/ui/async-await/dont-ice-for-type-mismatch-in-closure-in-async.stderr

+7-11
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,14 @@ LL | true
2121
found type `bool`
2222

2323
error[E0271]: expected `{[email protected]:6:10}` to be a closure that returns `bool`, but it returns `Option<()>`
24-
--> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:6:10
24+
--> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:6:16
2525
|
26-
LL | call(|| -> Option<()> {
27-
| _____----_^
28-
| | |
29-
| | required by a bound introduced by this call
30-
LL | |
31-
LL | | if true {
32-
LL | | false
33-
... |
34-
LL | | })
35-
| |_____^ expected `bool`, found `Option<()>`
26+
LL | call(|| -> Option<()> {
27+
| ---- ------^^^^^^^^^^
28+
| | | |
29+
| | | expected `bool`, found `Option<()>`
30+
| | this closure
31+
| required by a bound introduced by this call
3632
|
3733
= note: expected type `bool`
3834
found enum `Option<()>`

Diff for: tests/ui/closures/return-type-doesnt-match-bound.rs

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
use std::error::Error;
2+
use std::process::exit;
3+
4+
fn foo<F>(f: F) -> ()
5+
where
6+
F: FnOnce() -> Result<(), Box<dyn Error>>,
7+
{
8+
f().or_else(|e| -> ! { //~ ERROR to be a closure that returns
9+
eprintln!("{:?}", e);
10+
exit(1)
11+
});
12+
}
13+
14+
fn bar<F>(f: F) -> ()
15+
where
16+
F: FnOnce() -> Result<(), Box<dyn Error>>,
17+
{
18+
let c = |e| -> ! { //~ ERROR to be a closure that returns
19+
eprintln!("{:?}", e);
20+
exit(1)
21+
};
22+
f().or_else(c);
23+
}
24+
25+
fn main() {}
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error[E0271]: expected `{[email protected]:8:17}` to be a closure that returns `Result<(), _>`, but it returns `!`
2+
--> $DIR/return-type-doesnt-match-bound.rs:8:24
3+
|
4+
LL | f().or_else(|e| -> ! {
5+
| ------- -------^
6+
| | | |
7+
| | | expected `Result<(), _>`, found `!`
8+
| | this closure
9+
| required by a bound introduced by this call
10+
|
11+
= note: expected enum `Result<(), _>`
12+
found type `!`
13+
note: required by a bound in `Result::<T, E>::or_else`
14+
--> $SRC_DIR/core/src/result.rs:LL:COL
15+
16+
error[E0271]: expected `{[email protected]:18:13}` to be a closure that returns `Result<(), _>`, but it returns `!`
17+
--> $DIR/return-type-doesnt-match-bound.rs:18:20
18+
|
19+
LL | let c = |e| -> ! {
20+
| -------^
21+
| | |
22+
| | expected `Result<(), _>`, found `!`
23+
| this closure
24+
...
25+
LL | f().or_else(c);
26+
| ------- - closure used here
27+
| |
28+
| required by a bound introduced by this call
29+
|
30+
= note: expected enum `Result<(), _>`
31+
found type `!`
32+
note: required by a bound in `Result::<T, E>::or_else`
33+
--> $SRC_DIR/core/src/result.rs:LL:COL
34+
35+
error: aborting due to 2 previous errors
36+
37+
For more information about this error, try `rustc --explain E0271`.

Diff for: tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,10 @@ trait Ty<'a> {
3636

3737
fn main() {
3838
let v = Unit2.m(
39-
L {
40-
//~^ ERROR to be a closure that returns `Unit3`, but it returns `Unit4`
41-
//~| ERROR type mismatch
39+
L { //~ ERROR type mismatch
4240
f: |x| {
4341
drop(x);
44-
Unit4
42+
Unit4 //~ ERROR to be a closure that returns `Unit3`, but it returns `Unit4`
4543
},
4644
},
4745
);

0 commit comments

Comments
 (0)