Rollup merge of #152425 - Ozzy1423:test-runner, r=JonathanBrouwer
Port #![test_runner] to the attribute parser Tracking issue: https://github.com/rust-lang/rust/issues/131229 r? @JonathanBrouwer
This commit is contained in:
commit
9cbcd11ae4
9 changed files with 63 additions and 35 deletions
|
|
@ -228,3 +228,32 @@ impl<S: Stage> NoArgsAttributeParser<S> for RustcOutlivesParser {
|
|||
]);
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOutlives;
|
||||
}
|
||||
|
||||
pub(crate) struct TestRunnerParser;
|
||||
|
||||
impl<S: Stage> SingleAttributeParser<S> for TestRunnerParser {
|
||||
const PATH: &[Symbol] = &[sym::test_runner];
|
||||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const TEMPLATE: AttributeTemplate = template!(List: &["path"]);
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
|
||||
let Some(list) = args.list() else {
|
||||
cx.expected_list(cx.attr_span, args);
|
||||
return None;
|
||||
};
|
||||
|
||||
let Some(single) = list.single() else {
|
||||
cx.expected_single_argument(list.span);
|
||||
return None;
|
||||
};
|
||||
|
||||
let Some(meta) = single.meta_item() else {
|
||||
cx.unexpected_literal(single.span());
|
||||
return None;
|
||||
};
|
||||
|
||||
Some(AttributeKind::TestRunner(meta.path().0.clone()))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -218,6 +218,7 @@ attribute_parsers!(
|
|||
Single<SanitizeParser>,
|
||||
Single<ShouldPanicParser>,
|
||||
Single<SkipDuringMethodDispatchParser>,
|
||||
Single<TestRunnerParser>,
|
||||
Single<TransparencyParser>,
|
||||
Single<TypeLengthLimitParser>,
|
||||
Single<WindowsSubsystemParser>,
|
||||
|
|
|
|||
|
|
@ -1002,20 +1002,6 @@ pub(crate) struct AsmUnsupportedClobberAbi {
|
|||
pub(crate) macro_name: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("`test_runner` argument must be a path")]
|
||||
pub(crate) struct TestRunnerInvalid {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("`#![test_runner(..)]` accepts exactly 1 argument")]
|
||||
pub(crate) struct TestRunnerNargs {
|
||||
#[primary_span]
|
||||
pub(crate) span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("expected token: `,`")]
|
||||
pub(crate) struct ExpectedCommaInList {
|
||||
|
|
|
|||
|
|
@ -8,10 +8,11 @@ use rustc_ast::entry::EntryPointType;
|
|||
use rustc_ast::mut_visit::*;
|
||||
use rustc_ast::visit::Visitor;
|
||||
use rustc_ast::{ModKind, attr};
|
||||
use rustc_errors::DiagCtxtHandle;
|
||||
use rustc_attr_parsing::AttributeParser;
|
||||
use rustc_expand::base::{ExtCtxt, ResolverExpand};
|
||||
use rustc_expand::expand::{AstFragment, ExpansionConfig};
|
||||
use rustc_feature::Features;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::builtin::UNNAMEABLE_TEST_ITEMS;
|
||||
use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency};
|
||||
|
|
@ -60,7 +61,7 @@ pub fn inject(
|
|||
|
||||
// Do this here so that the test_runner crate attribute gets marked as used
|
||||
// even in non-test builds
|
||||
let test_runner = get_test_runner(dcx, krate);
|
||||
let test_runner = get_test_runner(sess, features, krate);
|
||||
|
||||
if sess.is_test_crate() {
|
||||
let panic_strategy = match (panic_strategy, sess.opts.unstable_opts.panic_abort_tests) {
|
||||
|
|
@ -386,20 +387,16 @@ fn get_test_name(i: &ast::Item) -> Option<Symbol> {
|
|||
attr::first_attr_value_str_by_name(&i.attrs, sym::rustc_test_marker)
|
||||
}
|
||||
|
||||
fn get_test_runner(dcx: DiagCtxtHandle<'_>, krate: &ast::Crate) -> Option<ast::Path> {
|
||||
let test_attr = attr::find_by_name(&krate.attrs, sym::test_runner)?;
|
||||
let meta_list = test_attr.meta_item_list()?;
|
||||
let span = test_attr.span;
|
||||
match &*meta_list {
|
||||
[single] => match single.meta_item() {
|
||||
Some(meta_item) if meta_item.is_word() => return Some(meta_item.path.clone()),
|
||||
_ => {
|
||||
dcx.emit_err(errors::TestRunnerInvalid { span });
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
dcx.emit_err(errors::TestRunnerNargs { span });
|
||||
}
|
||||
fn get_test_runner(sess: &Session, features: &Features, krate: &ast::Crate) -> Option<ast::Path> {
|
||||
match AttributeParser::parse_limited(
|
||||
sess,
|
||||
&krate.attrs,
|
||||
sym::test_runner,
|
||||
krate.spans.inner_span,
|
||||
krate.id,
|
||||
Some(features),
|
||||
) {
|
||||
Some(rustc_hir::Attribute::Parsed(AttributeKind::TestRunner(path))) => Some(path),
|
||||
_ => None,
|
||||
}
|
||||
None
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ pub use ReprAttr::*;
|
|||
use rustc_abi::Align;
|
||||
pub use rustc_ast::attr::data_structures::*;
|
||||
use rustc_ast::token::DocFragmentKind;
|
||||
use rustc_ast::{AttrStyle, ast};
|
||||
use rustc_ast::{AttrStyle, Path, ast};
|
||||
use rustc_data_structures::fx::FxIndexMap;
|
||||
use rustc_error_messages::{DiagArgValue, IntoDiagArg};
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
|
||||
|
|
@ -1367,6 +1367,9 @@ pub enum AttributeKind {
|
|||
/// `#[unsafe(force_target_feature(enable = "...")]`.
|
||||
TargetFeature { features: ThinVec<(Symbol, Span)>, attr_span: Span, was_forced: bool },
|
||||
|
||||
/// Represents `#![test_runner(path)]`
|
||||
TestRunner(Path),
|
||||
|
||||
/// Represents `#[thread_local]`
|
||||
ThreadLocal,
|
||||
|
||||
|
|
|
|||
|
|
@ -176,6 +176,7 @@ impl AttributeKind {
|
|||
ShouldPanic { .. } => No,
|
||||
Stability { .. } => Yes,
|
||||
TargetFeature { .. } => No,
|
||||
TestRunner(..) => Yes,
|
||||
ThreadLocal => No,
|
||||
TrackCaller(..) => Yes,
|
||||
TypeLengthLimit { .. } => No,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ use std::ops::Deref;
|
|||
use std::path::PathBuf;
|
||||
|
||||
use rustc_abi::Align;
|
||||
use rustc_ast::ast::{Path, join_path_idents};
|
||||
use rustc_ast::attr::data_structures::CfgEntry;
|
||||
use rustc_ast::attr::version::RustcVersion;
|
||||
use rustc_ast::token::{CommentKind, DocFragmentKind};
|
||||
|
|
@ -106,6 +107,16 @@ impl PrintAttribute for PathBuf {
|
|||
p.word(self.display().to_string());
|
||||
}
|
||||
}
|
||||
impl PrintAttribute for Path {
|
||||
fn should_render(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn print_attribute(&self, p: &mut Printer) {
|
||||
p.word(join_path_idents(self.segments.iter().map(|seg| seg.ident)));
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! print_skip {
|
||||
($($t: ty),* $(,)?) => {$(
|
||||
impl PrintAttribute for $t {
|
||||
|
|
|
|||
|
|
@ -364,6 +364,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| AttributeKind::RustcVariance
|
||||
| AttributeKind::RustcVarianceOfOpaques
|
||||
| AttributeKind::ShouldPanic { .. }
|
||||
| AttributeKind::TestRunner(..)
|
||||
| AttributeKind::ThreadLocal
|
||||
| AttributeKind::TypeLengthLimit { .. }
|
||||
| AttributeKind::UnstableFeatureBound(..)
|
||||
|
|
@ -411,9 +412,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
| sym::rustc_mir
|
||||
// crate-level attrs, are checked below
|
||||
| sym::feature
|
||||
| sym::register_tool
|
||||
| sym::test_runner,
|
||||
..
|
||||
| sym::register_tool, ..
|
||||
] => {}
|
||||
[name, rest@..] => {
|
||||
match BUILTIN_ATTRIBUTE_MAP.get(name) {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
#![feature(rustc_private)]
|
||||
#![feature(test)]
|
||||
#![feature(trim_prefix_suffix)]
|
||||
#![recursion_limit = "256"]
|
||||
#![warn(rustc::internal)]
|
||||
// tidy-alphabetical-end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue