@@ -48,30 +48,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
48
48
/// Produces warning on the given node, if the current point in the
49
49
/// function is unreachable, and there hasn't been another warning.
50
50
pub ( crate ) fn warn_if_unreachable ( & self , id : 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 ) ;
51
+ // If span arose from a desugaring of `if` or `while`, then it is the condition itself,
52
+ // which diverges, that we are about to lint on. This gives suboptimal diagnostics.
53
+ // Instead, stop here so that the `if`- or `while`-expression's block is linted instead.
54
+ if span. is_desugaring ( DesugaringKind :: CondTemporary ) {
55
+ return ;
56
+ }
62
57
63
- debug ! ( "warn_if_unreachable: id={:?} span={:?} kind={}" , id, span, kind) ;
58
+ // Don't lint if the result of an async block or async function is `!`.
59
+ // This does not affect the unreachable lints *within* the body.
60
+ if span. is_desugaring ( DesugaringKind :: Async ) {
61
+ return ;
62
+ }
64
63
65
- let msg = format ! ( "unreachable {kind}" ) ;
66
- self . tcx ( ) . node_span_lint ( lint:: builtin:: UNREACHABLE_CODE , id, span, |lint| {
67
- lint. primary_message ( msg. clone ( ) ) ;
68
- lint. span_label ( span, msg) . span_label (
69
- orig_span,
70
- custom_note. unwrap_or ( "any code following this expression is unreachable" ) ,
71
- ) ;
72
- } )
73
- }
64
+ // Don't lint *within* the `.await` operator, since that's all just desugaring junk.
65
+ // We only want to lint if there is a subsequent expression after the `.await`.
66
+ if span. is_desugaring ( DesugaringKind :: Await ) {
67
+ return ;
74
68
}
69
+
70
+ let Diverges :: Always { span : orig_span, custom_note } = self . diverges . get ( ) else {
71
+ return ;
72
+ } ;
73
+
74
+ // Don't warn twice.
75
+ self . diverges . set ( Diverges :: WarnedAlways ) ;
76
+
77
+ debug ! ( "warn_if_unreachable: id={:?} span={:?} kind={}" , id, span, kind) ;
78
+
79
+ let msg = format ! ( "unreachable {kind}" ) ;
80
+ self . tcx ( ) . node_span_lint ( lint:: builtin:: UNREACHABLE_CODE , id, span, |lint| {
81
+ lint. primary_message ( msg. clone ( ) ) ;
82
+ lint. span_label ( span, msg) . span_label (
83
+ orig_span,
84
+ custom_note. unwrap_or ( "any code following this expression is unreachable" ) ,
85
+ ) ;
86
+ } )
75
87
}
76
88
77
89
/// Resolves type and const variables in `ty` if possible. Unlike the infcx
0 commit comments