Fix #44851 by visiting tokens in DefCollector and BuildReducedGraphVisitor

This commit is contained in:
sinkuu 2017-10-23 17:22:28 +09:00
parent 1042190f8c
commit c0ccab4c23
4 changed files with 81 additions and 2 deletions

View File

@ -16,6 +16,7 @@ use syntax::ext::hygiene::Mark;
use syntax::visit; use syntax::visit;
use syntax::symbol::keywords; use syntax::symbol::keywords;
use syntax::symbol::Symbol; use syntax::symbol::Symbol;
use syntax::parse::token::{self, Token};
use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE}; 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), _ => 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);
}
}
_ => {}
}
}
}
} }

View File

@ -40,7 +40,7 @@ use syntax::ext::base::SyntaxExtension;
use syntax::ext::base::Determinacy::Undetermined; use syntax::ext::base::Determinacy::Undetermined;
use syntax::ext::hygiene::Mark; use syntax::ext::hygiene::Mark;
use syntax::ext::tt::macro_rules; use syntax::ext::tt::macro_rules;
use syntax::parse::token; use syntax::parse::token::{self, Token};
use syntax::symbol::keywords; use syntax::symbol::keywords;
use syntax::symbol::Symbol; use syntax::symbol::Symbol;
use syntax::visit::{self, Visitor}; use syntax::visit::{self, Visitor};
@ -830,4 +830,17 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
visit::walk_trait_item(self, item); visit::walk_trait_item(self, item);
self.resolver.current_module = parent; 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);
}
}
_ => {}
}
}
}
} }

View File

@ -27,6 +27,8 @@ use abi::Abi;
use ast::*; use ast::*;
use syntax_pos::Span; use syntax_pos::Span;
use codemap::Spanned; use codemap::Spanned;
use parse::token::Token;
use tokenstream::{TokenTree, TokenStream};
#[derive(Copy, Clone, PartialEq, Eq)] #[derive(Copy, Clone, PartialEq, Eq)]
pub enum FnKind<'a> { pub enum FnKind<'a> {
@ -130,7 +132,16 @@ pub trait Visitor<'ast>: Sized {
fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) { fn visit_assoc_type_binding(&mut self, type_binding: &'ast TypeBinding) {
walk_assoc_type_binding(self, type_binding) 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) { fn visit_vis(&mut self, vis: &'ast Visibility) {
walk_vis(self, vis) 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); 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);
}
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}