for attr in attrs {
let attr_is_valid = match attr.name_or_empty() {
sym::inline => self.check_inline(hir_id, attr, span, target),
+ sym::no_coverage => self.check_no_coverage(hir_id, attr, span, target),
sym::non_exhaustive => self.check_non_exhaustive(hir_id, attr, span, target),
sym::marker => self.check_marker(hir_id, attr, span, target),
sym::rustc_must_implement_one_of => {
}
}
+ /// Checks if a `#[no_coverage]` is applied directly to a function
+ fn check_no_coverage(
+ &self,
+ hir_id: HirId,
+ attr: &Attribute,
+ span: Span,
+ target: Target,
+ ) -> bool {
+ match target {
+ // no_coverage on function is fine
+ Target::Fn
+ | Target::Closure
+ | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
+
+ // function prototypes can't be covered
+ Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
+ self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+ lint.build("`#[no_coverage]` is ignored on function prototypes").emit();
+ });
+ true
+ }
+
+ Target::Mod | Target::ForeignMod | Target::Impl | Target::Trait => {
+ self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+ lint.build("`#[no_coverage]` does not propagate into items and must be applied to the contained functions directly").emit();
+ });
+ true
+ }
+
+ Target::Expression | Target::Statement | Target::Arm => {
+ self.tcx.struct_span_lint_hir(UNUSED_ATTRIBUTES, hir_id, attr.span, |lint| {
+ lint.build("`#[no_coverage]` may only be applied to function definitions")
+ .emit();
+ });
+ true
+ }
+
+ _ => {
+ struct_span_err!(
+ self.tcx.sess,
+ attr.span,
+ E0788,
+ "`#[no_coverage]` must be applied to coverable code",
+ )
+ .span_label(span, "not coverable code")
+ .emit();
+ false
+ }
+ }
+ }
+
fn check_generic_attr(
&self,
hir_id: HirId,
let parent_hir_id = self.tcx.hir().get_parent_item(hir_id);
let containing_item = self.tcx.hir().expect_item(parent_hir_id);
- if Target::from_item(containing_item) == Target::Impl {
+ if let hir::ItemKind::Impl(hir::Impl { of_trait: Some(_), .. }) = containing_item.kind {
let meta_items = attr.meta_item_list().unwrap();
let (span, replacement_span) = if meta_items.len() == 1 {