Skip to content

Commit b52c8c2

Browse files
committed
Reorder code, fix unittests
1 parent 366dd1b commit b52c8c2

9 files changed

+194
-88
lines changed

src/librustc/diagnostics.rs

+21-8
Original file line numberDiff line numberDiff line change
@@ -1049,18 +1049,19 @@ which expected that trait. This error typically occurs when working with
10491049
`Fn`-based types. Erroneous code example:
10501050
10511051
```compile_fail,E0281
1052-
fn foo<F: Fn()>(x: F) { }
1052+
fn foo<F: Fn(usize)>(x: F) { }
10531053
10541054
fn main() {
1055-
// type mismatch: the type ... implements the trait `core::ops::Fn<(_,)>`,
1056-
// but the trait `core::ops::Fn<()>` is required (expected (), found tuple
1055+
// type mismatch: ... implements the trait `core::ops::Fn<(String,)>`,
1056+
// but the trait `core::ops::Fn<(usize,)>` is required
10571057
// [E0281]
1058-
foo(|y| { });
1058+
foo(|y: String| { });
10591059
}
10601060
```
10611061
1062-
The issue in this case is that `foo` is defined as accepting a `Fn` with no
1063-
arguments, but the closure we attempted to pass to it requires one argument.
1062+
The issue in this case is that `foo` is defined as accepting a `Fn` with one
1063+
argument of type `String`, but the closure we attempted to pass to it requires
1064+
one arguments of type `usize`.
10641065
"##,
10651066

10661067
E0282: r##"
@@ -1807,6 +1808,20 @@ makes a difference in practice.)
18071808
[rfc401]: https://github.com/rust-lang/rfcs/blob/master/text/0401-coercions.md
18081809
"##,
18091810

1811+
E0593: r##"
1812+
You tried to supply an `Fn`-based type with an incorrect number of arguments
1813+
than what was expected. Erroneous code example:
1814+
1815+
```compile_fail,E0593
1816+
fn foo<F: Fn()>(x: F) { }
1817+
1818+
fn main() {
1819+
// [E0593] closure takes 1 argument but 0 arguments are required
1820+
foo(|y| { });
1821+
}
1822+
```
1823+
"##,
1824+
18101825
}
18111826

18121827

@@ -1850,6 +1865,4 @@ register_diagnostics! {
18501865
E0495, // cannot infer an appropriate lifetime due to conflicting requirements
18511866
E0566, // conflicting representation hints
18521867
E0587, // conflicting packed and align representation hints
1853-
E0593, // closure argument count mismatch
1854-
E0594 // closure mismatch
18551868
}

src/librustc/traits/error_reporting.rs

+97-52
Original file line numberDiff line numberDiff line change
@@ -664,61 +664,52 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
664664
return;
665665
}
666666
let expected_trait_ty = expected_trait_ref.self_ty();
667-
if expected_trait_ty.is_closure() {
668-
if let &TypeError::TupleSize(ref expected_found) = e {
669-
let mut err = struct_span_err!(self.tcx.sess, span, E0593,
670-
"closure takes {} parameter{} but {} parameter{} are required here",
671-
expected_found.found,
672-
if expected_found.found == 1 { "" } else { "s" },
673-
expected_found.expected,
674-
if expected_found.expected == 1 { "" } else { "s" });
675-
676-
err.span_label(span, &format!("expected closure that takes {} parameter{}",
677-
expected_found.expected,
678-
if expected_found.expected == 1 {
679-
""
680-
} else {
681-
"s"
682-
}));
683-
let closure_span = expected_trait_ty.ty_to_def_id().and_then(|did| {
684-
self.tcx.hir.span_if_local(did)
685-
});
686-
if let Some(span) = closure_span {
687-
err.span_label(span, &format!("takes {} parameter{}",
688-
expected_found.found,
689-
if expected_found.found == 1 {
690-
""
691-
} else {
692-
"s"
693-
}));
694-
}
695-
err
667+
let found_span = expected_trait_ty.ty_to_def_id().and_then(|did| {
668+
self.tcx.hir.span_if_local(did)
669+
});
670+
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()
696681
} else {
697-
let mut err = struct_span_err!(self.tcx.sess, span, E0594,
698-
"closure mismatch: `{}` implements the trait `{}`, \
699-
but the trait `{}` is required",
700-
expected_trait_ty,
701-
expected_trait_ref,
702-
actual_trait_ref);
703-
704-
let closure_span = expected_trait_ty.ty_to_def_id().and_then(|did| {
705-
self.tcx.hir.span_if_local(did)
706-
});
707-
if let Some(span) = closure_span {
708-
err.span_label(span, &format!("{}", e));
709-
} else {
710-
err.note(&format!("{}", e));
711-
}
712-
err
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)
713705
}
714706
} else {
715-
struct_span_err!(self.tcx.sess, span, E0281,
716-
"type mismatch: the type `{}` implements the trait `{}`, \
717-
but the trait `{}` is required ({})",
718-
expected_trait_ty,
719-
expected_trait_ref,
720-
actual_trait_ref,
721-
e)
707+
self.report_type_argument_mismatch(span,
708+
found_span,
709+
expected_trait_ty,
710+
expected_trait_ref,
711+
actual_trait_ref,
712+
e)
722713
}
723714
}
724715

@@ -731,6 +722,60 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
731722
self.note_obligation_cause(&mut err, obligation);
732723
err.emit();
733724
}
725+
726+
fn report_type_argument_mismatch(&self,
727+
span: Span,
728+
found_span: Option<Span>,
729+
expected_ty: Ty<'tcx>,
730+
expected_ref: ty::PolyTraitRef<'tcx>,
731+
found_ref: ty::PolyTraitRef<'tcx>,
732+
type_error: &TypeError<'tcx>)
733+
-> DiagnosticBuilder<'tcx>
734+
{
735+
let mut err = struct_span_err!(self.tcx.sess, span, E0281,
736+
"type mismatch: `{}` implements the trait `{}`, but the trait `{}` is required",
737+
expected_ty,
738+
expected_ref,
739+
found_ref);
740+
741+
err.span_label(span, &format!("{}", type_error));
742+
743+
if let Some(sp) = found_span {
744+
err.span_label(span, &format!("requires `{}`", found_ref));
745+
err.span_label(sp, &format!("implements `{}`", expected_ref));
746+
}
747+
748+
err
749+
}
750+
751+
fn report_arg_count_mismatch(&self,
752+
span: Span,
753+
found_span: Option<Span>,
754+
expected: usize,
755+
found: usize,
756+
is_closure: bool)
757+
-> DiagnosticBuilder<'tcx>
758+
{
759+
let mut err = struct_span_err!(self.tcx.sess, span, E0593,
760+
"{} takes {} argument{} but {} argument{} {} required",
761+
if is_closure { "closure" } else { "function" },
762+
found,
763+
if found == 1 { "" } else { "s" },
764+
expected,
765+
if expected == 1 { "" } else { "s" },
766+
if expected == 1 { "is" } else { "are" });
767+
768+
err.span_label(span, &format!("expected {} that takes {} argument{}",
769+
if is_closure { "closure" } else { "function" },
770+
expected,
771+
if expected == 1 { "" } else { "s" }));
772+
if let Some(span) = found_span {
773+
err.span_label(span, &format!("takes {} argument{}",
774+
found,
775+
if found == 1 { "" } else { "s" }));
776+
}
777+
err
778+
}
734779
}
735780

736781
impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {

src/test/compile-fail/E0281.rs

+12-3
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,18 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
fn foo<F: Fn()>(x: F) { }
11+
fn foo<F: Fn(usize)>(x: F) { }
1212

1313
fn main() {
14-
foo(|y| { }); //~ ERROR E0281
15-
//~^ ERROR E0281
14+
foo(|y: String| { });
15+
//~^ ERROR E0281
16+
//~| ERROR E0281
17+
//~| NOTE implements
18+
//~| NOTE implements
19+
//~| NOTE requires
20+
//~| NOTE requires
21+
//~| NOTE expected usize, found struct `std::string::String`
22+
//~| NOTE expected usize, found struct `std::string::String`
23+
//~| NOTE required by `foo`
24+
//~| NOTE required by `foo`
1625
}

src/test/compile-fail/fn-variance-1.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@ fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
1919
fn main() {
2020
apply(&3, takes_imm);
2121
apply(&3, takes_mut);
22-
//~^ ERROR (types differ in mutability)
22+
//~^ ERROR type mismatch
23+
//~| NOTE types differ in mutability
24+
//~| NOTE required by `apply`
2325

2426
apply(&mut 3, takes_mut);
2527
apply(&mut 3, takes_imm);
26-
//~^ ERROR (types differ in mutability)
28+
//~^ ERROR type mismatch
29+
//~| NOTE types differ in mutability
30+
//~| NOTE required by `apply`
2731
}

src/test/compile-fail/issue-36053-2.rs

+7
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,11 @@ fn main() {
1818
//~^ ERROR no method named `count`
1919
//~| ERROR E0281
2020
//~| ERROR E0281
21+
//~| NOTE expected &str, found str
22+
//~| NOTE expected &str, found str
23+
//~| NOTE implements
24+
//~| NOTE implements
25+
//~| NOTE requires
26+
//~| NOTE requires
27+
//~| NOTE the method `count` exists but the following trait bounds
2128
}

src/test/compile-fail/unboxed-closures-vtable-mismatch.rs

+8
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,16 @@ fn call_it<F:FnMut(isize,isize)->isize>(y: isize, mut f: F) -> isize {
2020

2121
pub fn main() {
2222
let f = to_fn_mut(|x: usize, y: isize| -> isize { (x as isize) + y });
23+
//~^ NOTE implements
24+
//~| NOTE implements
2325
let z = call_it(3, f);
2426
//~^ ERROR type mismatch
2527
//~| ERROR type mismatch
28+
//~| NOTE expected isize, found usize
29+
//~| NOTE expected isize, found usize
30+
//~| NOTE requires
31+
//~| NOTE requires
32+
//~| NOTE required by `call_it`
33+
//~| NOTE required by `call_it`
2634
println!("{}", z);
2735
}

src/test/ui/mismatched_types/closure-arg-count.rs

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
fn main() {
12+
[1, 2, 3].sort_by(|| panic!());
1213
[1, 2, 3].sort_by(|tuple| panic!());
1314
[1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
1415
}
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,59 @@
1-
error[E0593]: closure takes 1 parameter but 2 parameters are required here
1+
error[E0593]: closure takes 0 arguments but 2 arguments are required
22
--> $DIR/closure-arg-count.rs:12:15
33
|
4-
12 | [1, 2, 3].sort_by(|tuple| panic!());
5-
| ^^^^^^^ ---------------- takes 1 parameter
4+
12 | [1, 2, 3].sort_by(|| panic!());
5+
| ^^^^^^^ ----------- takes 0 arguments
66
| |
7-
| expected closure that takes 2 parameters
7+
| expected closure that takes 2 arguments
88

9-
error[E0593]: closure takes 1 parameter but 2 parameters are required here
9+
error[E0593]: closure takes 0 arguments but 2 arguments are required
1010
--> $DIR/closure-arg-count.rs:12:15
1111
|
12-
12 | [1, 2, 3].sort_by(|tuple| panic!());
13-
| ^^^^^^^ ---------------- takes 1 parameter
12+
12 | [1, 2, 3].sort_by(|| panic!());
13+
| ^^^^^^^ ----------- takes 0 arguments
1414
| |
15-
| expected closure that takes 2 parameters
15+
| expected closure that takes 2 arguments
16+
17+
error[E0593]: closure takes 1 argument but 2 arguments are required
18+
--> $DIR/closure-arg-count.rs:13:15
19+
|
20+
13 | [1, 2, 3].sort_by(|tuple| panic!());
21+
| ^^^^^^^ ---------------- takes 1 argument
22+
| |
23+
| expected closure that takes 2 arguments
24+
25+
error[E0593]: closure takes 1 argument but 2 arguments are required
26+
--> $DIR/closure-arg-count.rs:13:15
27+
|
28+
13 | [1, 2, 3].sort_by(|tuple| panic!());
29+
| ^^^^^^^ ---------------- takes 1 argument
30+
| |
31+
| expected closure that takes 2 arguments
1632

1733
error[E0308]: mismatched types
18-
--> $DIR/closure-arg-count.rs:13:24
34+
--> $DIR/closure-arg-count.rs:14:24
1935
|
20-
13 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
36+
14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
2137
| ^^^^^^^^^^^^^^^ expected &{integer}, found tuple
2238
|
2339
= note: expected type `&{integer}`
2440
found type `(_, _)`
2541

26-
error[E0593]: closure takes 1 parameter but 2 parameters are required here
27-
--> $DIR/closure-arg-count.rs:13:15
42+
error[E0593]: closure takes 1 argument but 2 arguments are required
43+
--> $DIR/closure-arg-count.rs:14:15
2844
|
29-
13 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
30-
| ^^^^^^^ -------------------------- takes 1 parameter
45+
14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
46+
| ^^^^^^^ -------------------------- takes 1 argument
3147
| |
32-
| expected closure that takes 2 parameters
48+
| expected closure that takes 2 arguments
3349

34-
error[E0593]: closure takes 1 parameter but 2 parameters are required here
35-
--> $DIR/closure-arg-count.rs:13:15
50+
error[E0593]: closure takes 1 argument but 2 arguments are required
51+
--> $DIR/closure-arg-count.rs:14:15
3652
|
37-
13 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
38-
| ^^^^^^^ -------------------------- takes 1 parameter
53+
14 | [1, 2, 3].sort_by(|(tuple, tuple2)| panic!());
54+
| ^^^^^^^ -------------------------- takes 1 argument
3955
| |
40-
| expected closure that takes 2 parameters
56+
| expected closure that takes 2 arguments
4157

42-
error: aborting due to 5 previous errors
58+
error: aborting due to 7 previous errors
4359

src/test/ui/mismatched_types/closure-mismatch.stderr

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,14 @@ error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.r
88
= note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
99
= note: required by `baz`
1010

11-
error[E0594]: closure mismatch: `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(&'r (),)>` is required
11+
error[E0281]: type mismatch: `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(&'r (),)>` is required
1212
--> $DIR/closure-mismatch.rs:18:5
1313
|
1414
18 | baz(|_| ());
15-
| ^^^ ------ expected concrete lifetime, found bound lifetime parameter
15+
| ^^^ ------ implements `std::ops::Fn<(_,)>`
16+
| |
17+
| requires `for<'r> std::ops::Fn<(&'r (),)>`
18+
| expected concrete lifetime, found bound lifetime parameter
1619
|
1720
= note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]`
1821
= note: required by `baz`

0 commit comments

Comments
 (0)