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!
This commit is contained in:
Zack M. Davis 2017-11-12 19:13:07 -08:00
parent 7f43981ebf
commit 5cc488d250
4 changed files with 54 additions and 9 deletions

View File

@ -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 {

View File

@ -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,6 +220,11 @@ fn report_projection_error(&self,
}
}
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
@ -226,6 +232,7 @@ fn report_projection_error(&self,
self.note_type_err(&mut diag, &obligation.cause, None, values, err);
self.note_obligation_cause(&mut diag, obligation);
diag.emit();
}
});
}

View File

@ -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 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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() {}
}

View File

@ -0,0 +1,21 @@
error[E0271]: type mismatch resolving `<std::collections::hash_map::Iter<'_, _, _> 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 `<std::collections::hash_map::Iter<'_, _, _> 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<std::collections::hash_map::Iter<'_, _, _>>`
error: aborting due to 2 previous errors