@@ -68,7 +68,8 @@ impl LateLintPass<'_> for UndocumentedUnsafeBlocks {
68
68
&& !in_external_macro ( cx. tcx . sess , block. span )
69
69
&& !is_lint_allowed ( cx, UNDOCUMENTED_UNSAFE_BLOCKS , block. hir_id )
70
70
&& !is_unsafe_from_proc_macro ( cx, block. span )
71
- && !block_has_safety_comment ( cx, block)
71
+ && !block_has_safety_comment ( cx, block. span )
72
+ && !block_parents_have_safety_comment ( cx, block. hir_id )
72
73
{
73
74
let source_map = cx. tcx . sess . source_map ( ) ;
74
75
let span = if source_map. is_multiline ( block. span ) {
@@ -126,8 +127,41 @@ fn is_unsafe_from_proc_macro(cx: &LateContext<'_>, span: Span) -> bool {
126
127
. map_or ( true , |src| !src. starts_with ( "unsafe" ) )
127
128
}
128
129
130
+ // Checks if any parent {expression, statement, block, local, const, static}
131
+ // has a safety comment
132
+ fn block_parents_have_safety_comment ( cx : & LateContext < ' _ > , id : hir:: HirId ) -> bool {
133
+ if let Some ( node) = get_parent_node ( cx. tcx , id) {
134
+ return match node {
135
+ Node :: Expr ( expr) => !is_branchy ( expr) && span_in_body_has_safety_comment ( cx, expr. span ) ,
136
+ Node :: Stmt ( hir:: Stmt {
137
+ kind :
138
+ hir:: StmtKind :: Local ( hir:: Local { span, .. } )
139
+ | hir:: StmtKind :: Expr ( hir:: Expr { span, .. } )
140
+ | hir:: StmtKind :: Semi ( hir:: Expr { span, .. } ) ,
141
+ ..
142
+ } )
143
+ | Node :: Local ( hir:: Local { span, .. } )
144
+ | Node :: Item ( hir:: Item {
145
+ kind : hir:: ItemKind :: Const ( ..) | ItemKind :: Static ( ..) ,
146
+ span,
147
+ ..
148
+ } ) => span_in_body_has_safety_comment ( cx, * span) ,
149
+ _ => false ,
150
+ } ;
151
+ }
152
+ false
153
+ }
154
+
155
+ /// Checks if an expression is "branchy", e.g. loop, match/if/etc.
156
+ fn is_branchy ( expr : & hir:: Expr < ' _ > ) -> bool {
157
+ matches ! (
158
+ expr. kind,
159
+ hir:: ExprKind :: If ( ..) | hir:: ExprKind :: Loop ( ..) | hir:: ExprKind :: Match ( ..)
160
+ )
161
+ }
162
+
129
163
/// Checks if the lines immediately preceding the block contain a safety comment.
130
- fn block_has_safety_comment ( cx : & LateContext < ' _ > , block : & hir :: Block < ' _ > ) -> bool {
164
+ fn block_has_safety_comment ( cx : & LateContext < ' _ > , span : Span ) -> bool {
131
165
// This intentionally ignores text before the start of a function so something like:
132
166
// ```
133
167
// // SAFETY: reason
@@ -136,7 +170,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, block: &hir::Block<'_>) -> boo
136
170
// won't work. This is to avoid dealing with where such a comment should be place relative to
137
171
// attributes and doc comments.
138
172
139
- span_from_macro_expansion_has_safety_comment ( cx, block . span ) || span_in_body_has_safety_comment ( cx, block . span )
173
+ span_from_macro_expansion_has_safety_comment ( cx, span) || span_in_body_has_safety_comment ( cx, span)
140
174
}
141
175
142
176
/// Checks if the lines immediately preceding the item contain a safety comment.
0 commit comments