@@ -2,7 +2,7 @@ use crate::callee::{self, DeferredCallResolution};
22use crate :: errors:: CtorIsPrivate ;
33use crate :: method:: { self , MethodCallee , SelfSource } ;
44use crate :: rvalue_scopes;
5- use crate :: { BreakableCtxt , Diverges , Expectation , FnCtxt , LoweredTy } ;
5+ use crate :: { BreakableCtxt , DivergeReason , Diverges , Expectation , FnCtxt , LoweredTy } ;
66use rustc_data_structures:: captures:: Captures ;
77use rustc_data_structures:: fx:: FxHashSet ;
88use rustc_errors:: { Applicability , Diag , ErrorGuaranteed , MultiSpan , StashKey } ;
@@ -48,36 +48,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
4848 /// Produces warning on the given node, if the current point in the
4949 /// function is unreachable, and there hasn't been another warning.
5050 pub ( in super :: super ) fn warn_if_unreachable ( & self , id : hir:: HirId , span : Span , kind : & str ) {
51- // FIXME: Combine these two 'if' expressions into one once
52- // let chains are implemented
53- if let Diverges :: Always { span : orig_span, custom_note } = self . diverges . get ( ) {
54- // If span arose from a desugaring of `if` or `while`, then it is the condition itself,
55- // which diverges, that we are about to lint on. This gives suboptimal diagnostics.
56- // Instead, stop here so that the `if`- or `while`-expression's block is linted instead.
57- if !span. is_desugaring ( DesugaringKind :: CondTemporary )
58- && !span. is_desugaring ( DesugaringKind :: Async )
59- && !orig_span. is_desugaring ( DesugaringKind :: Await )
60- {
61- self . diverges . set ( Diverges :: WarnedAlways ) ;
62-
63- debug ! ( "warn_if_unreachable: id={:?} span={:?} kind={}" , id, span, kind) ;
64-
65- let msg = format ! ( "unreachable {kind}" ) ;
66- self . tcx ( ) . node_span_lint (
67- lint:: builtin:: UNREACHABLE_CODE ,
68- id,
69- span,
70- msg. clone ( ) ,
71- |lint| {
72- lint. span_label ( span, msg) . span_label (
73- orig_span,
74- custom_note
75- . unwrap_or ( "any code following this expression is unreachable" ) ,
76- ) ;
77- } ,
78- )
79- }
51+ let Diverges :: Always ( reason, orig_span) = self . diverges . get ( ) else {
52+ return ;
53+ } ;
54+ // If span arose from a desugaring of `if` or `while`, then it is the condition itself,
55+ // which diverges, that we are about to lint on. This gives suboptimal diagnostics.
56+ // Instead, stop here so that the `if`- or `while`-expression's block is linted instead.
57+ if matches ! (
58+ span. desugaring_kind( ) ,
59+ Some ( DesugaringKind :: Async | DesugaringKind :: Await | DesugaringKind :: CondTemporary )
60+ ) {
61+ return ;
8062 }
63+
64+ self . diverges . set ( Diverges :: WarnedAlways ) ;
65+
66+ debug ! ( "warn_if_unreachable: id={:?} span={:?} kind={}" , id, span, kind) ;
67+
68+ let msg = format ! ( "unreachable {kind}" ) ;
69+ self . tcx ( ) . node_span_lint ( lint:: builtin:: UNREACHABLE_CODE , id, span, msg. clone ( ) , |lint| {
70+ let label = match reason {
71+ DivergeReason :: AllArmsDiverge => {
72+ "any code following this `match` expression is unreachable, as all arms diverge"
73+ }
74+ DivergeReason :: NeverPattern => "any code following a never pattern is unreachable" ,
75+ DivergeReason :: Other => "any code following this expression is unreachable" ,
76+ } ;
77+ lint. span_label ( span, msg) . span_label ( orig_span, label) ;
78+ } )
8179 }
8280
8381 /// Resolves type and const variables in `ty` if possible. Unlike the infcx
0 commit comments