Only emit expanded diagnostic information once

This commit is contained in:
Esteban Küber 2018-01-21 21:19:37 -08:00
parent e76d3f62cc
commit 864f6d180b
3 changed files with 28 additions and 10 deletions

View File

@ -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 @@ pub fn code(&mut self, s: DiagnosticId) -> &mut Self {
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>()
}

View File

@ -244,6 +244,7 @@ pub struct Handler {
continue_after_error: Cell<bool>,
delayed_span_bug: RefCell<Option<Diagnostic>>,
tracked_diagnostics: RefCell<Option<Vec<Diagnostic>>>,
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
@ -303,6 +304,7 @@ pub fn with_emitter_and_flags(e: Box<Emitter>, flags: HandlerFlags) -> 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()),
}
}
@ -575,6 +577,10 @@ pub fn track_diagnostics<F, R>(&self, f: F) -> (R, Vec<Diagnostic>)
(ret, diagnostics)
}
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 +588,10 @@ fn emit_db(&self, db: &DiagnosticBuilder) {
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();

View File

@ -290,18 +290,22 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
self.expr_ty,
fcx.ty_to_string(self.cast_ty)
);
if fcx.tcx.sess.opts.debugging_opts.explain {
if fcx.tcx.sess.opts.debugging_opts.explain
&& !fcx.tcx.sess.parse_sess.span_diagnostic
.code_emitted(&err.get_code().unwrap()) {
err.note(
"Thin pointers are \"simple\" pointers: they are purely a reference to a \
memory address.\n\n\
Fat pointers are pointers referencing \"Dynamically Sized Types\" (also \
called DST). DST don't have a statically known size, therefore they can \
only exist behind some kind of pointers that contain additional \
information. Slices and trait objects are DSTs. In the case of slices, \
the additional information the fat pointer holds is their size.");
"Thin pointers are \"simple\" pointers: they are purely a reference to a
memory address.
Fat pointers are pointers referencing \"Dynamically Sized Types\" (also
called DST). DST don't have a statically known size, therefore they can
only exist behind some kind of pointers that contain additional
information. Slices and trait objects are DSTs. In the case of slices,
the additional information the fat pointer holds is their size.");
err.note("to fix this error, don't try to cast directly between thin and fat \
pointers");
err.help("for more information about casts, take a look at [The Book]\
err.help("for more information about casts, take a look at
[The Book]\
(https://doc.rust-lang.org/book/first-edition/\
casting-between-types.html)");
}