1
Fork 0

Rollup merge of #126682 - Zalathar:coverage-attr, r=lcnr

coverage: Overhaul validation of the `#[coverage(..)]` attribute

This PR makes sweeping changes to how the (currently-unstable) coverage attribute is validated:
- Multiple coverage attributes on the same item/expression are now treated as an error.
- The attribute must always be `#[coverage(off)]` or `#[coverage(on)]`, and the error messages for this are more consistent.
  -  A trailing comma is still allowed after off/on, since that's part of the normal attribute syntax.
- Some places that silently ignored a coverage attribute now produce an error instead.
  - These cases were all clearly bugs.
- Some places that ignored a coverage attribute (with a warning) now produce an error instead.
  - These were originally added as lints, but I don't think it makes much sense to knowingly allow new attributes to be used in meaningless places.
  - Some of these errors might soon disappear, if it's easy to extend recursive coverage attributes to things like modules and impl blocks.

---

One of the goals of this PR is to lay a more solid foundation for making the coverage attribute recursive, so that it applies to all nested functions/closures instead of just the one it is directly attached to.

Fixes #126658.

This PR incorporates #126659, which adds more tests for validation of the coverage attribute.

`@rustbot` label +A-code-coverage
This commit is contained in:
Michael Goulet 2024-06-24 15:51:03 -04:00 committed by GitHub
commit 9ce2a070b3
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 706 additions and 377 deletions

View file

@ -4,8 +4,10 @@ use crate::{errors, parse_in};
use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::DelimSpan;
use rustc_ast::MetaItemKind;
use rustc_ast::{self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, Safety};
use rustc_ast::{
self as ast, AttrArgs, AttrArgsEq, Attribute, DelimArgs, MetaItem, MetaItemKind,
NestedMetaItem, Safety,
};
use rustc_errors::{Applicability, FatalError, PResult};
use rustc_feature::{
AttributeSafety, AttributeTemplate, BuiltinAttribute, Features, BUILTIN_ATTRIBUTE_MAP,
@ -184,9 +186,13 @@ pub(super) fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim
/// Checks that the given meta-item is compatible with this `AttributeTemplate`.
fn is_attr_template_compatible(template: &AttributeTemplate, meta: &ast::MetaItemKind) -> bool {
let is_one_allowed_subword = |items: &[NestedMetaItem]| match items {
[item] => item.is_word() && template.one_of.iter().any(|&word| item.has_name(word)),
_ => false,
};
match meta {
MetaItemKind::Word => template.word,
MetaItemKind::List(..) => template.list.is_some(),
MetaItemKind::List(items) => template.list.is_some() || is_one_allowed_subword(items),
MetaItemKind::NameValue(lit) if lit.kind.is_str() => template.name_value_str.is_some(),
MetaItemKind::NameValue(..) => false,
}
@ -230,6 +236,7 @@ fn emit_malformed_attribute(
if let Some(descr) = template.list {
suggestions.push(format!("#{inner}[{name}({descr})]"));
}
suggestions.extend(template.one_of.iter().map(|&word| format!("#{inner}[{name}({word})]")));
if let Some(descr) = template.name_value_str {
suggestions.push(format!("#{inner}[{name} = \"{descr}\"]"));
}