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, } -#[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 { + self.code.clone() + } + pub fn message(&self) -> String { self.message.iter().map(|i| i.0.to_owned()).collect::() } diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 1fb673815ee..cabafa052a3 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -244,6 +244,7 @@ pub struct Handler { continue_after_error: Cell, delayed_span_bug: RefCell>, tracked_diagnostics: RefCell>>, + tracked_diagnostic_codes: RefCell>, // 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 @@ 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()), } } @@ -575,6 +577,10 @@ impl Handler { (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 @@ 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(); diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs index d31a99dd171..3cd93a1c845 100644 --- a/src/librustc_typeck/check/cast.rs +++ b/src/librustc_typeck/check/cast.rs @@ -290,18 +290,22 @@ impl<'a, 'gcx, 'tcx> CastCheck<'tcx> { 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)"); }