Skip to content

Commit 0593dc7

Browse files
committed
Move #[test_case] to a syntax extension
1 parent e5ed105 commit 0593dc7

File tree

15 files changed

+108
-82
lines changed

15 files changed

+108
-82
lines changed

src/librustc_driver/driver.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,6 @@ where
828828
let (mut krate, features) = syntax::config::features(
829829
krate,
830830
&sess.parse_sess,
831-
sess.opts.test,
832831
sess.edition(),
833832
);
834833
// these need to be set "early" so that expansion sees `quote` if enabled.

src/librustc_lint/builtin.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1872,7 +1872,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems {
18721872
return;
18731873
}
18741874

1875-
if let Some(attr) = attr::find_by_name(&it.attrs, "test_case") {
1875+
if let Some(attr) = attr::find_by_name(&it.attrs, "rustc_test_marker") {
18761876
cx.struct_span_lint(
18771877
UNNAMEABLE_TEST_ITEMS,
18781878
attr.span,

src/librustc_resolve/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,7 @@ impl<'a, 'cl> Resolver<'a, 'cl> {
479479
return def;
480480
}
481481

482-
if kind == MacroKind::Attr && path.len() == 1 {
482+
if kind == MacroKind::Attr {
483483
if let Some(ext) = self.unshadowable_attrs.get(&path[0].name) {
484484
return Ok(ext.def());
485485
}

src/libsyntax/config.rs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,18 +21,16 @@ use ptr::P;
2121

2222
/// A folder that strips out items that do not belong in the current configuration.
2323
pub struct StripUnconfigured<'a> {
24-
pub should_test: bool,
2524
pub sess: &'a ParseSess,
2625
pub features: Option<&'a Features>,
2726
}
2827

2928
// `cfg_attr`-process the crate's attributes and compute the crate's features.
30-
pub fn features(mut krate: ast::Crate, sess: &ParseSess, should_test: bool, edition: Edition)
29+
pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition)
3130
-> (ast::Crate, Features) {
3231
let features;
3332
{
3433
let mut strip_unconfigured = StripUnconfigured {
35-
should_test,
3634
sess,
3735
features: None,
3836
};
@@ -118,11 +116,6 @@ impl<'a> StripUnconfigured<'a> {
118116
// Determine if a node with the given attributes should be included in this configuration.
119117
pub fn in_cfg(&mut self, attrs: &[ast::Attribute]) -> bool {
120118
attrs.iter().all(|attr| {
121-
// When not compiling with --test we should not compile the #[test] functions
122-
if !self.should_test && is_test(attr) {
123-
return false;
124-
}
125-
126119
let mis = if !is_cfg(attr) {
127120
return true;
128121
} else if let Some(mis) = attr.meta_item_list() {
@@ -249,7 +242,7 @@ impl<'a> StripUnconfigured<'a> {
249242
//
250243
// NB: This is intentionally not part of the fold_expr() function
251244
// in order for fold_opt_expr() to be able to avoid this check
252-
if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a) || is_test(a)) {
245+
if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) {
253246
let msg = "removing an expression is not supported in this position";
254247
self.sess.span_diagnostic.span_err(attr.span, msg);
255248
}
@@ -352,7 +345,3 @@ impl<'a> fold::Folder for StripUnconfigured<'a> {
352345
fn is_cfg(attr: &ast::Attribute) -> bool {
353346
attr.check_name("cfg")
354347
}
355-
356-
pub fn is_test(att: &ast::Attribute) -> bool {
357-
att.check_name("test_case")
358-
}

src/libsyntax/ext/expand.rs

Lines changed: 5 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -450,14 +450,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
450450
let (fragment_with_placeholders, invocations) = {
451451
let mut collector = InvocationCollector {
452452
cfg: StripUnconfigured {
453-
should_test: self.cx.ecfg.should_test,
454453
sess: self.cx.parse_sess,
455454
features: self.cx.ecfg.features,
456455
},
457456
cx: self.cx,
458457
invocations: Vec::new(),
459458
monotonic: self.monotonic,
460-
tests_nameable: true,
461459
};
462460
(fragment.fold_with(&mut collector), collector.invocations)
463461
};
@@ -475,7 +473,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
475473

476474
fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
477475
let mut cfg = StripUnconfigured {
478-
should_test: self.cx.ecfg.should_test,
479476
sess: self.cx.parse_sess,
480477
features: self.cx.ecfg.features,
481478
};
@@ -1047,11 +1044,6 @@ struct InvocationCollector<'a, 'b: 'a> {
10471044
cfg: StripUnconfigured<'a>,
10481045
invocations: Vec<Invocation>,
10491046
monotonic: bool,
1050-
1051-
/// Test functions need to be nameable. Tests inside functions or in other
1052-
/// unnameable locations need to be ignored. `tests_nameable` tracks whether
1053-
/// any test functions found in the current context would be nameable.
1054-
tests_nameable: bool,
10551047
}
10561048

10571049
impl<'a, 'b> InvocationCollector<'a, 'b> {
@@ -1069,20 +1061,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10691061
placeholder(fragment_kind, NodeId::placeholder_from_mark(mark))
10701062
}
10711063

1072-
/// Folds the item allowing tests to be expanded because they are still nameable.
1073-
/// This should probably only be called with module items
1074-
fn fold_nameable(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
1075-
fold::noop_fold_item(item, self)
1076-
}
1077-
1078-
/// Folds the item but doesn't allow tests to occur within it
1079-
fn fold_unnameable(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
1080-
let was_nameable = mem::replace(&mut self.tests_nameable, false);
1081-
let items = fold::noop_fold_item(item, self);
1082-
self.tests_nameable = was_nameable;
1083-
items
1084-
}
1085-
10861064
fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
10871065
self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
10881066
}
@@ -1297,7 +1275,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
12971275
fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
12981276
let item = configure!(self, item);
12991277

1300-
let (attr, traits, mut item) = self.classify_item(item);
1278+
let (attr, traits, item) = self.classify_item(item);
13011279
if attr.is_some() || !traits.is_empty() {
13021280
let item = Annotatable::Item(item);
13031281
return self.collect_attr(attr, traits, item, AstFragmentKind::Items).make_items();
@@ -1319,7 +1297,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13191297
}
13201298
ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
13211299
if item.ident == keywords::Invalid.ident() {
1322-
return self.fold_nameable(item);
1300+
return noop_fold_item(item, self);
13231301
}
13241302

13251303
let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
@@ -1359,32 +1337,13 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13591337

13601338
let orig_module =
13611339
mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
1362-
let result = self.fold_nameable(item);
1340+
let result = noop_fold_item(item, self);
13631341
self.cx.current_expansion.module = orig_module;
13641342
self.cx.current_expansion.directory_ownership = orig_directory_ownership;
13651343
result
13661344
}
13671345

1368-
// Ensure that test items can be exported by the harness generator.
1369-
// #[test] fn foo() {}
1370-
// becomes:
1371-
// #[test] pub fn foo_gensym(){}
1372-
ast::ItemKind::Const(..)
1373-
| ast::ItemKind::Static(..)
1374-
| ast::ItemKind::Fn(..) if self.cx.ecfg.should_test => {
1375-
if self.tests_nameable && attr::contains_name(&item.attrs, "test_case") {
1376-
// Publicize the item under gensymed name to avoid pollution
1377-
// This means #[test_case] items can't be referenced by user code
1378-
item = item.map(|mut item| {
1379-
item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
1380-
item.ident = item.ident.gensym();
1381-
item
1382-
});
1383-
}
1384-
1385-
self.fold_unnameable(item)
1386-
}
1387-
_ => self.fold_unnameable(item),
1346+
_ => noop_fold_item(item, self),
13881347
}
13891348
}
13901349

@@ -1609,6 +1568,7 @@ impl<'feat> ExpansionConfig<'feat> {
16091568
feature_tests! {
16101569
fn enable_quotes = quote,
16111570
fn enable_asm = asm,
1571+
fn enable_custom_test_frameworks = custom_test_frameworks,
16121572
fn enable_global_asm = global_asm,
16131573
fn enable_log_syntax = log_syntax,
16141574
fn enable_concat_idents = concat_idents,

src/libsyntax/feature_gate.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -777,10 +777,6 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
777777
("no_link", Normal, Ungated),
778778
("derive", Normal, Ungated),
779779
("should_panic", Normal, Ungated),
780-
("test_case", Normal, Gated(Stability::Unstable,
781-
"custom_test_frameworks",
782-
"Custom test frameworks are experimental",
783-
cfg_fn!(custom_test_frameworks))),
784780
("ignore", Normal, Ungated),
785781
("no_implicit_prelude", Normal, Ungated),
786782
("reexport_test_harness_main", Normal, Ungated),
@@ -965,6 +961,11 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
965961
attribute is just used for rustc unit \
966962
tests and will never be stable",
967963
cfg_fn!(rustc_attrs))),
964+
("rustc_test_marker", Normal, Gated(Stability::Unstable,
965+
"rustc_attrs",
966+
"the `#[rustc_test_marker]` attribute \
967+
is used internally to track tests",
968+
cfg_fn!(rustc_attrs))),
968969

969970
// RFC #2094
970971
("nll", Whitelisted, Gated(Stability::Unstable,
@@ -1164,7 +1165,7 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
11641165
("type_length_limit", CrateLevel, Ungated),
11651166
("test_runner", CrateLevel, Gated(Stability::Unstable,
11661167
"custom_test_frameworks",
1167-
"Custom Test Frameworks is an unstable feature",
1168+
EXPLAIN_CUSTOM_TEST_FRAMEWORKS,
11681169
cfg_fn!(custom_test_frameworks))),
11691170
];
11701171

@@ -1382,6 +1383,9 @@ pub const EXPLAIN_ASM: &'static str =
13821383
pub const EXPLAIN_GLOBAL_ASM: &'static str =
13831384
"`global_asm!` is not stable enough for use and is subject to change";
13841385

1386+
pub const EXPLAIN_CUSTOM_TEST_FRAMEWORKS: &'static str =
1387+
"custom test frameworks are an unstable feature";
1388+
13851389
pub const EXPLAIN_LOG_SYNTAX: &'static str =
13861390
"`log_syntax!` is not stable enough for use and is subject to change";
13871391

src/libsyntax/parse/parser.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6272,7 +6272,6 @@ impl<'a> Parser<'a> {
62726272
let (in_cfg, outer_attrs) = {
62736273
let mut strip_unconfigured = ::config::StripUnconfigured {
62746274
sess: self.sess,
6275-
should_test: false, // irrelevant
62766275
features: None, // don't perform gated feature checking
62776276
};
62786277
let outer_attrs = strip_unconfigured.process_cfg_attrs(outer_attrs.to_owned());

src/libsyntax/test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ fn visible_path(cx: &TestCtxt, path: &[Ident]) -> Vec<Ident>{
433433
}
434434

435435
fn is_test_case(i: &ast::Item) -> bool {
436-
attr::contains_name(&i.attrs, "test_case")
436+
attr::contains_name(&i.attrs, "rustc_test_marker")
437437
}
438438

439439
fn get_test_runner(sd: &errors::Handler, krate: &ast::Crate) -> Option<ast::Path> {

src/libsyntax_ext/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ mod global_asm;
5454
mod log_syntax;
5555
mod trace_macros;
5656
mod test;
57+
mod test_case;
5758

5859
pub mod proc_macro_registrar;
5960

@@ -145,6 +146,7 @@ pub fn register_builtins(resolver: &mut dyn syntax::ext::base::Resolver,
145146
assert: assert::expand_assert,
146147
}
147148

149+
register(Symbol::intern("test_case"), MultiModifier(Box::new(test_case::expand)));
148150

149151
// format_args uses `unstable` things internally.
150152
register(Symbol::intern("format_args"),

src/libsyntax_ext/test.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,14 @@ pub fn expand_test_or_bench(
135135
};
136136

137137
let mut test_const = cx.item(sp, item.ident.gensym(),
138-
// #[test_case]
139-
vec![cx.attribute(attr_sp, cx.meta_word(attr_sp, Symbol::intern("test_case")))],
138+
vec![
139+
// #[cfg(test)]
140+
cx.attribute(attr_sp, cx.meta_list(attr_sp, Symbol::intern("cfg"), vec![
141+
cx.meta_list_item_word(attr_sp, Symbol::intern("test"))
142+
])),
143+
// #[rustc_test_marker]
144+
cx.attribute(attr_sp, cx.meta_word(attr_sp, Symbol::intern("rustc_test_marker")))
145+
],
140146
// const $ident: test::TestDescAndFn =
141147
ast::ItemKind::Const(cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
142148
// test::TestDescAndFn {

0 commit comments

Comments
 (0)