diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index e3078a42f6538..f51ea3545e4c2 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::{CRATE_DEF_INDEX, DefIndex};
 use rustc::hir::map::{self, DefCollector};
@@ -21,7 +21,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_pos::Span;
 
@@ -97,6 +99,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 1f47a91fcc13e..63eee7df9e85d 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 3305c1eae2b00..e101757ad2322 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 0000000000000..969ed91f595e6
--- /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 0000000000000..d19b49ab18c07
--- /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() {}