Skip to content

Commit

Permalink
Deduplicate closure type errors
Browse files Browse the repository at this point in the history
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`.
  • Loading branch information
estebank committed Oct 1, 2019
1 parent 22bc9e1 commit 13e9b3d
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 153 deletions.
5 changes: 4 additions & 1 deletion src/librustc/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -155,6 +155,8 @@ pub struct InferCtxt<'a, 'tcx> {
/// avoid reporting the same error twice.
pub reported_trait_errors: RefCell<FxHashMap<Span, Vec<ty::Predicate<'tcx>>>>,

pub reported_closure_mismatch: RefCell<FxHashSet<(Span, Option<Span>)>>,

/// 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
Expand Down Expand Up @@ -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),
Expand Down
8 changes: 8 additions & 0 deletions src/librustc/traits/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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()],
Expand Down
11 changes: 0 additions & 11 deletions src/test/ui/anonymous-higher-ranked-lifetime.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down
141 changes: 10 additions & 131 deletions src/test/ui/anonymous-higher-ranked-lifetime.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,7 @@ LL | fn f1<F>(_: 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>(_: 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((), ()) -> _`
Expand All @@ -34,17 +23,6 @@ LL | fn f2<F>(_: 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>(_: 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((), ()) -> _`
| |
Expand All @@ -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((), ()) -> _`
Expand All @@ -76,18 +43,7 @@ LL | fn f4<F>(_: 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>(_: 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((), ()) -> _`
Expand All @@ -98,18 +54,7 @@ LL | fn f5<F>(_: 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>(_: 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((), ()) -> _`
Expand All @@ -120,18 +65,7 @@ LL | fn g1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
| -- ------------------------- 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>(_: F) where F: Fn(&(), Box<dyn Fn(&())>) {}
| -- ------------------------- 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((), ()) -> _`
Expand All @@ -142,18 +76,7 @@ LL | fn g2<F>(_: 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>(_: 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((), ()) -> _`
Expand All @@ -164,18 +87,7 @@ LL | fn g3<F>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
| -- ------------------------------------ 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>(_: F) where F: for<'s> Fn(&'s (), Box<dyn Fn(&())>) {}
| -- ---------------------------- 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((), ()) -> _`
Expand All @@ -186,18 +98,7 @@ LL | fn g4<F>(_: 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>(_: 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((), (), (), ()) -> _`
Expand All @@ -208,18 +109,7 @@ LL | fn h1<F>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), 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>(_: F) where F: Fn(&(), Box<dyn Fn(&())>, &(), 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((), (), (), ()) -> _`
Expand All @@ -229,16 +119,5 @@ LL | h2(|_: (), _: (), _: (), _: ()| {});
LL | fn h2<F>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'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>(_: F) where F: for<'t0> Fn(&(), Box<dyn Fn(&())>, &'t0 (), fn(&(), &())) {}
| -- ------------------------------------------------ required by this bound in `h2`

error: aborting due to 22 previous errors
error: aborting due to 11 previous errors

1 change: 0 additions & 1 deletion src/test/ui/mismatched_types/issue-36053-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
10 changes: 1 addition & 9 deletions src/test/ui/mismatched_types/issue-36053-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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`.

0 comments on commit 13e9b3d

Please sign in to comment.