Skip to content

Commit 8ef8d57

Browse files
authored
Rollup merge of #57793 - estebank:impl-trait-resolve, r=oli-obk
Explain type mismatch cause pointing to return type when it is `impl Trait` Fix #57743.
2 parents 2dd63a2 + ab2479b commit 8ef8d57

File tree

3 files changed

+78
-58
lines changed

3 files changed

+78
-58
lines changed

src/librustc_typeck/check/coercion.rs

+63-54
Original file line numberDiff line numberDiff line change
@@ -1199,7 +1199,6 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
11991199
(self.final_ty.unwrap_or(self.expected_ty), expression_ty)
12001200
};
12011201

1202-
let reason_label = "expected because of this statement";
12031202
let mut db;
12041203
match cause.code {
12051204
ObligationCauseCode::ReturnNoExpression => {
@@ -1209,63 +1208,20 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
12091208
db.span_label(cause.span, "return type is not `()`");
12101209
}
12111210
ObligationCauseCode::BlockTailExpression(blk_id) => {
1212-
db = fcx.report_mismatched_types(cause, expected, found, err);
1213-
1214-
let expr = expression.unwrap_or_else(|| {
1215-
span_bug!(cause.span,
1216-
"supposed to be part of a block tail expression, but the \
1217-
expression is empty");
1218-
});
1219-
let pointing_at_return_type = fcx.suggest_mismatched_types_on_tail(
1220-
&mut db,
1221-
expr,
1211+
let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
1212+
db = self.report_return_mismatched_types(
1213+
cause,
12221214
expected,
12231215
found,
1224-
cause.span,
1225-
blk_id,
1216+
err,
1217+
fcx,
1218+
parent_id,
1219+
expression.map(|expr| (expr, blk_id)),
12261220
);
1227-
// FIXME: replace with navigating up the chain until hitting an fn or
1228-
// bailing if no "pass-through" Node is found, in order to provide a
1229-
// suggestion when encountering something like:
1230-
// ```
1231-
// fn foo(a: bool) -> impl Debug {
1232-
// if a {
1233-
// bar()?;
1234-
// }
1235-
// {
1236-
// let x = unsafe { bar() };
1237-
// x
1238-
// }
1239-
// }
1240-
// ```
1241-
//
1242-
// Verify that this is a tail expression of a function, otherwise the
1243-
// label pointing out the cause for the type coercion will be wrong
1244-
// as prior return coercions would not be relevant (#57664).
1245-
let parent_id = fcx.tcx.hir().get_parent_node(blk_id);
1246-
let parent = fcx.tcx.hir().get(fcx.tcx.hir().get_parent_node(parent_id));
1247-
if fcx.get_node_fn_decl(parent).is_some() && !pointing_at_return_type {
1248-
if let Some(sp) = fcx.ret_coercion_span.borrow().as_ref() {
1249-
db.span_label(*sp, reason_label);
1250-
}
1251-
}
12521221
}
1253-
ObligationCauseCode::ReturnType(_id) => {
1254-
db = fcx.report_mismatched_types(cause, expected, found, err);
1255-
let _id = fcx.tcx.hir().get_parent_node(_id);
1256-
let mut pointing_at_return_type = false;
1257-
if let Some((fn_decl, can_suggest)) = fcx.get_fn_decl(_id) {
1258-
pointing_at_return_type = fcx.suggest_missing_return_type(
1259-
&mut db, &fn_decl, expected, found, can_suggest);
1260-
}
1261-
if let (Some(sp), false) = (
1262-
fcx.ret_coercion_span.borrow().as_ref(),
1263-
pointing_at_return_type,
1264-
) {
1265-
if !sp.overlaps(cause.span) {
1266-
db.span_label(*sp, reason_label);
1267-
}
1268-
}
1222+
ObligationCauseCode::ReturnType(id) => {
1223+
db = self.report_return_mismatched_types(
1224+
cause, expected, found, err, fcx, id, None);
12691225
}
12701226
_ => {
12711227
db = fcx.report_mismatched_types(cause, expected, found, err);
@@ -1283,6 +1239,59 @@ impl<'gcx, 'tcx, 'exprs, E> CoerceMany<'gcx, 'tcx, 'exprs, E>
12831239
}
12841240
}
12851241

1242+
fn report_return_mismatched_types<'a>(
1243+
&self,
1244+
cause: &ObligationCause<'tcx>,
1245+
expected: Ty<'tcx>,
1246+
found: Ty<'tcx>,
1247+
err: TypeError<'tcx>,
1248+
fcx: &FnCtxt<'a, 'gcx, 'tcx>,
1249+
id: syntax::ast::NodeId,
1250+
expression: Option<(&'gcx hir::Expr, syntax::ast::NodeId)>,
1251+
) -> DiagnosticBuilder<'a> {
1252+
let mut db = fcx.report_mismatched_types(cause, expected, found, err);
1253+
1254+
let mut pointing_at_return_type = false;
1255+
let mut return_sp = None;
1256+
1257+
// Verify that this is a tail expression of a function, otherwise the
1258+
// label pointing out the cause for the type coercion will be wrong
1259+
// as prior return coercions would not be relevant (#57664).
1260+
let parent_id = fcx.tcx.hir().get_parent_node(id);
1261+
let fn_decl = if let Some((expr, blk_id)) = expression {
1262+
pointing_at_return_type = fcx.suggest_mismatched_types_on_tail(
1263+
&mut db,
1264+
expr,
1265+
expected,
1266+
found,
1267+
cause.span,
1268+
blk_id,
1269+
);
1270+
let parent = fcx.tcx.hir().get(parent_id);
1271+
fcx.get_node_fn_decl(parent).map(|(fn_decl, _, is_main)| (fn_decl, is_main))
1272+
} else {
1273+
fcx.get_fn_decl(parent_id)
1274+
};
1275+
1276+
if let (Some((fn_decl, can_suggest)), _) = (fn_decl, pointing_at_return_type) {
1277+
if expression.is_none() {
1278+
pointing_at_return_type |= fcx.suggest_missing_return_type(
1279+
&mut db, &fn_decl, expected, found, can_suggest);
1280+
}
1281+
if !pointing_at_return_type {
1282+
return_sp = Some(fn_decl.output.span()); // `impl Trait` return type
1283+
}
1284+
}
1285+
if let (Some(sp), Some(return_sp)) = (fcx.ret_coercion_span.borrow().as_ref(), return_sp) {
1286+
db.span_label(return_sp, "expected because this return type...");
1287+
db.span_label( *sp, format!(
1288+
"...is found to be `{}` here",
1289+
fcx.resolve_type_vars_with_obligations(expected),
1290+
));
1291+
}
1292+
db
1293+
}
1294+
12861295
pub fn complete<'a>(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
12871296
if let Some(final_ty) = self.final_ty {
12881297
final_ty

src/test/ui/impl-trait/equality.stderr

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
error[E0308]: mismatched types
22
--> $DIR/equality.rs:15:5
33
|
4+
LL | fn two(x: bool) -> impl Foo {
5+
| -------- expected because this return type...
6+
LL | if x {
47
LL | return 1_i32;
5-
| ----- expected because of this statement
8+
| ----- ...is found to be `i32` here
69
LL | }
710
LL | 0_u32
811
| ^^^^^ expected i32, found u32

src/test/ui/point-to-type-err-cause-on-impl-trait-return.stderr

+11-3
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
error[E0308]: mismatched types
22
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
33
|
4+
LL | fn foo() -> impl std::fmt::Display {
5+
| ---------------------- expected because this return type...
6+
LL | if false {
47
LL | return 0i32;
5-
| ---- expected because of this statement
8+
| ---- ...is found to be `i32` here
69
LL | }
710
LL | 1u32
811
| ^^^^ expected i32, found u32
@@ -13,8 +16,11 @@ LL | 1u32
1316
error[E0308]: mismatched types
1417
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:13:16
1518
|
19+
LL | fn bar() -> impl std::fmt::Display {
20+
| ---------------------- expected because this return type...
21+
LL | if false {
1622
LL | return 0i32;
17-
| ---- expected because of this statement
23+
| ---- ...is found to be `i32` here
1824
LL | } else {
1925
LL | return 1u32;
2026
| ^^^^ expected i32, found u32
@@ -25,10 +31,12 @@ LL | return 1u32;
2531
error[E0308]: mismatched types
2632
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5
2733
|
34+
LL | fn baz() -> impl std::fmt::Display {
35+
| ---------------------- expected because this return type...
2836
LL | / if false {
2937
LL | | //~^ ERROR mismatched types
3038
LL | | return 0i32;
31-
| | ---- expected because of this statement
39+
| | ---- ...is found to be `i32` here
3240
LL | | } else {
3341
LL | | 1u32
3442
LL | | }

0 commit comments

Comments
 (0)