librustc_errors: Don't emit the same error message twice.
This commit is contained in:
parent
67f3dc3fee
commit
6fccd71f75
5 changed files with 36 additions and 9 deletions
1
src/Cargo.lock
generated
1
src/Cargo.lock
generated
|
@ -1705,6 +1705,7 @@ dependencies = [
|
||||||
name = "rustc_errors"
|
name = "rustc_errors"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"rustc_data_structures 0.0.0",
|
||||||
"serialize 0.0.0",
|
"serialize 0.0.0",
|
||||||
"syntax_pos 0.0.0",
|
"syntax_pos 0.0.0",
|
||||||
]
|
]
|
||||||
|
|
|
@ -11,3 +11,4 @@ crate-type = ["dylib"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
serialize = { path = "../libserialize" }
|
serialize = { path = "../libserialize" }
|
||||||
syntax_pos = { path = "../libsyntax_pos" }
|
syntax_pos = { path = "../libsyntax_pos" }
|
||||||
|
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||||
|
|
|
@ -17,7 +17,7 @@ use syntax_pos::{MultiSpan, Span};
|
||||||
use snippet::Style;
|
use snippet::Style;
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
|
||||||
pub struct Diagnostic {
|
pub struct Diagnostic {
|
||||||
pub level: Level,
|
pub level: Level,
|
||||||
pub message: Vec<(String, Style)>,
|
pub message: Vec<(String, Style)>,
|
||||||
|
@ -28,7 +28,7 @@ pub struct Diagnostic {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For example a note attached to an error.
|
/// 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 struct SubDiagnostic {
|
||||||
pub level: Level,
|
pub level: Level,
|
||||||
pub message: Vec<(String, Style)>,
|
pub message: Vec<(String, Style)>,
|
||||||
|
|
|
@ -18,10 +18,12 @@
|
||||||
#![feature(range_contains)]
|
#![feature(range_contains)]
|
||||||
#![cfg_attr(unix, feature(libc))]
|
#![cfg_attr(unix, feature(libc))]
|
||||||
#![feature(conservative_impl_trait)]
|
#![feature(conservative_impl_trait)]
|
||||||
|
#![feature(i128_type)]
|
||||||
|
|
||||||
extern crate term;
|
extern crate term;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
extern crate libc;
|
extern crate libc;
|
||||||
|
extern crate rustc_data_structures;
|
||||||
extern crate serialize as rustc_serialize;
|
extern crate serialize as rustc_serialize;
|
||||||
extern crate syntax_pos;
|
extern crate syntax_pos;
|
||||||
|
|
||||||
|
@ -31,6 +33,9 @@ use self::Level::*;
|
||||||
|
|
||||||
use emitter::{Emitter, EmitterWriter};
|
use emitter::{Emitter, EmitterWriter};
|
||||||
|
|
||||||
|
use rustc_data_structures::fx::FxHashSet;
|
||||||
|
use rustc_data_structures::stable_hasher::StableHasher;
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::cell::{RefCell, Cell};
|
use std::cell::{RefCell, Cell};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
@ -47,7 +52,7 @@ mod lock;
|
||||||
|
|
||||||
use syntax_pos::{BytePos, Loc, FileLinesResult, FileMap, FileName, MultiSpan, Span, NO_EXPANSION};
|
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 {
|
pub enum RenderSpan {
|
||||||
/// A FullSpan renders with both with an initial line for the
|
/// A FullSpan renders with both with an initial line for the
|
||||||
/// message, prefixed by file:linenum, followed by a summary of
|
/// message, prefixed by file:linenum, followed by a summary of
|
||||||
|
@ -61,7 +66,7 @@ pub enum RenderSpan {
|
||||||
Suggestion(CodeSuggestion),
|
Suggestion(CodeSuggestion),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
#[derive(Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
|
||||||
pub struct CodeSuggestion {
|
pub struct CodeSuggestion {
|
||||||
/// Each substitute can have multiple variants due to multiple
|
/// Each substitute can have multiple variants due to multiple
|
||||||
/// applicable suggestions
|
/// applicable suggestions
|
||||||
|
@ -86,7 +91,7 @@ pub struct CodeSuggestion {
|
||||||
pub show_code_when_inline: bool,
|
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`
|
/// See the docs on `CodeSuggestion::substitutions`
|
||||||
pub struct Substitution {
|
pub struct Substitution {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
@ -271,6 +276,11 @@ pub struct Handler {
|
||||||
continue_after_error: Cell<bool>,
|
continue_after_error: Cell<bool>,
|
||||||
delayed_span_bug: RefCell<Option<Diagnostic>>,
|
delayed_span_bug: RefCell<Option<Diagnostic>>,
|
||||||
tracked_diagnostics: RefCell<Option<Vec<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 {
|
impl Handler {
|
||||||
|
@ -295,6 +305,7 @@ impl Handler {
|
||||||
continue_after_error: Cell::new(true),
|
continue_after_error: Cell::new(true),
|
||||||
delayed_span_bug: RefCell::new(None),
|
delayed_span_bug: RefCell::new(None),
|
||||||
tracked_diagnostics: 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) {
|
fn emit_db(&self, db: &DiagnosticBuilder) {
|
||||||
|
let diagnostic = &**db;
|
||||||
|
|
||||||
if let Some(ref mut list) = *self.tracked_diagnostics.borrow_mut() {
|
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 {
|
pub enum Level {
|
||||||
Bug,
|
Bug,
|
||||||
Fatal,
|
Fatal,
|
||||||
|
|
|
@ -203,7 +203,7 @@ pub struct StyledString {
|
||||||
pub style: Style,
|
pub style: Style,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
|
#[derive(Copy, Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)]
|
||||||
pub enum Style {
|
pub enum Style {
|
||||||
HeaderMsg,
|
HeaderMsg,
|
||||||
LineAndColumn,
|
LineAndColumn,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue