Skip to content

Commit 97c51aa

Browse files
committed
Auto merge of #158854 - jdonszelmann:test-entrypoint, r=<try>
Add `#[rustc_test_entrypoint_marker]` try-job: x86_64-gnu-llvm-21-3
2 parents 48c2cee + b80ee35 commit 97c51aa

10 files changed

Lines changed: 107 additions & 0 deletions

File tree

compiler/rustc_attr_parsing/src/attributes/test_attrs.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,14 @@ impl SingleAttributeParser for RustcTestMarkerParser {
214214
Some(AttributeKind::RustcTestMarker(value_str))
215215
}
216216
}
217+
218+
pub(crate) struct RustcTestEntrypointMarkerParser;
219+
220+
impl NoArgsAttributeParser for RustcTestEntrypointMarkerParser {
221+
const PATH: &[Symbol] = &[sym::rustc_test_entrypoint_marker];
222+
const ALLOWED_TARGETS: AllowedTargets<'_> =
223+
AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::Closure)]);
224+
const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;
225+
const STABILITY: AttributeStability = unstable!(rustc_attrs);
226+
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTestEntrypointMarker;
227+
}

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,7 @@ attribute_parsers!(
328328
Single<WithoutArgs<RustcSpecializationTraitParser>>,
329329
Single<WithoutArgs<RustcStdInternalSymbolParser>>,
330330
Single<WithoutArgs<RustcStrictCoherenceParser>>,
331+
Single<WithoutArgs<RustcTestEntrypointMarkerParser>>,
331332
Single<WithoutArgs<RustcTrivialFieldReadsParser>>,
332333
Single<WithoutArgs<RustcUnsafeSpecializationMarkerParser>>,
333334
Single<WithoutArgs<SplatParser>>,

compiler/rustc_builtin_macros/src/test.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ use crate::util::{check_builtin_macro_attribute, warn_on_duplicate_attribute};
2424
///
2525
/// We mark item with an inert attribute "rustc_test_marker" which the test generation
2626
/// logic will pick up on.
27+
///
28+
/// The test function also gains a `#[rustc_test_entrypoint_marker]` attribute for tools to pick up
29+
/// on. This behavior is *unstable*.
2730
pub(crate) fn expand_test_case(
2831
ecx: &mut ExtCtxt<'_>,
2932
attr_sp: Span,
@@ -377,6 +380,12 @@ pub(crate) fn expand_test_or_bench(
377380
let test_extern =
378381
cx.item(sp, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None, test_ident));
379382

383+
let item = {
384+
let mut item = item;
385+
item.attrs.push(cx.attr_word(sym::rustc_test_entrypoint_marker, attr_sp));
386+
item
387+
};
388+
380389
debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
381390

382391
if is_stmt {

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,6 +365,7 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[
365365
sym::rustc_paren_sugar,
366366
sym::rustc_inherit_overflow_checks,
367367
sym::rustc_reservation_impl,
368+
sym::rustc_test_entrypoint_marker,
368369
sym::rustc_test_marker,
369370
sym::rustc_unsafe_specialization_marker,
370371
sym::rustc_specialization_trait,

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,6 +1636,9 @@ pub enum AttributeKind {
16361636
/// Represents `#[rustc_strict_coherence]`.
16371637
RustcStrictCoherence(Span),
16381638

1639+
/// Represents `#[rustc_test_entrypoint_marker]`
1640+
RustcTestEntrypointMarker,
1641+
16391642
/// Represents `#[rustc_test_marker]`
16401643
RustcTestMarker(Symbol),
16411644

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ impl AttributeKind {
189189
RustcSpecializationTrait => No,
190190
RustcStdInternalSymbol => No,
191191
RustcStrictCoherence(..) => Yes,
192+
RustcTestEntrypointMarker => No,
192193
RustcTestMarker(..) => No,
193194
RustcThenThisWouldNeed(..) => No,
194195
RustcTrivialFieldReads => Yes,

compiler/rustc_passes/src/check_attr.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
395395
AttributeKind::RustcSpecializationTrait => (),
396396
AttributeKind::RustcStdInternalSymbol => (),
397397
AttributeKind::RustcStrictCoherence(..) => (),
398+
AttributeKind::RustcTestEntrypointMarker => (),
398399
AttributeKind::RustcTestMarker(..) => (),
399400
AttributeKind::RustcThenThisWouldNeed(..) => (),
400401
AttributeKind::RustcTrivialFieldReads => (),

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1856,6 +1856,7 @@ symbols! {
18561856
rustc_specialization_trait,
18571857
rustc_std_internal_symbol,
18581858
rustc_strict_coherence,
1859+
rustc_test_entrypoint_marker,
18591860
rustc_test_marker,
18601861
rustc_then_this_would_need,
18611862
rustc_trivial_field_reads,

tests/pretty/tests-are-sorted.pp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
testfn: test::StaticTestFn(#[coverage(off)] ||
3131
test::assert_test_result(m_test())),
3232
};
33+
#[rustc_test_entrypoint_marker]
3334
fn m_test() {}
3435

3536
extern crate test;
@@ -55,6 +56,7 @@
5556
test::assert_test_result(z_test())),
5657
};
5758
#[ignore = "not yet implemented"]
59+
#[rustc_test_entrypoint_marker]
5860
fn z_test() {}
5961

6062
extern crate test;
@@ -79,6 +81,7 @@
7981
testfn: test::StaticTestFn(#[coverage(off)] ||
8082
test::assert_test_result(a_test())),
8183
};
84+
#[rustc_test_entrypoint_marker]
8285
fn a_test() {}
8386
#[rustc_main]
8487
#[coverage(off)]
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
//@ run-pass
2+
//@ ignore-cross-compile
3+
//@ ignore-remote
4+
//@ edition: 2024
5+
//! Uses a rustc driver to check that test entrypoints get a `#[rustc_test_entrypoint_marker]`
6+
//! and can be found using that attribute in rustc drivers (the main use for this attribute).
7+
8+
#![feature(rustc_private)]
9+
10+
extern crate rustc_driver;
11+
extern crate rustc_interface;
12+
extern crate rustc_middle;
13+
#[macro_use]
14+
extern crate rustc_hir;
15+
16+
use interface::Compiler;
17+
use rustc_driver::Compilation;
18+
use rustc_interface::interface;
19+
use rustc_middle::ty::TyCtxt;
20+
use std::io::Write;
21+
22+
const CRATE_NAME: &str = "input";
23+
24+
struct TestAttr {
25+
expected_tests: usize,
26+
}
27+
28+
impl rustc_driver::Callbacks for TestAttr {
29+
fn after_analysis<'tcx>(&mut self, _compiler: &Compiler, tcx: TyCtxt<'tcx>) -> Compilation {
30+
let mut tests = Vec::new();
31+
for did in tcx.hir_crate_items(()).definitions() {
32+
if find_attr!(tcx, did, RustcTestEntrypointMarker) {
33+
tests.push(did);
34+
}
35+
}
36+
37+
// the file contains one test, so we should find one entrypoint marker.
38+
assert_eq!(tests.len(), self.expected_tests);
39+
40+
Compilation::Stop
41+
}
42+
}
43+
44+
fn count_tests(src: &str, expected_tests: usize) {
45+
let path = "test_input.rs";
46+
let mut file = std::fs::File::create(path).unwrap();
47+
file.write_all(src.as_bytes()).unwrap();
48+
49+
let args = [
50+
"rustc".to_string(),
51+
"--test".to_string(),
52+
"--crate-type=lib".to_string(),
53+
"--crate-name".to_string(),
54+
CRATE_NAME.to_string(),
55+
path.to_string(),
56+
];
57+
rustc_driver::catch_fatal_errors(|| -> interface::Result<()> {
58+
rustc_driver::run_compiler(&args, &mut TestAttr { expected_tests });
59+
Ok(())
60+
})
61+
.unwrap()
62+
.unwrap();
63+
}
64+
65+
fn main() {
66+
count_tests(
67+
r#"
68+
#[test]
69+
fn one() {{ }}
70+
71+
#[test]
72+
fn two() {{ }}
73+
"#,
74+
2,
75+
);
76+
}

0 commit comments

Comments
 (0)