about summary refs log tree commit diff
path: root/src/librustc_errors
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-01-26 17:41:36 +0000
committerbors <bors@rust-lang.org>2018-01-26 17:41:36 +0000
commitbacb5c58dfdde7c35e99b2b0d8171238cc33cf6c (patch)
treea4a44364f143350bb7262ca8e63612e2ee71f6ed /src/librustc_errors
parenta97cd17f5d71fb4ec362f4fbd79373a6e7ed7b82 (diff)
parenta06d333a148f6c620044a765f47497f1ed1e4dde (diff)
downloadrust-bacb5c58dfdde7c35e99b2b0d8171238cc33cf6c.tar.gz
rust-bacb5c58dfdde7c35e99b2b0d8171238cc33cf6c.zip
Auto merge of #47748 - alexcrichton:rollup, r=alexcrichton
Rollup of 19 pull requests

- Successful merges: #47415, #47437, #47439, #47453, #47460, #47502, #47529, #47600, #47607, #47618, #47626, #47656, #47668, #47696, #47701, #47705, #47710, #47711, #47719
- Failed merges: #47455, #47521
Diffstat (limited to 'src/librustc_errors')
-rw-r--r--src/librustc_errors/diagnostic.rs6
-rw-r--r--src/librustc_errors/lib.rs34
2 files changed, 38 insertions, 2 deletions
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index 8da4321fa5b..2e654fe9929 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -27,7 +27,7 @@ pub struct Diagnostic {
     pub suggestions: Vec<CodeSuggestion>,
 }
 
-#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub enum DiagnosticId {
     Error(String),
     Lint(String),
@@ -281,6 +281,10 @@ impl Diagnostic {
         self
     }
 
+    pub fn get_code(&self) -> Option<DiagnosticId> {
+        self.code.clone()
+    }
+
     pub fn message(&self) -> String {
         self.message.iter().map(|i| i.0.to_owned()).collect::<String>()
     }
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index 1fb673815ee..3d50c95d3f4 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -19,6 +19,7 @@
 #![cfg_attr(unix, feature(libc))]
 #![feature(conservative_impl_trait)]
 #![feature(i128_type)]
+#![feature(optin_builtin_traits)]
 
 extern crate term;
 #[cfg(unix)]
@@ -44,6 +45,7 @@ use std::rc::Rc;
 use std::{error, fmt};
 use std::sync::atomic::AtomicUsize;
 use std::sync::atomic::Ordering::SeqCst;
+use std::panic;
 
 mod diagnostic;
 mod diagnostic_builder;
@@ -201,6 +203,18 @@ impl CodeSuggestion {
 #[must_use]
 pub struct FatalError;
 
+pub struct FatalErrorMarker;
+
+// Don't implement Send on FatalError. This makes it impossible to panic!(FatalError).
+// We don't want to invoke the panic handler and print a backtrace for fatal errors.
+impl !Send for FatalError {}
+
+impl FatalError {
+    pub fn raise(self) -> ! {
+        panic::resume_unwind(Box::new(FatalErrorMarker))
+    }
+}
+
 impl fmt::Display for FatalError {
     fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
         write!(f, "parser fatal error")
@@ -245,6 +259,11 @@ pub struct Handler {
     delayed_span_bug: RefCell<Option<Diagnostic>>,
     tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>,
 
+    // This set contains the `DiagnosticId` of all emitted diagnostics to avoid
+    // emitting the same diagnostic with extended help (`--teach`) twice, which
+    // would be uneccessary repetition.
+    tracked_diagnostic_codes: RefCell<FxHashSet<DiagnosticId>>,
+
     // This set contains a hash of every diagnostic that has been emitted by
     // this handler. These hashes is used to avoid emitting the same error
     // twice.
@@ -303,6 +322,7 @@ impl Handler {
             continue_after_error: Cell::new(true),
             delayed_span_bug: RefCell::new(None),
             tracked_diagnostics: RefCell::new(None),
+            tracked_diagnostic_codes: RefCell::new(FxHashSet()),
             emitted_diagnostics: RefCell::new(FxHashSet()),
         }
     }
@@ -539,7 +559,7 @@ impl Handler {
             }
         }
 
-        panic!(self.fatal(&s));
+        self.fatal(&s).raise();
     }
     pub fn emit(&self, msp: &MultiSpan, msg: &str, lvl: Level) {
         if lvl == Warning && !self.flags.can_emit_warnings {
@@ -575,6 +595,14 @@ impl Handler {
         (ret, diagnostics)
     }
 
+    /// `true` if a diagnostic with this code has already been emitted in this handler.
+    ///
+    /// Used to suppress emitting the same error multiple times with extended explanation when
+    /// calling `-Zteach`.
+    pub fn code_emitted(&self, code: &DiagnosticId) -> bool {
+        self.tracked_diagnostic_codes.borrow().contains(code)
+    }
+
     fn emit_db(&self, db: &DiagnosticBuilder) {
         let diagnostic = &**db;
 
@@ -582,6 +610,10 @@ impl Handler {
             list.push(diagnostic.clone());
         }
 
+        if let Some(ref code) = diagnostic.code {
+            self.tracked_diagnostic_codes.borrow_mut().insert(code.clone());
+        }
+
         let diagnostic_hash = {
             use std::hash::Hash;
             let mut hasher = StableHasher::new();