Skip to content

Commit 8b40531

Browse files
committed
Remove the MacroVisitor pass.
This pass was supposed to check use of gated features before `#[cfg]`-stripping but this was not the case since it in fact happens after. Checks that are actually important and must be done before macro expansion are now made where the features are actually used. Close rust-lang#32648. Also ensure that attributes on macro-generated macro invocations are checked as well. Close rust-lang#32782 and rust-lang#32655.
1 parent 3aa7137 commit 8b40531

File tree

11 files changed

+207
-199
lines changed

11 files changed

+207
-199
lines changed

src/librustc_driver/driver.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -512,19 +512,13 @@ pub fn phase_2_configure_and_expand(sess: &Session,
512512
middle::recursion_limit::update_recursion_limit(sess, &krate);
513513
});
514514

515-
time(time_passes, "gated macro checking", || {
516-
sess.track_errors(|| {
517-
let features =
518-
syntax::feature_gate::check_crate_macros(sess.codemap(),
519-
&sess.parse_sess.span_diagnostic,
520-
&krate);
521-
522-
// these need to be set "early" so that expansion sees `quote` if enabled.
523-
*sess.features.borrow_mut() = features;
524-
})
515+
// these need to be set "early" so that expansion sees `quote` if enabled.
516+
sess.track_errors(|| {
517+
*sess.features.borrow_mut() =
518+
syntax::feature_gate::get_features(&sess.parse_sess.span_diagnostic,
519+
&krate);
525520
})?;
526521

527-
528522
krate = time(time_passes, "crate injection", || {
529523
syntax::std_inject::maybe_inject_crates_ref(krate, sess.opts.alt_std_name.clone())
530524
});

src/librustc_plugin/load.rs

+22-17
Original file line numberDiff line numberDiff line change
@@ -51,27 +51,32 @@ pub fn load_plugins(sess: &Session,
5151
addl_plugins: Option<Vec<String>>) -> Vec<PluginRegistrar> {
5252
let mut loader = PluginLoader::new(sess, cstore, crate_name);
5353

54-
for attr in &krate.attrs {
55-
if !attr.check_name("plugin") {
56-
continue;
57-
}
58-
59-
let plugins = match attr.meta_item_list() {
60-
Some(xs) => xs,
61-
None => {
62-
call_malformed_plugin_attribute(sess, attr.span);
54+
// do not report any error now. since crate attributes are
55+
// not touched by expansion, every use of plugin without
56+
// the feature enabled will result in an error later...
57+
if sess.features.borrow().plugin {
58+
for attr in &krate.attrs {
59+
if !attr.check_name("plugin") {
6360
continue;
6461
}
65-
};
6662

67-
for plugin in plugins {
68-
if plugin.value_str().is_some() {
69-
call_malformed_plugin_attribute(sess, attr.span);
70-
continue;
63+
let plugins = match attr.meta_item_list() {
64+
Some(xs) => xs,
65+
None => {
66+
call_malformed_plugin_attribute(sess, attr.span);
67+
continue;
68+
}
69+
};
70+
71+
for plugin in plugins {
72+
if plugin.value_str().is_some() {
73+
call_malformed_plugin_attribute(sess, attr.span);
74+
continue;
75+
}
76+
77+
let args = plugin.meta_item_list().map(ToOwned::to_owned).unwrap_or_default();
78+
loader.load_plugin(plugin.span, &plugin.name(), args);
7179
}
72-
73-
let args = plugin.meta_item_list().map(ToOwned::to_owned).unwrap_or_default();
74-
loader.load_plugin(plugin.span, &plugin.name(), args);
7580
}
7681
}
7782

src/libsyntax/ext/expand.rs

+24-19
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,26 @@ use std_inject;
3535
use std::collections::HashSet;
3636
use std::env;
3737

38+
// this function is called to detect use of feature-gated or invalid attributes
39+
// on macro invoations since they will not be detected after macro expansion
40+
fn check_attributes(attrs: &[ast::Attribute], fld: &MacroExpander) {
41+
for attr in attrs.iter() {
42+
feature_gate::check_attribute(&attr, &fld.cx.parse_sess.span_diagnostic,
43+
&fld.cx.parse_sess.codemap(),
44+
&fld.cx.ecfg.features.unwrap());
45+
}
46+
}
47+
3848
pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
3949
let expr_span = e.span;
4050
return e.and_then(|ast::Expr {id, node, span, attrs}| match node {
4151

4252
// expr_mac should really be expr_ext or something; it's the
4353
// entry-point for all syntax extensions.
4454
ast::ExprKind::Mac(mac) => {
55+
if let Some(ref attrs) = attrs {
56+
check_attributes(attrs, fld);
57+
}
4558

4659
// Assert that we drop any macro attributes on the floor here
4760
drop(attrs);
@@ -367,6 +380,8 @@ pub fn expand_item_mac(it: P<ast::Item>,
367380
_ => fld.cx.span_bug(it.span, "invalid item macro invocation")
368381
});
369382

383+
check_attributes(&attrs, fld);
384+
370385
let fm = fresh_mark();
371386
let items = {
372387
let expanded = match fld.cx.syntax_env.find(extname) {
@@ -441,18 +456,6 @@ pub fn expand_item_mac(it: P<ast::Item>,
441456
let allow_internal_unstable = attr::contains_name(&attrs,
442457
"allow_internal_unstable");
443458

444-
// ensure any #[allow_internal_unstable]s are
445-
// detected (including nested macro definitions
446-
// etc.)
447-
if allow_internal_unstable && !fld.cx.ecfg.enable_allow_internal_unstable() {
448-
feature_gate::emit_feature_err(
449-
&fld.cx.parse_sess.span_diagnostic,
450-
"allow_internal_unstable",
451-
span,
452-
feature_gate::GateIssue::Language,
453-
feature_gate::EXPLAIN_ALLOW_INTERNAL_UNSTABLE)
454-
}
455-
456459
let export = attr::contains_name(&attrs, "macro_export");
457460
let def = ast::MacroDef {
458461
ident: ident,
@@ -516,6 +519,10 @@ fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> {
516519
_ => return expand_non_macro_stmt(stmt, fld)
517520
};
518521

522+
if let Some(ref attrs) = attrs {
523+
check_attributes(attrs, fld);
524+
}
525+
519526
// Assert that we drop any macro attributes on the floor here
520527
drop(attrs);
521528

@@ -1063,7 +1070,7 @@ fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)
10631070
attrs: ii.attrs,
10641071
vis: ii.vis,
10651072
defaultness: ii.defaultness,
1066-
node: match ii.node {
1073+
node: match ii.node {
10671074
ast::ImplItemKind::Method(sig, body) => {
10681075
let (sig, body) = expand_and_rename_method(sig, body, fld);
10691076
ast::ImplItemKind::Method(sig, body)
@@ -1072,13 +1079,11 @@ fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)
10721079
},
10731080
span: fld.new_span(ii.span)
10741081
}),
1075-
ast::ImplItemKind::Macro(_) => {
1076-
let (span, mac) = match ii.node {
1077-
ast::ImplItemKind::Macro(mac) => (ii.span, mac),
1078-
_ => unreachable!()
1079-
};
1082+
ast::ImplItemKind::Macro(mac) => {
1083+
check_attributes(&ii.attrs, fld);
1084+
10801085
let maybe_new_items =
1081-
expand_mac_invoc(mac, span,
1086+
expand_mac_invoc(mac, ii.span,
10821087
|r| r.make_impl_items(),
10831088
|meths, mark| meths.move_map(|m| mark_impl_item(m, mark)),
10841089
fld);

src/libsyntax/feature_gate.rs

+27-90
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,7 @@ pub fn check_for_pushpop_syntax(f: Option<&Features>, diag: &Handler, span: Span
688688
}
689689

690690
struct Context<'a> {
691-
features: Features,
691+
features: &'a Features,
692692
span_handler: &'a Handler,
693693
cm: &'a CodeMap,
694694
plugin_attributes: &'a [(String, AttributeType)],
@@ -739,9 +739,7 @@ impl<'a> Context<'a> {
739739
with the prefix `rustc_` \
740740
are reserved for internal compiler diagnostics");
741741
} else if name.starts_with("derive_") {
742-
gate_feature!(self, custom_derive, attr.span,
743-
"attributes of the form `#[derive_*]` are reserved \
744-
for the compiler");
742+
gate_feature!(self, custom_derive, attr.span, EXPLAIN_DERIVE_UNDERSCORE);
745743
} else {
746744
// Only run the custom attribute lint during regular
747745
// feature gate checking. Macro gating runs
@@ -759,6 +757,15 @@ impl<'a> Context<'a> {
759757
}
760758
}
761759

760+
pub fn check_attribute(attr: &ast::Attribute, handler: &Handler,
761+
cm: &CodeMap, features: &Features) {
762+
let cx = Context {
763+
features: features, span_handler: handler,
764+
cm: cm, plugin_attributes: &[]
765+
};
766+
cx.check_attribute(attr, true);
767+
}
768+
762769
fn find_lang_feature_issue(feature: &str) -> Option<u32> {
763770
if let Some(info) = ACTIVE_FEATURES.iter().find(|t| t.0 == feature) {
764771
let issue = info.2;
@@ -819,64 +826,8 @@ pub const EXPLAIN_ALLOW_INTERNAL_UNSTABLE: &'static str =
819826
pub const EXPLAIN_CUSTOM_DERIVE: &'static str =
820827
"`#[derive]` for custom traits is not stable enough for use and is subject to change";
821828

822-
struct MacroVisitor<'a> {
823-
context: &'a Context<'a>
824-
}
825-
826-
impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
827-
fn visit_mac(&mut self, mac: &ast::Mac) {
828-
let path = &mac.node.path;
829-
let name = path.segments.last().unwrap().identifier.name.as_str();
830-
831-
// Issue 22234: If you add a new case here, make sure to also
832-
// add code to catch the macro during or after expansion.
833-
//
834-
// We still keep this MacroVisitor (rather than *solely*
835-
// relying on catching cases during or after expansion) to
836-
// catch uses of these macros within conditionally-compiled
837-
// code, e.g. `#[cfg]`-guarded functions.
838-
839-
if name == "asm" {
840-
gate_feature!(self.context, asm, path.span, EXPLAIN_ASM);
841-
}
842-
843-
else if name == "log_syntax" {
844-
gate_feature!(self.context, log_syntax, path.span, EXPLAIN_LOG_SYNTAX);
845-
}
846-
847-
else if name == "trace_macros" {
848-
gate_feature!(self.context, trace_macros, path.span, EXPLAIN_TRACE_MACROS);
849-
}
850-
851-
else if name == "concat_idents" {
852-
gate_feature!(self.context, concat_idents, path.span, EXPLAIN_CONCAT_IDENTS);
853-
}
854-
}
855-
856-
fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
857-
self.context.check_attribute(attr, true);
858-
}
859-
860-
fn visit_expr(&mut self, e: &ast::Expr) {
861-
// Issue 22181: overloaded-`box` and placement-`in` are
862-
// implemented via a desugaring expansion, so their feature
863-
// gates go into MacroVisitor since that works pre-expansion.
864-
//
865-
// Issue 22234: we also check during expansion as well.
866-
// But we keep these checks as a pre-expansion check to catch
867-
// uses in e.g. conditionalized code.
868-
869-
if let ast::ExprKind::Box(_) = e.node {
870-
gate_feature!(self.context, box_syntax, e.span, EXPLAIN_BOX_SYNTAX);
871-
}
872-
873-
if let ast::ExprKind::InPlace(..) = e.node {
874-
gate_feature!(self.context, placement_in_syntax, e.span, EXPLAIN_PLACEMENT_IN);
875-
}
876-
877-
visit::walk_expr(self, e);
878-
}
879-
}
829+
pub const EXPLAIN_DERIVE_UNDERSCORE: &'static str =
830+
"attributes of the form `#[derive_*]` are reserved for the compiler";
880831

881832
struct PostExpansionVisitor<'a> {
882833
context: &'a Context<'a>,
@@ -1177,13 +1128,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
11771128
}
11781129
}
11791130

1180-
fn check_crate_inner<F>(cm: &CodeMap, span_handler: &Handler,
1181-
krate: &ast::Crate,
1182-
plugin_attributes: &[(String, AttributeType)],
1183-
check: F)
1184-
-> Features
1185-
where F: FnOnce(&mut Context, &ast::Crate)
1186-
{
1131+
pub fn get_features(span_handler: &Handler, krate: &ast::Crate) -> Features {
11871132
let mut features = Features::new();
11881133

11891134
for attr in &krate.attrs {
@@ -1226,32 +1171,24 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &Handler,
12261171
}
12271172
}
12281173

1229-
let mut cx = Context {
1230-
features: features,
1231-
span_handler: span_handler,
1232-
cm: cm,
1233-
plugin_attributes: plugin_attributes,
1234-
};
1235-
1236-
check(&mut cx, krate);
1237-
cx.features
1238-
}
1239-
1240-
pub fn check_crate_macros(cm: &CodeMap, span_handler: &Handler, krate: &ast::Crate)
1241-
-> Features {
1242-
check_crate_inner(cm, span_handler, krate, &[] as &'static [_],
1243-
|ctx, krate| visit::walk_crate(&mut MacroVisitor { context: ctx }, krate))
1174+
features
12441175
}
12451176

12461177
pub fn check_crate(cm: &CodeMap, span_handler: &Handler, krate: &ast::Crate,
12471178
plugin_attributes: &[(String, AttributeType)],
1248-
unstable: UnstableFeatures) -> Features
1249-
{
1179+
unstable: UnstableFeatures) -> Features {
12501180
maybe_stage_features(span_handler, krate, unstable);
1251-
1252-
check_crate_inner(cm, span_handler, krate, plugin_attributes,
1253-
|ctx, krate| visit::walk_crate(&mut PostExpansionVisitor { context: ctx },
1254-
krate))
1181+
let features = get_features(span_handler, krate);
1182+
{
1183+
let ctx = Context {
1184+
features: &features,
1185+
span_handler: span_handler,
1186+
cm: cm,
1187+
plugin_attributes: plugin_attributes,
1188+
};
1189+
visit::walk_crate(&mut PostExpansionVisitor { context: &ctx }, krate);
1190+
}
1191+
features
12551192
}
12561193

12571194
#[derive(Clone, Copy)]

0 commit comments

Comments
 (0)