diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 22f788e34ecff..4a6841aedca12 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -95,7 +95,7 @@ impl FromStr for TokenStream {
             // notify the expansion info that it is unhygienic
             let mark = Mark::fresh(mark);
             mark.set_expn_info(expn_info);
-            let span = call_site.with_ctxt(SyntaxContext::empty().apply_mark(mark));
+            let span = call_site.with_ctxt(call_site.ctxt().apply_mark(mark));
             let stream = parse::parse_stream_from_source_str(name, src, sess, Some(span));
             Ok(__internal::token_stream_wrap(stream))
         })
diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs
index dfa675f2e9351..7c2f0bc3cef84 100644
--- a/src/librustc/hir/map/definitions.rs
+++ b/src/librustc/hir/map/definitions.rs
@@ -575,7 +575,8 @@ impl Definitions {
             self.node_to_def_index.insert(node_id, index);
         }
 
-        if expansion.is_modern() {
+        let expansion = expansion.modern();
+        if expansion != Mark::root() {
             self.expansions.insert(index, expansion);
         }
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 3243152527ffc..85e2144f6cd79 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -1560,6 +1560,15 @@ impl<'a> Resolver<'a> {
         }
     }
 
+    fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
+        loop {
+            match self.macro_defs.get(&ctxt.outer()) {
+                Some(&def_id) => return def_id,
+                None => ctxt.remove_mark(),
+            };
+        }
+    }
+
     /// Entry point to crate resolution.
     pub fn resolve_crate(&mut self, krate: &Crate) {
         ImportResolver { resolver: self }.finalize_imports();
@@ -1663,7 +1672,7 @@ impl<'a> Resolver<'a> {
 
             module = match self.ribs[ns][i].kind {
                 ModuleRibKind(module) => module,
-                MacroDefinition(def) if def == self.macro_defs[&ident.ctxt.outer()] => {
+                MacroDefinition(def) if def == self.macro_def(ident.ctxt) => {
                     // If an invocation of this macro created `ident`, give up on `ident`
                     // and switch to `ident`'s source from the macro definition.
                     ident.ctxt.remove_mark();
@@ -1830,7 +1839,7 @@ impl<'a> Resolver<'a> {
                 // If an invocation of this macro created `ident`, give up on `ident`
                 // and switch to `ident`'s source from the macro definition.
                 MacroDefinition(def) => {
-                    if def == self.macro_defs[&ident.ctxt.outer()] {
+                    if def == self.macro_def(ident.ctxt) {
                         ident.ctxt.remove_mark();
                     }
                 }
diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs
index 951163d35fa0f..6f20104dda5d7 100644
--- a/src/libsyntax/parse/lexer/mod.rs
+++ b/src/libsyntax/parse/lexer/mod.rs
@@ -73,6 +73,13 @@ impl<'a> StringReader<'a> {
     fn mk_sp(&self, lo: BytePos, hi: BytePos) -> Span {
         unwrap_or!(self.override_span, Span::new(lo, hi, NO_EXPANSION))
     }
+    fn mk_ident(&self, string: &str) -> Ident {
+        let mut ident = Ident::from_str(string);
+        if let Some(span) = self.override_span {
+            ident.ctxt = span.ctxt();
+        }
+        ident
+    }
 
     fn next_token(&mut self) -> TokenAndSpan where Self: Sized {
         let res = self.try_next_token();
@@ -1103,7 +1110,7 @@ impl<'a> StringReader<'a> {
                     token::Underscore
                 } else {
                     // FIXME: perform NFKC normalization here. (Issue #2253)
-                    token::Ident(Ident::from_str(string))
+                    token::Ident(self.mk_ident(string))
                 }
             }));
         }
@@ -1286,13 +1293,13 @@ impl<'a> StringReader<'a> {
                     // expansion purposes. See #12512 for the gory details of why
                     // this is necessary.
                     let ident = self.with_str_from(start, |lifetime_name| {
-                        Ident::from_str(&format!("'{}", lifetime_name))
+                        self.mk_ident(&format!("'{}", lifetime_name))
                     });
 
                     // Conjure up a "keyword checking ident" to make sure that
                     // the lifetime name is not a keyword.
                     let keyword_checking_ident = self.with_str_from(start, |lifetime_name| {
-                        Ident::from_str(lifetime_name)
+                        self.mk_ident(lifetime_name)
                     });
                     let keyword_checking_token = &token::Ident(keyword_checking_ident);
                     let last_bpos = self.pos;
diff --git a/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs b/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs
index b1fb7d42d8683..773b16b945f07 100644
--- a/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs
+++ b/src/test/compile-fail-fulldeps/proc-macro/lints_in_proc_macros.rs
@@ -23,5 +23,5 @@ fn main() {
     bang_proc_macro2!();
     //~^ ERROR cannot find value `foobar2` in this scope
     //~^^ did you mean `foobar`?
-    println!("{}", x);
+    println!("{}", x); //~ ERROR cannot find value `x` in this scope
 }
diff --git a/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-42708.rs b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-42708.rs
new file mode 100644
index 0000000000000..58b4b2a5293b3
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/auxiliary/issue-42708.rs
@@ -0,0 +1,28 @@
+// 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.
+
+// no-prefer-dynamic
+
+#![crate_type = "proc-macro"]
+#![feature(proc_macro)]
+
+extern crate proc_macro;
+
+use proc_macro::TokenStream;
+
+#[proc_macro_derive(Test)]
+pub fn derive(_input: TokenStream) -> TokenStream {
+    "fn f(s: S) { s.x }".parse().unwrap()
+}
+
+#[proc_macro_attribute]
+pub fn attr_test(_attr: TokenStream, input: TokenStream) -> TokenStream {
+    input
+}
diff --git a/src/test/run-pass-fulldeps/proc-macro/issue-42708.rs b/src/test/run-pass-fulldeps/proc-macro/issue-42708.rs
new file mode 100644
index 0000000000000..e53e94ae475b2
--- /dev/null
+++ b/src/test/run-pass-fulldeps/proc-macro/issue-42708.rs
@@ -0,0 +1,36 @@
+// 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.
+
+// aux-build:issue-42708.rs
+// ignore-stage1
+
+#![feature(decl_macro, proc_macro)]
+#![allow(unused)]
+
+extern crate issue_42708;
+
+macro m() {
+    #[derive(issue_42708::Test)]
+    struct S { x: () }
+
+    #[issue_42708::attr_test]
+    struct S2 { x: () }
+
+    #[derive(Clone)]
+    struct S3 { x: () }
+
+    fn g(s: S, s2: S2, s3: S3) {
+        (s.x, s2.x, s3.x);
+    }
+}
+
+m!();
+
+fn main() {}