From 47030d300a7f3fe40fbab3454d298354c863fa10 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 8 Apr 2022 13:39:24 -0700 Subject: [PATCH 1/7] std: `::fmt` name the signal it died from --- .../std/src/sys/unix/process/process_unix.rs | 63 +++++++++++++++++++ .../sys/unix/process/process_unix/tests.rs | 6 +- 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 3d305cd7310fd..188e356a8b4e0 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -695,17 +695,80 @@ impl From for ExitStatus { } } +/// Convert a signal number to a readable, searchable name. +fn signal_string(signal: i32) -> String { + (match signal { + libc::SIGHUP => "SIGHUP", + libc::SIGINT => "SIGINT", + libc::SIGQUIT => "SIGQUIT", + libc::SIGILL => "SIGILL", + libc::SIGTRAP => "SIGTRAP", + libc::SIGABRT => "SIGABRT", + libc::SIGBUS => "SIGBUS", + libc::SIGFPE => "SIGFPE", + libc::SIGKILL => "SIGKILL", + libc::SIGUSR1 => "SIGUSR1", + libc::SIGSEGV => "SIGSEGV", + libc::SIGUSR2 => "SIGUSR2", + libc::SIGPIPE => "SIGPIPE", + libc::SIGALRM => "SIGALRM", + libc::SIGTERM => "SIGTERM", + libc::SIGCHLD => "SIGCHLD", + libc::SIGCONT => "SIGCONT", + libc::SIGSTOP => "SIGSTOP", + libc::SIGTSTP => "SIGTSTP", + libc::SIGTTIN => "SIGTTIN", + libc::SIGTTOU => "SIGTTOU", + libc::SIGURG => "SIGURG", + libc::SIGXCPU => "SIGXCPU", + libc::SIGXFSZ => "SIGXFSZ", + libc::SIGVTALRM => "SIGVTALRM", + libc::SIGPROF => "SIGPROF", + libc::SIGWINCH => "SIGWINCH", + libc::SIGIO => "SIGIO", + libc::SIGSYS => "SIGSYS", + #[cfg(target_os = "linux")] + libc::SIGSTKFLT => "SIGSTKFLT", + #[cfg(target_os = "linux")] + libc::SIGPWR => "SIGPWR", + #[cfg(any( + target_os = "macos", + target_os = "ios", + target_os = "tvos", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", + target_os = "dragonfly" + ))] + libc::SIGEMT => "SIGEMT", + #[cfg(any( + target_os = "macos", + target_os = "ios", + target_os = "tvos", + target_os = "freebsd", + target_os = "netbsd", + target_os = "openbsd", + target_os = "dragonfly" + ))] + libc::SIGINFO => "SIGINFO", + _ => return format!("{signal}"), + }) + .to_string() +} + impl fmt::Display for ExitStatus { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { if let Some(code) = self.code() { write!(f, "exit status: {code}") } else if let Some(signal) = self.signal() { + let signal = signal_string(signal); if self.core_dumped() { write!(f, "signal: {signal} (core dumped)") } else { write!(f, "signal: {signal}") } } else if let Some(signal) = self.stopped_signal() { + let signal = signal_string(signal); write!(f, "stopped (not terminated) by signal: {signal}") } else if self.continued() { write!(f, "continued (WIFCONTINUED)") diff --git a/library/std/src/sys/unix/process/process_unix/tests.rs b/library/std/src/sys/unix/process/process_unix/tests.rs index 560c62155d931..8d4f6b5179e9e 100644 --- a/library/std/src/sys/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/unix/process/process_unix/tests.rs @@ -14,8 +14,8 @@ fn exitstatus_display_tests() { let t = |v, s| assert_eq!(s, format!("{}", ::from_raw(v))); - t(0x0000f, "signal: 15"); - t(0x0008b, "signal: 11 (core dumped)"); + t(0x0000f, "signal: SIGTERM"); + t(0x0008b, "signal: SIGSEGV (core dumped)"); t(0x00000, "exit status: 0"); t(0x0ff00, "exit status: 255"); @@ -24,7 +24,7 @@ fn exitstatus_display_tests() { // The purpose of this test is to test our string formatting, not our understanding of the wait // status magic numbers. So restrict these to Linux. if cfg!(target_os = "linux") { - t(0x0137f, "stopped (not terminated) by signal: 19"); + t(0x0137f, "stopped (not terminated) by signal: SIGSTOP"); t(0x0ffff, "continued (WIFCONTINUED)"); } From 267a6c815663582e651b32dcd33c07da05cd3371 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 1 Jun 2022 11:20:11 -0700 Subject: [PATCH 2/7] std: show signal number along with name --- .../std/src/sys/unix/process/process_unix.rs | 90 ++++++++++--------- .../sys/unix/process/process_unix/tests.rs | 6 +- 2 files changed, 50 insertions(+), 46 deletions(-) diff --git a/library/std/src/sys/unix/process/process_unix.rs b/library/std/src/sys/unix/process/process_unix.rs index 188e356a8b4e0..31f1ea76701e3 100644 --- a/library/std/src/sys/unix/process/process_unix.rs +++ b/library/std/src/sys/unix/process/process_unix.rs @@ -696,41 +696,46 @@ impl From for ExitStatus { } /// Convert a signal number to a readable, searchable name. -fn signal_string(signal: i32) -> String { - (match signal { - libc::SIGHUP => "SIGHUP", - libc::SIGINT => "SIGINT", - libc::SIGQUIT => "SIGQUIT", - libc::SIGILL => "SIGILL", - libc::SIGTRAP => "SIGTRAP", - libc::SIGABRT => "SIGABRT", - libc::SIGBUS => "SIGBUS", - libc::SIGFPE => "SIGFPE", - libc::SIGKILL => "SIGKILL", - libc::SIGUSR1 => "SIGUSR1", - libc::SIGSEGV => "SIGSEGV", - libc::SIGUSR2 => "SIGUSR2", - libc::SIGPIPE => "SIGPIPE", - libc::SIGALRM => "SIGALRM", - libc::SIGTERM => "SIGTERM", - libc::SIGCHLD => "SIGCHLD", - libc::SIGCONT => "SIGCONT", - libc::SIGSTOP => "SIGSTOP", - libc::SIGTSTP => "SIGTSTP", - libc::SIGTTIN => "SIGTTIN", - libc::SIGTTOU => "SIGTTOU", - libc::SIGURG => "SIGURG", - libc::SIGXCPU => "SIGXCPU", - libc::SIGXFSZ => "SIGXFSZ", - libc::SIGVTALRM => "SIGVTALRM", - libc::SIGPROF => "SIGPROF", - libc::SIGWINCH => "SIGWINCH", - libc::SIGIO => "SIGIO", - libc::SIGSYS => "SIGSYS", +/// +/// This string should be displayed right after the signal number. +/// If a signal is unrecognized, it returns the empty string, so that +/// you just get the number like "0". If it is recognized, you'll get +/// something like "9 (SIGKILL)". +fn signal_string(signal: i32) -> &'static str { + match signal { + libc::SIGHUP => " (SIGHUP)", + libc::SIGINT => " (SIGINT)", + libc::SIGQUIT => " (SIGQUIT)", + libc::SIGILL => " (SIGILL)", + libc::SIGTRAP => " (SIGTRAP)", + libc::SIGABRT => " (SIGABRT)", + libc::SIGBUS => " (SIGBUS)", + libc::SIGFPE => " (SIGFPE)", + libc::SIGKILL => " (SIGKILL)", + libc::SIGUSR1 => " (SIGUSR1)", + libc::SIGSEGV => " (SIGSEGV)", + libc::SIGUSR2 => " (SIGUSR2)", + libc::SIGPIPE => " (SIGPIPE)", + libc::SIGALRM => " (SIGALRM)", + libc::SIGTERM => " (SIGTERM)", + libc::SIGCHLD => " (SIGCHLD)", + libc::SIGCONT => " (SIGCONT)", + libc::SIGSTOP => " (SIGSTOP)", + libc::SIGTSTP => " (SIGTSTP)", + libc::SIGTTIN => " (SIGTTIN)", + libc::SIGTTOU => " (SIGTTOU)", + libc::SIGURG => " (SIGURG)", + libc::SIGXCPU => " (SIGXCPU)", + libc::SIGXFSZ => " (SIGXFSZ)", + libc::SIGVTALRM => " (SIGVTALRM)", + libc::SIGPROF => " (SIGPROF)", + libc::SIGWINCH => " (SIGWINCH)", + libc::SIGIO => " (SIGIO)", + libc::SIGSYS => " (SIGSYS)", #[cfg(target_os = "linux")] - libc::SIGSTKFLT => "SIGSTKFLT", + libc::SIGSTKFLT => " (SIGSTKFLT)", #[cfg(target_os = "linux")] - libc::SIGPWR => "SIGPWR", + libc::SIGPWR => " (SIGPWR)", #[cfg(any( target_os = "macos", target_os = "ios", @@ -740,7 +745,7 @@ fn signal_string(signal: i32) -> String { target_os = "openbsd", target_os = "dragonfly" ))] - libc::SIGEMT => "SIGEMT", + libc::SIGEMT => " (SIGEMT)", #[cfg(any( target_os = "macos", target_os = "ios", @@ -750,10 +755,9 @@ fn signal_string(signal: i32) -> String { target_os = "openbsd", target_os = "dragonfly" ))] - libc::SIGINFO => "SIGINFO", - _ => return format!("{signal}"), - }) - .to_string() + libc::SIGINFO => " (SIGINFO)", + _ => "", + } } impl fmt::Display for ExitStatus { @@ -761,15 +765,15 @@ impl fmt::Display for ExitStatus { if let Some(code) = self.code() { write!(f, "exit status: {code}") } else if let Some(signal) = self.signal() { - let signal = signal_string(signal); + let signal_string = signal_string(signal); if self.core_dumped() { - write!(f, "signal: {signal} (core dumped)") + write!(f, "signal: {signal}{signal_string} (core dumped)") } else { - write!(f, "signal: {signal}") + write!(f, "signal: {signal}{signal_string}") } } else if let Some(signal) = self.stopped_signal() { - let signal = signal_string(signal); - write!(f, "stopped (not terminated) by signal: {signal}") + let signal_string = signal_string(signal); + write!(f, "stopped (not terminated) by signal: {signal}{signal_string}") } else if self.continued() { write!(f, "continued (WIFCONTINUED)") } else { diff --git a/library/std/src/sys/unix/process/process_unix/tests.rs b/library/std/src/sys/unix/process/process_unix/tests.rs index 8d4f6b5179e9e..e0e2d478fad73 100644 --- a/library/std/src/sys/unix/process/process_unix/tests.rs +++ b/library/std/src/sys/unix/process/process_unix/tests.rs @@ -14,8 +14,8 @@ fn exitstatus_display_tests() { let t = |v, s| assert_eq!(s, format!("{}", ::from_raw(v))); - t(0x0000f, "signal: SIGTERM"); - t(0x0008b, "signal: SIGSEGV (core dumped)"); + t(0x0000f, "signal: 15 (SIGTERM)"); + t(0x0008b, "signal: 11 (SIGSEGV) (core dumped)"); t(0x00000, "exit status: 0"); t(0x0ff00, "exit status: 255"); @@ -24,7 +24,7 @@ fn exitstatus_display_tests() { // The purpose of this test is to test our string formatting, not our understanding of the wait // status magic numbers. So restrict these to Linux. if cfg!(target_os = "linux") { - t(0x0137f, "stopped (not terminated) by signal: SIGSTOP"); + t(0x0137f, "stopped (not terminated) by signal: 19 (SIGSTOP)"); t(0x0ffff, "continued (WIFCONTINUED)"); } From 79c3011d9d1b5f4d1ebd1243d10f4f4a4296a2ee Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 1 Jun 2022 20:36:20 +0200 Subject: [PATCH 3/7] update explicit impls error msg --- compiler/rustc_typeck/src/coherence/mod.rs | 6 +++--- src/test/ui/coherence/coherence-impls-sized.stderr | 12 ++++++------ .../forbidden-discriminant-kind-impl.stderr | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_typeck/src/coherence/mod.rs b/compiler/rustc_typeck/src/coherence/mod.rs index 3f1b4828d1af3..3903448a00731 100644 --- a/compiler/rustc_typeck/src/coherence/mod.rs +++ b/compiler/rustc_typeck/src/coherence/mod.rs @@ -57,7 +57,7 @@ fn enforce_trait_manually_implementable( E0322, "explicit impls for the `Pointee` trait are not permitted" ) - .span_label(span, "impl of 'Pointee' not allowed") + .span_label(span, "impl of `Pointee` not allowed") .emit(); return; } @@ -70,7 +70,7 @@ fn enforce_trait_manually_implementable( E0322, "explicit impls for the `DiscriminantKind` trait are not permitted" ) - .span_label(span, "impl of 'DiscriminantKind' not allowed") + .span_label(span, "impl of `DiscriminantKind` not allowed") .emit(); return; } @@ -83,7 +83,7 @@ fn enforce_trait_manually_implementable( E0322, "explicit impls for the `Sized` trait are not permitted" ) - .span_label(span, "impl of 'Sized' not allowed") + .span_label(span, "impl of `Sized` not allowed") .emit(); return; } diff --git a/src/test/ui/coherence/coherence-impls-sized.stderr b/src/test/ui/coherence/coherence-impls-sized.stderr index 9cf5ed38c9c6b..e1e4acd4cd82d 100644 --- a/src/test/ui/coherence/coherence-impls-sized.stderr +++ b/src/test/ui/coherence/coherence-impls-sized.stderr @@ -35,37 +35,37 @@ error[E0322]: explicit impls for the `Sized` trait are not permitted --> $DIR/coherence-impls-sized.rs:14:1 | LL | impl Sized for TestE {} - | ^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed + | ^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed error[E0322]: explicit impls for the `Sized` trait are not permitted --> $DIR/coherence-impls-sized.rs:17:1 | LL | impl Sized for MyType {} - | ^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed + | ^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed error[E0322]: explicit impls for the `Sized` trait are not permitted --> $DIR/coherence-impls-sized.rs:20:1 | LL | impl Sized for (MyType, MyType) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed error[E0322]: explicit impls for the `Sized` trait are not permitted --> $DIR/coherence-impls-sized.rs:24:1 | LL | impl Sized for &'static NotSync {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed error[E0322]: explicit impls for the `Sized` trait are not permitted --> $DIR/coherence-impls-sized.rs:27:1 | LL | impl Sized for [MyType] {} - | ^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed + | ^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed error[E0322]: explicit impls for the `Sized` trait are not permitted --> $DIR/coherence-impls-sized.rs:31:1 | LL | impl Sized for &'static [NotSync] {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'Sized' not allowed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Sized` not allowed error: aborting due to 9 previous errors diff --git a/src/test/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr b/src/test/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr index 54360c4f47b3e..38cfd13b9b88e 100644 --- a/src/test/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr +++ b/src/test/ui/enum-discriminant/forbidden-discriminant-kind-impl.stderr @@ -2,7 +2,7 @@ error[E0322]: explicit impls for the `DiscriminantKind` trait are not permitted --> $DIR/forbidden-discriminant-kind-impl.rs:9:1 | LL | impl DiscriminantKind for NewType { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of 'DiscriminantKind' not allowed + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `DiscriminantKind` not allowed error: aborting due to previous error From d7645f4245518b9d1e216c461f232caea1dcd3f7 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 2 Jun 2022 11:13:31 +0200 Subject: [PATCH 4/7] don't use a `span_note` for ignored impls --- compiler/rustc_passes/src/dead.rs | 6 +----- .../ui/derive-uninhabited-enum-38885.stderr | 7 +------ .../ui/derives/clone-debug-dead-code.stderr | 21 +++---------------- .../ui/lint/dead-code/unused-variant.stderr | 7 +------ 4 files changed, 6 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index e78d9a5998284..519fb7ea2640a 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -722,11 +722,7 @@ impl<'tcx> DeadVisitor<'tcx> { traits_str, is_are ); - let multispan = ign_traits - .iter() - .map(|(_, impl_id)| self.tcx.def_span(*impl_id)) - .collect::>(); - err.span_note(multispan, &msg); + err.note(&msg); } err.emit(); }); diff --git a/src/test/ui/derive-uninhabited-enum-38885.stderr b/src/test/ui/derive-uninhabited-enum-38885.stderr index 2a44e56a3302c..58aaf978dc7d6 100644 --- a/src/test/ui/derive-uninhabited-enum-38885.stderr +++ b/src/test/ui/derive-uninhabited-enum-38885.stderr @@ -5,12 +5,7 @@ LL | Void(Void), | ^^^^^^^^^^ | = note: `-W dead-code` implied by `-W unused` -note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis - --> $DIR/derive-uninhabited-enum-38885.rs:10:10 - | -LL | #[derive(Debug)] - | ^^^^^ - = note: this warning originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `Foo` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis warning: 1 warning emitted diff --git a/src/test/ui/derives/clone-debug-dead-code.stderr b/src/test/ui/derives/clone-debug-dead-code.stderr index 67bb574315a72..031b8ce713eb4 100644 --- a/src/test/ui/derives/clone-debug-dead-code.stderr +++ b/src/test/ui/derives/clone-debug-dead-code.stderr @@ -16,12 +16,7 @@ error: field is never read: `f` LL | struct B { f: () } | ^^^^^ | -note: `B` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis - --> $DIR/clone-debug-dead-code.rs:9:10 - | -LL | #[derive(Clone)] - | ^^^^^ - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `B` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis error: field is never read: `f` --> $DIR/clone-debug-dead-code.rs:14:12 @@ -29,12 +24,7 @@ error: field is never read: `f` LL | struct C { f: () } | ^^^^^ | -note: `C` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis - --> $DIR/clone-debug-dead-code.rs:13:10 - | -LL | #[derive(Debug)] - | ^^^^^ - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `C` has a derived impl for the trait `Debug`, but this is intentionally ignored during dead code analysis error: field is never read: `f` --> $DIR/clone-debug-dead-code.rs:18:12 @@ -42,12 +32,7 @@ error: field is never read: `f` LL | struct D { f: () } | ^^^^^ | -note: `D` has derived impls for the traits `Clone` and `Debug`, but these are intentionally ignored during dead code analysis - --> $DIR/clone-debug-dead-code.rs:17:10 - | -LL | #[derive(Debug,Clone)] - | ^^^^^ ^^^^^ - = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `D` has derived impls for the traits `Clone` and `Debug`, but these are intentionally ignored during dead code analysis error: field is never read: `f` --> $DIR/clone-debug-dead-code.rs:21:12 diff --git a/src/test/ui/lint/dead-code/unused-variant.stderr b/src/test/ui/lint/dead-code/unused-variant.stderr index 3b5683a7748fa..57f8ca74f83dd 100644 --- a/src/test/ui/lint/dead-code/unused-variant.stderr +++ b/src/test/ui/lint/dead-code/unused-variant.stderr @@ -9,12 +9,7 @@ note: the lint level is defined here | LL | #![deny(dead_code)] | ^^^^^^^^^ -note: `Enum` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis - --> $DIR/unused-variant.rs:3:10 - | -LL | #[derive(Clone)] - | ^^^^^ - = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info) + = note: `Enum` has a derived impl for the trait `Clone`, but this is intentionally ignored during dead code analysis error: aborting due to previous error From 28988902a2d1410ff2f8f13bb146420a128c5754 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda <41065217+TaKO8Ki@users.noreply.github.com> Date: Thu, 2 Jun 2022 20:50:01 +0900 Subject: [PATCH 5/7] fix wrong suggestion for adding where clauses --- .../src/traits/error_reporting/suggestions.rs | 18 ++++++++++++++++-- src/test/ui/traits/issue-97576.rs | 13 +++++++++++++ src/test/ui/traits/issue-97576.stderr | 11 +++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/traits/issue-97576.rs create mode 100644 src/test/ui/traits/issue-97576.stderr diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index a51e6e58f67a9..d0f20022bfbad 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -21,7 +21,9 @@ use rustc_hir::lang_items::LangItem; use rustc_hir::{AsyncGeneratorKind, GeneratorKind, Node}; use rustc_middle::hir::map; use rustc_middle::ty::{ - self, suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree, + self, + subst::{GenericArgKind, SubstsRef}, + suggest_arbitrary_trait_bound, suggest_constraining_type_param, AdtKind, DefIdTree, GeneratorDiagnosticData, GeneratorInteriorTypeCause, Infer, InferTy, ToPredicate, Ty, TyCtxt, TypeFoldable, }; @@ -458,6 +460,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { _ => (false, None), }; + let generic_args_have_impl_trait = |args: SubstsRef<'tcx>| -> bool { + args.iter().any(|arg| match arg.unpack() { + GenericArgKind::Type(ty) => match ty.kind() { + ty::Param(param) => param.name.as_str().starts_with("impl"), + _ => false, + }, + _ => false, + }) + }; + // FIXME: Add check for trait bound that is already present, particularly `?Sized` so we // don't suggest `T: Sized + ?Sized`. let mut hir_id = body_id; @@ -588,7 +600,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { | hir::ItemKind::TraitAlias(generics, _) | hir::ItemKind::OpaqueTy(hir::OpaqueTy { generics, .. }), .. - }) if !param_ty => { + }) if !param_ty + && !generic_args_have_impl_trait(trait_pred.skip_binder().trait_ref.substs) => + { // Missing generic type parameter bound. let param_name = self_ty.to_string(); let constraint = trait_pred.print_modifiers_and_trait_path().to_string(); diff --git a/src/test/ui/traits/issue-97576.rs b/src/test/ui/traits/issue-97576.rs new file mode 100644 index 0000000000000..fdc85e9fa8956 --- /dev/null +++ b/src/test/ui/traits/issue-97576.rs @@ -0,0 +1,13 @@ +struct Foo { + bar: String, +} + +impl Foo { + pub fn new(bar: impl ToString) -> Self { + Self { + bar: bar.into(), //~ ERROR the trait bound `String: From` is not satisfied + } + } +} + +fn main() {} diff --git a/src/test/ui/traits/issue-97576.stderr b/src/test/ui/traits/issue-97576.stderr new file mode 100644 index 0000000000000..bdee073d6e39a --- /dev/null +++ b/src/test/ui/traits/issue-97576.stderr @@ -0,0 +1,11 @@ +error[E0277]: the trait bound `String: From` is not satisfied + --> $DIR/issue-97576.rs:8:22 + | +LL | bar: bar.into(), + | ^^^^ the trait `From` is not implemented for `String` + | + = note: required because of the requirements on the impl of `Into` for `impl ToString` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. From 6e2ac5df311412a2bae415c3dbef3187e67c2c58 Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Thu, 2 Jun 2022 12:36:11 +0200 Subject: [PATCH 6/7] Improve documentation for constructors of pinned `Box`es --- library/alloc/src/boxed.rs | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index e2c692b5299f4..7e548d639fd67 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -266,8 +266,13 @@ impl Box { Self::new_zeroed_in(Global) } - /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// Constructs a new `Pin>`. If `T` does not implement [`Unpin`], then /// `x` will be pinned in memory and unable to be moved. + /// + /// Constructing and pinning of the `Box` can also be done in two steps: `Box::pin(x)` + /// does the same as [Box::into_pin]\([Box::new]\(x)). Consider using + /// [`into_pin`](Box::into_pin) if you already have a `Box`, or if you want to + /// construct a (pinned) `Box` in a different way than with [`Box::new`]. #[cfg(not(no_global_oom_handling))] #[stable(feature = "pin", since = "1.33.0")] #[must_use] @@ -553,8 +558,13 @@ impl Box { unsafe { Ok(Box::from_raw_in(ptr.as_ptr(), alloc)) } } - /// Constructs a new `Pin>`. If `T` does not implement `Unpin`, then + /// Constructs a new `Pin>`. If `T` does not implement [`Unpin`], then /// `x` will be pinned in memory and unable to be moved. + /// + /// Constructing and pinning of the `Box` can also be done in two steps: `Box::pin_in(x, alloc)` + /// does the same as [Box::into_pin]\([Box::new_in]\(x, alloc)). Consider using + /// [`into_pin`](Box::into_pin) if you already have a `Box`, or if you want to + /// construct a (pinned) `Box` in a different way than with [`Box::new_in`]. #[cfg(not(no_global_oom_handling))] #[unstable(feature = "allocator_api", issue = "32838")] #[rustc_const_unstable(feature = "const_box", issue = "92521")] @@ -1170,12 +1180,18 @@ impl Box { unsafe { &mut *mem::ManuallyDrop::new(b).0.as_ptr() } } - /// Converts a `Box` into a `Pin>` + /// Converts a `Box` into a `Pin>`. If `T` does not implement [`Unpin`], then + /// `*boxed` will be pinned in memory and unable to be moved. /// /// This conversion does not allocate on the heap and happens in place. /// /// This is also available via [`From`]. /// + /// Constructing and pinning a `Box` with Box::into_pin([Box::new]\(x)) + /// can also be written more concisely using [Box::pin]\(x). + /// This `into_pin` method is useful if you already have a `Box`, or you are + /// constructing a (pinned) `Box` in a different way than with [`Box::new`]. + /// /// # Notes /// /// It's not recommended that crates add an impl like `From> for Pin`, @@ -1437,9 +1453,17 @@ impl const From> for Pin> where A: 'static, { - /// Converts a `Box` into a `Pin>` + /// Converts a `Box` into a `Pin>`. If `T` does not implement [`Unpin`], then + /// `*boxed` will be pinned in memory and unable to be moved. /// /// This conversion does not allocate on the heap and happens in place. + /// + /// This is also available via [`Box::into_pin`]. + /// + /// Constructing and pinning a `Box` with >>::from([Box::new]\(x)) + /// can also be written more concisely using [Box::pin]\(x). + /// This `From` implementation is useful if you already have a `Box`, or you are + /// constructing a (pinned) `Box` in a different way than with [`Box::new`]. fn from(boxed: Box) -> Self { Box::into_pin(boxed) } From 9292c907fa7c196f03d8f80130c14dade5c486e1 Mon Sep 17 00:00:00 2001 From: "onlinesoftwaredevok@protonmail.com" Date: Thu, 2 Jun 2022 11:50:36 -0300 Subject: [PATCH 7/7] rustdoc: Add more test coverage --- src/test/rustdoc/nested-modules.rs | 42 ++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/test/rustdoc/nested-modules.rs diff --git a/src/test/rustdoc/nested-modules.rs b/src/test/rustdoc/nested-modules.rs new file mode 100644 index 0000000000000..1596f46740e8f --- /dev/null +++ b/src/test/rustdoc/nested-modules.rs @@ -0,0 +1,42 @@ +#![crate_name = "aCrate"] + +mod a_module { + pub fn private_function() {} + + pub use a_module::private_function as other_private_function; + + pub mod a_nested_module { + // @has aCrate/a_nested_module/index.html '//a[@href="fn.a_nested_public_function.html"]' 'a_nested_public_function' + // @has aCrate/a_nested_module/fn.a_nested_public_function.html 'pub fn a_nested_public_function()' + pub fn a_nested_public_function() {} + + // @has aCrate/a_nested_module/index.html '//a[@href="fn.another_nested_public_function.html"]' 'another_nested_public_function' + // @has aCrate/a_nested_module/fn.another_nested_public_function.html 'pub fn another_nested_public_function()' + pub use a_nested_module::a_nested_public_function as another_nested_public_function; + } + + // @!has aCrate/a_nested_module/index.html 'yet_another_nested_public_function' + pub use a_nested_module::a_nested_public_function as yet_another_nested_public_function; + + // @!has aCrate/a_nested_module/index.html 'one_last_nested_public_function' + pub use a_nested_module::another_nested_public_function as one_last_nested_public_function; +} + +// @!has aCrate/index.html 'a_module' +// @has aCrate/index.html '//a[@href="a_nested_module/index.html"]' 'a_nested_module' +pub use a_module::a_nested_module; + +// @has aCrate/index.html '//a[@href="fn.a_nested_public_function.html"]' 'a_nested_public_function' +// @has aCrate/index.html '//a[@href="fn.another_nested_public_function.html"]' 'another_nested_public_function' +// @has aCrate/index.html '//a[@href="fn.yet_another_nested_public_function.html"]' 'yet_another_nested_public_function' +// @has aCrate/index.html '//a[@href="fn.one_last_nested_public_function.html"]' 'one_last_nested_public_function' +pub use a_module::{ + a_nested_module::{a_nested_public_function, another_nested_public_function}, + one_last_nested_public_function, yet_another_nested_public_function, +}; + +// @has aCrate/index.html '//a[@href="fn.private_function.html"]' 'private_function' +// @!has aCrate/fn.private_function.html 'a_module' +// @has aCrate/index.html '//a[@href="fn.other_private_function.html"]' 'other_private_function' +// @!has aCrate/fn.other_private_function.html 'a_module' +pub use a_module::{other_private_function, private_function};