about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Woerister <michaelwoerister@posteo>2017-10-25 15:01:06 +0200
committerMichael Woerister <michaelwoerister@posteo>2017-10-25 15:01:06 +0200
commit6fccd71f7552a26d6c002d4712a6d16ff49da31f (patch)
tree29a3df738d112ca072e619c9ff5f2ae8d73c6012
parent67f3dc3fee6a5bb5e651025368fb308d415a85b5 (diff)
downloadrust-6fccd71f7552a26d6c002d4712a6d16ff49da31f.tar.gz
rust-6fccd71f7552a26d6c002d4712a6d16ff49da31f.zip
librustc_errors: Don't emit the same error message twice.
-rw-r--r--src/Cargo.lock1
-rw-r--r--src/librustc_errors/Cargo.toml1
-rw-r--r--src/librustc_errors/diagnostic.rs4
-rw-r--r--src/librustc_errors/lib.rs37
-rw-r--r--src/librustc_errors/snippet.rs2
5 files changed, 36 insertions, 9 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock
index a8bcea6d781..76bdc8ef4c6 100644
--- a/src/Cargo.lock
+++ b/src/Cargo.lock
@@ -1705,6 +1705,7 @@ dependencies = [
 name = "rustc_errors"
 version = "0.0.0"
 dependencies = [
+ "rustc_data_structures 0.0.0",
  "serialize 0.0.0",
  "syntax_pos 0.0.0",
 ]
diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml
index 78ff52b4b23..c72e9dd0ea3 100644
--- a/src/librustc_errors/Cargo.toml
+++ b/src/librustc_errors/Cargo.toml
@@ -11,3 +11,4 @@ crate-type = ["dylib"]
 [dependencies]
 serialize = { path = "../libserialize" }
 syntax_pos = { path = "../libsyntax_pos" }
+rustc_data_structures = { path = "../librustc_data_structures" }
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index 02c0307e98c..64afdb1d2e0 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -17,7 +17,7 @@ use syntax_pos::{MultiSpan, Span};
 use snippet::Style;
 
 #[must_use]
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub struct Diagnostic {
     pub level: Level,
     pub message: Vec<(String, Style)>,
@@ -28,7 +28,7 @@ pub struct Diagnostic {
 }
 
 /// For example a note attached to an error.
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub struct SubDiagnostic {
     pub level: Level,
     pub message: Vec<(String, Style)>,
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index d9b0f4ac8a6..39bb0184289 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -18,10 +18,12 @@
 #![feature(range_contains)]
 #![cfg_attr(unix, feature(libc))]
 #![feature(conservative_impl_trait)]
+#![feature(i128_type)]
 
 extern crate term;
 #[cfg(unix)]
 extern crate libc;
+extern crate rustc_data_structures;
 extern crate serialize as rustc_serialize;
 extern crate syntax_pos;
 
@@ -31,6 +33,9 @@ use self::Level::*;
 
 use emitter::{Emitter, EmitterWriter};
 
+use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::stable_hasher::StableHasher;
+
 use std::borrow::Cow;
 use std::cell::{RefCell, Cell};
 use std::mem;
@@ -47,7 +52,7 @@ mod lock;
 
 use syntax_pos::{BytePos, Loc, FileLinesResult, FileMap, FileName, MultiSpan, Span, NO_EXPANSION};
 
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub enum RenderSpan {
     /// A FullSpan renders with both with an initial line for the
     /// message, prefixed by file:linenum, followed by a summary of
@@ -61,7 +66,7 @@ pub enum RenderSpan {
     Suggestion(CodeSuggestion),
 }
 
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub struct CodeSuggestion {
     /// Each substitute can have multiple variants due to multiple
     /// applicable suggestions
@@ -86,7 +91,7 @@ pub struct CodeSuggestion {
     pub show_code_when_inline: bool,
 }
 
-#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 /// See the docs on `CodeSuggestion::substitutions`
 pub struct Substitution {
     pub span: Span,
@@ -271,6 +276,11 @@ pub struct Handler {
     continue_after_error: Cell<bool>,
     delayed_span_bug: RefCell<Option<Diagnostic>>,
     tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>,
+
+    // 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.
+    emitted_diagnostics: RefCell<FxHashSet<u128>>,
 }
 
 impl Handler {
@@ -295,6 +305,7 @@ impl Handler {
             continue_after_error: Cell::new(true),
             delayed_span_bug: RefCell::new(None),
             tracked_diagnostics: RefCell::new(None),
+            emitted_diagnostics: RefCell::new(FxHashSet()),
         }
     }
 
@@ -559,15 +570,29 @@ impl Handler {
     }
 
     fn emit_db(&self, db: &DiagnosticBuilder) {
+        let diagnostic = &**db;
+
         if let Some(ref mut list) = *self.tracked_diagnostics.borrow_mut() {
-            list.push((**db).clone());
+            list.push(diagnostic.clone());
+        }
+
+        let diagnostic_hash = {
+            use std::hash::Hash;
+            let mut hasher = StableHasher::new();
+            diagnostic.hash(&mut hasher);
+            hasher.finish()
+        };
+
+        // Only emit the diagnostic if we haven't already emitted an equivalent
+        // one:
+        if self.emitted_diagnostics.borrow_mut().insert(diagnostic_hash) {
+            self.emitter.borrow_mut().emit(db);
         }
-        self.emitter.borrow_mut().emit(db);
     }
 }
 
 
-#[derive(Copy, PartialEq, Clone, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Copy, PartialEq, Clone, Hash, Debug, RustcEncodable, RustcDecodable)]
 pub enum Level {
     Bug,
     Fatal,
diff --git a/src/librustc_errors/snippet.rs b/src/librustc_errors/snippet.rs
index 52e3fcc1b47..2e8deeee5a5 100644
--- a/src/librustc_errors/snippet.rs
+++ b/src/librustc_errors/snippet.rs
@@ -203,7 +203,7 @@ pub struct StyledString {
     pub style: Style,
 }
 
-#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
 pub enum Style {
     HeaderMsg,
     LineAndColumn,