@@ -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,51 @@ 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
+ for ( _, node) in cx. tcx . hir ( ) . parent_iter ( id) {
134
+ match node {
135
+ Node :: Expr ( expr) => {
136
+ if !is_branchy ( expr) && span_in_body_has_safety_comment ( cx, expr. span ) {
137
+ return true ;
138
+ }
139
+ } ,
140
+ Node :: Stmt ( hir:: Stmt {
141
+ kind :
142
+ hir:: StmtKind :: Local ( hir:: Local { span, .. } )
143
+ | hir:: StmtKind :: Expr ( hir:: Expr { span, .. } )
144
+ | hir:: StmtKind :: Semi ( hir:: Expr { span, .. } ) ,
145
+ ..
146
+ } )
147
+ | Node :: Local ( hir:: Local { span, .. } )
148
+ | Node :: Item ( hir:: Item {
149
+ kind : hir:: ItemKind :: Const ( ..) | ItemKind :: Static ( ..) ,
150
+ span,
151
+ ..
152
+ } ) => {
153
+ if span_in_body_has_safety_comment ( cx, * span) {
154
+ return true ;
155
+ }
156
+ } ,
157
+ _ => {
158
+ break ;
159
+ } ,
160
+ }
161
+ }
162
+ false
163
+ }
164
+
165
+ /// Checks if an expression is "branchy", e.g. loop, match/if/etc.
166
+ fn is_branchy ( expr : & hir:: Expr < ' _ > ) -> bool {
167
+ matches ! (
168
+ expr. kind,
169
+ hir:: ExprKind :: If ( ..) | hir:: ExprKind :: Loop ( ..) | hir:: ExprKind :: Match ( ..)
170
+ )
171
+ }
172
+
129
173
/// Checks if the lines immediately preceding the block contain a safety comment.
130
- fn block_has_safety_comment ( cx : & LateContext < ' _ > , block : & hir :: Block < ' _ > ) -> bool {
174
+ fn block_has_safety_comment ( cx : & LateContext < ' _ > , span : Span ) -> bool {
131
175
// This intentionally ignores text before the start of a function so something like:
132
176
// ```
133
177
// // SAFETY: reason
@@ -136,7 +180,7 @@ fn block_has_safety_comment(cx: &LateContext<'_>, block: &hir::Block<'_>) -> boo
136
180
// won't work. This is to avoid dealing with where such a comment should be place relative to
137
181
// attributes and doc comments.
138
182
139
- span_from_macro_expansion_has_safety_comment ( cx, block . span ) || span_in_body_has_safety_comment ( cx, block . span )
183
+ span_from_macro_expansion_has_safety_comment ( cx, span) || span_in_body_has_safety_comment ( cx, span)
140
184
}
141
185
142
186
/// Checks if the lines immediately preceding the item contain a safety comment.
0 commit comments