Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 1d6f05f

Browse files
committed
Auto merge of rust-lang#116439 - compiler-errors:on-unimplemented, r=davidtwco
Pretty print `Fn` traits in `rustc_on_unimplemented` I don't think that users really ever should need to think about `Fn*` traits' tupled args for a simple trait error. r? diagnostics
2 parents 2429818 + c83f642 commit 1d6f05f

File tree

61 files changed

+169
-154
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+169
-154
lines changed

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,7 @@ symbols! {
316316
ToOwned,
317317
ToString,
318318
TokenStream,
319+
Trait,
319320
Try,
320321
TryCaptureGeneric,
321322
TryCapturePrintable,

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ static ALLOWED_FORMAT_SYMBOLS: &[Symbol] = &[
5353
sym::float,
5454
sym::_Self,
5555
sym::crate_local,
56+
sym::Trait,
5657
];
5758

5859
impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
@@ -183,6 +184,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
183184
flags.push((sym::cause, Some("MainFunctionType".to_string())));
184185
}
185186

187+
if let Some(kind) = self.tcx.fn_trait_kind_from_def_id(trait_ref.def_id)
188+
&& let ty::Tuple(args) = trait_ref.args.type_at(1).kind()
189+
{
190+
let args = args
191+
.iter()
192+
.map(|ty| ty.to_string())
193+
.collect::<Vec<_>>()
194+
.join(", ");
195+
flags.push((sym::Trait, Some(format!("{}({args})", kind.as_str()))));
196+
} else {
197+
flags.push((sym::Trait, Some(trait_ref.print_only_trait_path().to_string())));
198+
}
199+
186200
// Add all types without trimmed paths or visible paths, ensuring they end up with
187201
// their "canonical" def path.
188202
ty::print::with_no_trimmed_paths!(ty::print::with_no_visible_paths!({

library/core/src/ops/function.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ use crate::marker::Tuple;
5656
#[lang = "fn"]
5757
#[stable(feature = "rust1", since = "1.0.0")]
5858
#[rustc_paren_sugar]
59-
#[rustc_on_unimplemented(
59+
#[cfg_attr(not(bootstrap), rustc_on_unimplemented(
6060
on(
6161
Args = "()",
6262
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
@@ -67,9 +67,9 @@ use crate::marker::Tuple;
6767
// SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
6868
label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
6969
),
70-
message = "expected a `{Fn}<{Args}>` closure, found `{Self}`",
71-
label = "expected an `Fn<{Args}>` closure, found `{Self}`"
72-
)]
70+
message = "expected a `{Trait}` closure, found `{Self}`",
71+
label = "expected an `{Trait}` closure, found `{Self}`"
72+
))]
7373
#[fundamental] // so that regex can rely that `&str: !FnMut`
7474
#[must_use = "closures are lazy and do nothing unless called"]
7575
// FIXME(effects) #[const_trait]
@@ -143,7 +143,7 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
143143
#[lang = "fn_mut"]
144144
#[stable(feature = "rust1", since = "1.0.0")]
145145
#[rustc_paren_sugar]
146-
#[rustc_on_unimplemented(
146+
#[cfg_attr(not(bootstrap), rustc_on_unimplemented(
147147
on(
148148
Args = "()",
149149
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
@@ -154,9 +154,9 @@ pub trait Fn<Args: Tuple>: FnMut<Args> {
154154
// SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
155155
label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
156156
),
157-
message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`",
158-
label = "expected an `FnMut<{Args}>` closure, found `{Self}`"
159-
)]
157+
message = "expected a `{Trait}` closure, found `{Self}`",
158+
label = "expected an `{Trait}` closure, found `{Self}`"
159+
))]
160160
#[fundamental] // so that regex can rely that `&str: !FnMut`
161161
#[must_use = "closures are lazy and do nothing unless called"]
162162
// FIXME(effects) #[const_trait]
@@ -222,7 +222,7 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> {
222222
#[lang = "fn_once"]
223223
#[stable(feature = "rust1", since = "1.0.0")]
224224
#[rustc_paren_sugar]
225-
#[rustc_on_unimplemented(
225+
#[cfg_attr(not(bootstrap), rustc_on_unimplemented(
226226
on(
227227
Args = "()",
228228
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
@@ -233,9 +233,9 @@ pub trait FnMut<Args: Tuple>: FnOnce<Args> {
233233
// SAFETY: tidy is not smart enough to tell that the below unsafe block is a string
234234
label = "call the function in a closure: `|| unsafe {{ /* code */ }}`"
235235
),
236-
message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`",
237-
label = "expected an `FnOnce<{Args}>` closure, found `{Self}`"
238-
)]
236+
message = "expected a `{Trait}` closure, found `{Self}`",
237+
label = "expected an `{Trait}` closure, found `{Self}`"
238+
))]
239239
#[fundamental] // so that regex can rely that `&str: !FnMut`
240240
#[must_use = "closures are lazy and do nothing unless called"]
241241
// FIXME(effects) #[const_trait]

tests/ui/closures/closure-expected.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
fn main() {
22
let x = Some(1);
33
let y = x.or_else(4);
4-
//~^ ERROR expected a `FnOnce<()>` closure, found `{integer}`
4+
//~^ ERROR expected a `FnOnce()` closure, found `{integer}`
55
}

tests/ui/closures/closure-expected.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
error[E0277]: expected a `FnOnce<()>` closure, found `{integer}`
1+
error[E0277]: expected a `FnOnce()` closure, found `{integer}`
22
--> $DIR/closure-expected.rs:3:23
33
|
44
LL | let y = x.or_else(4);
5-
| ------- ^ expected an `FnOnce<()>` closure, found `{integer}`
5+
| ------- ^ expected an `FnOnce()` closure, found `{integer}`
66
| |
77
| required by a bound introduced by this call
88
|

tests/ui/closures/coerce-unsafe-to-closure.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0277]: expected a `FnOnce<(&str,)>` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
1+
error[E0277]: expected a `FnOnce(&str)` closure, found `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
22
--> $DIR/coerce-unsafe-to-closure.rs:2:44
33
|
44
LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);

tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
fn main() {
22
let number = 2;
3-
Some(true).filter({ //~ ERROR expected a `FnOnce<(&bool,)>` closure, found `bool`
3+
Some(true).filter({ //~ ERROR expected a `FnOnce(&bool)` closure, found `bool`
44
if number % 2 == 0 {
55
number == 0
66
} else {

tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0277]: expected a `FnOnce<(&bool,)>` closure, found `bool`
1+
error[E0277]: expected a `FnOnce(&bool)` closure, found `bool`
22
--> $DIR/block_instead_of_closure_in_arg.rs:3:23
33
|
44
LL | Some(true).filter({
@@ -12,7 +12,7 @@ LL | || number != 0
1212
LL | || }
1313
| ||_________- this tail expression is of type `bool`
1414
LL | | });
15-
| |______^ expected an `FnOnce<(&bool,)>` closure, found `bool`
15+
| |______^ expected an `FnOnce(&bool)` closure, found `bool`
1616
|
1717
= help: the trait `for<'a> FnOnce<(&'a bool,)>` is not implemented for `bool`
1818
note: required by a bound in `Option::<T>::filter`

tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
const x: usize =42;
22
fn main() {
3-
let p = Some(45).and_then({|x| //~ ERROR expected a `FnOnce<({integer},)>` closure, found `Option<usize>`
3+
let p = Some(45).and_then({|x| //~ ERROR expected a `FnOnce({integer})` closure, found `Option<usize>`
44
1 + 1;
55
Some(x * 2)
66
});

tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error[E0277]: expected a `FnOnce<({integer},)>` closure, found `Option<usize>`
1+
error[E0277]: expected a `FnOnce({integer})` closure, found `Option<usize>`
22
--> $DIR/ruby_style_closure_successful_parse.rs:3:31
33
|
44
LL | let p = Some(45).and_then({|x|
@@ -9,7 +9,7 @@ LL | | 1 + 1;
99
LL | | Some(x * 2)
1010
| | ----------- this tail expression is of type `Option<usize>`
1111
LL | | });
12-
| |_____^ expected an `FnOnce<({integer},)>` closure, found `Option<usize>`
12+
| |_____^ expected an `FnOnce({integer})` closure, found `Option<usize>`
1313
|
1414
= help: the trait `FnOnce<({integer},)>` is not implemented for `Option<usize>`
1515
note: required by a bound in `Option::<T>::and_then`

0 commit comments

Comments
 (0)