From 13e9b3deb43b228264c6ae6ccf8fb3126790ee80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 30 Sep 2019 17:48:22 -0700 Subject: [PATCH] Deduplicate closure type errors Closure typing obligations flow in both direcitons to properly infer types. Because of this, we will get 2 type errors whenever there's an unfulfilled obligation. To avoid this, we deduplicate them in the `InferCtxt`. --- src/librustc/infer/mod.rs | 5 +- src/librustc/traits/error_reporting.rs | 8 + .../ui/anonymous-higher-ranked-lifetime.rs | 11 -- .../anonymous-higher-ranked-lifetime.stderr | 141 ++---------------- src/test/ui/mismatched_types/issue-36053-2.rs | 1 - .../ui/mismatched_types/issue-36053-2.stderr | 10 +- 6 files changed, 23 insertions(+), 153 deletions(-) diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 750ca4e32a64e..b06b63455ba4b 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -23,7 +23,7 @@ use crate::ty::relate::RelateResult; use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef}; use crate::ty::{self, GenericParamDefKind, Ty, TyCtxt, InferConst}; use crate::ty::{FloatVid, IntVid, TyVid, ConstVid}; -use crate::util::nodemap::FxHashMap; +use crate::util::nodemap::{FxHashMap, FxHashSet}; use errors::DiagnosticBuilder; use rustc_data_structures::sync::Lrc; @@ -155,6 +155,8 @@ pub struct InferCtxt<'a, 'tcx> { /// avoid reporting the same error twice. pub reported_trait_errors: RefCell>>>, + pub reported_closure_mismatch: RefCell)>>, + /// When an error occurs, we want to avoid reporting "derived" /// errors that are due to this original failure. Normally, we /// handle this with the `err_count_on_creation` count, which @@ -538,6 +540,7 @@ impl<'tcx> InferCtxtBuilder<'tcx> { selection_cache: Default::default(), evaluation_cache: Default::default(), reported_trait_errors: Default::default(), + reported_closure_mismatch: Default::default(), tainted_by_errors_flag: Cell::new(false), err_count_on_creation: tcx.sess.err_count(), in_snapshot: Cell::new(false), diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index c2d531793372a..956fcdfd2d87c 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -885,6 +885,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.hir().span_if_local(did) ).map(|sp| self.tcx.sess.source_map().def_span(sp)); // the sp could be an fn def + if self.reported_closure_mismatch.borrow().contains(&(span, found_span)) { + // We check closures twice, with obligations flowing in different directions, + // but we want to complain about them only once. + return; + } + + self.reported_closure_mismatch.borrow_mut().insert((span, found_span)); + let found = match found_trait_ref.skip_binder().substs.type_at(1).kind { ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()], _ => vec![ArgKind::empty()], diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.rs b/src/test/ui/anonymous-higher-ranked-lifetime.rs index 8a1744ed5f8ae..898fe22fa234f 100644 --- a/src/test/ui/anonymous-higher-ranked-lifetime.rs +++ b/src/test/ui/anonymous-higher-ranked-lifetime.rs @@ -1,26 +1,15 @@ fn main() { f1(|_: (), _: ()| {}); //~ ERROR type mismatch - //~^ ERROR type mismatch f2(|_: (), _: ()| {}); //~ ERROR type mismatch - //~^ ERROR type mismatch f3(|_: (), _: ()| {}); //~ ERROR type mismatch - //~^ ERROR type mismatch f4(|_: (), _: ()| {}); //~ ERROR type mismatch - //~^ ERROR type mismatch f5(|_: (), _: ()| {}); //~ ERROR type mismatch - //~^ ERROR type mismatch g1(|_: (), _: ()| {}); //~ ERROR type mismatch - //~^ ERROR type mismatch g2(|_: (), _: ()| {}); //~ ERROR type mismatch - //~^ ERROR type mismatch g3(|_: (), _: ()| {}); //~ ERROR type mismatch - //~^ ERROR type mismatch g4(|_: (), _: ()| {}); //~ ERROR type mismatch - //~^ ERROR type mismatch h1(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch - //~^ ERROR type mismatch h2(|_: (), _: (), _: (), _: ()| {}); //~ ERROR type mismatch - //~^ ERROR type mismatch } // Basic diff --git a/src/test/ui/anonymous-higher-ranked-lifetime.stderr b/src/test/ui/anonymous-higher-ranked-lifetime.stderr index fbe2d192d0cce..9be44c7f44807 100644 --- a/src/test/ui/anonymous-higher-ranked-lifetime.stderr +++ b/src/test/ui/anonymous-higher-ranked-lifetime.stderr @@ -10,18 +10,7 @@ LL | fn f1(_: F) where F: Fn(&(), &()) {} | -- ------------ required by this bound in `f1` error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:2:5 - | -LL | f1(|_: (), _: ()| {}); - | ^^ -------------- found signature of `fn((), ()) -> _` - | | - | expected signature of `fn(&(), &()) -> _` -... -LL | fn f1(_: F) where F: Fn(&(), &()) {} - | -- ------------ required by this bound in `f1` - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:3:5 | LL | f2(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` @@ -34,17 +23,6 @@ LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} error[E0631]: type mismatch in closure arguments --> $DIR/anonymous-higher-ranked-lifetime.rs:4:5 | -LL | f2(|_: (), _: ()| {}); - | ^^ -------------- found signature of `fn((), ()) -> _` - | | - | expected signature of `fn(&'a (), &()) -> _` -... -LL | fn f2(_: F) where F: for<'a> Fn(&'a (), &()) {} - | -- --------------- required by this bound in `f2` - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 - | LL | f3(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` | | @@ -54,18 +32,7 @@ LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} | -- --------------- required by this bound in `f3` error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 - | -LL | f3(|_: (), _: ()| {}); - | ^^ -------------- found signature of `fn((), ()) -> _` - | | - | expected signature of `fn(&(), &()) -> _` -... -LL | fn f3<'a, F>(_: F) where F: Fn(&'a (), &()) {} - | -- --------------- required by this bound in `f3` - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:5:5 | LL | f4(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` @@ -76,18 +43,7 @@ LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} | -- ----------------------- required by this bound in `f4` error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 - | -LL | f4(|_: (), _: ()| {}); - | ^^ -------------- found signature of `fn((), ()) -> _` - | | - | expected signature of `fn(&(), &'r ()) -> _` -... -LL | fn f4(_: F) where F: for<'r> Fn(&(), &'r ()) {} - | -- --------------- required by this bound in `f4` - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:6:5 | LL | f5(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` @@ -98,18 +54,7 @@ LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} | -- -------------------------- required by this bound in `f5` error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 - | -LL | f5(|_: (), _: ()| {}); - | ^^ -------------- found signature of `fn((), ()) -> _` - | | - | expected signature of `fn(&'r (), &'r ()) -> _` -... -LL | fn f5(_: F) where F: for<'r> Fn(&'r (), &'r ()) {} - | -- ------------------ required by this bound in `f5` - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:7:5 | LL | g1(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` @@ -120,18 +65,7 @@ LL | fn g1(_: F) where F: Fn(&(), Box) {} | -- ------------------------- required by this bound in `g1` error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 - | -LL | g1(|_: (), _: ()| {}); - | ^^ -------------- found signature of `fn((), ()) -> _` - | | - | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` -... -LL | fn g1(_: F) where F: Fn(&(), Box) {} - | -- ------------------------- required by this bound in `g1` - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:8:5 | LL | g2(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` @@ -142,18 +76,7 @@ LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} | -- ---------------- required by this bound in `g2` error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:14:5 - | -LL | g2(|_: (), _: ()| {}); - | ^^ -------------- found signature of `fn((), ()) -> _` - | | - | expected signature of `fn(&(), for<'r> fn(&'r ())) -> _` -... -LL | fn g2(_: F) where F: Fn(&(), fn(&())) {} - | -- ---------------- required by this bound in `g2` - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:9:5 | LL | g3(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` @@ -164,18 +87,7 @@ LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} | -- ------------------------------------ required by this bound in `g3` error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:16:5 - | -LL | g3(|_: (), _: ()| {}); - | ^^ -------------- found signature of `fn((), ()) -> _` - | | - | expected signature of `fn(&'s (), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>) -> _` -... -LL | fn g3(_: F) where F: for<'s> Fn(&'s (), Box) {} - | -- ---------------------------- required by this bound in `g3` - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:10:5 | LL | g4(|_: (), _: ()| {}); | ^^ -------------- found signature of `fn((), ()) -> _` @@ -186,18 +98,7 @@ LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} | -- --------------------------- required by this bound in `g4` error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:18:5 - | -LL | g4(|_: (), _: ()| {}); - | ^^ -------------- found signature of `fn((), ()) -> _` - | | - | expected signature of `fn(&(), for<'r> fn(&'r ())) -> _` -... -LL | fn g4(_: F) where F: Fn(&(), for<'r> fn(&'r ())) {} - | -- --------------------------- required by this bound in `g4` - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:11:5 | LL | h1(|_: (), _: (), _: (), _: ()| {}); | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` @@ -208,18 +109,7 @@ LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} | -- -------------------------------------------- required by this bound in `h1` error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:20:5 - | -LL | h1(|_: (), _: (), _: (), _: ()| {}); - | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` - | | - | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &(), for<'r, 's> fn(&'r (), &'s ())) -> _` -... -LL | fn h1(_: F) where F: Fn(&(), Box, &(), fn(&(), &())) {} - | -- -------------------------------------------- required by this bound in `h1` - -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5 + --> $DIR/anonymous-higher-ranked-lifetime.rs:12:5 | LL | h2(|_: (), _: (), _: (), _: ()| {}); | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` @@ -229,16 +119,5 @@ LL | h2(|_: (), _: (), _: (), _: ()| {}); LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} | -- --------------------------------------------------------- required by this bound in `h2` -error[E0631]: type mismatch in closure arguments - --> $DIR/anonymous-higher-ranked-lifetime.rs:22:5 - | -LL | h2(|_: (), _: (), _: (), _: ()| {}); - | ^^ ---------------------------- found signature of `fn((), (), (), ()) -> _` - | | - | expected signature of `fn(&(), std::boxed::Box<(dyn for<'r> std::ops::Fn(&'r ()) + 'static)>, &'t0 (), for<'r, 's> fn(&'r (), &'s ())) -> _` -... -LL | fn h2(_: F) where F: for<'t0> Fn(&(), Box, &'t0 (), fn(&(), &())) {} - | -- ------------------------------------------------ required by this bound in `h2` - -error: aborting due to 22 previous errors +error: aborting due to 11 previous errors diff --git a/src/test/ui/mismatched_types/issue-36053-2.rs b/src/test/ui/mismatched_types/issue-36053-2.rs index 9edfebcd49471..9035e3380b0c5 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.rs +++ b/src/test/ui/mismatched_types/issue-36053-2.rs @@ -7,5 +7,4 @@ fn main() { once::<&str>("str").fuse().filter(|a: &str| true).count(); //~^ ERROR no method named `count` //~| ERROR type mismatch in closure arguments - //~| ERROR type mismatch in closure arguments } diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 89c7b0981158a..72f3220cc1aba 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -16,14 +16,6 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | | | expected signature of `for<'r> fn(&'r &str) -> _` -error[E0631]: type mismatch in closure arguments - --> $DIR/issue-36053-2.rs:7:32 - | -LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _` - | | - | expected signature of `fn(&&str) -> _` - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0599`.