Skip to content

Commit 374d4d8

Browse files
Fix error message with non-tupled bare fn trait
1 parent 9de7474 commit 374d4d8

File tree

8 files changed

+97
-30
lines changed

8 files changed

+97
-30
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1746,6 +1746,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17461746
if let Some(ValuePairs::PolyTraitRefs(exp_found)) = values
17471747
&& let ty::Closure(def_id, _) = exp_found.expected.skip_binder().self_ty().kind()
17481748
&& let Some(def_id) = def_id.as_local()
1749+
&& terr.involves_regions()
17491750
{
17501751
let span = self.tcx.def_span(def_id);
17511752
diag.span_note(span, "this closure does not fulfill the lifetime requirements");

compiler/rustc_infer/src/infer/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -1922,6 +1922,18 @@ impl<'tcx> TypeTrace<'tcx> {
19221922
}
19231923
}
19241924

1925+
pub fn poly_trait_refs(
1926+
cause: &ObligationCause<'tcx>,
1927+
a_is_expected: bool,
1928+
a: ty::PolyTraitRef<'tcx>,
1929+
b: ty::PolyTraitRef<'tcx>,
1930+
) -> TypeTrace<'tcx> {
1931+
TypeTrace {
1932+
cause: cause.clone(),
1933+
values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a.into(), b.into())),
1934+
}
1935+
}
1936+
19251937
pub fn consts(
19261938
cause: &ObligationCause<'tcx>,
19271939
a_is_expected: bool,

compiler/rustc_middle/src/ty/error.rs

+12
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,18 @@ pub enum TypeError<'tcx> {
7373
TargetFeatureCast(DefId),
7474
}
7575

76+
impl TypeError<'_> {
77+
pub fn involves_regions(&self) -> bool {
78+
match self {
79+
TypeError::RegionsDoesNotOutlive(_, _)
80+
| TypeError::RegionsInsufficientlyPolymorphic(_, _)
81+
| TypeError::RegionsOverlyPolymorphic(_, _)
82+
| TypeError::RegionsPlaceholderMismatch => true,
83+
_ => false,
84+
}
85+
}
86+
}
87+
7688
/// Explains the source of a type err in a short, human readable way. This is meant to be placed
7789
/// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
7890
/// afterwards to present additional details, particularly when it comes to lifetime-related

compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs

+27-3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use rustc_hir::intravisit::Visitor;
2222
use rustc_hir::GenericParam;
2323
use rustc_hir::Item;
2424
use rustc_hir::Node;
25+
use rustc_infer::infer::TypeTrace;
2526
use rustc_infer::traits::TraitEngine;
2627
use rustc_middle::traits::select::OverflowError;
2728
use rustc_middle::ty::abstract_const::NotConstEvaluatable;
@@ -940,20 +941,43 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
940941

941942
self.reported_closure_mismatch.borrow_mut().insert((span, found_span));
942943

944+
let mut not_tupled = false;
945+
943946
let found = match found_trait_ref.skip_binder().substs.type_at(1).kind() {
944947
ty::Tuple(ref tys) => vec![ArgKind::empty(); tys.len()],
945-
_ => vec![ArgKind::empty()],
948+
_ => {
949+
not_tupled = true;
950+
vec![ArgKind::empty()]
951+
}
946952
};
947953

948954
let expected_ty = expected_trait_ref.skip_binder().substs.type_at(1);
949955
let expected = match expected_ty.kind() {
950956
ty::Tuple(ref tys) => {
951957
tys.iter().map(|t| ArgKind::from_expected_ty(t, Some(span))).collect()
952958
}
953-
_ => vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())],
959+
_ => {
960+
not_tupled = true;
961+
vec![ArgKind::Arg("_".to_owned(), expected_ty.to_string())]
962+
}
954963
};
955964

956-
if found.len() == expected.len() {
965+
// If this is a `Fn` family trait and either the expected or found
966+
// is not tupled, then fall back to just a regular mismatch error.
967+
// This shouldn't be common unless manually implementing one of the
968+
// traits manually, but don't make it more confusing when it does
969+
// happen.
970+
if Some(expected_trait_ref.def_id()) != tcx.lang_items().gen_trait() && not_tupled {
971+
self.report_and_explain_type_error(
972+
TypeTrace::poly_trait_refs(
973+
&obligation.cause,
974+
true,
975+
expected_trait_ref,
976+
found_trait_ref,
977+
),
978+
&ty::error::TypeError::Mismatch,
979+
)
980+
} else if found.len() == expected.len() {
957981
self.report_closure_arg_mismatch(
958982
span,
959983
found_span,

src/test/ui/mismatched_types/E0631.stderr

+10-10
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ note: required by a bound in `foo`
1212
LL | fn foo<F: Fn(usize)>(_: F) {}
1313
| ^^^^^^^^^ required by this bound in `foo`
1414

15-
error[E0631]: type mismatch in closure arguments
15+
error[E0308]: mismatched types
1616
--> $DIR/E0631.rs:8:5
1717
|
1818
LL | bar(|_: isize| {});
19-
| ^^^ ---------- found signature of `fn(isize) -> _`
20-
| |
21-
| expected signature of `fn(usize) -> _`
19+
| ^^^ types differ
2220
|
21+
= note: expected trait `Fn<usize>`
22+
found trait `Fn<(isize,)>`
2323
note: required by a bound in `bar`
2424
--> $DIR/E0631.rs:4:11
2525
|
@@ -43,17 +43,16 @@ note: required by a bound in `foo`
4343
LL | fn foo<F: Fn(usize)>(_: F) {}
4444
| ^^^^^^^^^ required by this bound in `foo`
4545

46-
error[E0631]: type mismatch in function arguments
46+
error[E0308]: mismatched types
4747
--> $DIR/E0631.rs:10:9
4848
|
49-
LL | fn f(_: u64) {}
50-
| ------------ found signature of `fn(u64) -> _`
51-
...
5249
LL | bar(f);
53-
| --- ^ expected signature of `fn(usize) -> _`
50+
| --- ^ types differ
5451
| |
5552
| required by a bound introduced by this call
5653
|
54+
= note: expected trait `Fn<usize>`
55+
found trait `Fn<(u64,)>`
5756
note: required by a bound in `bar`
5857
--> $DIR/E0631.rs:4:11
5958
|
@@ -62,4 +61,5 @@ LL | fn bar<F: Fn<usize>>(_: F) {}
6261

6362
error: aborting due to 4 previous errors
6463

65-
For more information about this error, try `rustc --explain E0631`.
64+
Some errors have detailed explanations: E0308, E0631.
65+
For more information about an error, try `rustc --explain E0308`.

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

+10-17
Original file line numberDiff line numberDiff line change
@@ -45,41 +45,33 @@ help: change the closure to take multiple arguments instead of a single tuple
4545
LL | [1, 2, 3].sort_by(|tuple, tuple2| panic!());
4646
| ~~~~~~~~~~~~~~~
4747

48-
error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments
48+
error[E0308]: mismatched types
4949
--> $DIR/closure-arg-count.rs:13:5
5050
|
5151
LL | f(|| panic!());
52-
| ^ -- takes 0 arguments
53-
| |
54-
| expected closure that takes 1 argument
52+
| ^ types differ
5553
|
54+
= note: expected trait `Fn<usize>`
55+
found trait `Fn<()>`
5656
note: required by a bound in `f`
5757
--> $DIR/closure-arg-count.rs:3:9
5858
|
5959
LL | fn f<F: Fn<usize>>(_: F) {}
6060
| ^^^^^^^^^ required by this bound in `f`
61-
help: consider changing the closure to take and ignore the expected argument
62-
|
63-
LL | f(|_| panic!());
64-
| ~~~
6561

66-
error[E0593]: closure is expected to take 1 argument, but it takes 0 arguments
62+
error[E0308]: mismatched types
6763
--> $DIR/closure-arg-count.rs:15:5
6864
|
6965
LL | f( move || panic!());
70-
| ^ ---------- takes 0 arguments
71-
| |
72-
| expected closure that takes 1 argument
66+
| ^ types differ
7367
|
68+
= note: expected trait `Fn<usize>`
69+
found trait `Fn<()>`
7470
note: required by a bound in `f`
7571
--> $DIR/closure-arg-count.rs:3:9
7672
|
7773
LL | fn f<F: Fn<usize>>(_: F) {}
7874
| ^^^^^^^^^ required by this bound in `f`
79-
help: consider changing the closure to take and ignore the expected argument
80-
|
81-
LL | f( move |_| panic!());
82-
| ~~~
8375

8476
error[E0593]: closure is expected to take a single 2-tuple as argument, but it takes 2 distinct arguments
8577
--> $DIR/closure-arg-count.rs:18:53
@@ -198,4 +190,5 @@ LL | fn call<F, R>(_: F) where F: FnOnce() -> R {}
198190

199191
error: aborting due to 14 previous errors
200192

201-
For more information about this error, try `rustc --explain E0593`.
193+
Some errors have detailed explanations: E0308, E0593.
194+
For more information about an error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#![feature(unboxed_closures)]
2+
3+
fn a<F: Fn<usize>>(f: F) {}
4+
5+
fn main() {
6+
a(|_: usize| {});
7+
//~^ ERROR mismatched types
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/non-tupled-arg-mismatch.rs:6:5
3+
|
4+
LL | a(|_: usize| {});
5+
| ^ types differ
6+
|
7+
= note: expected trait `Fn<usize>`
8+
found trait `Fn<(usize,)>`
9+
note: required by a bound in `a`
10+
--> $DIR/non-tupled-arg-mismatch.rs:3:9
11+
|
12+
LL | fn a<F: Fn<usize>>(f: F) {}
13+
| ^^^^^^^^^ required by this bound in `a`
14+
15+
error: aborting due to previous error
16+
17+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)