From 9d3719bcfa45c977dcfd12a2d5f188652f56bdaf Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= <john.kare.alsaker@gmail.com>
Date: Thu, 1 Feb 2018 18:10:56 +0100
Subject: [PATCH] Do not run the default panic hook inside procedural macros.
 Fixes #47812

---
 src/Cargo.lock                                |  2 ++
 src/libproc_macro/lib.rs                      |  6 ++++++
 src/librustc/Cargo.toml                       |  2 ++
 src/librustc/lib.rs                           |  3 +++
 src/librustc/util/common.rs                   | 21 +++++++++++++++++++
 src/librustc_driver/driver.rs                 |  4 +++-
 src/test/ui-fulldeps/proc-macro/load-panic.rs |  1 +
 .../ui-fulldeps/proc-macro/load-panic.stderr  |  4 ++--
 8 files changed, 40 insertions(+), 3 deletions(-)

diff --git a/src/Cargo.lock b/src/Cargo.lock
index d8306c66daf84..5b56c6e12d624 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -1623,7 +1623,9 @@ dependencies = [
  "fmt_macros 0.0.0",
  "graphviz 0.0.0",
  "jobserver 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
+ "proc_macro 0.0.0",
  "rustc_apfloat 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
diff --git a/src/libproc_macro/lib.rs b/src/libproc_macro/lib.rs
index 6768e0ade4304..878a536836d23 100644
--- a/src/libproc_macro/lib.rs
+++ b/src/libproc_macro/lib.rs
@@ -844,6 +844,12 @@ pub mod __internal {
         })
     }
 
+    pub fn in_sess() -> bool
+    {
+        let p = CURRENT_SESS.with(|p| p.get());
+        !p.0.is_null()
+    }
+
     pub fn with_sess<F, R>(f: F) -> R
         where F: FnOnce((&ParseSess, Mark)) -> R
     {
diff --git a/src/librustc/Cargo.toml b/src/librustc/Cargo.toml
index 2c4898cb2c006..7e84a69dd7913 100644
--- a/src/librustc/Cargo.toml
+++ b/src/librustc/Cargo.toml
@@ -14,7 +14,9 @@ bitflags = "1.0"
 fmt_macros = { path = "../libfmt_macros" }
 graphviz = { path = "../libgraphviz" }
 jobserver = "0.1"
+lazy_static = "1.0.0"
 log = { version = "0.4", features = ["release_max_level_info", "std"] }
+proc_macro = { path = "../libproc_macro" }
 rustc_apfloat = { path = "../librustc_apfloat" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_math = { path = "../librustc_const_math" }
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index a7a2619505931..79333d1018ab1 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -60,6 +60,7 @@
 #![feature(never_type)]
 #![feature(non_exhaustive)]
 #![feature(nonzero)]
+#![feature(proc_macro_internals)]
 #![feature(quote)]
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
@@ -80,6 +81,7 @@ extern crate core;
 extern crate fmt_macros;
 extern crate getopts;
 extern crate graphviz;
+#[macro_use] extern crate lazy_static;
 #[cfg(windows)]
 extern crate libc;
 extern crate rustc_back;
@@ -91,6 +93,7 @@ extern crate rustc_errors as errors;
 #[macro_use] extern crate syntax;
 extern crate syntax_pos;
 extern crate jobserver;
+extern crate proc_macro;
 
 extern crate serialize as rustc_serialize; // used by deriving
 
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 2971f3e853a99..55e9a98e7ef13 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -16,6 +16,7 @@ use std::ffi::CString;
 use std::fmt::Debug;
 use std::hash::{Hash, BuildHasher};
 use std::iter::repeat;
+use std::panic;
 use std::path::Path;
 use std::time::{Duration, Instant};
 
@@ -23,6 +24,8 @@ use std::sync::mpsc::{Sender};
 use syntax_pos::{SpanData};
 use ty::maps::{QueryMsg};
 use dep_graph::{DepNode};
+use proc_macro;
+use lazy_static;
 
 // The name of the associated type for `Fn` return types
 pub const FN_OUTPUT_NAME: &'static str = "Output";
@@ -34,6 +37,24 @@ pub struct ErrorReported;
 
 thread_local!(static TIME_DEPTH: Cell<usize> = Cell::new(0));
 
+lazy_static! {
+    static ref DEFAULT_HOOK: Box<Fn(&panic::PanicInfo) + Sync + Send + 'static> = {
+        let hook = panic::take_hook();
+        panic::set_hook(Box::new(panic_hook));
+        hook
+    };
+}
+
+fn panic_hook(info: &panic::PanicInfo) {
+    if !proc_macro::__internal::in_sess() {
+        (*DEFAULT_HOOK)(info)
+    }
+}
+
+pub fn install_panic_hook() {
+    lazy_static::initialize(&DEFAULT_HOOK);
+}
+
 /// Initialized for -Z profile-queries
 thread_local!(static PROFQ_CHAN: RefCell<Option<Sender<ProfileQueriesMsg>>> = RefCell::new(None));
 
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index b8a1fe9910540..eb67c9ce4b7d8 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -24,7 +24,7 @@ use rustc::middle::cstore::CrateStore;
 use rustc::middle::privacy::AccessLevels;
 use rustc::ty::{self, TyCtxt, Resolutions, AllArenas};
 use rustc::traits;
-use rustc::util::common::{ErrorReported, time};
+use rustc::util::common::{ErrorReported, time, install_panic_hook};
 use rustc_allocator as allocator;
 use rustc_borrowck as borrowck;
 use rustc_incremental;
@@ -123,6 +123,8 @@ pub fn compile_input(trans: Box<TransCrate>,
         let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess);
         let crate_name =
             ::rustc_trans_utils::link::find_crate_name(Some(sess), &krate.attrs, input);
+        install_panic_hook();
+
         let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = {
             phase_2_configure_and_expand(
                 sess,
diff --git a/src/test/ui-fulldeps/proc-macro/load-panic.rs b/src/test/ui-fulldeps/proc-macro/load-panic.rs
index 328f398efd5c6..462eaf0341704 100644
--- a/src/test/ui-fulldeps/proc-macro/load-panic.rs
+++ b/src/test/ui-fulldeps/proc-macro/load-panic.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 // aux-build:derive-panic.rs
+// compile-flags:--error-format human
 
 #[macro_use]
 extern crate derive_panic;
diff --git a/src/test/ui-fulldeps/proc-macro/load-panic.stderr b/src/test/ui-fulldeps/proc-macro/load-panic.stderr
index 1be1609d45b2b..ab2ab84315a93 100644
--- a/src/test/ui-fulldeps/proc-macro/load-panic.stderr
+++ b/src/test/ui-fulldeps/proc-macro/load-panic.stderr
@@ -1,7 +1,7 @@
 error: proc-macro derive panicked
-  --> $DIR/load-panic.rs:16:10
+  --> $DIR/load-panic.rs:17:10
    |
-16 | #[derive(A)]
+17 | #[derive(A)]
    |          ^
    |
    = help: message: nope!