Skip to content

Commit e964329

Browse files
committed
Remove duplicated errors for closure type mismatch
1 parent 96e2c34 commit e964329

28 files changed

+183
-217
lines changed

src/librustc/infer/mod.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -169,9 +169,11 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
169169
/// Caches the results of trait evaluation.
170170
pub evaluation_cache: traits::EvaluationCache<'tcx>,
171171

172-
// the set of predicates on which errors have been reported, to
173-
// avoid reporting the same error twice.
172+
/// Set of predicates on which errors have been reported, to
173+
/// avoid reporting the same error twice.
174174
pub reported_trait_errors: RefCell<FxHashSet<traits::TraitErrorKey<'tcx>>>,
175+
/// Set of selection errors have been reported, to avoid reporting them twice.
176+
pub reported_selection_errors: RefCell<FxHashSet<(Span, traits::SelectionError<'tcx>)>>,
175177

176178
// Sadly, the behavior of projection varies a bit depending on the
177179
// stage of compilation. The specifics are given in the
@@ -502,6 +504,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
502504
evaluation_cache: traits::EvaluationCache::new(),
503505
projection_cache: RefCell::new(traits::ProjectionCache::new()),
504506
reported_trait_errors: RefCell::new(FxHashSet()),
507+
reported_selection_errors: RefCell::new(FxHashSet()),
505508
projection_mode: Reveal::UserFacing,
506509
tainted_by_errors_flag: Cell::new(false),
507510
err_count_on_creation: self.sess.err_count(),
@@ -540,6 +543,7 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
540543
selection_cache: traits::SelectionCache::new(),
541544
evaluation_cache: traits::EvaluationCache::new(),
542545
reported_trait_errors: RefCell::new(FxHashSet()),
546+
reported_selection_errors: RefCell::new(FxHashSet()),
543547
projection_mode: projection_mode,
544548
tainted_by_errors_flag: Cell::new(false),
545549
err_count_on_creation: tcx.sess.err_count(),

src/librustc/traits/error_reporting.rs

+23-46
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use super::{
1515
Obligation,
1616
ObligationCause,
1717
ObligationCauseCode,
18+
ParameterCountMismatch,
1819
OutputTypeParameterMismatch,
1920
TraitNotObjectSafe,
2021
PredicateObligation,
@@ -54,11 +55,11 @@ pub struct TraitErrorKey<'tcx> {
5455
impl<'a, 'gcx, 'tcx> TraitErrorKey<'tcx> {
5556
fn from_error(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
5657
e: &FulfillmentError<'tcx>) -> Self {
57-
let predicate =
58-
infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
58+
let predicate = infcx.resolve_type_vars_if_possible(&e.obligation.predicate);
59+
let predicate = infcx.tcx.erase_regions(&predicate);
5960
TraitErrorKey {
6061
span: e.obligation.cause.span,
61-
predicate: infcx.tcx.erase_regions(&predicate)
62+
predicate: predicate,
6263
}
6364
}
6465
}
@@ -523,6 +524,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
523524
{
524525
let span = obligation.cause.span;
525526

527+
if !self.reported_selection_errors.borrow_mut().insert((span, error.clone())) {
528+
debug!("report_selection_error: skipping duplicate {:?}", error);
529+
return;
530+
}
531+
526532
let mut err = match *error {
527533
SelectionError::Unimplemented => {
528534
if let ObligationCauseCode::CompareImplMethodObligation {
@@ -657,6 +663,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
657663
}
658664
}
659665

666+
ParameterCountMismatch(expected_found, ty, def_id) => {
667+
let found_span = self.tcx.hir.span_if_local(def_id);
668+
self.report_arg_count_mismatch(span,
669+
found_span,
670+
expected_found.expected,
671+
expected_found.found,
672+
ty.is_closure())
673+
}
660674
OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
661675
let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref);
662676
let actual_trait_ref = self.resolve_type_vars_if_possible(&*actual_trait_ref);
@@ -668,49 +682,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
668682
self.tcx.hir.span_if_local(did)
669683
});
670684

671-
if let &TypeError::TupleSize(ref expected_found) = e {
672-
// Expected `|x| { }`, found `|x, y| { }`
673-
self.report_arg_count_mismatch(span,
674-
found_span,
675-
expected_found.expected,
676-
expected_found.found,
677-
expected_trait_ty.is_closure())
678-
} else if let &TypeError::Sorts(ref expected_found) = e {
679-
let expected = if let ty::TyTuple(tys, _) = expected_found.expected.sty {
680-
tys.len()
681-
} else {
682-
1
683-
};
684-
let found = if let ty::TyTuple(tys, _) = expected_found.found.sty {
685-
tys.len()
686-
} else {
687-
1
688-
};
689-
690-
if expected != found {
691-
// Expected `|| { }`, found `|x, y| { }`
692-
// Expected `fn(x) -> ()`, found `|| { }`
693-
self.report_arg_count_mismatch(span,
694-
found_span,
695-
expected,
696-
found,
697-
expected_trait_ty.is_closure())
698-
} else {
699-
self.report_type_argument_mismatch(span,
700-
found_span,
701-
expected_trait_ty,
702-
expected_trait_ref,
703-
actual_trait_ref,
704-
e)
705-
}
706-
} else {
707-
self.report_type_argument_mismatch(span,
708-
found_span,
709-
expected_trait_ty,
710-
expected_trait_ref,
711-
actual_trait_ref,
712-
e)
713-
}
685+
self.report_type_argument_mismatch(span,
686+
found_span,
687+
expected_trait_ty,
688+
expected_trait_ref,
689+
actual_trait_ref,
690+
e)
714691
}
715692

716693
TraitNotObjectSafe(did) => {

src/librustc/traits/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -196,12 +196,13 @@ pub type TraitObligations<'tcx> = Vec<TraitObligation<'tcx>>;
196196

197197
pub type Selection<'tcx> = Vtable<'tcx, PredicateObligation<'tcx>>;
198198

199-
#[derive(Clone,Debug)]
199+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
200200
pub enum SelectionError<'tcx> {
201201
Unimplemented,
202202
OutputTypeParameterMismatch(ty::PolyTraitRef<'tcx>,
203203
ty::PolyTraitRef<'tcx>,
204204
ty::error::TypeError<'tcx>),
205+
ParameterCountMismatch(ExpectedFound<usize>, Ty<'tcx>, DefId),
205206
TraitNotObjectSafe(DefId),
206207
}
207208

src/librustc/traits/select.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ use super::project;
1919
use super::project::{normalize_with_depth, Normalized};
2020
use super::{PredicateObligation, TraitObligation, ObligationCause};
2121
use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
22-
use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
22+
use super::{SelectionError, Unimplemented, ParameterCountMismatch, OutputTypeParameterMismatch};
2323
use super::{ObjectCastObligation, Obligation};
2424
use super::Reveal;
2525
use super::TraitNotObjectSafe;
@@ -39,6 +39,7 @@ use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
3939
use traits;
4040
use ty::fast_reject;
4141
use ty::relate::TypeRelation;
42+
use ty::error::TypeError::{TupleSize, Sorts};
4243
use middle::lang_items;
4344

4445
use rustc_data_structures::bitvec::BitVector;
@@ -2425,7 +2426,42 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
24252426
expected_trait_ref.clone(),
24262427
obligation_trait_ref.clone())
24272428
.map(|InferOk { obligations, .. }| self.inferred_obligations.extend(obligations))
2428-
.map_err(|e| OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e))
2429+
.map_err(|e| {
2430+
let self_ty = expected_trait_ref.self_ty();
2431+
match (&self_ty.sty, &e) {
2432+
(&ty::TyClosure(def_id, ..), &TupleSize(expected_found)) |
2433+
(&ty::TyFnDef(def_id, ..), &TupleSize(expected_found)) => {
2434+
// Expected `fn(x)`/`|x| { }`, found `fn(x, y)`/`|x, y| { }`
2435+
ParameterCountMismatch(expected_found, self_ty, def_id)
2436+
}
2437+
(&ty::TyClosure(def_id, ..), &Sorts(expected_found)) |
2438+
(&ty::TyFnDef(def_id, ..), &Sorts(expected_found)) => {
2439+
// Expected `|| { }`, found `|x, y| { }`
2440+
// Expected `fn(x)`, found `|| { }`
2441+
let expected = if let ty::TyTuple(tys, _) = expected_found.expected.sty {
2442+
tys.len()
2443+
} else {
2444+
1
2445+
};
2446+
let found = if let ty::TyTuple(tys, _) = expected_found.found.sty {
2447+
tys.len()
2448+
} else {
2449+
1
2450+
};
2451+
2452+
if expected != found {
2453+
let expected_found = ty::error::ExpectedFound {
2454+
expected: expected,
2455+
found: found,
2456+
};
2457+
ParameterCountMismatch(expected_found, self_ty, def_id)
2458+
} else {
2459+
OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e)
2460+
}
2461+
}
2462+
_ => OutputTypeParameterMismatch(expected_trait_ref, obligation_trait_ref, e),
2463+
}
2464+
})
24292465
}
24302466

24312467
fn confirm_builtin_unsize_candidate(&mut self,

src/librustc/traits/structural_impls.rs

+5
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,11 @@ impl<'a, 'tcx> Lift<'tcx> for traits::SelectionError<'a> {
151151
fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
152152
match *self {
153153
super::Unimplemented => Some(super::Unimplemented),
154+
super::ParameterCountMismatch(expected_found, ref ty, def_id) => {
155+
tcx.lift(ty).map(|ty| {
156+
super::ParameterCountMismatch(expected_found, ty, def_id)
157+
})
158+
}
154159
super::OutputTypeParameterMismatch(a, b, ref err) => {
155160
tcx.lift(&(a, b)).and_then(|(a, b)| {
156161
tcx.lift(err).map(|err| {

src/librustc/ty/error.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,14 @@ use syntax_pos::Span;
2020

2121
use hir;
2222

23-
#[derive(Clone, Copy, Debug)]
23+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
2424
pub struct ExpectedFound<T> {
2525
pub expected: T,
2626
pub found: T,
2727
}
2828

2929
// Data structures used in type unification
30-
#[derive(Clone, Debug)]
30+
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
3131
pub enum TypeError<'tcx> {
3232
Mismatch,
3333
UnsafetyMismatch(ExpectedFound<hir::Unsafety>),

src/librustc/ty/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -613,7 +613,7 @@ pub struct ClosureUpvar<'tcx> {
613613
pub ty: Ty<'tcx>,
614614
}
615615

616-
#[derive(Clone, Copy, PartialEq)]
616+
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
617617
pub enum IntVarValue {
618618
IntType(ast::IntTy),
619619
UintType(ast::UintTy),

src/librustc_data_structures/obligation_forest/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ impl<O: ForestObligation> ObligationForest<O> {
261261
/// Convert all remaining obligations to the given error.
262262
///
263263
/// This cannot be done during a snapshot.
264-
pub fn to_errors<E: Clone>(&mut self, error: E) -> Vec<Error<O, E>> {
264+
pub fn to_errors<E: Clone + Debug>(&mut self, error: E) -> Vec<Error<O, E>> {
265265
assert!(!self.in_snapshot());
266266
let mut errors = vec![];
267267
for index in 0..self.nodes.len() {

src/test/compile-fail/extern-wrong-value-type.rs

-1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,4 @@ fn main() {
1818
let _x: extern "C" fn() = f; // OK
1919
is_fn(f);
2020
//~^ ERROR `extern "C" fn() {f}: std::ops::Fn<()>` is not satisfied
21-
//~| ERROR `extern "C" fn() {f}: std::ops::FnOnce<()>` is not satisfied
2221
}

src/test/compile-fail/fn-trait-formatting.rs

-1
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,4 @@ fn main() {
2828

2929
needs_fn(1);
3030
//~^ ERROR : std::ops::Fn<(isize,)>`
31-
//~| ERROR : std::ops::FnOnce<(isize,)>`
3231
}

src/test/compile-fail/issue-22034.rs

-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,5 @@ fn main() {
1717
let _: &mut Fn() = unsafe {
1818
&mut *(ptr as *mut Fn())
1919
//~^ ERROR `(): std::ops::Fn<()>` is not satisfied
20-
//~| ERROR `(): std::ops::FnOnce<()>` is not satisfied
2120
};
2221
}

src/test/compile-fail/issue-23966.rs

-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,4 @@
1111
fn main() {
1212
"".chars().fold(|_, _| (), ());
1313
//~^ ERROR E0277
14-
//~| ERROR E0277
1514
}

src/test/compile-fail/kindck-impl-type-params.rs

-2
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,12 @@ fn f<T>(val: T) {
2727
let t: S<T> = S(marker::PhantomData);
2828
let a = &t as &Gettable<T>;
2929
//~^ ERROR : std::marker::Send` is not satisfied
30-
//~^^ ERROR : std::marker::Copy` is not satisfied
3130
}
3231

3332
fn g<T>(val: T) {
3433
let t: S<T> = S(marker::PhantomData);
3534
let a: &Gettable<T> = &t;
3635
//~^ ERROR : std::marker::Send` is not satisfied
37-
//~^^ ERROR : std::marker::Copy` is not satisfied
3836
}
3937

4038
fn foo<'a>() {

src/test/compile-fail/not-panic-safe-2.rs

-1
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,4 @@ fn assert<T: UnwindSafe + ?Sized>() {}
1919
fn main() {
2020
assert::<Rc<RefCell<i32>>>();
2121
//~^ ERROR `std::cell::UnsafeCell<i32>: std::panic::RefUnwindSafe` is not satisfied
22-
//~^^ ERROR `std::cell::UnsafeCell<usize>: std::panic::RefUnwindSafe` is not satisfied
2322
}

src/test/compile-fail/not-panic-safe-3.rs

-1
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,4 @@ fn assert<T: UnwindSafe + ?Sized>() {}
1919
fn main() {
2020
assert::<Arc<RefCell<i32>>>();
2121
//~^ ERROR `std::cell::UnsafeCell<i32>: std::panic::RefUnwindSafe` is not satisfied
22-
//~^^ ERROR `std::cell::UnsafeCell<usize>: std::panic::RefUnwindSafe` is not satisfied
2322
}

src/test/compile-fail/not-panic-safe-4.rs

-1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,4 @@ fn assert<T: UnwindSafe + ?Sized>() {}
1818
fn main() {
1919
assert::<&RefCell<i32>>();
2020
//~^ ERROR `std::cell::UnsafeCell<i32>: std::panic::RefUnwindSafe` is not satisfied
21-
//~^^ ERROR `std::cell::UnsafeCell<usize>: std::panic::RefUnwindSafe` is not satisfied
2221
}

src/test/compile-fail/not-panic-safe-6.rs

-1
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,4 @@ fn assert<T: UnwindSafe + ?Sized>() {}
1818
fn main() {
1919
assert::<*mut RefCell<i32>>();
2020
//~^ ERROR `std::cell::UnsafeCell<i32>: std::panic::RefUnwindSafe` is not satisfied
21-
//~^^ ERROR `std::cell::UnsafeCell<usize>: std::panic::RefUnwindSafe` is not satisfied
2221
}

0 commit comments

Comments
 (0)