Port #[rustc_test_marker] to the attribute parser

This commit is contained in:
Oscar Bray 2026-02-13 11:18:24 +00:00
parent 3f808f29e6
commit 6ed7615608
6 changed files with 40 additions and 6 deletions

View file

@ -257,3 +257,36 @@ impl<S: Stage> SingleAttributeParser<S> for TestRunnerParser {
Some(AttributeKind::TestRunner(meta.path().0.clone()))
}
}
pub(crate) struct RustcTestMarkerParser;
impl<S: Stage> SingleAttributeParser<S> for RustcTestMarkerParser {
const PATH: &[Symbol] = &[sym::rustc_test_marker];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Const),
Allow(Target::Fn),
Allow(Target::Static),
]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "test_path");
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let Some(name_value) = args.name_value() else {
cx.expected_name_value(cx.attr_span, Some(sym::rustc_test_marker));
return None;
};
let Some(value_str) = name_value.value_as_str() else {
cx.expected_string_literal(name_value.value_span, None);
return None;
};
if value_str.as_str().trim().is_empty() {
cx.expected_non_empty_string_literal(name_value.value_span);
return None;
}
Some(AttributeKind::RustcTestMarker(value_str))
}
}

View file

@ -217,6 +217,7 @@ attribute_parsers!(
Single<RustcScalableVectorParser>,
Single<RustcSimdMonomorphizeLaneLimitParser>,
Single<RustcSymbolName>,
Single<RustcTestMarkerParser>,
Single<SanitizeParser>,
Single<ShouldPanicParser>,
Single<SkipDuringMethodDispatchParser>,

View file

@ -1336,6 +1336,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_symbol_name]`
RustcSymbolName(Span),
/// Represents `#[rustc_test_marker]`
RustcTestMarker(Symbol),
/// Represents `#[rustc_then_this_would_need]`
RustcThenThisWouldNeed(Span, ThinVec<Ident>),

View file

@ -170,6 +170,7 @@ impl AttributeKind {
RustcStdInternalSymbol(..) => No,
RustcStrictCoherence(..) => Yes,
RustcSymbolName(..) => Yes,
RustcTestMarker(..) => No,
RustcThenThisWouldNeed(..) => No,
RustcTrivialFieldReads => Yes,
RustcUnsafeSpecializationMarker(..) => No,

View file

@ -361,6 +361,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::RustcStdInternalSymbol (..)
| AttributeKind::RustcStrictCoherence(..)
| AttributeKind::RustcSymbolName(..)
| AttributeKind::RustcTestMarker(..)
| AttributeKind::RustcThenThisWouldNeed(..)
| AttributeKind::RustcTrivialFieldReads
| AttributeKind::RustcUnsafeSpecializationMarker(..)
@ -401,7 +402,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::rustc_on_unimplemented
| sym::rustc_do_not_const_check
| sym::rustc_doc_primitive
| sym::rustc_test_marker
| sym::rustc_layout
| sym::rustc_proc_macro_decls
| sym::rustc_autodiff

View file

@ -2343,11 +2343,7 @@ fn with_test_item_names(tcx: TyCtxt<'_>, module: LocalModDefId, f: impl FnOnce(&
// We could also check for the type name `test::TestDescAndFn`
&& let Res::Def(DefKind::Struct, _) = path.res
{
let has_test_marker = tcx
.hir_attrs(item.hir_id())
.iter()
.any(|a| a.has_name(sym::rustc_test_marker));
if has_test_marker {
if find_attr!(tcx.hir_attrs(item.hir_id()), AttributeKind::RustcTestMarker(..)) {
names.push(ident.name);
}
}