Change:
Compiling this: while not including as a dependency in , produces the following output:
Modify can keep track of wether a diagnostic of this type has already been emitted, and if it has, the help isn't shown.
But has access to the , which means we should be able to use the (if we slightly generalize it to take an rather than a to accomodate non-lint errors like the matter at hand). However, the reported code isn't reproducing the issue for me with a stage 1 compiler, perhaps hinting at something more subtle going on with this report.
That actually works and is a pretty elegant/quick fix. The only caveat is that you shouldn't pass the span in the tuple... i'm guessing, it messes up the hashcode, and the error ends up being different each time. I can't yet figure out why (complete newbie to the codebase) - so if you want to take up this issue & fix it, please feel free to do so, it'll take me a little while (I'm slow/don't have much time available to work on it :) ).
Update - i had some time to inspect it. Basically, the error is reported in two places. Here: and here: The second one is the one that is reported many times - and the primary span seems to be different each time (which is why if you include the span in the "key", it sees the messages as different and emits them all). I'm planning to go from the primary span to file/line/column string, and include that in the message - basically, the key for would be instead of ; this way, we would preserve the first two error messages, but remove the subsequent ones. Still feels a bit hackish, but I don't have a better idea.
But they look like they're all pointing to the same code-snippet; what could be making them different? It looks like ; if that's it, I'd rather manipulate that before setting/getting the entry than pollute the error message string itself with file-position data.
So, I printed the location from the span - most of the "repeated" ones are within the macros, e.g. I'm pretty sure I need to invoke EmitterWritter::fixmultispaninstdmacros() on the primary span, in order to retrieve the true location (, line 4) - only problem is, that method is private. And now it's late :) I have another idea, I'll try it tomorrow - anyway, this looks to be genuinely trickier than it first appeared to be
Ok guys, I've created PR - let me know if you think it's a reasonable solution.
did not contain the UI test to verify correctness. could you (or anybody interested) submit another PR to add the test? Sorry for the inconvenience.
Just to clarify: the request is that I add a test in that validates this issue is fixed (so that we can't have regressions in the future)? Basically, that means adding the code from the issue in , and the expected output in ? If yes - sure, I'll add it, sorry for not adding it from the start, I'm new to this project :).
that is exactly right :)
I the test with PR ... but, at least on my local build, it seems that the compilation error changed in the meanwhile? (I get a much-more reduced version of it). Not sure why/ if I changed something in the build environment, or the code changed due to other PRs, in . If the build fails in the PR, I'll need to re-evaluate how to produce a different testcase that still exposes the issue (if it's possible, at at all - I'll may need help on that). (FWIW, that's why I thought that a test won't be needed for this fix - error output tends to change in time, making such tests a bit fragile)
So it wasn't just a thing on my build environment - the error is now simply . need to figure out a different test, but it'll probably take me a few days.
in my opinion the way to go would be to write a complete , so as not to rely on the crate's attribute. Essentially, have an auxiliary crate with the configuration attribute (see ) and a test that tries to use it without a attribute. But someone else should also comment if that sounds sensible.

Discussion:
use hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefId, LOCAL_CRATE}; use ty::{self, TyCtxt}; use middle::privacy::AccessLevels; <ins> use session::DiagnosticMessageId; </ins> use syntax::symbol::Symbol; <del> use syntax_pos::{Span, DUMMY_SP}; </del> <ins> use syntax_pos::{Span, MultiSpan, DUMMY_SP}; </ins> use syntax::ast; use syntax::ast::{NodeId, Attribute}; use syntax::feature_gate::{GateIssue, emit_feature_err, find_lang_feature_accepted_version};

feature.as_str(), &r), None => format!("use of unstable library feature '{}'", &feature) }; <del> emit_feature_err(&self.sess.parse_sess, &feature.as_str(), span, GateIssue::Library(Some(issue)), &msg); </del> <ins> 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 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 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); } </ins> } Some(_) => { // Stable APIs are always ok to call and deprecated APIs are

pub working_dir: (String, bool), pub lint_store: RefCell<lint::LintStore>, pub buffered_lints: RefCell<Option<lint::LintBuffer>>, <del> /// Set of (LintId, Option<Span>, message) tuples tracking lint </del> <ins> /// Set of (DiagnosticId, Option<Span>, message) tuples tracking </ins> /// (sub)diagnostics that have been set once, but should not be set again, <del> /// in order to avoid redundantly verbose output (Issue #24690). pub one_time_diagnostics: RefCell<FxHashSet<(lint::LintId, Option<Span>, String)>>, </del> <ins> /// in order to avoid redundantly verbose output (Issue #24690, #44953). pub one_time_diagnostics: RefCell<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>, </ins> pub plugin_llvm_passes: RefCell<Vec<String>>, pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>, pub crate_types: RefCell<Vec<config::CrateType>>,

// add more variants as needed to support one-time diagnostics } <ins> /// 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) } </ins> impl Session { pub fn local_crate_disambiguator(&self) -> CrateDisambiguator { match *self.crate_disambiguator.borrow() {

do_method() }, _ => { <del> let lint_id = lint::LintId::of(lint); </del> <ins> let lint_id = DiagnosticMessageId::LintId(lint::LintId::of(lint)); </ins> let id_span_message = (lint_id, span, message.to_owned()); let fresh = self.one_time_diagnostics.borrow_mut().insert(id_span_message); if fresh {