From 39c0fa847e74e59f96dc6b01d912252f8cdb72eb Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 19 Nov 2019 21:35:11 -0500 Subject: Move syntax_expand::config to rustc_parse::config --- src/librustc_parse/config.rs | 375 ++++++++++++++++++++++++++++++++++++ src/librustc_parse/lib.rs | 2 + src/librustc_parse/parser/module.rs | 2 +- src/libsyntax_expand/config.rs | 365 ----------------------------------- src/libsyntax_expand/expand.rs | 2 +- src/libsyntax_expand/lib.rs | 2 +- 6 files changed, 380 insertions(+), 368 deletions(-) create mode 100644 src/librustc_parse/config.rs delete mode 100644 src/libsyntax_expand/config.rs (limited to 'src') diff --git a/src/librustc_parse/config.rs b/src/librustc_parse/config.rs new file mode 100644 index 00000000000..7ce555ed57a --- /dev/null +++ b/src/librustc_parse/config.rs @@ -0,0 +1,375 @@ +//! Process the potential `cfg` attributes on a module. +//! Also determine if the module should be included in this configuration. +//! +//! This module properly belongs in syntax_expand, but for now it's tied into +//! parsing, so we leave it here to avoid complicated out-of-line dependencies. +//! +//! A principled solution to this wrong location would be to implement [#64197]. +//! +//! [#64197]: https://github.com/rust-lang/rust/issues/64197 + +use crate::validate_attr; +use syntax::attr::HasAttrs; +use syntax::feature_gate::{ + feature_err, + EXPLAIN_STMT_ATTR_SYNTAX, + Features, + get_features, + GateIssue, +}; +use syntax::attr; +use syntax::ast; +use syntax::edition::Edition; +use syntax::mut_visit::*; +use syntax::ptr::P; +use syntax::sess::ParseSess; +use syntax::util::map_in_place::MapInPlace; +use syntax_pos::symbol::sym; + +use errors::Applicability; +use smallvec::SmallVec; + +/// A folder that strips out items that do not belong in the current configuration. +pub struct StripUnconfigured<'a> { + pub sess: &'a ParseSess, + pub features: Option<&'a Features>, +} + +// `cfg_attr`-process the crate's attributes and compute the crate's features. +pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition, + allow_features: &Option>) -> (ast::Crate, Features) { + let features; + { + let mut strip_unconfigured = StripUnconfigured { + sess, + features: None, + }; + + let unconfigured_attrs = krate.attrs.clone(); + let err_count = sess.span_diagnostic.err_count(); + if let Some(attrs) = strip_unconfigured.configure(krate.attrs) { + krate.attrs = attrs; + } else { // the entire crate is unconfigured + krate.attrs = Vec::new(); + krate.module.items = Vec::new(); + return (krate, Features::new()); + } + + features = get_features(&sess.span_diagnostic, &krate.attrs, edition, allow_features); + + // Avoid reconfiguring malformed `cfg_attr`s + if err_count == sess.span_diagnostic.err_count() { + strip_unconfigured.features = Some(&features); + strip_unconfigured.configure(unconfigured_attrs); + } + } + + (krate, features) +} + +#[macro_export] +macro_rules! configure { + ($this:ident, $node:ident) => { + match $this.configure($node) { + Some(node) => node, + None => return Default::default(), + } + } +} + +impl<'a> StripUnconfigured<'a> { + pub fn configure(&mut self, mut node: T) -> Option { + self.process_cfg_attrs(&mut node); + if self.in_cfg(node.attrs()) { Some(node) } else { None } + } + + /// Parse and expand all `cfg_attr` attributes into a list of attributes + /// that are within each `cfg_attr` that has a true configuration predicate. + /// + /// Gives compiler warnigns if any `cfg_attr` does not contain any + /// attributes and is in the original source code. Gives compiler errors if + /// the syntax of any `cfg_attr` is incorrect. + pub fn process_cfg_attrs(&mut self, node: &mut T) { + node.visit_attrs(|attrs| { + attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); + }); + } + + /// Parse and expand a single `cfg_attr` attribute into a list of attributes + /// when the configuration predicate is true, or otherwise expand into an + /// empty list of attributes. + /// + /// Gives a compiler warning when the `cfg_attr` contains no attributes and + /// is in the original source file. Gives a compiler error if the syntax of + /// the attribute is incorrect. + fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec { + if !attr.has_name(sym::cfg_attr) { + return vec![attr]; + } + if attr.get_normal_item().tokens.is_empty() { + self.sess.span_diagnostic + .struct_span_err( + attr.span, + "malformed `cfg_attr` attribute input", + ).span_suggestion( + attr.span, + "missing condition and attribute", + "#[cfg_attr(condition, attribute, other_attribute, ...)]".to_owned(), + Applicability::HasPlaceholders, + ).note("for more information, visit \ + ") + .emit(); + return vec![]; + } + + let res = crate::parse_in_attr(self.sess, &attr, |p| p.parse_cfg_attr()); + let (cfg_predicate, expanded_attrs) = match res { + Ok(result) => result, + Err(mut e) => { + e.emit(); + return vec![]; + } + }; + + // Lint on zero attributes in source. + if expanded_attrs.is_empty() { + return vec![attr]; + } + + // At this point we know the attribute is considered used. + attr::mark_used(&attr); + + if attr::cfg_matches(&cfg_predicate, self.sess, self.features) { + // We call `process_cfg_attr` recursively in case there's a + // `cfg_attr` inside of another `cfg_attr`. E.g. + // `#[cfg_attr(false, cfg_attr(true, some_attr))]`. + expanded_attrs.into_iter() + .flat_map(|(item, span)| self.process_cfg_attr(attr::mk_attr_from_item( + attr.style, + item, + span, + ))) + .collect() + } else { + vec![] + } + } + + /// Determines if a node with the given attributes should be included in this configuration. + pub fn in_cfg(&self, attrs: &[ast::Attribute]) -> bool { + attrs.iter().all(|attr| { + if !is_cfg(attr) { + return true; + } + + let error = |span, msg, suggestion: &str| { + let mut err = self.sess.span_diagnostic.struct_span_err(span, msg); + if !suggestion.is_empty() { + err.span_suggestion( + span, + "expected syntax is", + suggestion.into(), + Applicability::MaybeIncorrect, + ); + } + err.emit(); + true + }; + + let meta_item = match validate_attr::parse_meta(self.sess, attr) { + Ok(meta_item) => meta_item, + Err(mut err) => { err.emit(); return true; } + }; + let nested_meta_items = if let Some(nested_meta_items) = meta_item.meta_item_list() { + nested_meta_items + } else { + return error(meta_item.span, "`cfg` is not followed by parentheses", + "cfg(/* predicate */)"); + }; + + if nested_meta_items.is_empty() { + return error(meta_item.span, "`cfg` predicate is not specified", ""); + } else if nested_meta_items.len() > 1 { + return error(nested_meta_items.last().unwrap().span(), + "multiple `cfg` predicates are specified", ""); + } + + match nested_meta_items[0].meta_item() { + Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features), + None => error(nested_meta_items[0].span(), + "`cfg` predicate key cannot be a literal", ""), + } + }) + } + + /// Visit attributes on expression and statements (but not attributes on items in blocks). + fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) { + // flag the offending attributes + for attr in attrs.iter() { + self.maybe_emit_expr_attr_err(attr); + } + } + + /// If attributes are not allowed on expressions, emit an error for `attr` + pub fn maybe_emit_expr_attr_err(&self, attr: &ast::Attribute) { + if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) { + let mut err = feature_err(self.sess, + sym::stmt_expr_attributes, + attr.span, + GateIssue::Language, + EXPLAIN_STMT_ATTR_SYNTAX); + + if attr.is_doc_comment() { + err.help("`///` is for documentation comments. For a plain comment, use `//`."); + } + + err.emit(); + } + } + + pub fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) { + let ast::ForeignMod { abi: _, items } = foreign_mod; + items.flat_map_in_place(|item| self.configure(item)); + } + + pub fn configure_generic_params(&mut self, params: &mut Vec) { + params.flat_map_in_place(|param| self.configure(param)); + } + + fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) { + match vdata { + ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) => + fields.flat_map_in_place(|field| self.configure(field)), + ast::VariantData::Unit(_) => {} + } + } + + pub fn configure_item_kind(&mut self, item: &mut ast::ItemKind) { + match item { + ast::ItemKind::Struct(def, _generics) | + ast::ItemKind::Union(def, _generics) => self.configure_variant_data(def), + ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => { + variants.flat_map_in_place(|variant| self.configure(variant)); + for variant in variants { + self.configure_variant_data(&mut variant.data); + } + } + _ => {} + } + } + + pub fn configure_expr_kind(&mut self, expr_kind: &mut ast::ExprKind) { + match expr_kind { + ast::ExprKind::Match(_m, arms) => { + arms.flat_map_in_place(|arm| self.configure(arm)); + } + ast::ExprKind::Struct(_path, fields, _base) => { + fields.flat_map_in_place(|field| self.configure(field)); + } + _ => {} + } + } + + pub fn configure_expr(&mut self, expr: &mut P) { + self.visit_expr_attrs(expr.attrs()); + + // If an expr is valid to cfg away it will have been removed by the + // outer stmt or expression folder before descending in here. + // Anything else is always required, and thus has to error out + // in case of a cfg attr. + // + // N.B., this is intentionally not part of the visit_expr() function + // in order for filter_map_expr() to be able to avoid this check + if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) { + let msg = "removing an expression is not supported in this position"; + self.sess.span_diagnostic.span_err(attr.span, msg); + } + + self.process_cfg_attrs(expr) + } + + pub fn configure_pat(&mut self, pat: &mut P) { + if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.kind { + fields.flat_map_in_place(|field| self.configure(field)); + } + } + + pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) { + fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg)); + } +} + +impl<'a> MutVisitor for StripUnconfigured<'a> { + fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) { + self.configure_foreign_mod(foreign_mod); + noop_visit_foreign_mod(foreign_mod, self); + } + + fn visit_item_kind(&mut self, item: &mut ast::ItemKind) { + self.configure_item_kind(item); + noop_visit_item_kind(item, self); + } + + fn visit_expr(&mut self, expr: &mut P) { + self.configure_expr(expr); + self.configure_expr_kind(&mut expr.kind); + noop_visit_expr(expr, self); + } + + fn filter_map_expr(&mut self, expr: P) -> Option> { + let mut expr = configure!(self, expr); + self.configure_expr_kind(&mut expr.kind); + noop_visit_expr(&mut expr, self); + Some(expr) + } + + fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { + noop_flat_map_stmt(configure!(self, stmt), self) + } + + fn flat_map_item(&mut self, item: P) -> SmallVec<[P; 1]> { + noop_flat_map_item(configure!(self, item), self) + } + + fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> { + noop_flat_map_impl_item(configure!(self, item), self) + } + + fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> { + noop_flat_map_trait_item(configure!(self, item), self) + } + + fn visit_mac(&mut self, _mac: &mut ast::Mac) { + // Don't configure interpolated AST (cf. issue #34171). + // Interpolated AST will get configured once the surrounding tokens are parsed. + } + + fn visit_pat(&mut self, pat: &mut P) { + self.configure_pat(pat); + noop_visit_pat(pat, self) + } + + fn visit_fn_decl(&mut self, mut fn_decl: &mut P) { + self.configure_fn_decl(&mut fn_decl); + noop_visit_fn_decl(fn_decl, self); + } +} + +fn is_cfg(attr: &ast::Attribute) -> bool { + attr.check_name(sym::cfg) +} + +/// Process the potential `cfg` attributes on a module. +/// Also determine if the module should be included in this configuration. +pub fn process_configure_mod( + sess: &ParseSess, + cfg_mods: bool, + attrs: &[ast::Attribute], +) -> (bool, Vec) { + // Don't perform gated feature checking. + let mut strip_unconfigured = StripUnconfigured { sess, features: None }; + let mut attrs = attrs.to_owned(); + strip_unconfigured.process_cfg_attrs(&mut attrs); + (!cfg_mods || strip_unconfigured.in_cfg(&attrs), attrs) +} diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs index 3a983404220..1215c7a199a 100644 --- a/src/librustc_parse/lib.rs +++ b/src/librustc_parse/lib.rs @@ -25,6 +25,8 @@ pub mod parser; use parser::{Parser, emit_unclosed_delims, make_unclosed_delims_error}; pub mod lexer; pub mod validate_attr; +#[macro_use] +pub mod config; #[derive(Clone)] pub struct Directory<'a> { diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 3110f15e80b..1621c9ffc02 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -41,7 +41,7 @@ impl<'a> Parser<'a> { /// Parses a `mod { ... }` or `mod ;` item. pub(super) fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> { // HACK(Centril): See documentation on `ParseSess::process_cfg_mod`. - let (in_cfg, outer_attrs) = (self.sess.process_cfg_mod)( + let (in_cfg, outer_attrs) = crate::config::process_configure_mod( self.sess, self.cfg_mods, outer_attrs, diff --git a/src/libsyntax_expand/config.rs b/src/libsyntax_expand/config.rs deleted file mode 100644 index 7b927fb55f9..00000000000 --- a/src/libsyntax_expand/config.rs +++ /dev/null @@ -1,365 +0,0 @@ -use rustc_parse::validate_attr; -use syntax::attr::HasAttrs; -use syntax::feature_gate::{ - feature_err, - EXPLAIN_STMT_ATTR_SYNTAX, - Features, - get_features, - GateIssue, -}; -use syntax::attr; -use syntax::ast; -use syntax::edition::Edition; -use syntax::mut_visit::*; -use syntax::ptr::P; -use syntax::sess::ParseSess; -use syntax::util::map_in_place::MapInPlace; -use syntax_pos::symbol::sym; - -use errors::Applicability; -use smallvec::SmallVec; - -/// A folder that strips out items that do not belong in the current configuration. -pub struct StripUnconfigured<'a> { - pub sess: &'a ParseSess, - pub features: Option<&'a Features>, -} - -// `cfg_attr`-process the crate's attributes and compute the crate's features. -pub fn features(mut krate: ast::Crate, sess: &ParseSess, edition: Edition, - allow_features: &Option>) -> (ast::Crate, Features) { - let features; - { - let mut strip_unconfigured = StripUnconfigured { - sess, - features: None, - }; - - let unconfigured_attrs = krate.attrs.clone(); - let err_count = sess.span_diagnostic.err_count(); - if let Some(attrs) = strip_unconfigured.configure(krate.attrs) { - krate.attrs = attrs; - } else { // the entire crate is unconfigured - krate.attrs = Vec::new(); - krate.module.items = Vec::new(); - return (krate, Features::new()); - } - - features = get_features(&sess.span_diagnostic, &krate.attrs, edition, allow_features); - - // Avoid reconfiguring malformed `cfg_attr`s - if err_count == sess.span_diagnostic.err_count() { - strip_unconfigured.features = Some(&features); - strip_unconfigured.configure(unconfigured_attrs); - } - } - - (krate, features) -} - -#[macro_export] -macro_rules! configure { - ($this:ident, $node:ident) => { - match $this.configure($node) { - Some(node) => node, - None => return Default::default(), - } - } -} - -impl<'a> StripUnconfigured<'a> { - pub fn configure(&mut self, mut node: T) -> Option { - self.process_cfg_attrs(&mut node); - if self.in_cfg(node.attrs()) { Some(node) } else { None } - } - - /// Parse and expand all `cfg_attr` attributes into a list of attributes - /// that are within each `cfg_attr` that has a true configuration predicate. - /// - /// Gives compiler warnigns if any `cfg_attr` does not contain any - /// attributes and is in the original source code. Gives compiler errors if - /// the syntax of any `cfg_attr` is incorrect. - pub fn process_cfg_attrs(&mut self, node: &mut T) { - node.visit_attrs(|attrs| { - attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr)); - }); - } - - /// Parse and expand a single `cfg_attr` attribute into a list of attributes - /// when the configuration predicate is true, or otherwise expand into an - /// empty list of attributes. - /// - /// Gives a compiler warning when the `cfg_attr` contains no attributes and - /// is in the original source file. Gives a compiler error if the syntax of - /// the attribute is incorrect. - fn process_cfg_attr(&mut self, attr: ast::Attribute) -> Vec { - if !attr.has_name(sym::cfg_attr) { - return vec![attr]; - } - if attr.get_normal_item().tokens.is_empty() { - self.sess.span_diagnostic - .struct_span_err( - attr.span, - "malformed `cfg_attr` attribute input", - ).span_suggestion( - attr.span, - "missing condition and attribute", - "#[cfg_attr(condition, attribute, other_attribute, ...)]".to_owned(), - Applicability::HasPlaceholders, - ).note("for more information, visit \ - ") - .emit(); - return vec![]; - } - - let res = rustc_parse::parse_in_attr(self.sess, &attr, |p| p.parse_cfg_attr()); - let (cfg_predicate, expanded_attrs) = match res { - Ok(result) => result, - Err(mut e) => { - e.emit(); - return vec![]; - } - }; - - // Lint on zero attributes in source. - if expanded_attrs.is_empty() { - return vec![attr]; - } - - // At this point we know the attribute is considered used. - attr::mark_used(&attr); - - if attr::cfg_matches(&cfg_predicate, self.sess, self.features) { - // We call `process_cfg_attr` recursively in case there's a - // `cfg_attr` inside of another `cfg_attr`. E.g. - // `#[cfg_attr(false, cfg_attr(true, some_attr))]`. - expanded_attrs.into_iter() - .flat_map(|(item, span)| self.process_cfg_attr(attr::mk_attr_from_item( - attr.style, - item, - span, - ))) - .collect() - } else { - vec![] - } - } - - /// Determines if a node with the given attributes should be included in this configuration. - pub fn in_cfg(&self, attrs: &[ast::Attribute]) -> bool { - attrs.iter().all(|attr| { - if !is_cfg(attr) { - return true; - } - - let error = |span, msg, suggestion: &str| { - let mut err = self.sess.span_diagnostic.struct_span_err(span, msg); - if !suggestion.is_empty() { - err.span_suggestion( - span, - "expected syntax is", - suggestion.into(), - Applicability::MaybeIncorrect, - ); - } - err.emit(); - true - }; - - let meta_item = match validate_attr::parse_meta(self.sess, attr) { - Ok(meta_item) => meta_item, - Err(mut err) => { err.emit(); return true; } - }; - let nested_meta_items = if let Some(nested_meta_items) = meta_item.meta_item_list() { - nested_meta_items - } else { - return error(meta_item.span, "`cfg` is not followed by parentheses", - "cfg(/* predicate */)"); - }; - - if nested_meta_items.is_empty() { - return error(meta_item.span, "`cfg` predicate is not specified", ""); - } else if nested_meta_items.len() > 1 { - return error(nested_meta_items.last().unwrap().span(), - "multiple `cfg` predicates are specified", ""); - } - - match nested_meta_items[0].meta_item() { - Some(meta_item) => attr::cfg_matches(meta_item, self.sess, self.features), - None => error(nested_meta_items[0].span(), - "`cfg` predicate key cannot be a literal", ""), - } - }) - } - - /// Visit attributes on expression and statements (but not attributes on items in blocks). - fn visit_expr_attrs(&mut self, attrs: &[ast::Attribute]) { - // flag the offending attributes - for attr in attrs.iter() { - self.maybe_emit_expr_attr_err(attr); - } - } - - /// If attributes are not allowed on expressions, emit an error for `attr` - pub fn maybe_emit_expr_attr_err(&self, attr: &ast::Attribute) { - if !self.features.map(|features| features.stmt_expr_attributes).unwrap_or(true) { - let mut err = feature_err(self.sess, - sym::stmt_expr_attributes, - attr.span, - GateIssue::Language, - EXPLAIN_STMT_ATTR_SYNTAX); - - if attr.is_doc_comment() { - err.help("`///` is for documentation comments. For a plain comment, use `//`."); - } - - err.emit(); - } - } - - pub fn configure_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) { - let ast::ForeignMod { abi: _, items } = foreign_mod; - items.flat_map_in_place(|item| self.configure(item)); - } - - pub fn configure_generic_params(&mut self, params: &mut Vec) { - params.flat_map_in_place(|param| self.configure(param)); - } - - fn configure_variant_data(&mut self, vdata: &mut ast::VariantData) { - match vdata { - ast::VariantData::Struct(fields, ..) | ast::VariantData::Tuple(fields, _) => - fields.flat_map_in_place(|field| self.configure(field)), - ast::VariantData::Unit(_) => {} - } - } - - pub fn configure_item_kind(&mut self, item: &mut ast::ItemKind) { - match item { - ast::ItemKind::Struct(def, _generics) | - ast::ItemKind::Union(def, _generics) => self.configure_variant_data(def), - ast::ItemKind::Enum(ast::EnumDef { variants }, _generics) => { - variants.flat_map_in_place(|variant| self.configure(variant)); - for variant in variants { - self.configure_variant_data(&mut variant.data); - } - } - _ => {} - } - } - - pub fn configure_expr_kind(&mut self, expr_kind: &mut ast::ExprKind) { - match expr_kind { - ast::ExprKind::Match(_m, arms) => { - arms.flat_map_in_place(|arm| self.configure(arm)); - } - ast::ExprKind::Struct(_path, fields, _base) => { - fields.flat_map_in_place(|field| self.configure(field)); - } - _ => {} - } - } - - pub fn configure_expr(&mut self, expr: &mut P) { - self.visit_expr_attrs(expr.attrs()); - - // If an expr is valid to cfg away it will have been removed by the - // outer stmt or expression folder before descending in here. - // Anything else is always required, and thus has to error out - // in case of a cfg attr. - // - // N.B., this is intentionally not part of the visit_expr() function - // in order for filter_map_expr() to be able to avoid this check - if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(a)) { - let msg = "removing an expression is not supported in this position"; - self.sess.span_diagnostic.span_err(attr.span, msg); - } - - self.process_cfg_attrs(expr) - } - - pub fn configure_pat(&mut self, pat: &mut P) { - if let ast::PatKind::Struct(_path, fields, _etc) = &mut pat.kind { - fields.flat_map_in_place(|field| self.configure(field)); - } - } - - pub fn configure_fn_decl(&mut self, fn_decl: &mut ast::FnDecl) { - fn_decl.inputs.flat_map_in_place(|arg| self.configure(arg)); - } -} - -impl<'a> MutVisitor for StripUnconfigured<'a> { - fn visit_foreign_mod(&mut self, foreign_mod: &mut ast::ForeignMod) { - self.configure_foreign_mod(foreign_mod); - noop_visit_foreign_mod(foreign_mod, self); - } - - fn visit_item_kind(&mut self, item: &mut ast::ItemKind) { - self.configure_item_kind(item); - noop_visit_item_kind(item, self); - } - - fn visit_expr(&mut self, expr: &mut P) { - self.configure_expr(expr); - self.configure_expr_kind(&mut expr.kind); - noop_visit_expr(expr, self); - } - - fn filter_map_expr(&mut self, expr: P) -> Option> { - let mut expr = configure!(self, expr); - self.configure_expr_kind(&mut expr.kind); - noop_visit_expr(&mut expr, self); - Some(expr) - } - - fn flat_map_stmt(&mut self, stmt: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { - noop_flat_map_stmt(configure!(self, stmt), self) - } - - fn flat_map_item(&mut self, item: P) -> SmallVec<[P; 1]> { - noop_flat_map_item(configure!(self, item), self) - } - - fn flat_map_impl_item(&mut self, item: ast::ImplItem) -> SmallVec<[ast::ImplItem; 1]> { - noop_flat_map_impl_item(configure!(self, item), self) - } - - fn flat_map_trait_item(&mut self, item: ast::TraitItem) -> SmallVec<[ast::TraitItem; 1]> { - noop_flat_map_trait_item(configure!(self, item), self) - } - - fn visit_mac(&mut self, _mac: &mut ast::Mac) { - // Don't configure interpolated AST (cf. issue #34171). - // Interpolated AST will get configured once the surrounding tokens are parsed. - } - - fn visit_pat(&mut self, pat: &mut P) { - self.configure_pat(pat); - noop_visit_pat(pat, self) - } - - fn visit_fn_decl(&mut self, mut fn_decl: &mut P) { - self.configure_fn_decl(&mut fn_decl); - noop_visit_fn_decl(fn_decl, self); - } -} - -fn is_cfg(attr: &ast::Attribute) -> bool { - attr.check_name(sym::cfg) -} - -/// Process the potential `cfg` attributes on a module. -/// Also determine if the module should be included in this configuration. -pub fn process_configure_mod( - sess: &ParseSess, - cfg_mods: bool, - attrs: &[ast::Attribute], -) -> (bool, Vec) { - // Don't perform gated feature checking. - let mut strip_unconfigured = StripUnconfigured { sess, features: None }; - let mut attrs = attrs.to_owned(); - strip_unconfigured.process_cfg_attrs(&mut attrs); - (!cfg_mods || strip_unconfigured.in_cfg(&attrs), attrs) -} diff --git a/src/libsyntax_expand/expand.rs b/src/libsyntax_expand/expand.rs index 06aa5deb6e0..2532bbc0fe2 100644 --- a/src/libsyntax_expand/expand.rs +++ b/src/libsyntax_expand/expand.rs @@ -4,7 +4,7 @@ use crate::hygiene::{ExpnId, SyntaxContext, ExpnData, ExpnKind}; use crate::mbe::macro_rules::annotate_err_with_kind; use crate::placeholders::{placeholder, PlaceholderExpander}; use crate::config::StripUnconfigured; -use crate::configure; +use rustc_parse::configure; use rustc_parse::DirectoryOwnership; use rustc_parse::parser::Parser; diff --git a/src/libsyntax_expand/lib.rs b/src/libsyntax_expand/lib.rs index 46d59dd249c..0aa34af7a76 100644 --- a/src/libsyntax_expand/lib.rs +++ b/src/libsyntax_expand/lib.rs @@ -33,7 +33,7 @@ pub use mbe::macro_rules::compile_declarative_macro; pub mod base; pub mod build; pub mod expand; -#[macro_use] pub mod config; +pub use rustc_parse::config; pub mod proc_macro; crate mod mbe; -- cgit 1.4.1-3-g733a5 From 70805e6444c7519167c6fb386586bf1099b502eb Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 19 Nov 2019 21:38:31 -0500 Subject: Delete ProcessCfgMod The previous commit removes the use of this, and now we cleanup. --- src/librustc/session/mod.rs | 8 +------- src/librustc_interface/interface.rs | 3 +-- src/librustc_interface/tests.rs | 3 +-- src/librustc_interface/util.rs | 2 -- src/librustc_parse/parser/module.rs | 1 - src/librustdoc/html/highlight.rs | 3 +-- src/librustdoc/passes/check_code_block_syntax.rs | 3 +-- src/librustdoc/test.rs | 3 +-- src/libsyntax/sess.rs | 24 +++++----------------- src/libsyntax_expand/parse/lexer/tests.rs | 3 --- src/libsyntax_expand/parse/tests.rs | 3 +-- src/libsyntax_expand/tests.rs | 5 ++--- src/test/ui-fulldeps/ast_stmt_expr_attr.rs | 3 +-- src/test/ui-fulldeps/mod_dir_path_canonicalized.rs | 3 +-- src/test/ui-fulldeps/pprust-expr-roundtrip.rs | 3 +-- 15 files changed, 17 insertions(+), 53 deletions(-) (limited to 'src') diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 1af20188ab5..af6522df61e 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -24,7 +24,7 @@ use syntax::edition::Edition; use syntax::feature_gate; use errors::json::JsonEmitter; use syntax::source_map; -use syntax::sess::{ParseSess, ProcessCfgMod}; +use syntax::sess::ParseSess; use syntax_pos::{MultiSpan, Span}; use rustc_target::spec::{PanicStrategy, RelroLevel, Target, TargetTriple}; @@ -925,7 +925,6 @@ pub fn build_session( sopts: config::Options, local_crate_source_file: Option, registry: errors::registry::Registry, - process_cfg_mod: ProcessCfgMod, ) -> Session { let file_path_mapping = sopts.file_path_mapping(); @@ -936,7 +935,6 @@ pub fn build_session( Lrc::new(source_map::SourceMap::new(file_path_mapping)), DiagnosticOutput::Default, Default::default(), - process_cfg_mod, ) } @@ -1015,7 +1013,6 @@ pub fn build_session_with_source_map( source_map: Lrc, diagnostics_output: DiagnosticOutput, lint_caps: FxHashMap, - process_cfg_mod: ProcessCfgMod, ) -> Session { // FIXME: This is not general enough to make the warning lint completely override // normal diagnostic warnings, since the warning lint can also be denied and changed @@ -1061,7 +1058,6 @@ pub fn build_session_with_source_map( diagnostic_handler, source_map, lint_caps, - process_cfg_mod, ) } @@ -1071,7 +1067,6 @@ fn build_session_( span_diagnostic: errors::Handler, source_map: Lrc, driver_lint_caps: FxHashMap, - process_cfg_mod: ProcessCfgMod, ) -> Session { let self_profiler = if let SwitchWithOptPath::Enabled(ref d) = sopts.debugging_opts.self_profile { @@ -1109,7 +1104,6 @@ fn build_session_( let parse_sess = ParseSess::with_span_handler( span_diagnostic, source_map, - process_cfg_mod, ); let sysroot = match &sopts.maybe_sysroot { Some(sysroot) => sysroot.clone(), diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs index c153de7103a..70ed4aad7b4 100644 --- a/src/librustc_interface/interface.rs +++ b/src/librustc_interface/interface.rs @@ -21,7 +21,6 @@ use syntax::ast::{self, MetaItemKind}; use syntax::token; use syntax::source_map::{FileName, FileLoader, SourceMap}; use syntax::sess::ParseSess; -use syntax_expand::config::process_configure_mod; use syntax_pos::edition; pub type Result = result::Result; @@ -69,7 +68,7 @@ impl Compiler { pub fn parse_cfgspecs(cfgspecs: Vec) -> FxHashSet<(String, Option)> { syntax::with_default_globals(move || { let cfg = cfgspecs.into_iter().map(|s| { - let sess = ParseSess::with_silent_emitter(process_configure_mod); + let sess = ParseSess::with_silent_emitter(); let filename = FileName::cfg_spec_source_code(&s); let mut parser = new_parser_from_source_str(&sess, filename, s.to_string()); diff --git a/src/librustc_interface/tests.rs b/src/librustc_interface/tests.rs index 8c1dac21576..d39a5d3a073 100644 --- a/src/librustc_interface/tests.rs +++ b/src/librustc_interface/tests.rs @@ -17,7 +17,6 @@ use rustc_target::spec::{MergeFunctions, PanicStrategy, RelroLevel}; use syntax::symbol::sym; use syntax::edition::{Edition, DEFAULT_EDITION}; use syntax; -use syntax_expand::config::process_configure_mod; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ColorConfig, emitter::HumanReadableErrorType, registry}; @@ -32,7 +31,7 @@ fn build_session_options_and_crate_config(matches: getopts::Matches) -> (Options fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) { let registry = registry::Registry::new(&[]); let (sessopts, cfg) = build_session_options_and_crate_config(matches); - let sess = build_session(sessopts, None, registry, process_configure_mod); + let sess = build_session(sessopts, None, registry); (sess, cfg) } diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs index 2b4320c04e6..d8e20e17ce8 100644 --- a/src/librustc_interface/util.rs +++ b/src/librustc_interface/util.rs @@ -31,7 +31,6 @@ use syntax::util::lev_distance::find_best_match_for_name; use syntax::source_map::{FileLoader, RealFileLoader, SourceMap}; use syntax::symbol::{Symbol, sym}; use syntax::{self, ast, attr}; -use syntax_expand::config::process_configure_mod; use syntax_pos::edition::Edition; #[cfg(not(parallel_compiler))] use std::{thread, panic}; @@ -81,7 +80,6 @@ pub fn create_session( source_map.clone(), diagnostic_output, lint_caps, - process_configure_mod, ); sess.prof.register_queries(|profiler| { diff --git a/src/librustc_parse/parser/module.rs b/src/librustc_parse/parser/module.rs index 1621c9ffc02..59d7c2b4239 100644 --- a/src/librustc_parse/parser/module.rs +++ b/src/librustc_parse/parser/module.rs @@ -40,7 +40,6 @@ impl<'a> Parser<'a> { /// Parses a `mod { ... }` or `mod ;` item. pub(super) fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> PResult<'a, ItemInfo> { - // HACK(Centril): See documentation on `ParseSess::process_cfg_mod`. let (in_cfg, outer_attrs) = crate::config::process_configure_mod( self.sess, self.cfg_mods, diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index bf4a1440e1b..bfc82ad6e8b 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -16,7 +16,6 @@ use syntax::token::{self, Token}; use syntax::sess::ParseSess; use syntax::source_map::SourceMap; use syntax::symbol::{kw, sym}; -use syntax_expand::config::process_configure_mod; use syntax_pos::{Span, FileName}; /// Highlights `src`, returning the HTML output. @@ -34,7 +33,7 @@ pub fn render_with_highlighting( class, tooltip).unwrap(); } - let sess = ParseSess::with_silent_emitter(process_configure_mod); + let sess = ParseSess::with_silent_emitter(); let fm = sess.source_map().new_source_file( FileName::Custom(String::from("rustdoc-highlighting")), src.to_owned(), diff --git a/src/librustdoc/passes/check_code_block_syntax.rs b/src/librustdoc/passes/check_code_block_syntax.rs index 5c4c975cec0..8d5463ddbd7 100644 --- a/src/librustdoc/passes/check_code_block_syntax.rs +++ b/src/librustdoc/passes/check_code_block_syntax.rs @@ -3,7 +3,6 @@ use rustc_parse::lexer::{StringReader as Lexer}; use syntax::token; use syntax::sess::ParseSess; use syntax::source_map::FilePathMapping; -use syntax_expand::config::process_configure_mod; use syntax_pos::{InnerSpan, FileName}; use crate::clean; @@ -28,7 +27,7 @@ struct SyntaxChecker<'a, 'tcx> { impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> { fn check_rust_syntax(&self, item: &clean::Item, dox: &str, code_block: RustCodeBlock) { - let sess = ParseSess::new(FilePathMapping::empty(), process_configure_mod); + let sess = ParseSess::new(FilePathMapping::empty()); let source_file = sess.source_map().new_source_file( FileName::Custom(String::from("doctest")), dox[code_block.code].to_owned(), diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 98e18d666f1..22f209b8bad 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -17,7 +17,6 @@ use std::path::PathBuf; use std::process::{self, Command, Stdio}; use std::str; use syntax::symbol::sym; -use syntax_expand::config::process_configure_mod; use syntax_pos::{BytePos, DUMMY_SP, Pos, Span, FileName}; use tempfile::Builder as TempFileBuilder; use testing; @@ -415,7 +414,7 @@ pub fn make_test(s: &str, let emitter = EmitterWriter::new(box io::sink(), None, false, false, false, None, false); // FIXME(misdreavus): pass `-Z treat-err-as-bug` to the doctest parser let handler = Handler::with_emitter(false, None, box emitter); - let sess = ParseSess::with_span_handler(handler, cm, process_configure_mod); + let sess = ParseSess::with_span_handler(handler, cm); let mut found_main = false; let mut found_extern_crate = cratename.is_none(); diff --git a/src/libsyntax/sess.rs b/src/libsyntax/sess.rs index 953f0d1d190..740e9dfe459 100644 --- a/src/libsyntax/sess.rs +++ b/src/libsyntax/sess.rs @@ -1,7 +1,7 @@ //! Contains `ParseSess` which holds state living beyond what one `Parser` might. //! It also serves as an input to the parser itself. -use crate::ast::{CrateConfig, NodeId, Attribute}; +use crate::ast::{CrateConfig, NodeId}; use crate::early_buffered_lints::{BufferedEarlyLint, BufferedEarlyLintId}; use crate::source_map::{SourceMap, FilePathMapping}; use crate::feature_gate::UnstableFeatures; @@ -89,22 +89,10 @@ pub struct ParseSess { pub gated_spans: GatedSpans, /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors. pub reached_eof: Lock, - /// Process the potential `cfg` attributes on a module. - /// Also determine if the module should be included in this configuration. - /// - /// HACK(Centril): This is used to break a cyclic dependency between - /// the parser and cfg-stripping as defined in `syntax_expand::config`. - /// The dependency edge from the parser comes from `parse_item_mod`. - /// A principled solution to this hack would be to implement [#64197]. - /// - /// [#64197]: https://github.com/rust-lang/rust/issues/64197 - pub process_cfg_mod: ProcessCfgMod, } -pub type ProcessCfgMod = fn(&ParseSess, bool, &[Attribute]) -> (bool, Vec); - impl ParseSess { - pub fn new(file_path_mapping: FilePathMapping, process_cfg_mod: ProcessCfgMod) -> Self { + pub fn new(file_path_mapping: FilePathMapping) -> Self { let cm = Lrc::new(SourceMap::new(file_path_mapping)); let handler = Handler::with_tty_emitter( ColorConfig::Auto, @@ -112,17 +100,15 @@ impl ParseSess { None, Some(cm.clone()), ); - ParseSess::with_span_handler(handler, cm, process_cfg_mod) + ParseSess::with_span_handler(handler, cm) } pub fn with_span_handler( handler: Handler, source_map: Lrc, - process_cfg_mod: ProcessCfgMod, ) -> Self { Self { span_diagnostic: handler, - process_cfg_mod, unstable_features: UnstableFeatures::from_environment(), config: FxHashSet::default(), edition: ExpnId::root().expn_data().edition, @@ -138,10 +124,10 @@ impl ParseSess { } } - pub fn with_silent_emitter(process_cfg_mod: ProcessCfgMod) -> Self { + pub fn with_silent_emitter() -> Self { let cm = Lrc::new(SourceMap::new(FilePathMapping::empty())); let handler = Handler::with_emitter(false, None, Box::new(SilentEmitter)); - ParseSess::with_span_handler(handler, cm, process_cfg_mod) + ParseSess::with_span_handler(handler, cm) } #[inline] diff --git a/src/libsyntax_expand/parse/lexer/tests.rs b/src/libsyntax_expand/parse/lexer/tests.rs index d8a1c359c95..75e4ee805b2 100644 --- a/src/libsyntax_expand/parse/lexer/tests.rs +++ b/src/libsyntax_expand/parse/lexer/tests.rs @@ -1,5 +1,3 @@ -use crate::config::process_configure_mod; - use rustc_data_structures::sync::Lrc; use rustc_parse::lexer::StringReader; use syntax::token::{self, Token, TokenKind}; @@ -27,7 +25,6 @@ fn mk_sess(sm: Lrc) -> ParseSess { ParseSess::with_span_handler( Handler::with_emitter(true, None, Box::new(emitter)), sm, - process_configure_mod, ) } diff --git a/src/libsyntax_expand/parse/tests.rs b/src/libsyntax_expand/parse/tests.rs index 60911617995..08950ddefba 100644 --- a/src/libsyntax_expand/parse/tests.rs +++ b/src/libsyntax_expand/parse/tests.rs @@ -1,4 +1,3 @@ -use crate::config::process_configure_mod; use crate::tests::{matches_codepattern, string_to_stream, with_error_checking_parse}; use rustc_parse::new_parser_from_source_str; @@ -19,7 +18,7 @@ use errors::PResult; use std::path::PathBuf; fn sess() -> ParseSess { - ParseSess::new(FilePathMapping::empty(), process_configure_mod) + ParseSess::new(FilePathMapping::empty()) } /// Parses an item. diff --git a/src/libsyntax_expand/tests.rs b/src/libsyntax_expand/tests.rs index 2683620e845..425eb305845 100644 --- a/src/libsyntax_expand/tests.rs +++ b/src/libsyntax_expand/tests.rs @@ -1,4 +1,3 @@ -use crate::config::process_configure_mod; use rustc_parse::{source_file_to_stream, new_parser_from_source_str, parser::Parser}; use syntax::ast; use syntax::tokenstream::TokenStream; @@ -34,7 +33,7 @@ crate fn with_error_checking_parse<'a, T, F>(s: String, ps: &'a ParseSess, f: F) /// Maps a string to tts, using a made-up filename. crate fn string_to_stream(source_str: String) -> TokenStream { - let ps = ParseSess::new(FilePathMapping::empty(), process_configure_mod); + let ps = ParseSess::new(FilePathMapping::empty()); source_file_to_stream( &ps, ps.source_map().new_source_file(PathBuf::from("bogofile").into(), @@ -44,7 +43,7 @@ crate fn string_to_stream(source_str: String) -> TokenStream { /// Parses a string, returns a crate. crate fn string_to_crate(source_str : String) -> ast::Crate { - let ps = ParseSess::new(FilePathMapping::empty(), process_configure_mod); + let ps = ParseSess::new(FilePathMapping::empty()); with_error_checking_parse(source_str, &ps, |p| { p.parse_crate_mod() }) diff --git a/src/test/ui-fulldeps/ast_stmt_expr_attr.rs b/src/test/ui-fulldeps/ast_stmt_expr_attr.rs index 0bf17302b06..d6d49df63ef 100644 --- a/src/test/ui-fulldeps/ast_stmt_expr_attr.rs +++ b/src/test/ui-fulldeps/ast_stmt_expr_attr.rs @@ -22,7 +22,6 @@ use syntax::source_map::{FilePathMapping, FileName}; use syntax::ptr::P; use syntax::print::pprust; use syntax::token; -use syntax_expand::config::process_configure_mod; use std::fmt; // Copied out of syntax::util::parser_testing @@ -75,7 +74,7 @@ fn str_compare String>(e: &str, expected: &[T], actual: &[T], f: } fn sess() -> ParseSess { - ParseSess::new(FilePathMapping::empty(), process_configure_mod) + ParseSess::new(FilePathMapping::empty()) } fn check_expr_attrs(es: &str, expected: &[&str]) { diff --git a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs index 2411b9634c3..cf675831cfe 100644 --- a/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs +++ b/src/test/ui-fulldeps/mod_dir_path_canonicalized.rs @@ -12,7 +12,6 @@ use rustc_parse::new_parser_from_file; use std::path::Path; use syntax::sess::ParseSess; use syntax::source_map::FilePathMapping; -use syntax_expand::config::process_configure_mod; #[path = "mod_dir_simple/test.rs"] mod gravy; @@ -24,7 +23,7 @@ pub fn main() { } fn parse() { - let parse_session = ParseSess::new(FilePathMapping::empty(), process_configure_mod); + let parse_session = ParseSess::new(FilePathMapping::empty()); let path = Path::new(file!()); let path = path.canonicalize().unwrap(); diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs index 5da0297f645..290562046e2 100644 --- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs +++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs @@ -33,7 +33,6 @@ use syntax::source_map::FilePathMapping; use syntax::mut_visit::{self, MutVisitor, visit_clobber}; use syntax::print::pprust; use syntax::ptr::P; -use syntax_expand::config::process_configure_mod; fn parse_expr(ps: &ParseSess, src: &str) -> Option> { let src_as_string = src.to_string(); @@ -205,7 +204,7 @@ fn main() { } fn run() { - let ps = ParseSess::new(FilePathMapping::empty(), process_configure_mod); + let ps = ParseSess::new(FilePathMapping::empty()); iter_exprs(2, &mut |mut e| { // If the pretty printer is correct, then `parse(print(e))` should be identical to `e`, -- cgit 1.4.1-3-g733a5