From 5cc488d2500999ef4b934c90f155022b25dcdd19 Mon Sep 17 00:00:00 2001 From: "Zack M. Davis" Date: Sun, 12 Nov 2017 19:13:07 -0800 Subject: [PATCH] deduplicate projection error (E0271) messages The `ErrorId` variant takes a u16 so that `DiagnosticMessageId` can retain its `Copy` status (the present author's first choice having been the "EXXX" code as a string). The duplicated "type mismatch resolving `{}`" literal is unfortunate, but the `struct_span_err!` macro (which we want to mark that error code as used) is fussy about taking a literal, and the one-time-diagnostics set needs an owned string. This is concerning #33941 and probably #45805! --- src/librustc/session/mod.rs | 6 ++++-- src/librustc/traits/error_reporting.rs | 21 ++++++++++++++------- src/test/ui/issue-33941.rs | 15 +++++++++++++++ src/test/ui/issue-33941.stderr | 21 +++++++++++++++++++++ 4 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 src/test/ui/issue-33941.rs create mode 100644 src/test/ui/issue-33941.stderr diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 39cf50787ef..00a91eeb9c1 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -164,11 +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 +/// Diagnostic message ID—used by `Session.one_time_diagnostics` to avoid +/// emitting the same message more than once #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub enum DiagnosticMessageId { + ErrorId(u16), // EXXXX error code as integer LintId(lint::LintId), - StabilityId(u32) + StabilityId(u32) // issue number } impl Session { diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index e2b23c12cf1..106b1b08656 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -36,6 +36,7 @@ use rustc::lint::builtin::EXTRA_REQUIREMENT_IN_IMPL; use std::fmt; use syntax::ast; +use session::DiagnosticMessageId; use ty::{self, AdtKind, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable}; use ty::error::ExpectedFound; use ty::fast_reject; @@ -219,13 +220,19 @@ fn report_projection_error(&self, } } - let mut diag = struct_span_err!( - self.tcx.sess, obligation.cause.span, E0271, - "type mismatch resolving `{}`", predicate - ); - self.note_type_err(&mut diag, &obligation.cause, None, values, err); - self.note_obligation_cause(&mut diag, obligation); - diag.emit(); + let msg = format!("type mismatch resolving `{}`", predicate); + let error_id = (DiagnosticMessageId::ErrorId(271), + Some(obligation.cause.span), msg.clone()); + let fresh = self.tcx.sess.one_time_diagnostics.borrow_mut().insert(error_id); + if fresh { + let mut diag = struct_span_err!( + self.tcx.sess, obligation.cause.span, E0271, + "type mismatch resolving `{}`", predicate + ); + self.note_type_err(&mut diag, &obligation.cause, None, values, err); + self.note_obligation_cause(&mut diag, obligation); + diag.emit(); + } }); } diff --git a/src/test/ui/issue-33941.rs b/src/test/ui/issue-33941.rs new file mode 100644 index 00000000000..eb111d33b99 --- /dev/null +++ b/src/test/ui/issue-33941.rs @@ -0,0 +1,15 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::collections::HashMap; + +fn main() { + for _ in HashMap::new().iter().cloned() {} +} diff --git a/src/test/ui/issue-33941.stderr b/src/test/ui/issue-33941.stderr new file mode 100644 index 00000000000..5a8d1fab3f6 --- /dev/null +++ b/src/test/ui/issue-33941.stderr @@ -0,0 +1,21 @@ +error[E0271]: type mismatch resolving ` as std::iter::Iterator>::Item == &_` + --> $DIR/issue-33941.rs:14:36 + | +14 | for _ in HashMap::new().iter().cloned() {} + | ^^^^^^ expected tuple, found reference + | + = note: expected type `(&_, &_)` + found type `&_` + +error[E0271]: type mismatch resolving ` as std::iter::Iterator>::Item == &_` + --> $DIR/issue-33941.rs:14:5 + | +14 | for _ in HashMap::new().iter().cloned() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected tuple, found reference + | + = note: expected type `(&_, &_)` + found type `&_` + = note: required because of the requirements on the impl of `std::iter::Iterator` for `std::iter::Cloned>` + +error: aborting due to 2 previous errors +