about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-12-28 00:31:28 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2018-12-28 00:44:47 +0300
commite40d7d9643b810b2bc62f279e1d6f4ad68a35bc2 (patch)
treefa910b36cf72542f9a427860865c05471c4b4ee4
parent24af9f88a5555120eadc7897be7eeaa7c8e1f9af (diff)
downloadrust-e40d7d9643b810b2bc62f279e1d6f4ad68a35bc2.tar.gz
rust-e40d7d9643b810b2bc62f279e1d6f4ad68a35bc2.zip
Resolve `$crate`s for pretty-printing at more appropriate time
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs11
-rw-r--r--src/librustc_resolve/macros.rs25
-rw-r--r--src/libsyntax/ext/base.rs14
-rw-r--r--src/libsyntax/ext/expand.rs4
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-57089.rs3
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-57089.stderr11
-rw-r--r--src/test/ui/proc-macro/dollar-crate-issue-57089.stdout25
7 files changed, 53 insertions, 40 deletions
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 8f5d110655a..21fb29974c8 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -1025,15 +1025,4 @@ impl<'a, 'b> Visitor<'a> for BuildReducedGraphVisitor<'a, 'b> {
         }
         visit::walk_attribute(self, attr);
     }
-
-    fn visit_ident(&mut self, ident: Ident) {
-        if ident.name == keywords::DollarCrate.name() {
-            let name = match self.resolver.resolve_crate_root(ident).kind {
-                ModuleKind::Def(_, name) if name != keywords::Invalid.name() => name,
-                _ => keywords::Crate.name(),
-            };
-            ident.span.ctxt().set_dollar_crate_name(name);
-        }
-        visit::walk_ident(self, ident);
-    }
 }
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 98c6773cec3..9d91856f32b 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -1,6 +1,6 @@
 use {AmbiguityError, AmbiguityKind, AmbiguityErrorMisc};
 use {CrateLint, Resolver, ResolutionError, ScopeSet, Weak};
-use {Module, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
+use {Module, ModuleKind, NameBinding, NameBindingKind, PathResult, Segment, ToNameBinding};
 use {is_known_tool, resolve_error};
 use ModuleOrUniformRoot;
 use Namespace::*;
@@ -15,12 +15,13 @@ use syntax::ast::{self, Ident};
 use syntax::attr;
 use syntax::errors::DiagnosticBuilder;
 use syntax::ext::base::{self, Determinacy};
-use syntax::ext::base::{MacroKind, SyntaxExtension};
+use syntax::ext::base::{Annotatable, MacroKind, SyntaxExtension};
 use syntax::ext::expand::{AstFragment, Invocation, InvocationKind};
 use syntax::ext::hygiene::{self, Mark};
 use syntax::ext::tt::macro_rules;
 use syntax::feature_gate::{feature_err, is_builtin_attr_name, GateIssue};
 use syntax::symbol::{Symbol, keywords};
+use syntax::visit::Visitor;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax_pos::{Span, DUMMY_SP};
 use errors::Applicability;
@@ -126,6 +127,26 @@ impl<'a> base::Resolver for Resolver<'a> {
         mark
     }
 
+    fn resolve_dollar_crates(&mut self, annotatable: &Annotatable) {
+        pub struct ResolveDollarCrates<'a, 'b: 'a> {
+            pub resolver: &'a mut Resolver<'b>,
+        }
+        impl<'a> Visitor<'a> for ResolveDollarCrates<'a, '_> {
+            fn visit_ident(&mut self, ident: Ident) {
+                if ident.name == keywords::DollarCrate.name() {
+                    let name = match self.resolver.resolve_crate_root(ident).kind {
+                        ModuleKind::Def(_, name) if name != keywords::Invalid.name() => name,
+                        _ => keywords::Crate.name(),
+                    };
+                    ident.span.ctxt().set_dollar_crate_name(name);
+                }
+            }
+            fn visit_mac(&mut self, _: &ast::Mac) {}
+        }
+
+        annotatable.visit_with(&mut ResolveDollarCrates { resolver: self });
+    }
+
     fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
                                             derives: &[Mark]) {
         let invocation = self.invocations[&mark];
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index d576397c942..12375a35b6a 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -14,6 +14,7 @@ use parse::token;
 use ptr::P;
 use smallvec::SmallVec;
 use symbol::{keywords, Ident, Symbol};
+use visit::Visitor;
 use ThinVec;
 
 use rustc_data_structures::fx::FxHashMap;
@@ -135,6 +136,17 @@ impl Annotatable {
             _ => false,
         }
     }
+
+    pub fn visit_with<'a, V: Visitor<'a>>(&'a self, visitor: &mut V) {
+        match self {
+            Annotatable::Item(item) => visitor.visit_item(item),
+            Annotatable::TraitItem(trait_item) => visitor.visit_trait_item(trait_item),
+            Annotatable::ImplItem(impl_item) => visitor.visit_impl_item(impl_item),
+            Annotatable::ForeignItem(foreign_item) => visitor.visit_foreign_item(foreign_item),
+            Annotatable::Stmt(stmt) => visitor.visit_stmt(stmt),
+            Annotatable::Expr(expr) => visitor.visit_expr(expr),
+        }
+    }
 }
 
 // A more flexible ItemDecorator.
@@ -723,6 +735,7 @@ pub trait Resolver {
     fn next_node_id(&mut self) -> ast::NodeId;
     fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
 
+    fn resolve_dollar_crates(&mut self, annotatable: &Annotatable);
     fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
                                             derives: &[Mark]);
     fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
@@ -756,6 +769,7 @@ impl Resolver for DummyResolver {
     fn next_node_id(&mut self) -> ast::NodeId { ast::DUMMY_NODE_ID }
     fn get_module_scope(&mut self, _id: ast::NodeId) -> Mark { Mark::root() }
 
+    fn resolve_dollar_crates(&mut self, _annotatable: &Annotatable) {}
     fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment,
                                             _derives: &[Mark]) {}
     fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 55012bb7f5a..bca2fe254ce 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -576,6 +576,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                 Some(invoc.fragment_kind.expect_from_annotatables(items))
             }
             AttrProcMacro(ref mac, ..) => {
+                // Resolve `$crate`s in case we have to go though stringification.
+                self.cx.resolver.resolve_dollar_crates(&item);
                 self.gate_proc_macro_attr_item(attr.span, &item);
                 let item_tok = TokenTree::Token(DUMMY_SP, Token::interpolated(match item {
                     Annotatable::Item(item) => token::NtItem(item),
@@ -918,6 +920,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
 
         match *ext {
             ProcMacroDerive(ref ext, ..) => {
+                // Resolve `$crate`s in case we have to go though stringification.
+                self.cx.resolver.resolve_dollar_crates(&item);
                 invoc.expansion_data.mark.set_expn_info(expn_info);
                 let span = span.with_ctxt(self.cx.backtrace());
                 let dummy = ast::MetaItem { // FIXME(jseyfried) avoid this
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.rs b/src/test/ui/proc-macro/dollar-crate-issue-57089.rs
index c38b2782cd6..2d54c07ff95 100644
--- a/src/test/ui/proc-macro/dollar-crate-issue-57089.rs
+++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.rs
@@ -1,3 +1,4 @@
+// compile-pass
 // edition:2018
 // aux-build:dollar-crate.rs
 
@@ -15,7 +16,7 @@ macro_rules! m {
             struct M($crate::S);
         }
 
-        #[dollar_crate::a] //~ ERROR expected type, found `$`
+        #[dollar_crate::a]
         struct A($crate::S);
     };
 }
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stderr b/src/test/ui/proc-macro/dollar-crate-issue-57089.stderr
deleted file mode 100644
index f82cf22a9ce..00000000000
--- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stderr
+++ /dev/null
@@ -1,11 +0,0 @@
-error: expected type, found `$`
-  --> $DIR/dollar-crate-in-tokens.rs:18:9
-   |
-LL |         #[dollar_crate::a] //~ ERROR expected type, found `$`
-   |         ^^^^^^^^^^^^^^^^^^
-...
-LL | m!();
-   | ----- in this macro invocation
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
index f599a7f45b1..09340988c89 100644
--- a/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
+++ b/src/test/ui/proc-macro/dollar-crate-issue-57089.stdout
@@ -38,48 +38,43 @@ PROC MACRO INPUT: TokenStream [
         span: #2 bytes(LO..HI)
     }
 ]
-ATTRIBUTE INPUT (PRETTY-PRINTED): struct A($crate::S);
+ATTRIBUTE INPUT (PRETTY-PRINTED): struct A(crate::S);
 ATTRIBUTE INPUT: TokenStream [
     Ident {
         ident: "struct",
-        span: #0 bytes(0..0)
+        span: #2 bytes(LO..HI)
     },
     Ident {
         ident: "A",
-        span: #0 bytes(0..0)
+        span: #2 bytes(LO..HI)
     },
     Group {
         delimiter: Parenthesis,
         stream: TokenStream [
-            Punct {
-                ch: '$',
-                spacing: Alone,
-                span: #0 bytes(0..0)
-            },
             Ident {
-                ident: "crate",
-                span: #0 bytes(0..0)
+                ident: "$crate",
+                span: #2 bytes(LO..HI)
             },
             Punct {
                 ch: ':',
                 spacing: Joint,
-                span: #0 bytes(0..0)
+                span: #2 bytes(LO..HI)
             },
             Punct {
                 ch: ':',
                 spacing: Alone,
-                span: #0 bytes(0..0)
+                span: #2 bytes(LO..HI)
             },
             Ident {
                 ident: "S",
-                span: #0 bytes(0..0)
+                span: #2 bytes(LO..HI)
             }
         ],
-        span: #0 bytes(0..0)
+        span: #2 bytes(LO..HI)
     },
     Punct {
         ch: ';',
         spacing: Alone,
-        span: #0 bytes(0..0)
+        span: #2 bytes(LO..HI)
     }
 ]