diff options
| author | bors <bors@rust-lang.org> | 2019-02-12 12:10:10 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-02-12 12:10:10 +0000 |
| commit | c84e7976423bb910bb5eb5eecffc7e33a897a97f (patch) | |
| tree | 24570884cb7742fe817286a3cde2643722eb8c6a /src/libsyntax | |
| parent | a54b5c7a645ead203d77e78245362f9e0f00dd3c (diff) | |
| parent | bbe524d7c1a1028737a93c7c71c508a68363b681 (diff) | |
| download | rust-c84e7976423bb910bb5eb5eecffc7e33a897a97f.tar.gz rust-c84e7976423bb910bb5eb5eecffc7e33a897a97f.zip | |
Auto merge of #58098 - oli-obk:maybe_allow_internal_unstable, r=petrochenkov
Require a list of features in `#[allow_internal_unstable]` The blanket-permission slip is not great and will likely give us trouble some point down the road.
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 20 | ||||
| -rw-r--r-- | src/libsyntax/ext/derive.rs | 5 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 28 | ||||
| -rw-r--r-- | src/libsyntax/ext/source_util.rs | 2 | ||||
| -rw-r--r-- | src/libsyntax/ext/tt/macro_rules.rs | 19 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 25 | ||||
| -rw-r--r-- | src/libsyntax/std_inject.rs | 4 | ||||
| -rw-r--r-- | src/libsyntax/test.rs | 6 |
8 files changed, 75 insertions, 34 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 465b53184dc..f7225810aca 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -621,7 +621,8 @@ pub enum SyntaxExtension { /// A function-like procedural macro. TokenStream -> TokenStream. ProcMacro { expander: Box<dyn ProcMacro + sync::Sync + sync::Send>, - allow_internal_unstable: bool, + /// Whitelist of unstable features that are treated as stable inside this macro + allow_internal_unstable: Option<Lrc<[Symbol]>>, edition: Edition, }, @@ -638,8 +639,10 @@ pub enum SyntaxExtension { expander: Box<dyn TTMacroExpander + sync::Sync + sync::Send>, def_info: Option<(ast::NodeId, Span)>, /// Whether the contents of the macro can - /// directly use `#[unstable]` things (true == yes). - allow_internal_unstable: bool, + /// directly use `#[unstable]` things. + /// + /// Only allows things that require a feature gate in the given whitelist + allow_internal_unstable: Option<Lrc<[Symbol]>>, /// Whether the contents of the macro can use `unsafe` /// without triggering the `unsafe_code` lint. allow_internal_unsafe: bool, @@ -654,8 +657,11 @@ pub enum SyntaxExtension { /// A function-like syntax extension that has an extra ident before /// the block. - /// - IdentTT(Box<dyn IdentMacroExpander + sync::Sync + sync::Send>, Option<Span>, bool), + IdentTT { + expander: Box<dyn IdentMacroExpander + sync::Sync + sync::Send>, + span: Option<Span>, + allow_internal_unstable: Option<Lrc<[Symbol]>>, + }, /// An attribute-like procedural macro. TokenStream -> TokenStream. /// The input is the annotated item. @@ -682,7 +688,7 @@ impl SyntaxExtension { match *self { SyntaxExtension::DeclMacro { .. } | SyntaxExtension::NormalTT { .. } | - SyntaxExtension::IdentTT(..) | + SyntaxExtension::IdentTT { .. } | SyntaxExtension::ProcMacro { .. } => MacroKind::Bang, SyntaxExtension::NonMacroAttr { .. } | @@ -716,7 +722,7 @@ impl SyntaxExtension { SyntaxExtension::ProcMacroDerive(.., edition) => edition, // Unstable legacy stuff SyntaxExtension::NonMacroAttr { .. } | - SyntaxExtension::IdentTT(..) | + SyntaxExtension::IdentTT { .. } | SyntaxExtension::MultiDecorator(..) | SyntaxExtension::MultiModifier(..) | SyntaxExtension::BuiltinDerive(..) => hygiene::default_edition(), diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index 50cec9e7908..6df369133d0 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -58,7 +58,10 @@ pub fn add_derived_markers<T>(cx: &mut ExtCtxt<'_>, span: Span, traits: &[ast::P call_site: span, def_site: None, format: ExpnFormat::MacroAttribute(Symbol::intern(&pretty_name)), - allow_internal_unstable: true, + allow_internal_unstable: Some(vec![ + Symbol::intern("rustc_attrs"), + Symbol::intern("structural_match"), + ].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 89d59478a5d..60359531b7f 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -558,7 +558,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { call_site: attr.span, def_site: None, format: MacroAttribute(Symbol::intern(&attr.path.to_string())), - allow_internal_unstable: false, + allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, edition: ext.edition(), @@ -725,7 +725,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> { // 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| { + && !span.allows_unstable(&feature.as_str()) + && this.cx.ecfg.features.map_or(true, |feats| { // macro features will count as lib features !feats.declared_lib_features.iter().any(|&(feat, _)| feat == feature) }) { @@ -757,7 +758,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let opt_expanded = match *ext { DeclMacro { ref expander, def_info, edition, .. } => { if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s), - false, false, false, None, + None, false, false, None, edition) { dummy_span } else { @@ -768,14 +769,14 @@ impl<'a, 'b> MacroExpander<'a, 'b> { NormalTT { ref expander, def_info, - allow_internal_unstable, + ref allow_internal_unstable, allow_internal_unsafe, local_inner_macros, unstable_feature, edition, } => { if let Err(dummy_span) = validate_and_set_expn_info(self, def_info.map(|(_, s)| s), - allow_internal_unstable, + allow_internal_unstable.clone(), allow_internal_unsafe, local_inner_macros, unstable_feature, @@ -791,7 +792,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } - IdentTT(ref expander, tt_span, allow_internal_unstable) => { + IdentTT { ref expander, span: tt_span, ref allow_internal_unstable } => { if ident.name == keywords::Invalid.name() { self.cx.span_err(path.span, &format!("macro {}! expects an ident argument", path)); @@ -802,7 +803,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { call_site: span, def_site: tt_span, format: macro_bang_format(path), - allow_internal_unstable, + allow_internal_unstable: allow_internal_unstable.clone(), allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), @@ -827,7 +828,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { kind.dummy(span) } - SyntaxExtension::ProcMacro { ref expander, allow_internal_unstable, edition } => { + SyntaxExtension::ProcMacro { ref expander, ref allow_internal_unstable, edition } => { if ident.name != keywords::Invalid.name() { let msg = format!("macro {}! expects no ident argument, given '{}'", path, ident); @@ -843,7 +844,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { def_site: None, format: macro_bang_format(path), // FIXME probably want to follow macro_rules macros here. - allow_internal_unstable, + allow_internal_unstable: allow_internal_unstable.clone(), allow_internal_unsafe: false, local_inner_macros: false, edition, @@ -918,7 +919,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { call_site: span, def_site: None, format: MacroAttribute(pretty_name), - allow_internal_unstable: false, + allow_internal_unstable: None, allow_internal_unsafe: false, local_inner_macros: false, edition: ext.edition(), @@ -937,7 +938,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> { Some(invoc.fragment_kind.expect_from_annotatables(items)) } BuiltinDerive(func) => { - expn_info.allow_internal_unstable = true; + expn_info.allow_internal_unstable = Some(vec![ + Symbol::intern("rustc_attrs"), + Symbol::intern("derive_clone_copy"), + Symbol::intern("derive_eq"), + Symbol::intern("libstd_sys_internals"), // RustcDeserialize and RustcSerialize + ].into()); invoc.expansion_data.mark.set_expn_info(expn_info); let span = span.with_ctxt(self.cx.backtrace()); let mut items = Vec::new(); diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 31a134b856d..549de1628eb 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -44,7 +44,7 @@ pub fn expand_column(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTr /* __rust_unstable_column!(): expands to the current column number */ pub fn expand_column_gated(cx: &mut ExtCtxt<'_>, sp: Span, tts: &[tokenstream::TokenTree]) -> Box<dyn base::MacResult+'static> { - if sp.allows_unstable() { + if sp.allows_unstable("__rust_unstable_column") { expand_column(cx, sp, tts) } else { cx.span_fatal(sp, "the __rust_unstable_column macro is unstable"); diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 33ea675f9d1..cc5531c4010 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -376,7 +376,24 @@ pub fn compile( }); if body.legacy { - let allow_internal_unstable = attr::contains_name(&def.attrs, "allow_internal_unstable"); + let allow_internal_unstable = attr::find_by_name(&def.attrs, "allow_internal_unstable") + .map(|attr| attr + .meta_item_list() + .map(|list| list.iter() + .map(|it| it.name().unwrap_or_else(|| sess.span_diagnostic.span_bug( + it.span, "allow internal unstable expects feature names", + ))) + .collect::<Vec<Symbol>>().into() + ) + .unwrap_or_else(|| { + sess.span_diagnostic.span_warn( + attr.span, "allow_internal_unstable expects list of feature names. In the \ + future this will become a hard error. Please use `allow_internal_unstable(\ + foo, bar)` to only allow the `foo` and `bar` features", + ); + vec![Symbol::intern("allow_internal_unstable_backcompat_hack")].into() + }) + ); let allow_internal_unsafe = attr::contains_name(&def.attrs, "allow_internal_unsafe"); let mut local_inner_macros = false; if let Some(macro_export) = attr::find_by_name(&def.attrs, "macro_export") { diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 0853b4399d2..4d24c7bfb40 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -1091,7 +1091,8 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu stable", cfg_fn!(profiler_runtime))), - ("allow_internal_unstable", Normal, template!(Word), Gated(Stability::Unstable, + ("allow_internal_unstable", Normal, template!(Word, List: "feat1, feat2, ..."), + Gated(Stability::Unstable, "allow_internal_unstable", EXPLAIN_ALLOW_INTERNAL_UNSTABLE, cfg_fn!(allow_internal_unstable))), @@ -1199,7 +1200,7 @@ pub const BUILTIN_ATTRIBUTES: &[(&str, AttributeType, AttributeTemplate, Attribu ("proc_macro", Normal, template!(Word), Ungated), ("rustc_proc_macro_decls", Normal, template!(Word), Gated(Stability::Unstable, - "rustc_proc_macro_decls", + "rustc_attrs", "used internally by rustc", cfg_fn!(rustc_attrs))), @@ -1284,7 +1285,7 @@ impl GatedCfg { pub fn check_and_emit(&self, sess: &ParseSess, features: &Features) { let (cfg, feature, has_feature) = GATED_CFGS[self.index]; - if !has_feature(features) && !self.span.allows_unstable() { + if !has_feature(features) && !self.span.allows_unstable(feature) { let explain = format!("`cfg({})` is experimental and subject to change", cfg); emit_feature_err(sess, feature, self.span, GateIssue::Language, &explain); } @@ -1303,7 +1304,7 @@ macro_rules! gate_feature_fn { name, explain, level) = ($cx, $has_feature, $span, $name, $explain, $level); let has_feature: bool = has_feature(&$cx.features); debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature); - if !has_feature && !span.allows_unstable() { + if !has_feature && !span.allows_unstable($name) { leveled_feature_err(cx.parse_sess, name, span, GateIssue::Language, explain, level) .emit(); } @@ -1328,7 +1329,11 @@ impl<'a> Context<'a> { for &(n, ty, _template, ref gateage) in BUILTIN_ATTRIBUTES { if name == n { if let Gated(_, name, desc, ref has_feature) = *gateage { - gate_feature_fn!(self, has_feature, attr.span, name, desc, GateStrength::Hard); + if !attr.span.allows_unstable(name) { + gate_feature_fn!( + self, has_feature, attr.span, name, desc, GateStrength::Hard + ); + } } else if name == "doc" { if let Some(content) = attr.meta_item_list() { if content.iter().any(|c| c.check_name("include")) { @@ -1493,13 +1498,13 @@ struct PostExpansionVisitor<'a> { macro_rules! gate_feature_post { ($cx: expr, $feature: ident, $span: expr, $explain: expr) => {{ let (cx, span) = ($cx, $span); - if !span.allows_unstable() { + if !span.allows_unstable(stringify!($feature)) { gate_feature!(cx.context, $feature, span, $explain) } }}; ($cx: expr, $feature: ident, $span: expr, $explain: expr, $level: expr) => {{ let (cx, span) = ($cx, $span); - if !span.allows_unstable() { + if !span.allows_unstable(stringify!($feature)) { gate_feature!(cx.context, $feature, span, $explain, $level) } }} @@ -1610,10 +1615,8 @@ impl<'a> PostExpansionVisitor<'a> { impl<'a> Visitor<'a> for PostExpansionVisitor<'a> { fn visit_attribute(&mut self, attr: &ast::Attribute) { - if !attr.span.allows_unstable() { - // check for gated attributes - self.context.check_attribute(attr, false); - } + // check for gated attributes + self.context.check_attribute(attr, false); if attr.check_name("doc") { if let Some(content) = attr.meta_item_list() { diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 5b904fa86ad..b9758bd655c 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -20,7 +20,9 @@ fn ignored_span(sp: Span) -> Span { call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("std_inject")), - allow_internal_unstable: true, + allow_internal_unstable: Some(vec![ + Symbol::intern("prelude_import"), + ].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 703c4f2db34..f45bf034ba2 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -285,7 +285,11 @@ fn generate_test_harness(sess: &ParseSess, call_site: DUMMY_SP, def_site: None, format: MacroAttribute(Symbol::intern("test_case")), - allow_internal_unstable: true, + allow_internal_unstable: Some(vec![ + Symbol::intern("main"), + Symbol::intern("test"), + Symbol::intern("rustc_attrs"), + ].into()), allow_internal_unsafe: false, local_inner_macros: false, edition: hygiene::default_edition(), |
