From 1383f0e9afa019bdf470e4c6cce4b819f8755aad Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Mon, 29 Aug 2022 16:53:36 +0300 Subject: [PATCH 1/4] Make the trait bound is not satisfied specify kind --- .../src/traits/error_reporting/mod.rs | 37 +++++++++++++++---- .../async-await/issues/issue-62009-1.stderr | 2 +- src/test/ui/binop/issue-77910-1.stderr | 2 +- .../closures/coerce-unsafe-to-closure.stderr | 2 +- .../ui/extern/extern-wrong-value-type.stderr | 2 +- .../intrinsics/const-eval-select-bad.stderr | 2 +- src/test/ui/issues/issue-59488.stderr | 4 +- ...70724-add_type_neq_err_label-unwrap.stderr | 2 +- src/test/ui/issues/issue-99875.rs | 16 ++++++++ src/test/ui/issues/issue-99875.stderr | 33 +++++++++++++++++ src/test/ui/namespace/namespace-mix.stderr | 8 ++-- src/test/ui/proc-macro/signature.stderr | 2 +- .../fn-traits.stderr | 12 +++--- ...rg-where-it-should-have-been-called.stderr | 4 +- ...rg-where-it-should-have-been-called.stderr | 4 +- .../unboxed-closures-unsafe-extern-fn.stderr | 6 +-- .../unboxed-closures-wrong-abi.stderr | 6 +-- ...d-closures-wrong-arg-type-extern-fn.stderr | 6 +-- 18 files changed, 111 insertions(+), 39 deletions(-) create mode 100644 src/test/ui/issues/issue-99875.rs create mode 100644 src/test/ui/issues/issue-99875.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index e4af7022239b..8910194f3ee1 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -450,12 +450,27 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { { "consider using `()`, or a `Result`".to_owned() } else { - format!( - "{}the trait `{}` is not implemented for `{}`", - pre_message, - trait_predicate.print_modifiers_and_trait_path(), - trait_ref.skip_binder().self_ty(), - ) + let ty_desc = match trait_ref.skip_binder().self_ty().kind() { + ty::FnDef(_, _) => Some("fn item"), + ty::Closure(_, _) => Some("closure"), + _ => None, + }; + + match ty_desc { + Some(desc) => format!( + "{}the trait `{}` is not implemented for {} `{}`", + pre_message, + trait_predicate.print_modifiers_and_trait_path(), + desc, + trait_ref.skip_binder().self_ty(), + ), + None => format!( + "{}the trait `{}` is not implemented for `{}`", + pre_message, + trait_predicate.print_modifiers_and_trait_path(), + trait_ref.skip_binder().self_ty(), + ), + } }; if self.suggest_add_reference_to_arg( @@ -1805,13 +1820,21 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> { return false; } if candidates.len() == 1 { + let ty_desc = match candidates[0].self_ty().kind() { + ty::FnPtr(_) => Some("fn pointer"), + _ => None, + }; + let the_desc = match ty_desc { + Some(desc) => format!(" implemented for {} `", desc), + None => " implemented for `".to_string(), + }; err.highlighted_help(vec![ ( format!("the trait `{}` ", candidates[0].print_only_trait_path()), Style::NoStyle, ), ("is".to_string(), Style::Highlight), - (" implemented for `".to_string(), Style::NoStyle), + (the_desc, Style::NoStyle), (candidates[0].self_ty().to_string(), Style::Highlight), ("`".to_string(), Style::NoStyle), ]); diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr index fb9dee11f2a0..0e323443ae8b 100644 --- a/src/test/ui/async-await/issues/issue-62009-1.stderr +++ b/src/test/ui/async-await/issues/issue-62009-1.stderr @@ -30,7 +30,7 @@ error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future LL | (|_| 2333).await; | ^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future | - = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` + = help: the trait `Future` is not implemented for closure `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` = note: [closure@$DIR/issue-62009-1.rs:12:6: 12:9] must be a future or must implement `IntoFuture` to be awaited = note: required for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` to implement `IntoFuture` help: remove the `.await` diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr index 68303b842088..097a14f26f86 100644 --- a/src/test/ui/binop/issue-77910-1.stderr +++ b/src/test/ui/binop/issue-77910-1.stderr @@ -18,7 +18,7 @@ LL | fn foo(s: &i32) -> &i32 { LL | assert_eq!(foo, y); | ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}` + = help: the trait `Debug` is not implemented for fn item `for<'r> fn(&'r i32) -> &'r i32 {foo}` = help: use parentheses to call the function: `foo(s)` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/closures/coerce-unsafe-to-closure.stderr b/src/test/ui/closures/coerce-unsafe-to-closure.stderr index bd095c2d83d8..6ce63e829b31 100644 --- a/src/test/ui/closures/coerce-unsafe-to-closure.stderr +++ b/src/test/ui/closures/coerce-unsafe-to-closure.stderr @@ -6,7 +6,7 @@ LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` + = help: the trait `FnOnce<(&str,)>` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `Option::::map` --> $SRC_DIR/core/src/option.rs:LL:COL diff --git a/src/test/ui/extern/extern-wrong-value-type.stderr b/src/test/ui/extern/extern-wrong-value-type.stderr index c6f0d5df9b53..ff2934a2ba88 100644 --- a/src/test/ui/extern/extern-wrong-value-type.stderr +++ b/src/test/ui/extern/extern-wrong-value-type.stderr @@ -6,7 +6,7 @@ LL | is_fn(f); | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for `extern "C" fn() {f}` + = help: the trait `Fn<()>` is not implemented for fn item `extern "C" fn() {f}` = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `is_fn` --> $DIR/extern-wrong-value-type.rs:4:28 diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr index 1a761ad5441c..904e83624b3f 100644 --- a/src/test/ui/intrinsics/const-eval-select-bad.stderr +++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr @@ -6,7 +6,7 @@ LL | const_eval_select((), || {}, || {}); | | | required by a bound introduced by this call | - = help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]` + = help: the trait `~const FnOnce<()>` is not implemented for closure `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]` note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`, but that implementation is not `const` --> $DIR/const-eval-select-bad.rs:7:27 | diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr index bb6843a19586..229dfcca47a2 100644 --- a/src/test/ui/issues/issue-59488.stderr +++ b/src/test/ui/issues/issue-59488.stderr @@ -93,7 +93,7 @@ error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` LL | assert_eq!(Foo::Bar, i); | ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}` + = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}` = help: the following other types implement trait `Debug`: extern "C" fn() -> Ret extern "C" fn(A, B) -> Ret @@ -112,7 +112,7 @@ error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` LL | assert_eq!(Foo::Bar, i); | ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}` + = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}` = help: the following other types implement trait `Debug`: extern "C" fn() -> Ret extern "C" fn(A, B) -> Ret diff --git a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr index c6e6ea1e096a..b80abad2f67e 100644 --- a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr +++ b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr @@ -33,7 +33,7 @@ LL | fn a() -> i32 { LL | assert_eq!(a, 0); | ^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug` | - = help: the trait `Debug` is not implemented for `fn() -> i32 {a}` + = help: the trait `Debug` is not implemented for fn item `fn() -> i32 {a}` = help: use parentheses to call the function: `a()` = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/src/test/ui/issues/issue-99875.rs b/src/test/ui/issues/issue-99875.rs new file mode 100644 index 000000000000..cf73fd8d31fb --- /dev/null +++ b/src/test/ui/issues/issue-99875.rs @@ -0,0 +1,16 @@ +struct Argument; +struct Return; + +fn function(_: Argument) -> Return { todo!() } + +trait Trait {} +impl Trait for fn(Argument) -> Return {} + +fn takes(_: impl Trait) {} + +fn main() { + takes(function); + //~^ ERROR the trait bound + takes(|_: Argument| -> Return { todo!() }); + //~^ ERROR the trait bound +} diff --git a/src/test/ui/issues/issue-99875.stderr b/src/test/ui/issues/issue-99875.stderr new file mode 100644 index 000000000000..3ff8f12f1b8c --- /dev/null +++ b/src/test/ui/issues/issue-99875.stderr @@ -0,0 +1,33 @@ +error[E0277]: the trait bound `fn(Argument) -> Return {function}: Trait` is not satisfied + --> $DIR/issue-99875.rs:12:11 + | +LL | takes(function); + | ----- ^^^^^^^^ the trait `Trait` is not implemented for fn item `fn(Argument) -> Return {function}` + | | + | required by a bound introduced by this call + | + = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return` +note: required by a bound in `takes` + --> $DIR/issue-99875.rs:9:18 + | +LL | fn takes(_: impl Trait) {} + | ^^^^^ required by this bound in `takes` + +error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied + --> $DIR/issue-99875.rs:14:11 + | +LL | takes(|_: Argument| -> Return { todo!() }); + | ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `[closure@$DIR/issue-99875.rs:14:11: 14:34]` + | | + | required by a bound introduced by this call + | + = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return` +note: required by a bound in `takes` + --> $DIR/issue-99875.rs:9:18 + | +LL | fn takes(_: impl Trait) {} + | ^^^^^ required by this bound in `takes` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr index b04ea14d1a58..c07914df7273 100644 --- a/src/test/ui/namespace/namespace-mix.stderr +++ b/src/test/ui/namespace/namespace-mix.stderr @@ -218,7 +218,7 @@ error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfi --> $DIR/namespace-mix.rs:56:11 | LL | check(m3::TS); - | ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}` + | ----- ^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> c::TS {c::TS}` | | | required by a bound introduced by this call | @@ -274,7 +274,7 @@ error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::T --> $DIR/namespace-mix.rs:62:11 | LL | check(xm3::TS); - | ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}` | | | required by a bound introduced by this call | @@ -526,7 +526,7 @@ error[E0277]: the trait bound `fn() -> c::E {c::E::TV}: Impossible` is not satis --> $DIR/namespace-mix.rs:122:11 | LL | check(m9::TV); - | ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}` + | ----- ^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> c::E {c::E::TV}` | | | required by a bound introduced by this call | @@ -582,7 +582,7 @@ error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7:: --> $DIR/namespace-mix.rs:128:11 | LL | check(xm9::TV); - | ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}` + | ----- ^^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}` | | | required by a bound introduced by this call | diff --git a/src/test/ui/proc-macro/signature.stderr b/src/test/ui/proc-macro/signature.stderr index 78b0beff0da3..59b3e44c74a5 100644 --- a/src/test/ui/proc-macro/signature.stderr +++ b/src/test/ui/proc-macro/signature.stderr @@ -10,7 +10,7 @@ LL | | } | |_call the function in a closure: `|| unsafe { /* code */ }` | required by a bound introduced by this call | - = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}` + = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for fn item `unsafe extern "C" fn(i32, u32) -> u32 {foo}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `ProcMacro::custom_derive` --> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index 94a90a568548..fc7bf22775dd 100644 --- a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -6,7 +6,7 @@ LL | call(foo); | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for `fn() {foo}` + = help: the trait `Fn<()>` is not implemented for fn item `fn() {foo}` = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call` @@ -23,7 +23,7 @@ LL | call_mut(foo); | | | required by a bound introduced by this call | - = help: the trait `FnMut<()>` is not implemented for `fn() {foo}` + = help: the trait `FnMut<()>` is not implemented for fn item `fn() {foo}` = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` @@ -40,7 +40,7 @@ LL | call_once(foo); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<()>` is not implemented for `fn() {foo}` + = help: the trait `FnOnce<()>` is not implemented for fn item `fn() {foo}` = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_once` @@ -57,7 +57,7 @@ LL | call(foo_unsafe); | | | required by a bound introduced by this call | - = help: the trait `Fn<()>` is not implemented for `unsafe fn() {foo_unsafe}` + = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}` = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call` @@ -74,7 +74,7 @@ LL | call_mut(foo_unsafe); | | | required by a bound introduced by this call | - = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {foo_unsafe}` + = help: the trait `FnMut<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}` = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_mut` @@ -91,7 +91,7 @@ LL | call_once(foo_unsafe); | | | required by a bound introduced by this call | - = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {foo_unsafe}` + = help: the trait `FnOnce<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}` = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }` = note: `#[target_feature]` functions do not implement the `Fn` traits note: required by a bound in `call_once` diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index c7d420e0aae8..bfd506c9f6e0 100644 --- a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -9,7 +9,7 @@ LL | bar(foo); | | | required by a bound introduced by this call | - = help: the trait `Future` is not implemented for `fn() -> impl Future {foo}` + = help: the trait `Future` is not implemented for fn item `fn() -> impl Future {foo}` = note: fn() -> impl Future {foo} must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 @@ -31,7 +31,7 @@ LL | bar(async_closure); | | | required by a bound introduced by this call | - = help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` + = help: the trait `Future` is not implemented for closure `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]` = note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33] must be a future or must implement `IntoFuture` to be awaited note: required by a bound in `bar` --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16 diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr index fb0a6f70bfb4..fe603b67575d 100644 --- a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr +++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr @@ -5,7 +5,7 @@ LL | fn foo() -> impl T { S } | --- consider calling this function ... LL | bar(foo); - | --- ^^^ the trait `T` is not implemented for `fn() -> impl T {foo}` + | --- ^^^ the trait `T` is not implemented for fn item `fn() -> impl T {foo}` | | | required by a bound introduced by this call | @@ -25,7 +25,7 @@ error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-shou LL | let closure = || S; | -- consider calling this closure LL | bar(closure); - | --- ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]` + | --- ^^^^^^^ the trait `T` is not implemented for closure `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]` | | | required by a bound introduced by this call | diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index 18e133957ba3..9833304c636b 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -6,7 +6,7 @@ LL | let x = call_it(&square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15 @@ -22,7 +22,7 @@ LL | let y = call_it_mut(&mut square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_mut` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19 @@ -38,7 +38,7 @@ LL | let z = call_it_once(square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_once` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20 diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index 77c176de625c..54c92e0cd040 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -6,7 +6,7 @@ LL | let x = call_it(&square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}` note: required by a bound in `call_it` --> $DIR/unboxed-closures-wrong-abi.rs:9:15 | @@ -21,7 +21,7 @@ LL | let y = call_it_mut(&mut square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}` note: required by a bound in `call_it_mut` --> $DIR/unboxed-closures-wrong-abi.rs:12:19 | @@ -36,7 +36,7 @@ LL | let z = call_it_once(square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}` + = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}` note: required by a bound in `call_it_once` --> $DIR/unboxed-closures-wrong-abi.rs:15:20 | diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index c826af3c4c38..2fedb5b92c28 100644 --- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -6,7 +6,7 @@ LL | let x = call_it(&square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15 @@ -22,7 +22,7 @@ LL | let y = call_it_mut(&mut square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_mut` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19 @@ -38,7 +38,7 @@ LL | let z = call_it_once(square, 22); | | | required by a bound introduced by this call | - = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}` + = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}` = note: unsafe function cannot be called generically without an unsafe block note: required by a bound in `call_it_once` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20 From 12a49523697f4a64609558b467c460b9a4b333c1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 3 Sep 2022 07:24:55 +0000 Subject: [PATCH 2/4] Suggest associated method on deref types --- .../rustc_typeck/src/check/method/suggest.rs | 62 ++++++++++++++++++- src/test/ui/suggestions/deref-path-method.rs | 6 ++ .../ui/suggestions/deref-path-method.stderr | 14 +++++ 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/suggestions/deref-path-method.rs create mode 100644 src/test/ui/suggestions/deref-path-method.stderr diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs index e99782fdc652..998405bcbe1c 100644 --- a/compiler/rustc_typeck/src/check/method/suggest.rs +++ b/compiler/rustc_typeck/src/check/method/suggest.rs @@ -16,8 +16,8 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi use rustc_middle::traits::util::supertraits; use rustc_middle::ty::fast_reject::{simplify_type, TreatParams}; use rustc_middle::ty::print::with_crate_prefix; -use rustc_middle::ty::ToPolyTraitRef; use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable}; +use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef}; use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Symbol; use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span}; @@ -30,7 +30,7 @@ use rustc_trait_selection::traits::{ use std::cmp::Ordering; use std::iter; -use super::probe::{Mode, ProbeScope}; +use super::probe::{IsSuggestion, Mode, ProbeScope}; use super::{CandidateSource, MethodError, NoMatchData}; impl<'a, 'tcx> FnCtxt<'a, 'tcx> { @@ -1069,6 +1069,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + self.check_for_deref_method(&mut err, source, rcvr_ty, item_name); + return Some(err); } @@ -1651,6 +1653,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } + fn check_for_deref_method( + &self, + err: &mut Diagnostic, + self_source: SelfSource<'tcx>, + rcvr_ty: Ty<'tcx>, + item_name: Ident, + ) { + let SelfSource::QPath(ty) = self_source else { return; }; + for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) { + if let Ok(pick) = self.probe_for_name( + ty.span, + Mode::Path, + item_name, + IsSuggestion(true), + deref_ty, + ty.hir_id, + ProbeScope::TraitsInScope, + ) { + if deref_ty.is_suggestable(self.tcx, true) + // If this method receives `&self`, then the provided + // argument _should_ coerce, so it's valid to suggest + // just changing the path. + && pick.item.fn_has_self_parameter + && let Some(self_ty) = + self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0) + && self_ty.is_ref() + { + let suggested_path = match deref_ty.kind() { + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Str + | ty::Projection(_) + | ty::Param(_) => format!("{deref_ty}"), + _ => format!("<{deref_ty}>"), + }; + err.span_suggestion_verbose( + ty.span, + format!("the function `{item_name}` is implemented on `{deref_ty}`"), + suggested_path, + Applicability::MaybeIncorrect, + ); + } else { + err.span_note( + ty.span, + format!("the function `{item_name}` is implemented on `{deref_ty}`"), + ); + } + return; + } + } + } + /// Print out the type for use in value namespace. fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String { match ty.kind() { diff --git a/src/test/ui/suggestions/deref-path-method.rs b/src/test/ui/suggestions/deref-path-method.rs new file mode 100644 index 000000000000..0281cdb6b37c --- /dev/null +++ b/src/test/ui/suggestions/deref-path-method.rs @@ -0,0 +1,6 @@ +fn main() { + let vec = Vec::new(); + Vec::contains(&vec, &0); + //~^ ERROR no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope + //~| HELP the function `contains` is implemented on `[_]` +} diff --git a/src/test/ui/suggestions/deref-path-method.stderr b/src/test/ui/suggestions/deref-path-method.stderr new file mode 100644 index 000000000000..1cc37d61151c --- /dev/null +++ b/src/test/ui/suggestions/deref-path-method.stderr @@ -0,0 +1,14 @@ +error[E0599]: no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope + --> $DIR/deref-path-method.rs:3:10 + | +LL | Vec::contains(&vec, &0); + | ^^^^^^^^ function or associated item not found in `Vec<_, _>` + | +help: the function `contains` is implemented on `[_]` + | +LL | <[_]>::contains(&vec, &0); + | ~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. From e9b01c745d52e5bb05ee2e8c184c188b92a349fb Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 3 Sep 2022 08:05:48 +0000 Subject: [PATCH 3/4] Fix global_asm macro pretty printing --- compiler/rustc_ast_pretty/src/pprust/state/item.rs | 2 ++ src/test/ui/asm/unpretty-expanded.rs | 3 +++ src/test/ui/asm/unpretty-expanded.stdout | 9 +++++++++ 3 files changed, 14 insertions(+) create mode 100644 src/test/ui/asm/unpretty-expanded.rs create mode 100644 src/test/ui/asm/unpretty-expanded.stdout diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs index bd87987010e8..54bac29a6cee 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs @@ -218,6 +218,8 @@ impl<'a> State<'a> { ast::ItemKind::GlobalAsm(ref asm) => { self.head(visibility_qualified(&item.vis, "global_asm!")); self.print_inline_asm(asm); + self.word(";"); + self.end(); self.end(); } ast::ItemKind::TyAlias(box ast::TyAlias { diff --git a/src/test/ui/asm/unpretty-expanded.rs b/src/test/ui/asm/unpretty-expanded.rs new file mode 100644 index 000000000000..6128f49b89a3 --- /dev/null +++ b/src/test/ui/asm/unpretty-expanded.rs @@ -0,0 +1,3 @@ +// check-pass +// compile-flags: -Zunpretty=expanded +core::arch::global_asm!("x: .byte 42"); diff --git a/src/test/ui/asm/unpretty-expanded.stdout b/src/test/ui/asm/unpretty-expanded.stdout new file mode 100644 index 000000000000..15b60d1559c6 --- /dev/null +++ b/src/test/ui/asm/unpretty-expanded.stdout @@ -0,0 +1,9 @@ +#![feature(prelude_import)] +#![no_std] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; +// check-pass +// compile-flags: -Zunpretty=expanded +global_asm! ("x: .byte 42"); From cee90dd77361406b94d8e1b8eca6bf657ba88ee5 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 2 Sep 2022 15:44:06 -0700 Subject: [PATCH 4/4] rustdoc: remove `.impl-items { flex-basis }` CSS, not in flex container Added in 34bd2b845b3acd84c5a9bddae3ff8081c19ec5e9 For this to actually do anything, [according to MDN] (and Firefox Dev Tools), it must be a "flex item", which only happens if its a direct child of a node with `display: flex` on it. It seems like it could not have worked at the time when this rule was added, because the only items in `rustdoc.css` with `display: flex` active were: * `#help` This should not contain anything like this. * `.impl-items h4, h4.impl, h3.impl` These are all headers, so they shouldn't contain `.impl-items` either. * `.content .impl-items .method, .content .impl-items > .type, .impl-items > .associatedconstant` Associated constants and methods definitely shouldn't contain a list of impl items, and the `.type` class seems to refer to type aliases, which, when shown inside of an impl, only show a link to the aliased type. [according to MDN]: https://developer.mozilla.org/en-US/docs/Web/CSS/flex-basis Nowadays, `display: flex` is a lot more prolific, but `.impl-items` still seems to only be used in plain block parents: * If it's not a trait impl, then it's nested below a `
` with an id but no class, added in a5216cf67d93de97091b41ecba85de2e08f39863. This will be `display: block`, probably. For example, [vec deref] * Inherent impls also get a `
` tag, for example [vec impl], and they are also wrapped by their own non-flexbox `
` tag. * If it's a tait implementation, then it's also nested below a `
` container, like [deref cstring]. [vec impl]: https://doc.rust-lang.org/1.63.0/std/vec/struct.Vec.html#impl [vec deref]: https://doc.rust-lang.org/1.63.0/std/vec/struct.Vec.html#deref-methods-%5BT%5D [deref cstring]: https://doc.rust-lang.org/1.63.0/std/ops/trait.Deref.html#impl-Deref Also, this would imply that trait items ought to take up as much space as possible, pushing everything else to the edge of the screen. If this is nested directly below the `.rustdoc` container, which has a row basis, that would be bad. --- src/librustdoc/html/static/css/rustdoc.css | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 38b6ebd66d39..fddff771f1cf 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -778,10 +778,6 @@ pre, .rustdoc.source .example-wrap { margin-bottom: .6em; } -.impl-items { - flex-basis: 100%; -} - #main-content > .item-info { margin-top: 0; margin-left: 0;