diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 308a3d8ebc2cf..50fd72f061319 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If there are no arms, that is a diverging match; a special case. if arms.is_empty() { - self.diverges.set(self.diverges.get() | Diverges::Always); + self.diverges.set(self.diverges.get() | Diverges::always(expr.span)); return tcx.types.never; } @@ -69,7 +69,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // warnings). match all_pats_diverge { Diverges::Maybe => Diverges::Maybe, - Diverges::Always | Diverges::WarnedAlways => Diverges::WarnedAlways, + Diverges::Always { .. } | Diverges::WarnedAlways => Diverges::WarnedAlways, } }).collect(); @@ -167,6 +167,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { prior_arm_ty = Some(arm_ty); } + // If all of the arms in the `match` diverge, + // and we're dealing with an actual `match` block + // (as opposed to a `match` desugared from something else'), + // we can emit a better note. Rather than pointing + // at a diverging expression in an arbitrary arm, + // we can point at the entire `match` expression + if let (Diverges::Always { .. }, hir::MatchSource::Normal) = (all_arms_diverge, match_src) { + all_arms_diverge = Diverges::Always { + span: expr.span, + custom_note: Some( + "any code following this `match` expression is unreachable, as all arms diverge" + ) + }; + } + // We won't diverge unless the discriminant or all arms diverge. self.diverges.set(discrim_diverges | all_arms_diverge); @@ -176,7 +191,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// When the previously checked expression (the scrutinee) diverges, /// warn the user about the match arms being unreachable. fn warn_arms_when_scrutinee_diverges(&self, arms: &'tcx [hir::Arm], source: hir::MatchSource) { - if self.diverges.get().always() { + if self.diverges.get().is_always() { use hir::MatchSource::*; let msg = match source { IfDesugar { .. } | IfLetDesugar { .. } => "block in `if` expression", diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 56bd903040ab4..049f2eb16bb00 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -170,7 +170,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Any expression that produces a value of type `!` must have diverged if ty.is_never() { - self.diverges.set(self.diverges.get() | Diverges::Always); + self.diverges.set(self.diverges.get() | Diverges::always(expr.span)); } // Record the type, which applies it effects. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 1197160fa9501..1d68d79db8856 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -450,7 +450,20 @@ pub enum Diverges { /// Definitely known to diverge and therefore /// not reach the next sibling or its parent. - Always, + Always { + /// The `Span` points to the expression + /// that caused us to diverge + /// (e.g. `return`, `break`, etc). + span: Span, + /// In some cases (e.g. a `match` expression + /// where all arms diverge), we may be + /// able to provide a more informative + /// message to the user. + /// If this is `None`, a default messsage + /// will be generated, which is suitable + /// for most cases. + custom_note: Option<&'static str> + }, /// Same as `Always` but with a reachability /// warning already emitted. @@ -486,8 +499,22 @@ impl ops::BitOrAssign for Diverges { } impl Diverges { - fn always(self) -> bool { - self >= Diverges::Always + /// Creates a `Diverges::Always` with the provided `span` and the default note message. + fn always(span: Span) -> Diverges { + Diverges::Always { + span, + custom_note: None + } + } + + fn is_always(self) -> bool { + // Enum comparison ignores the + // contents of fields, so we just + // fill them in with garbage here. + self >= Diverges::Always { + span: DUMMY_SP, + custom_note: None + } } } @@ -2307,17 +2334,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// Produces warning on the given node, if the current point in the /// function is unreachable, and there hasn't been another warning. fn warn_if_unreachable(&self, id: hir::HirId, span: Span, kind: &str) { - if self.diverges.get() == Diverges::Always && + // FIXME: Combine these two 'if' expressions into one once + // let chains are implemented + if let Diverges::Always { span: orig_span, custom_note } = self.diverges.get() { // If span arose from a desugaring of `if` or `while`, then it is the condition itself, // which diverges, that we are about to lint on. This gives suboptimal diagnostics. // Instead, stop here so that the `if`- or `while`-expression's block is linted instead. - !span.is_desugaring(DesugaringKind::CondTemporary) { - self.diverges.set(Diverges::WarnedAlways); + if !span.is_desugaring(DesugaringKind::CondTemporary) { + self.diverges.set(Diverges::WarnedAlways); - debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind); + debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind); - let msg = format!("unreachable {}", kind); - self.tcx().lint_hir(lint::builtin::UNREACHABLE_CODE, id, span, &msg); + let msg = format!("unreachable {}", kind); + self.tcx().struct_span_lint_hir(lint::builtin::UNREACHABLE_CODE, id, span, &msg) + .span_note( + orig_span, + custom_note.unwrap_or("any code following this expression is unreachable") + ) + .emit(); + } } } @@ -3825,7 +3860,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // // #41425 -- label the implicit `()` as being the // "found type" here, rather than the "expected type". - if !self.diverges.get().always() { + if !self.diverges.get().is_always() { // #50009 -- Do not point at the entire fn block span, point at the return type // span, as it is the cause of the requirement, and // `consider_hint_about_removing_semicolon` will point at the last expression diff --git a/src/test/ui/dead-code-ret.stderr b/src/test/ui/dead-code-ret.stderr index 092a176f443b2..0ce31ea40ddbb 100644 --- a/src/test/ui/dead-code-ret.stderr +++ b/src/test/ui/dead-code-ret.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/dead-code-ret.rs:6:5 + | +LL | return; + | ^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/if-ret.stderr b/src/test/ui/if-ret.stderr index 73402e55a4fd8..2df8f22944ee8 100644 --- a/src/test/ui/if-ret.stderr +++ b/src/test/ui/if-ret.stderr @@ -5,4 +5,9 @@ LL | fn foo() { if (return) { } } | ^^^ | = note: `#[warn(unreachable_code)]` on by default +note: any code following this expression is unreachable + --> $DIR/if-ret.rs:6:15 + | +LL | fn foo() { if (return) { } } + | ^^^^^^^^ diff --git a/src/test/ui/issues/issue-2150.stderr b/src/test/ui/issues/issue-2150.stderr index 59000f3dd5338..623f098d0b337 100644 --- a/src/test/ui/issues/issue-2150.stderr +++ b/src/test/ui/issues/issue-2150.stderr @@ -9,6 +9,12 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/issue-2150.rs:7:5 + | +LL | panic!(); + | ^^^^^^^^^ + = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/issues/issue-7246.stderr b/src/test/ui/issues/issue-7246.stderr index e049295e9136f..d1b23672dc7f4 100644 --- a/src/test/ui/issues/issue-7246.stderr +++ b/src/test/ui/issues/issue-7246.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/issue-7246.rs:6:5 + | +LL | return; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/lint/lint-attr-non-item-node.stderr b/src/test/ui/lint/lint-attr-non-item-node.stderr index 6eb72c098df5c..e6c76c24c9110 100644 --- a/src/test/ui/lint/lint-attr-non-item-node.stderr +++ b/src/test/ui/lint/lint-attr-non-item-node.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #[deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/lint-attr-non-item-node.rs:6:9 + | +LL | break; + | ^^^^^ error: aborting due to previous error diff --git a/src/test/ui/liveness/liveness-unused.stderr b/src/test/ui/liveness/liveness-unused.stderr index 40a677c08f2b0..84e9b5bab99ff 100644 --- a/src/test/ui/liveness/liveness-unused.stderr +++ b/src/test/ui/liveness/liveness-unused.stderr @@ -10,6 +10,11 @@ note: lint level defined here LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]` +note: any code following this expression is unreachable + --> $DIR/liveness-unused.rs:91:9 + | +LL | continue; + | ^^^^^^^^ error: unused variable: `x` --> $DIR/liveness-unused.rs:8:7 diff --git a/src/test/ui/match/match-no-arms-unreachable-after.stderr b/src/test/ui/match/match-no-arms-unreachable-after.stderr index 65dcc6ee46554..6c46b2473cce6 100644 --- a/src/test/ui/match/match-no-arms-unreachable-after.stderr +++ b/src/test/ui/match/match-no-arms-unreachable-after.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/match-no-arms-unreachable-after.rs:7:5 + | +LL | match v { } + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/never-assign-dead-code.stderr b/src/test/ui/never-assign-dead-code.stderr index b1b5bf03fe52a..436c703e4b6b9 100644 --- a/src/test/ui/never-assign-dead-code.stderr +++ b/src/test/ui/never-assign-dead-code.stderr @@ -10,12 +10,24 @@ note: lint level defined here LL | #![warn(unused)] | ^^^^^^ = note: `#[warn(unreachable_code)]` implied by `#[warn(unused)]` +note: any code following this expression is unreachable + --> $DIR/never-assign-dead-code.rs:9:16 + | +LL | let x: ! = panic!("aah"); + | ^^^^^^^^^^^^^ + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) warning: unreachable call --> $DIR/never-assign-dead-code.rs:10:5 | LL | drop(x); | ^^^^ + | +note: any code following this expression is unreachable + --> $DIR/never-assign-dead-code.rs:10:10 + | +LL | drop(x); + | ^ warning: unused variable: `x` --> $DIR/never-assign-dead-code.rs:9:9 diff --git a/src/test/ui/reachable/expr_add.stderr b/src/test/ui/reachable/expr_add.stderr index 02b29021cb61a..47b4e467abecb 100644 --- a/src/test/ui/reachable/expr_add.stderr +++ b/src/test/ui/reachable/expr_add.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_add.rs:17:19 + | +LL | let x = Foo + return; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_again.stderr b/src/test/ui/reachable/expr_again.stderr index bdc3d143ea57e..8e246d940fd8d 100644 --- a/src/test/ui/reachable/expr_again.stderr +++ b/src/test/ui/reachable/expr_again.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_again.rs:7:9 + | +LL | continue; + | ^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_array.stderr b/src/test/ui/reachable/expr_array.stderr index 18d7ffe74bd18..419a332e632f3 100644 --- a/src/test/ui/reachable/expr_array.stderr +++ b/src/test/ui/reachable/expr_array.stderr @@ -9,12 +9,23 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_array.rs:9:26 + | +LL | let x: [usize; 2] = [return, 22]; + | ^^^^^^ error: unreachable expression --> $DIR/expr_array.rs:14:25 | LL | let x: [usize; 2] = [22, return]; | ^^^^^^^^^^^^ + | +note: any code following this expression is unreachable + --> $DIR/expr_array.rs:14:30 + | +LL | let x: [usize; 2] = [22, return]; + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_assign.stderr b/src/test/ui/reachable/expr_assign.stderr index def16d90a7490..7388fb4a6b9b2 100644 --- a/src/test/ui/reachable/expr_assign.stderr +++ b/src/test/ui/reachable/expr_assign.stderr @@ -9,18 +9,35 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_assign.rs:10:9 + | +LL | x = return; + | ^^^^^^ error: unreachable expression --> $DIR/expr_assign.rs:20:14 | LL | *p = return; | ^^^^^^ + | +note: any code following this expression is unreachable + --> $DIR/expr_assign.rs:20:9 + | +LL | *p = return; + | ^^ error: unreachable expression --> $DIR/expr_assign.rs:26:15 | LL | *{return; &mut i} = 22; | ^^^^^^ + | +note: any code following this expression is unreachable + --> $DIR/expr_assign.rs:26:7 + | +LL | *{return; &mut i} = 22; + | ^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/reachable/expr_block.stderr b/src/test/ui/reachable/expr_block.stderr index a498502e6cb1a..03a6139d688bb 100644 --- a/src/test/ui/reachable/expr_block.stderr +++ b/src/test/ui/reachable/expr_block.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_block.rs:9:9 + | +LL | return; + | ^^^^^^ error: unreachable statement --> $DIR/expr_block.rs:25:9 @@ -16,6 +21,11 @@ error: unreachable statement LL | println!("foo"); | ^^^^^^^^^^^^^^^^ | +note: any code following this expression is unreachable + --> $DIR/expr_block.rs:24:9 + | +LL | return; + | ^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_box.stderr b/src/test/ui/reachable/expr_box.stderr index 63137ce3da180..d0f666d2be44b 100644 --- a/src/test/ui/reachable/expr_box.stderr +++ b/src/test/ui/reachable/expr_box.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_box.rs:6:17 + | +LL | let x = box return; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_call.stderr b/src/test/ui/reachable/expr_call.stderr index f2db17e4dfe8e..3fcea90e7cd87 100644 --- a/src/test/ui/reachable/expr_call.stderr +++ b/src/test/ui/reachable/expr_call.stderr @@ -9,12 +9,23 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_call.rs:13:9 + | +LL | foo(return, 22); + | ^^^^^^ error: unreachable call --> $DIR/expr_call.rs:18:5 | LL | bar(return); | ^^^ + | +note: any code following this expression is unreachable + --> $DIR/expr_call.rs:18:9 + | +LL | bar(return); + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_cast.stderr b/src/test/ui/reachable/expr_cast.stderr index 3086745d28ed4..d3ce0ca079f90 100644 --- a/src/test/ui/reachable/expr_cast.stderr +++ b/src/test/ui/reachable/expr_cast.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_cast.rs:9:14 + | +LL | let x = {return} as !; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_if.stderr b/src/test/ui/reachable/expr_if.stderr index f1690e595e5d1..03284576086a7 100644 --- a/src/test/ui/reachable/expr_if.stderr +++ b/src/test/ui/reachable/expr_if.stderr @@ -12,6 +12,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_if.rs:7:9 + | +LL | if {return} { + | ^^^^^^ error: unreachable statement --> $DIR/expr_if.rs:27:5 @@ -19,6 +24,11 @@ error: unreachable statement LL | println!("But I am."); | ^^^^^^^^^^^^^^^^^^^^^^ | +note: any code following this expression is unreachable + --> $DIR/expr_if.rs:21:9 + | +LL | return; + | ^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_loop.stderr b/src/test/ui/reachable/expr_loop.stderr index 4d3e06c93a376..a4cf8cfcfd9e6 100644 --- a/src/test/ui/reachable/expr_loop.stderr +++ b/src/test/ui/reachable/expr_loop.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_loop.rs:7:12 + | +LL | loop { return; } + | ^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: unreachable statement @@ -17,6 +22,11 @@ error: unreachable statement LL | println!("I am dead."); | ^^^^^^^^^^^^^^^^^^^^^^^ | +note: any code following this expression is unreachable + --> $DIR/expr_loop.rs:20:12 + | +LL | loop { return; } + | ^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: unreachable statement @@ -25,6 +35,11 @@ error: unreachable statement LL | println!("I am dead."); | ^^^^^^^^^^^^^^^^^^^^^^^ | +note: any code following this expression is unreachable + --> $DIR/expr_loop.rs:31:5 + | +LL | loop { 'middle: loop { loop { break 'middle; } } } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/src/test/ui/reachable/expr_match.stderr b/src/test/ui/reachable/expr_match.stderr index 1aef06aec5ba6..f587e524d350d 100644 --- a/src/test/ui/reachable/expr_match.stderr +++ b/src/test/ui/reachable/expr_match.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this `match` expression is unreachable, as all arms diverge + --> $DIR/expr_match.rs:7:5 + | +LL | match () { () => return } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: unreachable statement @@ -17,6 +22,11 @@ error: unreachable statement LL | println!("I am dead"); | ^^^^^^^^^^^^^^^^^^^^^^ | +note: any code following this `match` expression is unreachable, as all arms diverge + --> $DIR/expr_match.rs:18:5 + | +LL | match () { () if false => return, () => return } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_method.stderr b/src/test/ui/reachable/expr_method.stderr index 947ea0fee889c..7ad279c9f487a 100644 --- a/src/test/ui/reachable/expr_method.stderr +++ b/src/test/ui/reachable/expr_method.stderr @@ -9,12 +9,23 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_method.rs:16:13 + | +LL | Foo.foo(return, 22); + | ^^^^^^ error: unreachable call --> $DIR/expr_method.rs:21:9 | LL | Foo.bar(return); | ^^^ + | +note: any code following this expression is unreachable + --> $DIR/expr_method.rs:21:13 + | +LL | Foo.bar(return); + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_repeat.stderr b/src/test/ui/reachable/expr_repeat.stderr index 0536cdef72128..3ff6be76daea5 100644 --- a/src/test/ui/reachable/expr_repeat.stderr +++ b/src/test/ui/reachable/expr_repeat.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_repeat.rs:9:26 + | +LL | let x: [usize; 2] = [return; 2]; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_return.stderr b/src/test/ui/reachable/expr_return.stderr index 3317da58aba1c..31f7ebe7618ea 100644 --- a/src/test/ui/reachable/expr_return.stderr +++ b/src/test/ui/reachable/expr_return.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_return.rs:10:30 + | +LL | let x = {return {return {return;}}}; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_return_in_macro.rs b/src/test/ui/reachable/expr_return_in_macro.rs new file mode 100644 index 0000000000000..4e57618bf5e77 --- /dev/null +++ b/src/test/ui/reachable/expr_return_in_macro.rs @@ -0,0 +1,15 @@ +// Tests that we generate nice error messages +// when an expression is unreachble due to control +// flow inside of a macro expansion. +#![deny(unreachable_code)] + +macro_rules! early_return { + () => { + return () + } +} + +fn main() { + return early_return!(); + //~^ ERROR unreachable expression +} diff --git a/src/test/ui/reachable/expr_return_in_macro.stderr b/src/test/ui/reachable/expr_return_in_macro.stderr new file mode 100644 index 0000000000000..ff3abb5551f92 --- /dev/null +++ b/src/test/ui/reachable/expr_return_in_macro.stderr @@ -0,0 +1,22 @@ +error: unreachable expression + --> $DIR/expr_return_in_macro.rs:13:5 + | +LL | return early_return!(); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/expr_return_in_macro.rs:4:9 + | +LL | #![deny(unreachable_code)] + | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_return_in_macro.rs:8:9 + | +LL | return () + | ^^^^^^^^^ +... +LL | return early_return!(); + | --------------- in this macro invocation + +error: aborting due to previous error + diff --git a/src/test/ui/reachable/expr_struct.stderr b/src/test/ui/reachable/expr_struct.stderr index dcccb7a4db307..d08bcc4f0d1ae 100644 --- a/src/test/ui/reachable/expr_struct.stderr +++ b/src/test/ui/reachable/expr_struct.stderr @@ -9,24 +9,47 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_struct.rs:14:35 + | +LL | let x = Foo { a: 22, b: 33, ..return }; + | ^^^^^^ error: unreachable expression --> $DIR/expr_struct.rs:19:33 | LL | let x = Foo { a: return, b: 33, ..return }; | ^^ + | +note: any code following this expression is unreachable + --> $DIR/expr_struct.rs:19:22 + | +LL | let x = Foo { a: return, b: 33, ..return }; + | ^^^^^^ error: unreachable expression --> $DIR/expr_struct.rs:24:39 | LL | let x = Foo { a: 22, b: return, ..return }; | ^^^^^^ + | +note: any code following this expression is unreachable + --> $DIR/expr_struct.rs:24:29 + | +LL | let x = Foo { a: 22, b: return, ..return }; + | ^^^^^^ error: unreachable expression --> $DIR/expr_struct.rs:29:13 | LL | let x = Foo { a: 22, b: return }; | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: any code following this expression is unreachable + --> $DIR/expr_struct.rs:29:29 + | +LL | let x = Foo { a: 22, b: return }; + | ^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/reachable/expr_tup.stderr b/src/test/ui/reachable/expr_tup.stderr index 1837031107d59..788499533db33 100644 --- a/src/test/ui/reachable/expr_tup.stderr +++ b/src/test/ui/reachable/expr_tup.stderr @@ -9,12 +9,23 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_tup.rs:9:30 + | +LL | let x: (usize, usize) = (return, 2); + | ^^^^^^ error: unreachable expression --> $DIR/expr_tup.rs:14:29 | LL | let x: (usize, usize) = (2, return); | ^^^^^^^^^^^ + | +note: any code following this expression is unreachable + --> $DIR/expr_tup.rs:14:33 + | +LL | let x: (usize, usize) = (2, return); + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_type.stderr b/src/test/ui/reachable/expr_type.stderr index f867c89163415..15eb735da75d8 100644 --- a/src/test/ui/reachable/expr_type.stderr +++ b/src/test/ui/reachable/expr_type.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_type.rs:9:14 + | +LL | let x = {return}: !; + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/reachable/expr_unary.stderr b/src/test/ui/reachable/expr_unary.stderr index 61982289cdc6e..7f86519616639 100644 --- a/src/test/ui/reachable/expr_unary.stderr +++ b/src/test/ui/reachable/expr_unary.stderr @@ -15,6 +15,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_unary.rs:8:20 + | +LL | let x: ! = ! { return; }; + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/reachable/expr_while.stderr b/src/test/ui/reachable/expr_while.stderr index fc528926b4c97..b6d6d11ac691e 100644 --- a/src/test/ui/reachable/expr_while.stderr +++ b/src/test/ui/reachable/expr_while.stderr @@ -13,6 +13,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/expr_while.rs:7:12 + | +LL | while {return} { + | ^^^^^^ error: unreachable block in `while` expression --> $DIR/expr_while.rs:22:20 @@ -23,6 +28,12 @@ LL | | LL | | println!("I am dead."); LL | | } | |_____^ + | +note: any code following this expression is unreachable + --> $DIR/expr_while.rs:22:12 + | +LL | while {return} { + | ^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/rfc-2497-if-let-chains/protect-precedences.stderr b/src/test/ui/rfc-2497-if-let-chains/protect-precedences.stderr index be7ef658411e1..ca98a3947146e 100644 --- a/src/test/ui/rfc-2497-if-let-chains/protect-precedences.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/protect-precedences.stderr @@ -5,4 +5,9 @@ LL | if let _ = return true && false {}; | ^^ | = note: `#[warn(unreachable_code)]` on by default +note: any code following this expression is unreachable + --> $DIR/protect-precedences.rs:13:20 + | +LL | if let _ = return true && false {}; + | ^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/unreachable/unreachable-code.stderr b/src/test/ui/unreachable/unreachable-code.stderr index 803bb966be8fc..226f088c63a5e 100644 --- a/src/test/ui/unreachable/unreachable-code.stderr +++ b/src/test/ui/unreachable/unreachable-code.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/unreachable-code.rs:5:3 + | +LL | loop{} + | ^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/unreachable/unreachable-in-call.stderr b/src/test/ui/unreachable/unreachable-in-call.stderr index c740011c4a125..928f5634a1248 100644 --- a/src/test/ui/unreachable/unreachable-in-call.stderr +++ b/src/test/ui/unreachable/unreachable-in-call.stderr @@ -9,12 +9,23 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/unreachable-in-call.rs:13:10 + | +LL | call(diverge(), + | ^^^^^^^^^ error: unreachable call --> $DIR/unreachable-in-call.rs:17:5 | LL | call( | ^^^^ + | +note: any code following this expression is unreachable + --> $DIR/unreachable-in-call.rs:19:9 + | +LL | diverge()); + | ^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/unreachable/unreachable-try-pattern.stderr b/src/test/ui/unreachable/unreachable-try-pattern.stderr index 758aa5a45bc17..889df790124da 100644 --- a/src/test/ui/unreachable/unreachable-try-pattern.stderr +++ b/src/test/ui/unreachable/unreachable-try-pattern.stderr @@ -9,6 +9,11 @@ note: lint level defined here | LL | #![warn(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/unreachable-try-pattern.rs:19:36 + | +LL | let y = (match x { Ok(n) => Ok(n as u32), Err(e) => Err(e) })?; + | ^ warning: unreachable pattern --> $DIR/unreachable-try-pattern.rs:19:24 diff --git a/src/test/ui/unreachable/unwarned-match-on-never.stderr b/src/test/ui/unreachable/unwarned-match-on-never.stderr index ccb70d7431145..9ce6e3df8046e 100644 --- a/src/test/ui/unreachable/unwarned-match-on-never.stderr +++ b/src/test/ui/unreachable/unwarned-match-on-never.stderr @@ -9,12 +9,23 @@ note: lint level defined here | LL | #![deny(unreachable_code)] | ^^^^^^^^^^^^^^^^ +note: any code following this expression is unreachable + --> $DIR/unwarned-match-on-never.rs:8:11 + | +LL | match x {} + | ^ error: unreachable arm --> $DIR/unwarned-match-on-never.rs:15:15 | LL | () => () | ^^ + | +note: any code following this expression is unreachable + --> $DIR/unwarned-match-on-never.rs:14:11 + | +LL | match (return) { + | ^^^^^^^^ error: unreachable expression --> $DIR/unwarned-match-on-never.rs:21:5 @@ -23,6 +34,12 @@ LL | / match () { LL | | () => (), LL | | } | |_____^ + | +note: any code following this expression is unreachable + --> $DIR/unwarned-match-on-never.rs:20:5 + | +LL | return; + | ^^^^^^ error: aborting due to 3 previous errors