From e20fa70bb349026226616b92ea44f7bdfd270d75 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Thu, 18 Oct 2018 09:00:11 -0400 Subject: [PATCH] suppress duplicate -- or near duplicate -- type test errors --- src/librustc/infer/region_constraints/mod.rs | 2 +- .../borrow_check/nll/region_infer/mod.rs | 30 ++++++++++++++++--- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs index 525ae03dfaf9..df30ad360062 100644 --- a/src/librustc/infer/region_constraints/mod.rs +++ b/src/librustc/infer/region_constraints/mod.rs @@ -149,7 +149,7 @@ pub struct Verify<'tcx> { pub bound: VerifyBound<'tcx>, } -#[derive(Copy, Clone, PartialEq, Eq)] +#[derive(Copy, Clone, PartialEq, Eq, Hash)] pub enum GenericKind<'tcx> { Param(ty::ParamTy), Projection(ty::ProjectionTy<'tcx>), diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 0fabcfe45644..95b3943746d1 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -25,7 +25,7 @@ use rustc::mir::{ use rustc::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable}; use rustc::util::common; use rustc_data_structures::bit_set::BitSet; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::scc::Sccs; use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::{Diagnostic, DiagnosticBuilder}; @@ -580,6 +580,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) { let tcx = infcx.tcx; + // Sometimes we register equivalent type-tests that would + // result in basically the exact same error being reported to + // the user. Avoid that. + let mut deduplicate_errors = FxHashSet::default(); + for type_test in &self.type_tests { debug!("check_type_test: {:?}", type_test); @@ -605,11 +610,29 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - // Oh the humanity. Obviously we will do better than this error eventually. + // Type-test failed. Report the error. + + // Try to convert the lower-bound region into something named we can print for the user. let lower_bound_region = self.to_error_region(type_test.lower_bound); + + // Skip duplicate-ish errors. + let type_test_span = type_test.locations.span(mir); + let erased_generic_kind = tcx.erase_regions(&type_test.generic_kind); + if !deduplicate_errors.insert((erased_generic_kind, lower_bound_region, type_test.locations)) { + continue; + } else { + debug!( + "check_type_test: reporting error for erased_generic_kind={:?}, \ + lower_bound_region={:?}, \ + type_test.locations={:?}", + erased_generic_kind, + lower_bound_region, + type_test.locations, + ); + } + if let Some(lower_bound_region) = lower_bound_region { let region_scope_tree = &tcx.region_scope_tree(mir_def_id); - let type_test_span = type_test.locations.span(mir); infcx .construct_generic_bound_failure( region_scope_tree, @@ -629,7 +652,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { // to report it; we could probably handle it by // iterating over the universal regions and reporting // an error that multiple bounds are required. - let type_test_span = type_test.locations.span(mir); tcx.sess .struct_span_err( type_test_span,