Skip to content

Commit 8994c6d

Browse files
committed
expansion: Remove restriction on use of macro attributes with test/bench
The restrictions were introduced in rust-lang#54277 and no longer necessary now because legacy plugins are now expanded in usual left-to-right order
1 parent 60a1d4e commit 8994c6d

File tree

7 files changed

+44
-114
lines changed

7 files changed

+44
-114
lines changed

src/librustc_resolve/macros.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use syntax::attr;
2424
use syntax::errors::DiagnosticBuilder;
2525
use syntax::ext::base::{self, Determinacy};
2626
use syntax::ext::base::{MacroKind, SyntaxExtension, Resolver as SyntaxResolver};
27-
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind, TogetherWith};
27+
use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
2828
use syntax::ext::hygiene::{self, Mark};
2929
use syntax::ext::tt::macro_rules;
3030
use syntax::feature_gate::{self, feature_err, emit_feature_err, is_builtin_attr_name, GateIssue};
@@ -313,29 +313,24 @@ impl<'a, 'crateloader: 'a> base::Resolver for Resolver<'a, 'crateloader> {
313313

314314
fn resolve_macro_invocation(&mut self, invoc: &Invocation, invoc_id: Mark, force: bool)
315315
-> Result<Option<Lrc<SyntaxExtension>>, Determinacy> {
316-
let (path, kind, derives_in_scope, together_with) = match invoc.kind {
316+
let (path, kind, derives_in_scope, after_derive) = match invoc.kind {
317317
InvocationKind::Attr { attr: None, .. } =>
318318
return Ok(None),
319-
InvocationKind::Attr { attr: Some(ref attr), ref traits, together_with, .. } =>
320-
(&attr.path, MacroKind::Attr, traits.clone(), together_with),
319+
InvocationKind::Attr { attr: Some(ref attr), ref traits, after_derive, .. } =>
320+
(&attr.path, MacroKind::Attr, traits.clone(), after_derive),
321321
InvocationKind::Bang { ref mac, .. } =>
322-
(&mac.node.path, MacroKind::Bang, Vec::new(), TogetherWith::None),
322+
(&mac.node.path, MacroKind::Bang, Vec::new(), false),
323323
InvocationKind::Derive { ref path, .. } =>
324-
(path, MacroKind::Derive, Vec::new(), TogetherWith::None),
324+
(path, MacroKind::Derive, Vec::new(), false),
325325
};
326326

327327
let parent_scope = self.invoc_parent_scope(invoc_id, derives_in_scope);
328328
let (def, ext) = self.resolve_macro_to_def(path, kind, &parent_scope, force)?;
329329

330330
if let Def::Macro(def_id, _) = def {
331-
match together_with {
332-
TogetherWith::Derive =>
333-
self.session.span_err(invoc.span(),
334-
"macro attributes must be placed before `#[derive]`"),
335-
TogetherWith::TestBench if !self.session.features_untracked().plugin =>
336-
self.session.span_err(invoc.span(),
337-
"macro attributes cannot be used together with `#[test]` or `#[bench]`"),
338-
_ => {}
331+
if after_derive {
332+
self.session.span_err(invoc.span(),
333+
"macro attributes must be placed before `#[derive]`");
339334
}
340335
self.macro_defs.insert(invoc.expansion_data.mark, def_id);
341336
let normal_module_def_id =

src/libsyntax/ext/expand.rs

+30-43
Original file line numberDiff line numberDiff line change
@@ -220,14 +220,6 @@ pub struct Invocation {
220220
pub expansion_data: ExpansionData,
221221
}
222222

223-
// Needed for feature-gating attributes used after derives or together with test/bench
224-
#[derive(Clone, Copy, PartialEq)]
225-
pub enum TogetherWith {
226-
None,
227-
Derive,
228-
TestBench,
229-
}
230-
231223
pub enum InvocationKind {
232224
Bang {
233225
mac: ast::Mac,
@@ -238,7 +230,8 @@ pub enum InvocationKind {
238230
attr: Option<ast::Attribute>,
239231
traits: Vec<Path>,
240232
item: Annotatable,
241-
together_with: TogetherWith,
233+
// We temporarily report errors for attribute macros placed after derives
234+
after_derive: bool,
242235
},
243236
Derive {
244237
path: Path,
@@ -1084,19 +1077,17 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10841077
traits: Vec<Path>,
10851078
item: Annotatable,
10861079
kind: AstFragmentKind,
1087-
together_with: TogetherWith)
1080+
after_derive: bool)
10881081
-> AstFragment {
1089-
self.collect(kind, InvocationKind::Attr { attr, traits, item, together_with })
1082+
self.collect(kind, InvocationKind::Attr { attr, traits, item, after_derive })
10901083
}
10911084

1092-
fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, together_with: &mut TogetherWith)
1085+
fn find_attr_invoc(&self, attrs: &mut Vec<ast::Attribute>, after_derive: &mut bool)
10931086
-> Option<ast::Attribute> {
10941087
let attr = attrs.iter()
10951088
.position(|a| {
10961089
if a.path == "derive" {
1097-
*together_with = TogetherWith::Derive
1098-
} else if a.path == "rustc_test_marker2" {
1099-
*together_with = TogetherWith::TestBench
1090+
*after_derive = true;
11001091
}
11011092
!attr::is_known(a) && !is_builtin_attr(a)
11021093
})
@@ -1109,19 +1100,15 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
11091100
"non-builtin inner attributes are unstable");
11101101
}
11111102
}
1112-
if together_with == &TogetherWith::None &&
1113-
attrs.iter().any(|a| a.path == "rustc_test_marker2") {
1114-
*together_with = TogetherWith::TestBench;
1115-
}
11161103
attr
11171104
}
11181105

11191106
/// If `item` is an attr invocation, remove and return the macro attribute and derive traits.
11201107
fn classify_item<T>(&mut self, mut item: T)
1121-
-> (Option<ast::Attribute>, Vec<Path>, T, TogetherWith)
1108+
-> (Option<ast::Attribute>, Vec<Path>, T, /* after_derive */ bool)
11221109
where T: HasAttrs,
11231110
{
1124-
let (mut attr, mut traits, mut together_with) = (None, Vec::new(), TogetherWith::None);
1111+
let (mut attr, mut traits, mut after_derive) = (None, Vec::new(), false);
11251112

11261113
item = item.map_attrs(|mut attrs| {
11271114
if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
@@ -1130,20 +1117,20 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
11301117
return attrs;
11311118
}
11321119

1133-
attr = self.find_attr_invoc(&mut attrs, &mut together_with);
1120+
attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
11341121
traits = collect_derives(&mut self.cx, &mut attrs);
11351122
attrs
11361123
});
11371124

1138-
(attr, traits, item, together_with)
1125+
(attr, traits, item, after_derive)
11391126
}
11401127

11411128
/// Alternative of `classify_item()` that ignores `#[derive]` so invocations fallthrough
11421129
/// to the unused-attributes lint (making it an error on statements and expressions
11431130
/// is a breaking change)
11441131
fn classify_nonitem<T: HasAttrs>(&mut self, mut item: T)
1145-
-> (Option<ast::Attribute>, T, TogetherWith) {
1146-
let (mut attr, mut together_with) = (None, TogetherWith::None);
1132+
-> (Option<ast::Attribute>, T, /* after_derive */ bool) {
1133+
let (mut attr, mut after_derive) = (None, false);
11471134

11481135
item = item.map_attrs(|mut attrs| {
11491136
if let Some(legacy_attr_invoc) = self.cx.resolver.find_legacy_attr_invoc(&mut attrs,
@@ -1152,11 +1139,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
11521139
return attrs;
11531140
}
11541141

1155-
attr = self.find_attr_invoc(&mut attrs, &mut together_with);
1142+
attr = self.find_attr_invoc(&mut attrs, &mut after_derive);
11561143
attrs
11571144
});
11581145

1159-
(attr, item, together_with)
1146+
(attr, item, after_derive)
11601147
}
11611148

11621149
fn configure<T: HasAttrs>(&mut self, node: T) -> Option<T> {
@@ -1195,7 +1182,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
11951182
expr.node = self.cfg.configure_expr_kind(expr.node);
11961183

11971184
// ignore derives so they remain unused
1198-
let (attr, expr, together_with) = self.classify_nonitem(expr);
1185+
let (attr, expr, after_derive) = self.classify_nonitem(expr);
11991186

12001187
if attr.is_some() {
12011188
// collect the invoc regardless of whether or not attributes are permitted here
@@ -1204,7 +1191,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
12041191

12051192
// AstFragmentKind::Expr requires the macro to emit an expression
12061193
return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
1207-
AstFragmentKind::Expr, together_with).make_expr();
1194+
AstFragmentKind::Expr, after_derive).make_expr();
12081195
}
12091196

12101197
if let ast::ExprKind::Mac(mac) = expr.node {
@@ -1220,13 +1207,13 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
12201207
expr.node = self.cfg.configure_expr_kind(expr.node);
12211208

12221209
// ignore derives so they remain unused
1223-
let (attr, expr, together_with) = self.classify_nonitem(expr);
1210+
let (attr, expr, after_derive) = self.classify_nonitem(expr);
12241211

12251212
if attr.is_some() {
12261213
attr.as_ref().map(|a| self.cfg.maybe_emit_expr_attr_err(a));
12271214

12281215
return self.collect_attr(attr, vec![], Annotatable::Expr(P(expr)),
1229-
AstFragmentKind::OptExpr, together_with).make_opt_expr();
1216+
AstFragmentKind::OptExpr, after_derive).make_opt_expr();
12301217
}
12311218

12321219
if let ast::ExprKind::Mac(mac) = expr.node {
@@ -1258,18 +1245,18 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
12581245

12591246
// we'll expand attributes on expressions separately
12601247
if !stmt.is_expr() {
1261-
let (attr, derives, stmt_, together_with) = if stmt.is_item() {
1248+
let (attr, derives, stmt_, after_derive) = if stmt.is_item() {
12621249
self.classify_item(stmt)
12631250
} else {
12641251
// ignore derives on non-item statements so it falls through
12651252
// to the unused-attributes lint
1266-
let (attr, stmt, together_with) = self.classify_nonitem(stmt);
1267-
(attr, vec![], stmt, together_with)
1253+
let (attr, stmt, after_derive) = self.classify_nonitem(stmt);
1254+
(attr, vec![], stmt, after_derive)
12681255
};
12691256

12701257
if attr.is_some() || !derives.is_empty() {
12711258
return self.collect_attr(attr, derives, Annotatable::Stmt(P(stmt_)),
1272-
AstFragmentKind::Stmts, together_with).make_stmts();
1259+
AstFragmentKind::Stmts, after_derive).make_stmts();
12731260
}
12741261

12751262
stmt = stmt_;
@@ -1311,10 +1298,10 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13111298
fn fold_item(&mut self, item: P<ast::Item>) -> SmallVec<[P<ast::Item>; 1]> {
13121299
let item = configure!(self, item);
13131300

1314-
let (attr, traits, item, together_with) = self.classify_item(item);
1301+
let (attr, traits, item, after_derive) = self.classify_item(item);
13151302
if attr.is_some() || !traits.is_empty() {
13161303
return self.collect_attr(attr, traits, Annotatable::Item(item),
1317-
AstFragmentKind::Items, together_with).make_items();
1304+
AstFragmentKind::Items, after_derive).make_items();
13181305
}
13191306

13201307
match item.node {
@@ -1386,10 +1373,10 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
13861373
fn fold_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> {
13871374
let item = configure!(self, item);
13881375

1389-
let (attr, traits, item, together_with) = self.classify_item(item);
1376+
let (attr, traits, item, after_derive) = self.classify_item(item);
13901377
if attr.is_some() || !traits.is_empty() {
13911378
return self.collect_attr(attr, traits, Annotatable::TraitItem(P(item)),
1392-
AstFragmentKind::TraitItems, together_with).make_trait_items()
1379+
AstFragmentKind::TraitItems, after_derive).make_trait_items()
13931380
}
13941381

13951382
match item.node {
@@ -1405,10 +1392,10 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
14051392
fn fold_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> {
14061393
let item = configure!(self, item);
14071394

1408-
let (attr, traits, item, together_with) = self.classify_item(item);
1395+
let (attr, traits, item, after_derive) = self.classify_item(item);
14091396
if attr.is_some() || !traits.is_empty() {
14101397
return self.collect_attr(attr, traits, Annotatable::ImplItem(P(item)),
1411-
AstFragmentKind::ImplItems, together_with).make_impl_items();
1398+
AstFragmentKind::ImplItems, after_derive).make_impl_items();
14121399
}
14131400

14141401
match item.node {
@@ -1440,11 +1427,11 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
14401427
fn fold_foreign_item(&mut self, foreign_item: ast::ForeignItem)
14411428
-> SmallVec<[ast::ForeignItem; 1]>
14421429
{
1443-
let (attr, traits, foreign_item, together_with) = self.classify_item(foreign_item);
1430+
let (attr, traits, foreign_item, after_derive) = self.classify_item(foreign_item);
14441431

14451432
if attr.is_some() || !traits.is_empty() {
14461433
return self.collect_attr(attr, traits, Annotatable::ForeignItem(P(foreign_item)),
1447-
AstFragmentKind::ForeignItems, together_with)
1434+
AstFragmentKind::ForeignItems, after_derive)
14481435
.make_foreign_items();
14491436
}
14501437

src/libsyntax/feature_gate.rs

-4
Original file line numberDiff line numberDiff line change
@@ -990,10 +990,6 @@ pub const BUILTIN_ATTRIBUTES: &'static [(&'static str, AttributeType, AttributeG
990990
"the `#[rustc_test_marker]` attribute \
991991
is used internally to track tests",
992992
cfg_fn!(rustc_attrs))),
993-
("rustc_test_marker2", Normal, Gated(Stability::Unstable,
994-
"rustc_attrs",
995-
"temporarily used by rustc to report some errors",
996-
cfg_fn!(rustc_attrs))),
997993
("rustc_transparent_macro", Whitelisted, Gated(Stability::Unstable,
998994
"rustc_attrs",
999995
"used internally for testing macro hygiene",

src/libsyntax_ext/test.rs

+1-7
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ pub fn expand_test_or_bench(
4949
// If we're not in test configuration, remove the annotated item
5050
if !cx.ecfg.should_test { return vec![]; }
5151

52-
let mut item =
52+
let item =
5353
if let Annotatable::Item(i) = item { i }
5454
else {
5555
cx.parse_sess.span_diagnostic.span_fatal(item.span(),
@@ -192,12 +192,6 @@ pub fn expand_test_or_bench(
192192

193193
debug!("Synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
194194

195-
// Temporarily add another marker to the original item for error reporting
196-
let marker2 = cx.attribute(
197-
attr_sp, cx.meta_word(attr_sp, Symbol::intern("rustc_test_marker2"))
198-
);
199-
item.attrs.push(marker2);
200-
201195
vec![
202196
// Access to libtest under a gensymed name
203197
Annotatable::Item(test_extern),

src/test/run-pass-fulldeps/macro-crate.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@
1919
#[macro_use] #[no_link]
2020
extern crate macro_crate_test;
2121

22-
#[derive(PartialEq, Clone, Debug)]
2322
#[rustc_into_multi_foo]
23+
#[derive(PartialEq, Clone, Debug)]
2424
fn foo() -> AnotherFakeTypeThatHadBetterGoAway {}
2525

2626
// Check that the `#[into_multi_foo]`-generated `foo2` is configured away
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
11
// aux-build:attr_proc_macro.rs
2-
// compile-flags:--test
32

4-
#![feature(test)]
5-
6-
extern crate test;
73
extern crate attr_proc_macro;
84
use attr_proc_macro::*;
95

@@ -15,18 +11,4 @@ struct Before;
1511
#[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]`
1612
struct After;
1713

18-
#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
19-
#[test]
20-
fn test_before() {}
21-
22-
#[test]
23-
#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
24-
fn test_after() {}
25-
26-
#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
27-
#[bench]
28-
fn bench_before(b: &mut test::Bencher) {}
29-
30-
#[bench]
31-
#[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
32-
fn bench_after(b: &mut test::Bencher) {}
14+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,8 @@
11
error: macro attributes must be placed before `#[derive]`
2-
--> $DIR/attribute-order-restricted.rs:15:1
2+
--> $DIR/attribute-order-restricted.rs:11:1
33
|
44
LL | #[attr_proc_macro] //~ ERROR macro attributes must be placed before `#[derive]`
55
| ^^^^^^^^^^^^^^^^^^
66

7-
error: macro attributes cannot be used together with `#[test]` or `#[bench]`
8-
--> $DIR/attribute-order-restricted.rs:18:1
9-
|
10-
LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
11-
| ^^^^^^^^^^^^^^^^^^
12-
13-
error: macro attributes cannot be used together with `#[test]` or `#[bench]`
14-
--> $DIR/attribute-order-restricted.rs:23:1
15-
|
16-
LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
17-
| ^^^^^^^^^^^^^^^^^^
18-
19-
error: macro attributes cannot be used together with `#[test]` or `#[bench]`
20-
--> $DIR/attribute-order-restricted.rs:26:1
21-
|
22-
LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
23-
| ^^^^^^^^^^^^^^^^^^
24-
25-
error: macro attributes cannot be used together with `#[test]` or `#[bench]`
26-
--> $DIR/attribute-order-restricted.rs:31:1
27-
|
28-
LL | #[attr_proc_macro] //~ ERROR macro attributes cannot be used together with `#[test]` or `#[bench]`
29-
| ^^^^^^^^^^^^^^^^^^
30-
31-
error: aborting due to 5 previous errors
7+
error: aborting due to previous error
328

0 commit comments

Comments
 (0)