diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs
index 067e3fff3eb29..c177eb1f00bbd 100644
--- a/src/libsyntax/diagnostic.rs
+++ b/src/libsyntax/diagnostic.rs
@@ -727,30 +727,45 @@ impl EmitterWriter {
                              cm: &codemap::CodeMap,
                              sp: Span)
                              -> io::Result<()> {
-        let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> io::Result<_> {
-            match expn_info {
-                Some(ei) => {
-                    let ss = ei.callee.span.map_or(String::new(),
-                                                   |span| cm.span_to_string(span));
-                    let (pre, post) = match ei.callee.format {
-                        codemap::MacroAttribute(..) => ("#[", "]"),
-                        codemap::MacroBang(..) => ("", "!"),
-                        codemap::CompilerExpansion(..) => ("", ""),
-                    };
-                    try!(self.print_diagnostic(&ss, Note,
-                                               &format!("in expansion of {}{}{}",
-                                                        pre,
-                                                        ei.callee.name(),
-                                                        post),
-                                               None));
-                    let ss = cm.span_to_string(ei.call_site);
-                    try!(self.print_diagnostic(&ss, Note, "expansion site", None));
-                    Ok(Some(ei.call_site))
+        let mut last_span = codemap::DUMMY_SP;
+        let mut sp_opt = Some(sp);
+
+        while let Some(sp) = sp_opt {
+            sp_opt = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> io::Result<_> {
+                match expn_info {
+                    Some(ei) => {
+                        let (pre, post) = match ei.callee.format {
+                            codemap::MacroAttribute(..) => ("#[", "]"),
+                            codemap::MacroBang(..) => ("", "!"),
+                            codemap::CompilerExpansion(..) => ("", ""),
+                        };
+                        // Don't print recursive invocations
+                        if ei.call_site != last_span {
+                            last_span = ei.call_site;
+
+                            let mut diag_string = format!("in this expansion of {}{}{}",
+                                                          pre,
+                                                          ei.callee.name(),
+                                                          post);
+
+                            if let Some(def_site_span) = ei.callee.span {
+                                diag_string.push_str(&format!(" (defined in {})",
+                                                              cm.span_to_filename(def_site_span)));
+                            }
+
+                            try!(self.print_diagnostic(&cm.span_to_string(ei.call_site),
+                                                       Note,
+                                                       &diag_string,
+                                                       None));
+                        }
+                        Ok(Some(ei.call_site))
+                    }
+                    None => Ok(None)
                 }
-                None => Ok(None)
+            }));
         }
-        }));
-        cs.map_or(Ok(()), |call_site| self.print_macro_backtrace(cm, call_site))
+
+        Ok(())
     }
 }
 
diff --git a/src/test/compile-fail/for-expn-2.rs b/src/test/compile-fail/for-expn-2.rs
index 6b1dbf9d2d0ba..ce2315f3a38d4 100644
--- a/src/test/compile-fail/for-expn-2.rs
+++ b/src/test/compile-fail/for-expn-2.rs
@@ -10,7 +10,7 @@
 
 // Test that we get an expansion stack for `for` loops.
 
-// error-pattern:in expansion of for loop expansion
+// error-pattern:in this expansion of for loop expansion
 
 fn main() {
     for t in &foo {
diff --git a/src/test/compile-fail/macro-backtrace-invalid-internals.rs b/src/test/compile-fail/macro-backtrace-invalid-internals.rs
index 34aa1c75872f3..5069ec7d2846a 100644
--- a/src/test/compile-fail/macro-backtrace-invalid-internals.rs
+++ b/src/test/compile-fail/macro-backtrace-invalid-internals.rs
@@ -10,25 +10,25 @@
 
 // Macros in statement vs expression position handle backtraces differently.
 
-macro_rules! fake_method_stmt { //~ NOTE in expansion of
+macro_rules! fake_method_stmt {
      () => {
           1.fake() //~ ERROR no method named `fake` found
      }
 }
 
-macro_rules! fake_field_stmt { //~ NOTE in expansion of
+macro_rules! fake_field_stmt {
      () => {
           1.fake //~ ERROR no field with that name
      }
 }
 
-macro_rules! fake_anon_field_stmt { //~ NOTE in expansion of
+macro_rules! fake_anon_field_stmt {
      () => {
           (1).0 //~ ERROR type was not a tuple
      }
 }
 
-macro_rules! fake_method_expr { //~ NOTE in expansion of
+macro_rules! fake_method_expr {
      () => {
           1.fake() //~ ERROR no method named `fake` found
      }
@@ -47,11 +47,13 @@ macro_rules! fake_anon_field_expr {
 }
 
 fn main() {
-    fake_method_stmt!(); //~ NOTE expansion site
-    fake_field_stmt!(); //~ NOTE expansion site
-    fake_anon_field_stmt!(); //~ NOTE expansion site
+    fake_method_stmt!(); //~ NOTE in this expansion of
+    fake_field_stmt!(); //~ NOTE in this expansion of
+    fake_anon_field_stmt!(); //~ NOTE in this expansion of
 
-    let _ = fake_method_expr!(); //~ NOTE expansion site
+    let _ = fake_method_expr!(); //~ NOTE in this expansion of
     let _ = fake_field_expr!(); //~ ERROR no field with that name
+                                //~^ NOTE in this expansion of
     let _ = fake_anon_field_expr!(); //~ ERROR type was not a tuple
+                                     //~^ NOTE in this expansion of
 }
diff --git a/src/test/compile-fail/macro-backtrace-nested.rs b/src/test/compile-fail/macro-backtrace-nested.rs
index 7c1dc1a468c76..a429681bb2181 100644
--- a/src/test/compile-fail/macro-backtrace-nested.rs
+++ b/src/test/compile-fail/macro-backtrace-nested.rs
@@ -19,11 +19,11 @@ macro_rules! call_nested_expr {
     () => (nested_expr!())
 }
 
-macro_rules! call_nested_expr_sum { //~ NOTE in expansion of
+macro_rules! call_nested_expr_sum {
     () => { 1 + nested_expr!(); } //~ ERROR unresolved name
 }
 
 fn main() {
     1 + call_nested_expr!(); //~ ERROR unresolved name
-    call_nested_expr_sum!(); //~ NOTE expansion site
+    call_nested_expr_sum!(); //~ NOTE in this expansion of
 }
diff --git a/src/test/compile-fail/macro-backtrace-println.rs b/src/test/compile-fail/macro-backtrace-println.rs
index 0c66bbfcf044a..294892662d464 100644
--- a/src/test/compile-fail/macro-backtrace-println.rs
+++ b/src/test/compile-fail/macro-backtrace-println.rs
@@ -16,14 +16,15 @@
 
 fn print(_args: std::fmt::Arguments) {}
 
-macro_rules! myprint { //~ NOTE in expansion of
-    ($($arg:tt)*) => (print(format_args!($($arg)*)));
+macro_rules! myprint {
+    ($($arg:tt)*) => (print(format_args!($($arg)*)));   //~ NOTE in this expansion of
 }
 
-macro_rules! myprintln { //~ NOTE in expansion of
+macro_rules! myprintln {
     ($fmt:expr) => (myprint!(concat!($fmt, "\n"))); //~ ERROR invalid reference to argument `0`
+                                                    //~^ NOTE in this expansion of
 }
 
 fn main() {
-    myprintln!("{}"); //~ NOTE expansion site
+    myprintln!("{}"); //~ NOTE in this expansion of
 }
diff --git a/src/test/compile-fail/method-macro-backtrace.rs b/src/test/compile-fail/method-macro-backtrace.rs
index c9ef2df8e1326..967a8531b2c0a 100644
--- a/src/test/compile-fail/method-macro-backtrace.rs
+++ b/src/test/compile-fail/method-macro-backtrace.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// forbid-output: in expansion of
+// forbid-output: in this expansion of
 
 macro_rules! make_method {
     ($name:ident) => ( fn $name(&self) { } )