diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index fe6909f759159..de7a3dc5ceeb2 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -138,7 +138,23 @@ impl<'a> base::Resolver for Resolver<'a> {
         struct EliminateCrateVar<'b, 'a: 'b>(&'b mut Resolver<'a>, Span);
 
         impl<'a, 'b> Folder for EliminateCrateVar<'a, 'b> {
-            fn fold_path(&mut self, mut path: ast::Path) -> ast::Path {
+            fn fold_path(&mut self, path: ast::Path) -> ast::Path {
+                match self.fold_qpath(None, path) {
+                    (None, path) => path,
+                    _ => unreachable!(),
+                }
+            }
+
+            fn fold_qpath(&mut self, mut qself: Option<ast::QSelf>, mut path: ast::Path)
+                          -> (Option<ast::QSelf>, ast::Path) {
+                qself = qself.map(|ast::QSelf { ty, path_span, position }| {
+                    ast::QSelf {
+                        ty: self.fold_ty(ty),
+                        path_span: self.new_span(path_span),
+                        position,
+                    }
+                });
+
                 let ident = path.segments[0].ident;
                 if ident.name == keywords::DollarCrate.name() {
                     path.segments[0].ident.name = keywords::CrateRoot.name();
@@ -150,10 +166,13 @@ impl<'a> base::Resolver for Resolver<'a> {
                                 ast::Ident::with_empty_ctxt(name).with_span_pos(span)
                             ),
                             _ => unreachable!(),
-                        })
+                        });
+                        if let Some(qself) = &mut qself {
+                            qself.position += 1;
+                        }
                     }
                 }
-                path
+                (qself, path)
             }
 
             fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 2f209b347a4b6..1056b3dad1739 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -168,6 +168,10 @@ pub trait Folder : Sized {
         noop_fold_path(p, self)
     }
 
+    fn fold_qpath(&mut self, qs: Option<QSelf>, p: Path) -> (Option<QSelf>, Path) {
+        noop_fold_qpath(qs, p, self)
+    }
+
     fn fold_path_parameters(&mut self, p: PathParameters) -> PathParameters {
         noop_fold_path_parameters(p, self)
     }
@@ -370,14 +374,8 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
             TyKind::Tup(tys) => TyKind::Tup(tys.move_map(|ty| fld.fold_ty(ty))),
             TyKind::Paren(ty) => TyKind::Paren(fld.fold_ty(ty)),
             TyKind::Path(qself, path) => {
-                let qself = qself.map(|QSelf { ty, path_span, position }| {
-                    QSelf {
-                        ty: fld.fold_ty(ty),
-                        path_span: fld.new_span(path_span),
-                        position,
-                    }
-                });
-                TyKind::Path(qself, fld.fold_path(path))
+                let (qself, path) = fld.fold_qpath(qself, path);
+                TyKind::Path(qself, path)
             }
             TyKind::Array(ty, length) => {
                 TyKind::Array(fld.fold_ty(ty), fld.fold_anon_const(length))
@@ -442,6 +440,19 @@ pub fn noop_fold_path<T: Folder>(Path { segments, span }: Path, fld: &mut T) ->
     }
 }
 
+pub fn noop_fold_qpath<T: Folder>(qself: Option<QSelf>,
+                                  path: Path,
+                                  fld: &mut T) -> (Option<QSelf>, Path) {
+    let qself = qself.map(|QSelf { ty, path_span, position }| {
+        QSelf {
+            ty: fld.fold_ty(ty),
+            path_span: fld.new_span(path_span),
+            position,
+        }
+    });
+    (qself, fld.fold_path(path))
+}
+
 pub fn noop_fold_path_parameters<T: Folder>(path_parameters: PathParameters, fld: &mut T)
                                             -> PathParameters
 {
@@ -1097,15 +1108,9 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
                 PatKind::TupleStruct(folder.fold_path(pth),
                         pats.move_map(|x| folder.fold_pat(x)), ddpos)
             }
-            PatKind::Path(opt_qself, pth) => {
-                let opt_qself = opt_qself.map(|qself| {
-                    QSelf {
-                        ty: folder.fold_ty(qself.ty),
-                        path_span: folder.new_span(qself.path_span),
-                        position: qself.position,
-                    }
-                });
-                PatKind::Path(opt_qself, folder.fold_path(pth))
+            PatKind::Path(qself, pth) => {
+                let (qself, pth) = folder.fold_qpath(qself, pth);
+                PatKind::Path(qself, pth)
             }
             PatKind::Struct(pth, fields, etc) => {
                 let pth = folder.fold_path(pth);
@@ -1267,14 +1272,8 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span, attrs}: Expr, folder: &mu
                                 lim)
             }
             ExprKind::Path(qself, path) => {
-                let qself = qself.map(|QSelf { ty, path_span, position }| {
-                    QSelf {
-                        ty: folder.fold_ty(ty),
-                        path_span: folder.new_span(path_span),
-                        position,
-                    }
-                });
-                ExprKind::Path(qself, folder.fold_path(path))
+                let (qself, path) = folder.fold_qpath(qself, path);
+                ExprKind::Path(qself, path)
             }
             ExprKind::Break(opt_label, opt_expr) => {
                 ExprKind::Break(opt_label.map(|label| folder.fold_label(label)),
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs
index f4404b737f952..a6c9817f24714 100644
--- a/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/double.rs
@@ -16,6 +16,8 @@ extern crate proc_macro;
 
 use proc_macro::TokenStream;
 
+// Outputs another copy of the struct.  Useful for testing the tokens
+// seen by the proc_macro.
 #[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/auxiliary/external-crate-var.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/external-crate-var.rs
new file mode 100644
index 0000000000000..030c53b3e6f32
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/external-crate-var.rs
@@ -0,0 +1,51 @@
+// 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.
+
+pub struct ExternFoo;
+
+pub trait ExternTrait {
+    const CONST: u32;
+    type Assoc;
+}
+
+impl ExternTrait for ExternFoo {
+    const CONST: u32 = 0;
+    type Assoc = ExternFoo;
+}
+
+#[macro_export]
+macro_rules! external { () => {
+    mod bar {
+        #[derive(Double)]
+        struct Bar($crate::ExternFoo);
+    }
+
+    mod qself {
+        #[derive(Double)]
+        struct QSelf(<$crate::ExternFoo as $crate::ExternTrait>::Assoc);
+    }
+
+    mod qself_recurse {
+        #[derive(Double)]
+        struct QSelfRecurse(<
+            <$crate::ExternFoo as $crate::ExternTrait>::Assoc
+            as $crate::ExternTrait>::Assoc
+        );
+    }
+
+    mod qself_in_const {
+        #[derive(Double)]
+        #[repr(u32)]
+        enum QSelfInConst {
+            Variant = <$crate::ExternFoo as $crate::ExternTrait>::CONST,
+        }
+    }
+} }
+
diff --git a/src/test/run-pass-fulldeps/proc-macro/crate-var.rs b/src/test/run-pass-fulldeps/proc-macro/crate-var.rs
index b6acb0faab2a5..41c15195bc840 100644
--- a/src/test/run-pass-fulldeps/proc-macro/crate-var.rs
+++ b/src/test/run-pass-fulldeps/proc-macro/crate-var.rs
@@ -9,19 +9,63 @@
 // except according to those terms.
 
 // aux-build:double.rs
+// aux-build:external-crate-var.rs
 // ignore-stage1
 
 #![allow(unused)]
 
 #[macro_use]
 extern crate double;
+#[macro_use]
+extern crate external_crate_var;
 
 struct Foo;
 
-macro_rules! m { () => {
-    #[derive(Double)]
-    struct Bar($crate::Foo);
+trait Trait {
+    const CONST: u32;
+    type Assoc;
+}
+
+impl Trait for Foo {
+    const CONST: u32 = 0;
+    type Assoc = Foo;
+}
+
+macro_rules! local { () => {
+    // derive_Double outputs secondary copies of each definition
+    // to test what the proc_macro sees.
+    mod bar {
+        #[derive(Double)]
+        struct Bar($crate::Foo);
+    }
+
+    mod qself {
+        #[derive(Double)]
+        struct QSelf(<::Foo as $crate::Trait>::Assoc);
+    }
+
+    mod qself_recurse {
+        #[derive(Double)]
+        struct QSelfRecurse(<<$crate::Foo as $crate::Trait>::Assoc as $crate::Trait>::Assoc);
+    }
+
+    mod qself_in_const {
+        #[derive(Double)]
+        #[repr(u32)]
+        enum QSelfInConst {
+            Variant = <::Foo as $crate::Trait>::CONST,
+        }
+    }
 } }
-m!();
+
+mod local {
+    local!();
+}
+
+// and now repeat the above tests, using a macro defined in another crate
+
+mod external {
+    external!{}
+}
 
 fn main() {}