Skip to content

Commit 504bacf

Browse files
committed
check stability of macro invocations
1 parent 9284353 commit 504bacf

File tree

5 files changed

+57
-19
lines changed

5 files changed

+57
-19
lines changed

src/librustc_plugin/registry.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -106,14 +106,16 @@ impl<'a> Registry<'a> {
106106
expander,
107107
def_info: _,
108108
allow_internal_unstable,
109-
allow_internal_unsafe
109+
allow_internal_unsafe,
110+
unstable_feature
110111
} => {
111112
let nid = ast::CRATE_NODE_ID;
112113
NormalTT {
113114
expander,
114115
def_info: Some((nid, self.krate_span)),
115116
allow_internal_unstable,
116-
allow_internal_unsafe
117+
allow_internal_unsafe,
118+
unstable_feature
117119
}
118120
}
119121
IdentTT(ext, _, allow_internal_unstable) => {
@@ -149,6 +151,7 @@ impl<'a> Registry<'a> {
149151
def_info: None,
150152
allow_internal_unstable: false,
151153
allow_internal_unsafe: false,
154+
unstable_feature: None,
152155
});
153156
}
154157

src/libsyntax/ext/base.rs

+2
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,8 @@ pub enum SyntaxExtension {
554554
/// Whether the contents of the macro can use `unsafe`
555555
/// without triggering the `unsafe_code` lint.
556556
allow_internal_unsafe: bool,
557+
/// The macro's feature name if it is unstable, and the stability feature
558+
unstable_feature: Option<(Symbol, u32)>,
557559
},
558560

559561
/// A function-like syntax extension that has an extra ident before

src/libsyntax/ext/expand.rs

+36-16
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use ext::base::*;
1818
use ext::derive::{add_derived_markers, collect_derives};
1919
use ext::hygiene::{Mark, SyntaxContext};
2020
use ext::placeholders::{placeholder, PlaceholderExpander};
21-
use feature_gate::{self, Features, is_builtin_attr};
21+
use feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err};
2222
use fold;
2323
use fold::*;
2424
use parse::{DirectoryOwnership, PResult};
@@ -531,11 +531,33 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
531531
let path = &mac.node.path;
532532

533533
let ident = ident.unwrap_or_else(|| keywords::Invalid.ident());
534-
let validate_and_set_expn_info = |def_site_span,
534+
let validate_and_set_expn_info = |self_: &mut Self, // arg instead of capture
535+
def_site_span,
535536
allow_internal_unstable,
536-
allow_internal_unsafe| {
537+
allow_internal_unsafe,
538+
// can't infer this type
539+
unstable_feature: Option<(Symbol, u32)>| {
540+
541+
// feature-gate the macro invocation
542+
if let Some((feature, issue)) = unstable_feature {
543+
// only if the outer span doesn't allow unstable invocations
544+
if !span.allows_unstable() && self_.cx.ecfg.features.map_or(true, |feats| {
545+
// macro features will count as lib features
546+
!feats.declared_lib_features.iter().any(|&(feat, _)| feat == feature)
547+
}) {
548+
let explain = format!("macro {}! is unstable", path);
549+
emit_feature_err(self_.cx.parse_sess, &*feature.as_str(), span,
550+
GateIssue::Library(Some(issue)), &explain);
551+
self_.cx.trace_macros_diag();
552+
return Err(kind.dummy(span));
553+
}
554+
}
555+
537556
if ident.name != keywords::Invalid.name() {
538-
return Err(format!("macro {}! expects no ident argument, given '{}'", path, ident));
557+
let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident);
558+
self_.cx.span_err(path.span, &msg);
559+
self_.cx.trace_macros_diag();
560+
return Err(kind.dummy(span));
539561
}
540562
mark.set_expn_info(ExpnInfo {
541563
call_site: span,
@@ -551,11 +573,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
551573

552574
let opt_expanded = match *ext {
553575
DeclMacro(ref expand, def_span) => {
554-
if let Err(msg) = validate_and_set_expn_info(def_span.map(|(_, s)| s),
555-
false, false) {
556-
self.cx.span_err(path.span, &msg);
557-
self.cx.trace_macros_diag();
558-
kind.dummy(span)
576+
if let Err(dummy_span) = validate_and_set_expn_info(self, def_span.map(|(_, s)| s),
577+
false, false, None) {
578+
dummy_span
559579
} else {
560580
kind.make_from(expand.expand(self.cx, span, mac.node.stream()))
561581
}
@@ -565,14 +585,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
565585
ref expander,
566586
def_info,
567587
allow_internal_unstable,
568-
allow_internal_unsafe
588+
allow_internal_unsafe,
589+
unstable_feature,
569590
} => {
570-
if let Err(msg) = validate_and_set_expn_info(def_info.map(|(_, s)| s),
571-
allow_internal_unstable,
572-
allow_internal_unsafe) {
573-
self.cx.span_err(path.span, &msg);
574-
self.cx.trace_macros_diag();
575-
kind.dummy(span)
591+
if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s),
592+
allow_internal_unstable,
593+
allow_internal_unsafe,
594+
unstable_feature) {
595+
dummy_span
576596
} else {
577597
kind.make_from(expander.expand(self.cx, span, mac.node.stream()))
578598
}

src/libsyntax/ext/tt/macro_rules.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -283,11 +283,22 @@ pub fn compile(sess: &ParseSess, features: &RefCell<Features>, def: &ast::Item)
283283
if body.legacy {
284284
let allow_internal_unstable = attr::contains_name(&def.attrs, "allow_internal_unstable");
285285
let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe");
286+
287+
let unstable_feature = attr::find_stability(&sess.span_diagnostic,
288+
&def.attrs, def.span).and_then(|stability| {
289+
if let attr::StabilityLevel::Unstable { issue, .. } = stability.level {
290+
Some((stability.feature, issue))
291+
} else {
292+
None
293+
}
294+
});
295+
286296
NormalTT {
287297
expander,
288298
def_info: Some((def.id, def.span)),
289299
allow_internal_unstable,
290-
allow_internal_unsafe
300+
allow_internal_unsafe,
301+
unstable_feature
291302
}
292303
} else {
293304
SyntaxExtension::DeclMacro(expander, Some((def.id, def.span)))

src/libsyntax_ext/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
6666
def_info: None,
6767
allow_internal_unstable: false,
6868
allow_internal_unsafe: false,
69+
unstable_feature: None,
6970
});
7071
)* }
7172
}
@@ -119,6 +120,7 @@ pub fn register_builtins(resolver: &mut syntax::ext::base::Resolver,
119120
def_info: None,
120121
allow_internal_unstable: true,
121122
allow_internal_unsafe: false,
123+
unstable_feature: None
122124
});
123125

124126
for (name, ext) in user_exts {

0 commit comments

Comments
 (0)