about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-11-10 11:25:17 -0800
committerGitHub <noreply@github.com>2016-11-10 11:25:17 -0800
commit3dced6f71e6e8cf8f59e3614194a61427a3a408b (patch)
treed774bf9b6a1fda191695d4917979b0243652812d
parentbc1cc1db6ddee8d57d20adc05b740e3b73649ab5 (diff)
parent67eeb0a72081ae7db45a07de55fd2cb77b2ebee1 (diff)
Auto merge of #37645 - jseyfried:fix_crate_var_in_custom_derives, r=nrc
Fix regression involving custom derives on items with `$crate`

The regression was introduced in #37213.

I believe we cannot make the improvements from #37213 work with the current custom derive setup (c.f. https://github.com/rust-lang/rust/issues/37637#issuecomment-258959145) -- we'll have to wait for `TokenStream`'s API to improve.

Fixes #37637.
r? @nrc
-rw-r--r--src/librustc_resolve/macros.rs29
-rw-r--r--src/libsyntax/ext/base.rs2
-rw-r--r--src/libsyntax_ext/deriving/custom.rs2
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs24
-rw-r--r--src/test/run-pass-fulldeps/proc-macro/crate-var.rs27
5 files changed, 82 insertions, 2 deletions
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index f9d91e3aa63..f30c129c48f 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use {Module, Resolver};
+use {Module, ModuleKind, Resolver};
 use build_reduced_graph::BuildReducedGraphVisitor;
 use rustc::hir::def_id::{DefId, BUILTIN_MACROS_CRATE, CRATE_DEF_INDEX, DefIndex};
 use rustc::hir::def::{Def, Export};
@@ -22,7 +22,9 @@ use syntax::ext::base::{NormalTT, SyntaxExtension};
 use syntax::ext::expand::Expansion;
 use syntax::ext::hygiene::Mark;
 use syntax::ext::tt::macro_rules;
+use syntax::fold::Folder;
 use syntax::parse::token::intern;
+use syntax::ptr::P;
 use syntax::util::lev_distance::find_best_match_for_name;
 use syntax::visit::Visitor;
 use syntax_pos::Span;
@@ -99,6 +101,31 @@ impl<'a> base::Resolver for Resolver<'a> {
         mark
     }
 
+    fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> {
+        struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>);
+
+        impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> {
+            fn fold_path(&mut self, mut path: ast::Path) -> ast::Path {
+                let ident = path.segments[0].identifier;
+                if &ident.name.as_str() == "$crate" {
+                    path.global = true;
+                    let module = self.0.resolve_crate_var(ident.ctxt);
+                    if module.is_local() {
+                        path.segments.remove(0);
+                    } else {
+                        path.segments[0].identifier = match module.kind {
+                            ModuleKind::Def(_, name) => ast::Ident::with_empty_ctxt(name),
+                            _ => unreachable!(),
+                        };
+                    }
+                }
+                path
+            }
+        }
+
+        EliminateCrateVar(self).fold_item(item).expect_one("")
+    }
+
     fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion) {
         let invocation = self.invocations[&mark];
         self.collect_def_ids(invocation, expansion);
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index 1f47a91fcc1..63eee7df9e8 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -517,6 +517,7 @@ pub type NamedSyntaxExtension = (Name, SyntaxExtension);
 pub trait Resolver {
     fn next_node_id(&mut self) -> ast::NodeId;
     fn get_module_scope(&mut self, id: ast::NodeId) -> Mark;
+    fn eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item>;
 
     fn visit_expansion(&mut self, mark: Mark, expansion: &Expansion);
     fn add_macro(&mut self, scope: Mark, def: ast::MacroDef, export: bool);
@@ -539,6 +540,7 @@ pub struct DummyResolver;
 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 eliminate_crate_var(&mut self, item: P<ast::Item>) -> P<ast::Item> { item }
 
     fn visit_expansion(&mut self, _invoc: Mark, _expansion: &Expansion) {}
     fn add_macro(&mut self, _scope: Mark, _def: ast::MacroDef, _export: bool) {}
diff --git a/src/libsyntax_ext/deriving/custom.rs b/src/libsyntax_ext/deriving/custom.rs
index 3305c1eae2b..e101757ad23 100644
--- a/src/libsyntax_ext/deriving/custom.rs
+++ b/src/libsyntax_ext/deriving/custom.rs
@@ -73,7 +73,7 @@ impl MultiItemModifier for CustomDerive {
         // Mark attributes as known, and used.
         MarkAttrs(&self.attrs).visit_item(&item);
 
-        let input = __internal::new_token_stream(item.clone());
+        let input = __internal::new_token_stream(ecx.resolver.eliminate_crate_var(item.clone()));
         let res = __internal::set_parse_sess(&ecx.parse_sess, || {
             let inner = self.inner;
             panic::catch_unwind(panic::AssertUnwindSafe(|| inner(input)))
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs
new file mode 100644
index 00000000000..969ed91f595
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs
@@ -0,0 +1,24 @@
+// Copyright 2016 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.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro)]
+#![feature(proc_macro_lib)]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Double)]
+pub fn derive(input: TokenStream) -> TokenStream {
+    format!("mod foo {{ {} }}", input.to_string()).parse().unwrap()
+}
diff --git a/src/test/run-pass-fulldeps/proc-macro/crate-var.rs b/src/test/run-pass-fulldeps/proc-macro/crate-var.rs
new file mode 100644
index 00000000000..d19b49ab18c
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/crate-var.rs
@@ -0,0 +1,27 @@
+// Copyright 2016 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.
+
+// aux-build:double.rs
+
+#![feature(proc_macro)]
+#![allow(unused)]
+
+#[macro_use]
+extern crate double;
+
+struct Foo;
+
+macro_rules! m { () => {
+    #[derive(Double)]
+    struct Bar($crate::Foo);
+} }
+m!();
+
+fn main() {}