@@ -76,6 +76,7 @@ impl CheckAttrVisitor<'_> {
76
76
for attr in attrs {
77
77
let attr_is_valid = match attr. name_or_empty ( ) {
78
78
sym:: inline => self . check_inline ( hir_id, attr, span, target) ,
79
+ sym:: no_coverage => self . check_no_coverage ( hir_id, attr, span, target) ,
79
80
sym:: non_exhaustive => self . check_non_exhaustive ( hir_id, attr, span, target) ,
80
81
sym:: marker => self . check_marker ( hir_id, attr, span, target) ,
81
82
sym:: rustc_must_implement_one_of => {
@@ -292,6 +293,56 @@ impl CheckAttrVisitor<'_> {
292
293
}
293
294
}
294
295
296
+ /// Checks if a `#[no_coverage]` is applied directly to a function
297
+ fn check_no_coverage (
298
+ & self ,
299
+ hir_id : HirId ,
300
+ attr : & Attribute ,
301
+ span : Span ,
302
+ target : Target ,
303
+ ) -> bool {
304
+ match target {
305
+ // no_coverage on function is fine
306
+ Target :: Fn
307
+ | Target :: Closure
308
+ | Target :: Method ( MethodKind :: Trait { body : true } | MethodKind :: Inherent ) => true ,
309
+
310
+ // function prototypes can't be covered
311
+ Target :: Method ( MethodKind :: Trait { body : false } ) | Target :: ForeignFn => {
312
+ self . tcx . struct_span_lint_hir ( UNUSED_ATTRIBUTES , hir_id, attr. span , |lint| {
313
+ lint. build ( "`#[no_coverage]` is ignored on function prototypes" ) . emit ( ) ;
314
+ } ) ;
315
+ true
316
+ }
317
+
318
+ Target :: Mod | Target :: ForeignMod | Target :: Impl | Target :: Trait => {
319
+ self . tcx . struct_span_lint_hir ( UNUSED_ATTRIBUTES , hir_id, attr. span , |lint| {
320
+ lint. build ( "`#[no_coverage]` cannot be done recursively and must be applied to functions directly" ) . emit ( ) ;
321
+ } ) ;
322
+ true
323
+ }
324
+
325
+ Target :: Expression | Target :: Statement | Target :: Arm => {
326
+ self . tcx . struct_span_lint_hir ( UNUSED_ATTRIBUTES , hir_id, attr. span , |lint| {
327
+ lint. build ( "`#[no_coverage]` can only be applied at the function level, not on code directly" ) . emit ( ) ;
328
+ } ) ;
329
+ true
330
+ }
331
+
332
+ _ => {
333
+ struct_span_err ! (
334
+ self . tcx. sess,
335
+ attr. span,
336
+ E0788 ,
337
+ "`#[no_coverage]` must be applied to coverable code" ,
338
+ )
339
+ . span_label ( span, "not coverable code" )
340
+ . emit ( ) ;
341
+ false
342
+ }
343
+ }
344
+ }
345
+
295
346
fn check_generic_attr (
296
347
& self ,
297
348
hir_id : HirId ,
0 commit comments