diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index 0d946c3bbcd..b30d5e38488 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -18,6 +18,7 @@ use hir::def::Def; use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use ty::{self, TyCtxt}; use middle::privacy::AccessLevels; +use session::DiagnosticMessageId; use syntax::symbol::Symbol; use syntax_pos::{Span, MultiSpan, DUMMY_SP}; use syntax::ast; @@ -601,27 +602,25 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { let msp: MultiSpan = span.into(); let cm = &self.sess.parse_sess.codemap(); - let span_key = - msp.primary_span().and_then(|sp:Span| - if sp != DUMMY_SP { - let fname = cm.lookup_char_pos(sp.lo()).file.as_ref().name.clone(); - if fname.starts_with("<") && fname.ends_with(" macros>") { - None - } else { - Some(span) - } - } else { + let span_key = msp.primary_span().and_then(|sp: Span| + if sp != DUMMY_SP { + let file = cm.lookup_char_pos(sp.lo()).file; + if file.name.starts_with("<") && file.name.ends_with(" macros>") { None + } else { + Some(span) } - ); + } else { + None + } + ); - let tuple = (None, span_key, msg.clone()); - let fresh = self.sess.one_time_diagnostics.borrow_mut().insert(tuple); + let error_id = (DiagnosticMessageId::StabilityId(issue), span_key, msg.clone()); + let fresh = self.sess.one_time_diagnostics.borrow_mut().insert(error_id); if fresh { emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span, GateIssue::Library(Some(issue)), &msg); } - } Some(_) => { // Stable APIs are always ok to call and deprecated APIs are diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 177e595273b..9254b2e3364 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -75,10 +75,10 @@ pub struct Session { pub working_dir: (String, bool), pub lint_store: RefCell, pub buffered_lints: RefCell>, - /// Set of (LintId, Option, message) tuples tracking lint + /// Set of (DiagnosticId, Option, message) tuples tracking /// (sub)diagnostics that have been set once, but should not be set again, - /// in order to avoid redundantly verbose output (Issue #24690). - pub one_time_diagnostics: RefCell, Option, String)>>, + /// in order to avoid redundantly verbose output (Issue #24690, #44953). + pub one_time_diagnostics: RefCell, String)>>, pub plugin_llvm_passes: RefCell>, pub plugin_attributes: RefCell>, pub crate_types: RefCell>, @@ -164,6 +164,13 @@ enum DiagnosticBuilderMethod { // add more variants as needed to support one-time diagnostics } +/// Diagnostic message id - used in order to avoid emitting the same message more than once +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum DiagnosticMessageId { + LintId(lint::LintId), + StabilityId(u32) +} + impl Session { pub fn local_crate_disambiguator(&self) -> CrateDisambiguator { match *self.crate_disambiguator.borrow() { @@ -361,7 +368,7 @@ impl Session { }, _ => { let lint_id = lint::LintId::of(lint); - let id_span_message = (Some(lint_id), span, message.to_owned()); + let id_span_message = (DiagnosticMessageId::LintId(lint_id), span, message.to_owned()); let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message); if fresh { do_method()