From c0ccab4c2330659b67edb5889d7f9ee702aebbe3 Mon Sep 17 00:00:00 2001 From: sinkuu Date: Mon, 23 Oct 2017 17:22:28 +0900 Subject: [PATCH] Fix #44851 by visiting tokens in `DefCollector` and `BuildReducedGraphVisitor` --- src/librustc/hir/map/def_collector.rs | 14 ++++++++++ src/librustc_resolve/build_reduced_graph.rs | 15 ++++++++++- src/libsyntax/visit.rs | 30 ++++++++++++++++++++- src/test/run-pass/issue-44851.rs | 24 +++++++++++++++++ 4 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 src/test/run-pass/issue-44851.rs diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index 673e6d3bbfb..567f0ee3b0d 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -16,6 +16,7 @@ use syntax::ext::hygiene::Mark; use syntax::visit; use syntax::symbol::keywords; use syntax::symbol::Symbol; +use syntax::parse::token::{self, Token}; use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE}; @@ -283,4 +284,17 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> { _ => visit::walk_stmt(self, stmt), } } + + fn visit_token(&mut self, t: Token) { + if let Token::Interpolated(nt) = t { + match nt.0 { + token::NtExpr(ref expr) => { + if let ExprKind::Mac(..) = expr.node { + self.visit_macro_invoc(expr.id, false); + } + } + _ => {} + } + } + } } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index a4d1ae16215..7b1a602d849 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -40,7 +40,7 @@ use syntax::ext::base::SyntaxExtension; use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::hygiene::Mark; use syntax::ext::tt::macro_rules; -use syntax::parse::token; +use syntax::parse::token::{self, Token}; use syntax::symbol::keywords; use syntax::symbol::Symbol; use syntax::visit::{self, Visitor}; @@ -830,4 +830,17 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> { visit::walk_trait_item(self, item); self.resolver.current_module = parent; } + + fn visit_token(&mut self, t: Token) { + if let Token::Interpolated(nt) = t { + match nt.0 { + token::NtExpr(ref expr) => { + if let ast::ExprKind::Mac(..) = expr.node { + self.visit_invoc(expr.id); + } + } + _ => {} + } + } + } } diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index 521c6030eba..7893145a4a7 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -27,6 +27,8 @@ use abi::Abi; use ast::*; use syntax_pos::Span; use codemap::Spanned; +use parse::token::Token; +use tokenstream::{TokenTree, TokenStream}; #[derive(Copy, Clone, PartialEq, Eq)] pub enum FnKind<'a> { @@ -130,7 +132,16 @@ pub trait Visitor<'ast>: Sized { fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) { walk_assoc_type_binding(self, type_binding) } - fn visit_attribute(&mut self, _attr: &'ast Attribute) {} + fn visit_attribute(&mut self, attr: &'ast Attribute) { + walk_attribute(self, attr) + } + fn visit_tt(&mut self, tt: TokenTree) { + walk_tt(self, tt) + } + fn visit_tts(&mut self, tts: TokenStream) { + walk_tts(self, tts) + } + fn visit_token(&mut self, _t: Token) {} fn visit_vis(&mut self, vis: &'ast Visibility) { walk_vis(self, vis) } @@ -810,3 +821,20 @@ pub fn walk_vis<'a, V: Visitor<'a>>(visitor: &mut V, vis: &'a Visibility) { visitor.visit_path(path, id); } } + +pub fn walk_attribute<'a, V: Visitor<'a>>(visitor: &mut V, attr: &'a Attribute) { + visitor.visit_tts(attr.tokens.clone()); +} + +pub fn walk_tt<'a, V: Visitor<'a>>(visitor: &mut V, tt: TokenTree) { + match tt { + TokenTree::Token(_, tok) => visitor.visit_token(tok), + TokenTree::Delimited(_, delimed) => visitor.visit_tts(delimed.stream()), + } +} + +pub fn walk_tts<'a, V: Visitor<'a>>(visitor: &mut V, tts: TokenStream) { + for tt in tts.trees() { + visitor.visit_tt(tt); + } +} diff --git a/src/test/run-pass/issue-44851.rs b/src/test/run-pass/issue-44851.rs new file mode 100644 index 00000000000..62d675b13be --- /dev/null +++ b/src/test/run-pass/issue-44851.rs @@ -0,0 +1,24 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! a { + () => { "a" } +} + +macro_rules! b { + ($doc:expr) => { + #[doc = $doc] + pub struct B; + } +} + +b!(a!()); + +fn main() {}