Skip to content

Commit 435095f

Browse files
committed
Auto merge of #32791 - LeoTestard:feature-gate-clean, r=nikomatsakis
Feature gate clean This PR does a bit of cleaning in the feature-gate-handling code of libsyntax. It also fixes two bugs (#32782 and #32648). Changes include: * Change the way the existing features are declared in `feature_gate.rs`. The array of features and the `Features` struct are now defined together by a single macro. `featureck.py` has been updated accordingly. Note: there are now three different arrays for active, removed and accepted features instead of a single one with a `Status` item to tell wether a feature is active, removed, or accepted. This is mainly due to the way I implemented my macro in the first time and I can switch back to a single array if needed. But an advantage of the way it is now is that when an active feature is used, the parser only searches through the list of active features. It goes through the other arrays only if the feature is not found. I like to think that error checking (in this case, checking that an used feature is active) does not slow down compilation of valid code. :) But this is not very important... * Feature-gate checking pass now use the `Features` structure instead of looking through a string vector. This should speed them up a bit. The construction of the `Features` struct should be faster too since it is build directly when parsing features instead of calling `has_feature` dozens of times. * The MacroVisitor pass has been removed, it was mostly useless since the `#[cfg]-stripping` phase happens before (fixes #32648). The features that must actually be checked before expansion are now checked at the time they are used. This also allows us to check attributes that are generated by macro expansion and not visible to MacroVisitor, but are also removed by macro expansion and thus not visible to PostExpansionVisitor either. This fixes #32782. Note that in order for `#[derive_*]` to be feature-gated but still accepted when generated by `#[derive(Trait)]`, I had to do a little bit of trickery with spans that I'm not totally confident into. Please review that part carefully. (It's in `libsyntax_ext/deriving/mod.rs`.):: Note: this is a [breaking change], since programs with feature-gated attributes on macro-generated macro invocations were not rejected before. For example: ```rust macro_rules! bar ( () => () ); macro_rules! foo ( () => ( #[allow_internal_unstable] //~ ERROR allow_internal_unstable side-steps bar!(); ); ); ``` foo!();
2 parents cda7c1c + fa23d10 commit 435095f

12 files changed

+625
-676
lines changed

src/librustc_driver/driver.rs

+5-11
Original file line numberDiff line numberDiff line change
@@ -528,19 +528,13 @@ pub fn phase_2_configure_and_expand(sess: &Session,
528528
middle::recursion_limit::update_recursion_limit(sess, &krate);
529529
});
530530

531-
time(time_passes, "gated macro checking", || {
532-
sess.track_errors(|| {
533-
let features =
534-
syntax::feature_gate::check_crate_macros(sess.codemap(),
535-
&sess.parse_sess.span_diagnostic,
536-
&krate);
537-
538-
// these need to be set "early" so that expansion sees `quote` if enabled.
539-
*sess.features.borrow_mut() = features;
540-
})
531+
// these need to be set "early" so that expansion sees `quote` if enabled.
532+
sess.track_errors(|| {
533+
*sess.features.borrow_mut() =
534+
syntax::feature_gate::get_features(&sess.parse_sess.span_diagnostic,
535+
&krate);
541536
})?;
542537

543-
544538
krate = time(time_passes, "crate injection", || {
545539
syntax::std_inject::maybe_inject_crates_ref(krate, sess.opts.alt_std_name.clone())
546540
});

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

+37-30
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);
@@ -70,10 +83,12 @@ pub fn expand_expr(e: P<ast::Expr>, fld: &mut MacroExpander) -> P<ast::Expr> {
7083

7184
ast::ExprKind::InPlace(placer, value_expr) => {
7285
// Ensure feature-gate is enabled
73-
feature_gate::check_for_placement_in(
74-
fld.cx.ecfg.features,
75-
&fld.cx.parse_sess.span_diagnostic,
76-
expr_span);
86+
if !fld.cx.ecfg.features.unwrap().placement_in_syntax {
87+
feature_gate::emit_feature_err(
88+
&fld.cx.parse_sess.span_diagnostic, "placement_in_syntax", expr_span,
89+
feature_gate::GateIssue::Language, feature_gate::EXPLAIN_PLACEMENT_IN
90+
);
91+
}
7792

7893
let placer = fld.fold_expr(placer);
7994
let value_expr = fld.fold_expr(value_expr);
@@ -370,6 +385,8 @@ pub fn expand_item_mac(it: P<ast::Item>,
370385
_ => fld.cx.span_bug(it.span, "invalid item macro invocation")
371386
});
372387

388+
check_attributes(&attrs, fld);
389+
373390
let fm = fresh_mark();
374391
let items = {
375392
let expanded = match fld.cx.syntax_env.find(extname) {
@@ -444,18 +461,6 @@ pub fn expand_item_mac(it: P<ast::Item>,
444461
let allow_internal_unstable = attr::contains_name(&attrs,
445462
"allow_internal_unstable");
446463

447-
// ensure any #[allow_internal_unstable]s are
448-
// detected (including nested macro definitions
449-
// etc.)
450-
if allow_internal_unstable && !fld.cx.ecfg.enable_allow_internal_unstable() {
451-
feature_gate::emit_feature_err(
452-
&fld.cx.parse_sess.span_diagnostic,
453-
"allow_internal_unstable",
454-
span,
455-
feature_gate::GateIssue::Language,
456-
feature_gate::EXPLAIN_ALLOW_INTERNAL_UNSTABLE)
457-
}
458-
459464
let export = attr::contains_name(&attrs, "macro_export");
460465
let def = ast::MacroDef {
461466
ident: ident,
@@ -519,6 +524,10 @@ fn expand_stmt(stmt: Stmt, fld: &mut MacroExpander) -> SmallVector<Stmt> {
519524
_ => return expand_non_macro_stmt(stmt, fld)
520525
};
521526

527+
if let Some(ref attrs) = attrs {
528+
check_attributes(attrs, fld);
529+
}
530+
522531
// Assert that we drop any macro attributes on the floor here
523532
drop(attrs);
524533

@@ -1066,7 +1075,7 @@ fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)
10661075
attrs: ii.attrs,
10671076
vis: ii.vis,
10681077
defaultness: ii.defaultness,
1069-
node: match ii.node {
1078+
node: match ii.node {
10701079
ast::ImplItemKind::Method(sig, body) => {
10711080
let (sig, body) = expand_and_rename_method(sig, body, fld);
10721081
ast::ImplItemKind::Method(sig, body)
@@ -1075,13 +1084,11 @@ fn expand_impl_item(ii: ast::ImplItem, fld: &mut MacroExpander)
10751084
},
10761085
span: fld.new_span(ii.span)
10771086
}),
1078-
ast::ImplItemKind::Macro(_) => {
1079-
let (span, mac) = match ii.node {
1080-
ast::ImplItemKind::Macro(mac) => (ii.span, mac),
1081-
_ => unreachable!()
1082-
};
1087+
ast::ImplItemKind::Macro(mac) => {
1088+
check_attributes(&ii.attrs, fld);
1089+
10831090
let maybe_new_items =
1084-
expand_mac_invoc(mac, span,
1091+
expand_mac_invoc(mac, ii.span,
10851092
|r| r.make_impl_items(),
10861093
|meths, mark| meths.move_map(|m| mark_impl_item(m, mark)),
10871094
fld);
@@ -1348,14 +1355,14 @@ impl<'feat> ExpansionConfig<'feat> {
13481355
}
13491356

13501357
feature_tests! {
1351-
fn enable_quotes = allow_quote,
1352-
fn enable_asm = allow_asm,
1353-
fn enable_log_syntax = allow_log_syntax,
1354-
fn enable_concat_idents = allow_concat_idents,
1355-
fn enable_trace_macros = allow_trace_macros,
1358+
fn enable_quotes = quote,
1359+
fn enable_asm = asm,
1360+
fn enable_log_syntax = log_syntax,
1361+
fn enable_concat_idents = concat_idents,
1362+
fn enable_trace_macros = trace_macros,
13561363
fn enable_allow_internal_unstable = allow_internal_unstable,
1357-
fn enable_custom_derive = allow_custom_derive,
1358-
fn enable_pushpop_unsafe = allow_pushpop_unsafe,
1364+
fn enable_custom_derive = custom_derive,
1365+
fn enable_pushpop_unsafe = pushpop_unsafe,
13591366
}
13601367
}
13611368

0 commit comments

Comments
 (0)