mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-01 19:23:50 +00:00
Rollup merge of #64083 - estebank:tweak-e0308, r=oli-obk
Point at appropriate arm on type error on if/else/match with one non-! arm Fix https://github.com/rust-lang/rust/issues/61281.
This commit is contained in:
commit
59237ec665
@ -3687,6 +3687,40 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// If `expr` is a `match` expression that has only one non-`!` arm, use that arm's tail
|
||||||
|
/// expression's `Span`, otherwise return `expr.span`. This is done to give better errors
|
||||||
|
/// when given code like the following:
|
||||||
|
/// ```text
|
||||||
|
/// if false { return 0i32; } else { 1u32 }
|
||||||
|
/// // ^^^^ point at this instead of the whole `if` expression
|
||||||
|
/// ```
|
||||||
|
fn get_expr_coercion_span(&self, expr: &hir::Expr) -> syntax_pos::Span {
|
||||||
|
if let hir::ExprKind::Match(_, arms, _) = &expr.node {
|
||||||
|
let arm_spans: Vec<Span> = arms.iter().filter_map(|arm| {
|
||||||
|
self.in_progress_tables
|
||||||
|
.and_then(|tables| tables.borrow().node_type_opt(arm.body.hir_id))
|
||||||
|
.and_then(|arm_ty| {
|
||||||
|
if arm_ty.is_never() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(match &arm.body.node {
|
||||||
|
// Point at the tail expression when possible.
|
||||||
|
hir::ExprKind::Block(block, _) => block.expr
|
||||||
|
.as_ref()
|
||||||
|
.map(|e| e.span)
|
||||||
|
.unwrap_or(block.span),
|
||||||
|
_ => arm.body.span,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}).collect();
|
||||||
|
if arm_spans.len() == 1 {
|
||||||
|
return arm_spans[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
expr.span
|
||||||
|
}
|
||||||
|
|
||||||
fn check_block_with_expected(
|
fn check_block_with_expected(
|
||||||
&self,
|
&self,
|
||||||
blk: &'tcx hir::Block,
|
blk: &'tcx hir::Block,
|
||||||
@ -3746,12 +3780,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let coerce = ctxt.coerce.as_mut().unwrap();
|
let coerce = ctxt.coerce.as_mut().unwrap();
|
||||||
if let Some(tail_expr_ty) = tail_expr_ty {
|
if let Some(tail_expr_ty) = tail_expr_ty {
|
||||||
let tail_expr = tail_expr.unwrap();
|
let tail_expr = tail_expr.unwrap();
|
||||||
let cause = self.cause(tail_expr.span,
|
let span = self.get_expr_coercion_span(tail_expr);
|
||||||
ObligationCauseCode::BlockTailExpression(blk.hir_id));
|
let cause = self.cause(span, ObligationCauseCode::BlockTailExpression(blk.hir_id));
|
||||||
coerce.coerce(self,
|
coerce.coerce(self, &cause, tail_expr, tail_expr_ty);
|
||||||
&cause,
|
|
||||||
tail_expr,
|
|
||||||
tail_expr_ty);
|
|
||||||
} else {
|
} else {
|
||||||
// Subtle: if there is no explicit tail expression,
|
// Subtle: if there is no explicit tail expression,
|
||||||
// that is typically equivalent to a tail expression
|
// that is typically equivalent to a tail expression
|
||||||
|
@ -17,10 +17,10 @@ fn bar() -> impl std::fmt::Display {
|
|||||||
|
|
||||||
fn baz() -> impl std::fmt::Display {
|
fn baz() -> impl std::fmt::Display {
|
||||||
if false {
|
if false {
|
||||||
//~^ ERROR mismatched types
|
|
||||||
return 0i32;
|
return 0i32;
|
||||||
} else {
|
} else {
|
||||||
1u32
|
1u32
|
||||||
|
//~^ ERROR mismatched types
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -33,4 +33,33 @@ fn qux() -> impl std::fmt::Display {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bat() -> impl std::fmt::Display {
|
||||||
|
match 13 {
|
||||||
|
0 => return 0i32,
|
||||||
|
_ => 1u32,
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can() -> impl std::fmt::Display {
|
||||||
|
match 13 {
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
0 => return 0i32,
|
||||||
|
1 => 1u32,
|
||||||
|
_ => 2u32,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cat() -> impl std::fmt::Display {
|
||||||
|
match 13 {
|
||||||
|
0 => {
|
||||||
|
return 0i32;
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
1u32
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
@ -29,18 +29,16 @@ LL | return 1u32;
|
|||||||
found type `u32`
|
found type `u32`
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:19:5
|
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:22:9
|
||||||
|
|
|
|
||||||
LL | fn baz() -> impl std::fmt::Display {
|
LL | fn baz() -> impl std::fmt::Display {
|
||||||
| ---------------------- expected because this return type...
|
| ---------------------- expected because this return type...
|
||||||
LL | / if false {
|
LL | if false {
|
||||||
LL | |
|
LL | return 0i32;
|
||||||
LL | | return 0i32;
|
| ---- ...is found to be `i32` here
|
||||||
| | ---- ...is found to be `i32` here
|
LL | } else {
|
||||||
LL | | } else {
|
LL | 1u32
|
||||||
LL | | 1u32
|
| ^^^^ expected i32, found u32
|
||||||
LL | | }
|
|
||||||
| |_____^ expected i32, found u32
|
|
||||||
|
|
|
|
||||||
= note: expected type `i32`
|
= note: expected type `i32`
|
||||||
found type `u32`
|
found type `u32`
|
||||||
@ -61,6 +59,52 @@ LL | | }
|
|||||||
= note: expected type `i32`
|
= note: expected type `i32`
|
||||||
found type `u32`
|
found type `u32`
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:39:14
|
||||||
|
|
|
||||||
|
LL | fn bat() -> impl std::fmt::Display {
|
||||||
|
| ---------------------- expected because this return type...
|
||||||
|
LL | match 13 {
|
||||||
|
LL | 0 => return 0i32,
|
||||||
|
| ---- ...is found to be `i32` here
|
||||||
|
LL | _ => 1u32,
|
||||||
|
| ^^^^ expected i32, found u32
|
||||||
|
|
|
||||||
|
= note: expected type `i32`
|
||||||
|
found type `u32`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:45:5
|
||||||
|
|
|
||||||
|
LL | fn can() -> impl std::fmt::Display {
|
||||||
|
| ---------------------- expected because this return type...
|
||||||
|
LL | / match 13 {
|
||||||
|
LL | |
|
||||||
|
LL | | 0 => return 0i32,
|
||||||
|
| | ---- ...is found to be `i32` here
|
||||||
|
LL | | 1 => 1u32,
|
||||||
|
LL | | _ => 2u32,
|
||||||
|
LL | | }
|
||||||
|
| |_____^ expected i32, found u32
|
||||||
|
|
|
||||||
|
= note: expected type `i32`
|
||||||
|
found type `u32`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:59:13
|
||||||
|
|
|
||||||
|
LL | fn cat() -> impl std::fmt::Display {
|
||||||
|
| ---------------------- expected because this return type...
|
||||||
|
...
|
||||||
|
LL | return 0i32;
|
||||||
|
| ---- ...is found to be `i32` here
|
||||||
|
...
|
||||||
|
LL | 1u32
|
||||||
|
| ^^^^ expected i32, found u32
|
||||||
|
|
|
||||||
|
= note: expected type `i32`
|
||||||
|
found type `u32`
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
Loading…
Reference in New Issue
Block a user