diff options
| author | bors <bors@rust-lang.org> | 2018-03-16 02:46:23 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-03-16 02:46:23 +0000 |
| commit | a7170b0412d1baa4e30cb31d1ea326617021f086 (patch) | |
| tree | c29e3be6c0201716b609c9e2f714f8703a580b3a /src/libsyntax/ext/expand.rs | |
| parent | 36b66873187e37a9d79adad89563088a9cb86028 (diff) | |
| parent | 69035f20b92870a7ad5dbc22c65aee971d8f8698 (diff) | |
| download | rust-a7170b0412d1baa4e30cb31d1ea326617021f086.tar.gz rust-a7170b0412d1baa4e30cb31d1ea326617021f086.zip | |
Auto merge of #48524 - abonander:check-macro-stability, r=petrochenkov
check stability of macro invocations I haven't implemented tests yet but this should be a pretty solid prototype. I think as-implemented it will also stability-check macro invocations in the same crate, dunno if we want that or not. I don't know if we want this to go through `rustc::middle::stability` or not, considering the information there wouldn't be available at the time of macro expansion (even for external crates, right?). r? @nrc closes #34079 cc @petrochenkov @durka @jseyfried #38356
Diffstat (limited to 'src/libsyntax/ext/expand.rs')
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 56 |
1 files changed, 40 insertions, 16 deletions
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 3e75afcee1c..7ccace014d0 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -18,7 +18,7 @@ use ext::base::*; use ext::derive::{add_derived_markers, collect_derives}; use ext::hygiene::{Mark, SyntaxContext}; use ext::placeholders::{placeholder, PlaceholderExpander}; -use feature_gate::{self, Features, is_builtin_attr}; +use feature_gate::{self, Features, GateIssue, is_builtin_attr, emit_feature_err}; use fold; use fold::*; use parse::{DirectoryOwnership, PResult}; @@ -229,6 +229,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { module.directory.pop(); self.cx.root_path = module.directory.clone(); self.cx.current_expansion.module = Rc::new(module); + self.cx.current_expansion.crate_span = Some(krate.span); let orig_mod_span = krate.module.inner; @@ -533,11 +534,36 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let path = &mac.node.path; let ident = ident.unwrap_or_else(|| keywords::Invalid.ident()); - let validate_and_set_expn_info = |def_site_span, + let validate_and_set_expn_info = |this: &mut Self, // arg instead of capture + def_site_span: Option<Span>, allow_internal_unstable, - allow_internal_unsafe| { + allow_internal_unsafe, + // can't infer this type + unstable_feature: Option<(Symbol, u32)>| { + + // feature-gate the macro invocation + if let Some((feature, issue)) = unstable_feature { + let crate_span = this.cx.current_expansion.crate_span.unwrap(); + // don't stability-check macros in the same crate + // (the only time this is null is for syntax extensions registered as macros) + if def_site_span.map_or(false, |def_span| !crate_span.contains(def_span)) + && !span.allows_unstable() && this.cx.ecfg.features.map_or(true, |feats| { + // macro features will count as lib features + !feats.declared_lib_features.iter().any(|&(feat, _)| feat == feature) + }) { + let explain = format!("macro {}! is unstable", path); + emit_feature_err(this.cx.parse_sess, &*feature.as_str(), span, + GateIssue::Library(Some(issue)), &explain); + this.cx.trace_macros_diag(); + return Err(kind.dummy(span)); + } + } + if ident.name != keywords::Invalid.name() { - return Err(format!("macro {}! expects no ident argument, given '{}'", path, ident)); + let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident); + this.cx.span_err(path.span, &msg); + this.cx.trace_macros_diag(); + return Err(kind.dummy(span)); } mark.set_expn_info(ExpnInfo { call_site: span, @@ -553,11 +579,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let opt_expanded = match *ext { DeclMacro(ref expand, def_span) => { - if let Err(msg) = validate_and_set_expn_info(def_span.map(|(_, s)| s), - false, false) { - self.cx.span_err(path.span, &msg); - self.cx.trace_macros_diag(); - kind.dummy(span) + if let Err(dummy_span) = validate_and_set_expn_info(self, def_span.map(|(_, s)| s), + false, false, None) { + dummy_span } else { kind.make_from(expand.expand(self.cx, span, mac.node.stream())) } @@ -567,14 +591,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { ref expander, def_info, allow_internal_unstable, - allow_internal_unsafe + allow_internal_unsafe, + unstable_feature, } => { - if let Err(msg) = validate_and_set_expn_info(def_info.map(|(_, s)| s), - allow_internal_unstable, - allow_internal_unsafe) { - self.cx.span_err(path.span, &msg); - self.cx.trace_macros_diag(); - kind.dummy(span) + if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s), + allow_internal_unstable, + allow_internal_unsafe, + unstable_feature) { + dummy_span } else { kind.make_from(expander.expand(self.cx, span, mac.node.stream())) } |
