From 472fcb5973b5f655c0d27c09bb1eb45c554857ba Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Tue, 1 Mar 2016 09:28:42 +0000 Subject: [PATCH] Fix the search paths for macro-expanded non-inline modules --- src/libsyntax/ext/base.rs | 8 +++++ src/libsyntax/ext/expand.rs | 47 +++++++++++++++++++++++++++-- src/libsyntax/ext/tt/macro_rules.rs | 8 ++++- 3 files changed, 60 insertions(+), 3 deletions(-) diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 2a9d96fa861..c0306b8494b 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -552,6 +552,10 @@ pub struct ExtCtxt<'a> { pub syntax_env: SyntaxEnv, pub recursion_count: usize, + + pub filename: Option, + pub mod_path_stack: Vec, + pub in_block: bool, } impl<'a> ExtCtxt<'a> { @@ -570,6 +574,10 @@ impl<'a> ExtCtxt<'a> { exported_macros: Vec::new(), syntax_env: env, recursion_count: 0, + + filename: None, + mod_path_stack: Vec::new(), + in_block: false, } } diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index e8e042c1321..e8098cfff45 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -1183,6 +1183,11 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } impl<'a, 'b> Folder for MacroExpander<'a, 'b> { + fn fold_crate(&mut self, c: Crate) -> Crate { + self.cx.filename = Some(self.cx.parse_sess.codemap().span_to_filename(c.span)); + noop_fold_crate(c, self) + } + fn fold_expr(&mut self, expr: P) -> P { expand_expr(expr, self) } @@ -1192,7 +1197,27 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { } fn fold_item(&mut self, item: P) -> SmallVector> { - expand_item(item, self) + use std::mem::replace; + let result; + if let ast::ItemKind::Mod(ast::Mod { inner, .. }) = item.node { + if item.span.contains(inner) { + self.push_mod_path(item.ident, &item.attrs); + result = expand_item(item, self); + self.pop_mod_path(); + } else { + let filename = if inner != codemap::DUMMY_SP { + Some(self.cx.parse_sess.codemap().span_to_filename(inner)) + } else { None }; + let orig_filename = replace(&mut self.cx.filename, filename); + let orig_mod_path_stack = replace(&mut self.cx.mod_path_stack, Vec::new()); + result = expand_item(item, self); + self.cx.filename = orig_filename; + self.cx.mod_path_stack = orig_mod_path_stack; + } + } else { + result = expand_item(item, self); + } + result } fn fold_item_kind(&mut self, item: ast::ItemKind) -> ast::ItemKind { @@ -1204,7 +1229,10 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { } fn fold_block(&mut self, block: P) -> P { - expand_block(block, self) + let was_in_block = ::std::mem::replace(&mut self.cx.in_block, true); + let result = expand_block(block, self); + self.cx.in_block = was_in_block; + result } fn fold_arm(&mut self, arm: ast::Arm) -> ast::Arm { @@ -1230,6 +1258,21 @@ impl<'a, 'b> Folder for MacroExpander<'a, 'b> { } } +impl<'a, 'b> MacroExpander<'a, 'b> { + fn push_mod_path(&mut self, id: Ident, attrs: &[ast::Attribute]) { + let default_path = id.name.as_str(); + let file_path = match ::attr::first_attr_value_str_by_name(attrs, "path") { + Some(d) => d, + None => default_path, + }; + self.cx.mod_path_stack.push(file_path) + } + + fn pop_mod_path(&mut self) { + self.cx.mod_path_stack.pop().unwrap(); + } +} + fn new_span(cx: &ExtCtxt, sp: Span) -> Span { /* this discards information in the case of macro-defining macros */ Span { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index c641c478a6b..77bae4cb3f6 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -16,7 +16,7 @@ use ext::tt::macro_parser::{Success, Error, Failure}; use ext::tt::macro_parser::{MatchedSeq, MatchedNonterminal}; use ext::tt::macro_parser::parse; use parse::lexer::new_tt_reader; -use parse::parser::Parser; +use parse::parser::{Parser, Restrictions}; use parse::token::{self, special_idents, gensym_ident, NtTT, Token}; use parse::token::Token::*; use print; @@ -195,6 +195,12 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, imported_from, rhs); let mut p = Parser::new(cx.parse_sess(), cx.cfg(), Box::new(trncbr)); + p.filename = cx.filename.clone(); + p.mod_path_stack = cx.mod_path_stack.clone(); + p.restrictions = match cx.in_block { + true => Restrictions::NO_NONINLINE_MOD, + false => Restrictions::empty(), + }; p.check_unknown_macro_variable(); // Let the context choose how to interpret the result. // Weird, but useful for X-macros.