diff options
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/ext/base.rs | 16 | ||||
| -rw-r--r-- | src/libsyntax/ext/expand.rs | 71 | ||||
| -rw-r--r-- | src/libsyntax/feature_gate.rs | 61 |
3 files changed, 45 insertions, 103 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 8450daa3f7c..de391ee4219 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -589,7 +589,7 @@ impl MacroKind { /// An enum representing the different kinds of syntax extensions. pub enum SyntaxExtension { /// A trivial "extension" that does nothing, only keeps the attribute and marks it as known. - NonMacroAttr, + NonMacroAttr { mark_used: bool }, /// A syntax extension that is attached to an item and creates new items /// based upon it. @@ -670,7 +670,7 @@ impl SyntaxExtension { SyntaxExtension::IdentTT(..) | SyntaxExtension::ProcMacro { .. } => MacroKind::Bang, - SyntaxExtension::NonMacroAttr | + SyntaxExtension::NonMacroAttr { .. } | SyntaxExtension::MultiDecorator(..) | SyntaxExtension::MultiModifier(..) | SyntaxExtension::AttrProcMacro(..) => @@ -700,7 +700,7 @@ impl SyntaxExtension { SyntaxExtension::AttrProcMacro(.., edition) | SyntaxExtension::ProcMacroDerive(.., edition) => edition, // Unstable legacy stuff - SyntaxExtension::NonMacroAttr | + SyntaxExtension::NonMacroAttr { .. } | SyntaxExtension::IdentTT(..) | SyntaxExtension::MultiDecorator(..) | SyntaxExtension::MultiModifier(..) | @@ -726,7 +726,7 @@ pub trait Resolver { fn find_legacy_attr_invoc(&mut self, attrs: &mut Vec<Attribute>, allow_derive: bool) -> Option<Attribute>; - fn resolve_invoc(&mut self, invoc: &mut Invocation, scope: Mark, force: bool) + fn resolve_invoc(&mut self, invoc: &Invocation, scope: Mark, force: bool) -> Result<Option<Lrc<SyntaxExtension>>, Determinacy>; fn resolve_macro(&mut self, scope: Mark, path: &ast::Path, kind: MacroKind, force: bool) -> Result<Lrc<SyntaxExtension>, Determinacy>; @@ -739,6 +739,12 @@ pub enum Determinacy { Undetermined, } +impl Determinacy { + pub fn determined(determined: bool) -> Determinacy { + if determined { Determinacy::Determined } else { Determinacy::Undetermined } + } +} + pub struct DummyResolver; impl Resolver for DummyResolver { @@ -754,7 +760,7 @@ impl Resolver for DummyResolver { fn resolve_imports(&mut self) {} fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>, _allow_derive: bool) -> Option<Attribute> { None } - fn resolve_invoc(&mut self, _invoc: &mut Invocation, _scope: Mark, _force: bool) + fn resolve_invoc(&mut self, _invoc: &Invocation, _scope: Mark, _force: bool) -> Result<Option<Lrc<SyntaxExtension>>, Determinacy> { Err(Determinacy::Determined) } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 8bd30e43476..12941a85669 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -244,19 +244,12 @@ impl Invocation { } } - pub fn path_span(&self) -> Span { + pub fn path(&self) -> Option<&Path> { match self.kind { - InvocationKind::Bang { ref mac, .. } => mac.node.path.span, - InvocationKind::Attr { attr: Some(ref attr), .. } => attr.path.span, - InvocationKind::Attr { attr: None, .. } => DUMMY_SP, - InvocationKind::Derive { ref path, .. } => path.span, - } - } - - pub fn attr_id(&self) -> Option<ast::AttrId> { - match self.kind { - InvocationKind::Attr { attr: Some(ref attr), .. } => Some(attr.id), - _ => None, + InvocationKind::Bang { ref mac, .. } => Some(&mac.node.path), + InvocationKind::Attr { attr: Some(ref attr), .. } => Some(&attr.path), + InvocationKind::Attr { attr: None, .. } => None, + InvocationKind::Derive { ref path, .. } => Some(path), } } } @@ -338,7 +331,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let mut undetermined_invocations = Vec::new(); let (mut progress, mut force) = (false, !self.monotonic); loop { - let mut invoc = if let Some(invoc) = invocations.pop() { + let invoc = if let Some(invoc) = invocations.pop() { invoc } else { self.resolve_imports(); @@ -350,20 +343,10 @@ impl<'a, 'b> MacroExpander<'a, 'b> { let scope = if self.monotonic { invoc.expansion_data.mark } else { orig_expansion_data.mark }; - let attr_id_before = invoc.attr_id(); - let ext = match self.cx.resolver.resolve_invoc(&mut invoc, scope, force) { + let ext = match self.cx.resolver.resolve_invoc(&invoc, scope, force) { Ok(ext) => Some(ext), Err(Determinacy::Determined) => None, Err(Determinacy::Undetermined) => { - // Sometimes attributes which we thought were invocations - // end up being custom attributes for custom derives. If - // that's the case our `invoc` will have changed out from - // under us. If this is the case we're making progress so we - // want to flag it as such, and we test this by looking if - // the `attr_id()` method has been changing over time. - if invoc.attr_id() != attr_id_before { - progress = true; - } undetermined_invocations.push(invoc); continue } @@ -533,6 +516,15 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } fn expand_invoc(&mut self, invoc: Invocation, ext: &SyntaxExtension) -> Option<AstFragment> { + if invoc.fragment_kind == AstFragmentKind::ForeignItems && + !self.cx.ecfg.macros_in_extern_enabled() { + if let SyntaxExtension::NonMacroAttr { .. } = *ext {} else { + emit_feature_err(&self.cx.parse_sess, "macros_in_extern", + invoc.span(), GateIssue::Language, + "macro invocations in `extern {}` blocks are experimental"); + } + } + let result = match invoc.kind { InvocationKind::Bang { .. } => self.expand_bang_invoc(invoc, ext)?, InvocationKind::Attr { .. } => self.expand_attr_invoc(invoc, ext)?, @@ -565,7 +557,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { _ => unreachable!(), }; - attr::mark_used(&attr); + if let NonMacroAttr { mark_used: false } = *ext {} else { + // Macro attrs are always used when expanded, + // non-macro attrs are considered used when the field says so. + attr::mark_used(&attr); + } invoc.expansion_data.mark.set_expn_info(ExpnInfo { call_site: attr.span, def_site: None, @@ -577,7 +573,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { }); match *ext { - NonMacroAttr => { + NonMacroAttr { .. } => { attr::mark_known(&attr); let item = item.map_attrs(|mut attrs| { attrs.push(attr); attrs }); Some(invoc.fragment_kind.expect_from_annotatables(iter::once(item))) @@ -827,7 +823,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } MultiDecorator(..) | MultiModifier(..) | - AttrProcMacro(..) | SyntaxExtension::NonMacroAttr => { + AttrProcMacro(..) | SyntaxExtension::NonMacroAttr { .. } => { self.cx.span_err(path.span, &format!("`{}` can only be used in attributes", path)); self.cx.trace_macros_diag(); @@ -1497,20 +1493,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { foreign_item: ast::ForeignItem) -> SmallVector<ast::ForeignItem> { let (attr, traits, foreign_item) = self.classify_item(foreign_item); - let explain = if self.cx.ecfg.use_extern_macros_enabled() { - feature_gate::EXPLAIN_PROC_MACROS_IN_EXTERN - } else { - feature_gate::EXPLAIN_MACROS_IN_EXTERN - }; - - if attr.is_some() || !traits.is_empty() { - if !self.cx.ecfg.macros_in_extern_enabled() { - if let Some(ref attr) = attr { - emit_feature_err(&self.cx.parse_sess, "macros_in_extern", attr.span, - GateIssue::Language, explain); - } - } - + if attr.is_some() || !traits.is_empty() { let item = Annotatable::ForeignItem(P(foreign_item)); return self.collect_attr(attr, traits, item, AstFragmentKind::ForeignItems) .make_foreign_items(); @@ -1518,12 +1501,6 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> { if let ast::ForeignItemKind::Macro(mac) = foreign_item.node { self.check_attributes(&foreign_item.attrs); - - if !self.cx.ecfg.macros_in_extern_enabled() { - emit_feature_err(&self.cx.parse_sess, "macros_in_extern", foreign_item.span, - GateIssue::Language, explain); - } - return self.collect_bang(mac, foreign_item.span, AstFragmentKind::ForeignItems) .make_foreign_items(); } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 6d71d276390..65eeaff3f10 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -32,7 +32,7 @@ use attr; use codemap::Spanned; use edition::{ALL_EDITIONS, Edition}; use syntax_pos::{Span, DUMMY_SP}; -use errors::{DiagnosticBuilder, Handler, FatalError}; +use errors::{DiagnosticBuilder, Handler}; use visit::{self, FnKind, Visitor}; use parse::ParseSess; use symbol::{keywords, Symbol}; @@ -83,8 +83,14 @@ macro_rules! declare_features { } pub fn use_extern_macros(&self) -> bool { - // The `decl_macro` and `tool_attributes` features imply `use_extern_macros`. - self.use_extern_macros || self.decl_macro || self.tool_attributes + // A number of "advanced" macro features enable + // macro modularization (`use_extern_macros`) implicitly. + self.use_extern_macros || self.decl_macro || + self.tool_attributes || self.custom_attribute || + self.macros_in_extern || self.proc_macro_path_invoc || + self.proc_macro_mod || self.proc_macro_expr || + self.proc_macro_non_items || self.proc_macro_gen || + self.stmt_expr_attributes } } }; @@ -714,7 +720,7 @@ pub fn is_builtin_attr_name(name: ast::Name) -> bool { } pub fn is_builtin_attr(attr: &ast::Attribute) -> bool { - BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.check_name(builtin_name)) || + BUILTIN_ATTRIBUTES.iter().any(|&(builtin_name, _, _)| attr.path == builtin_name) || attr.name().as_str().starts_with("rustc_") } @@ -1364,13 +1370,6 @@ pub const EXPLAIN_UNSIZED_TUPLE_COERCION: &'static str = pub const EXPLAIN_MACRO_AT_MOST_ONCE_REP: &'static str = "using the `?` macro Kleene operator for \"at most one\" repetition is unstable"; -pub const EXPLAIN_MACROS_IN_EXTERN: &'static str = - "macro invocations in `extern {}` blocks are experimental."; - -// mention proc-macros when enabled -pub const EXPLAIN_PROC_MACROS_IN_EXTERN: &'static str = - "macro and proc-macro invocations in `extern {}` blocks are experimental."; - struct PostExpansionVisitor<'a> { context: &'a Context<'a>, } @@ -1914,9 +1913,6 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } let mut features = Features::new(); - - let mut feature_checker = FeatureChecker::default(); - let mut edition_enabled_features = FxHashMap(); for &(name, .., f_edition, set) in ACTIVE_FEATURES.iter() { @@ -1982,7 +1978,6 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], ).emit(); } else { set(&mut features, mi.span); - feature_checker.collect(&features, mi.span); features.declared_lang_features.push((name, mi.span, None)); } continue @@ -2005,45 +2000,9 @@ pub fn get_features(span_handler: &Handler, krate_attrs: &[ast::Attribute], } } - feature_checker.check(span_handler); - features } -/// A collector for mutually exclusive and interdependent features and their flag spans. -#[derive(Default)] -struct FeatureChecker { - use_extern_macros: Option<Span>, - custom_attribute: Option<Span>, -} - -impl FeatureChecker { - // If this method turns out to be a hotspot due to branching, - // the branching can be eliminated by modifying `set!()` to set these spans - // only for the features that need to be checked for mutual exclusion. - fn collect(&mut self, features: &Features, span: Span) { - if features.use_extern_macros() { - // If self.use_extern_macros is None, set to Some(span) - self.use_extern_macros = self.use_extern_macros.or(Some(span)); - } - - if features.custom_attribute { - self.custom_attribute = self.custom_attribute.or(Some(span)); - } - } - - fn check(self, handler: &Handler) { - if let (Some(pm_span), Some(ca_span)) = (self.use_extern_macros, self.custom_attribute) { - handler.struct_span_err(pm_span, "Cannot use `#![feature(use_extern_macros)]` and \ - `#![feature(custom_attribute)] at the same time") - .span_note(ca_span, "`#![feature(custom_attribute)]` declared here") - .emit(); - - FatalError.raise(); - } - } -} - pub fn check_crate(krate: &ast::Crate, sess: &ParseSess, features: &Features, |
