From ea9a253ff1e0a24e6439c122960f9a17a6e8d58d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 24 Jan 2025 04:06:47 +0000 Subject: [PATCH 01/10] Properly report error when object type param default references self --- .../src/error_codes/E0393.md | 12 +++++------ compiler/rustc_hir_analysis/messages.ftl | 8 +++++++- .../src/hir_ty_lowering/dyn_compatibility.rs | 8 +------- .../default-param-self-projection.rs | 17 ++++++++++++++++ .../default-param-self-projection.stderr | 18 +++++++++++++++++ tests/ui/error-codes/E0393.stderr | 2 +- tests/ui/issues/issue-22370.stderr | 2 +- ...onicalize-fresh-infer-vars-issue-103626.rs | 1 + ...alize-fresh-infer-vars-issue-103626.stderr | 20 +++++++++++++++++-- .../unspecified-self-in-trait-ref.stderr | 2 +- ...parameter-defaults-referencing-Self.stderr | 2 +- 11 files changed, 71 insertions(+), 21 deletions(-) create mode 100644 tests/ui/dyn-compatibility/default-param-self-projection.rs create mode 100644 tests/ui/dyn-compatibility/default-param-self-projection.stderr diff --git a/compiler/rustc_error_codes/src/error_codes/E0393.md b/compiler/rustc_error_codes/src/error_codes/E0393.md index 50225b25163fe..c72608159051e 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0393.md +++ b/compiler/rustc_error_codes/src/error_codes/E0393.md @@ -3,12 +3,10 @@ A type parameter which references `Self` in its default value was not specified. Erroneous code example: ```compile_fail,E0393 -trait A {} +trait A {} -fn together_we_will_rule_the_galaxy(son: &A) {} -// error: the type parameter `T` must be explicitly specified in an -// object type because its default value `Self` references the -// type `Self` +fn together_we_will_rule_the_galaxy(son: &dyn A) {} +// error: the type parameter `T` must be explicitly specified ``` A trait object is defined over a single, fully-defined trait. With a regular @@ -23,7 +21,7 @@ disallowed. Making the trait concrete by explicitly specifying the value of the defaulted parameter will fix this issue. Fixed example: ``` -trait A {} +trait A {} -fn together_we_will_rule_the_galaxy(son: &A) {} // Ok! +fn together_we_will_rule_the_galaxy(son: &dyn A) {} // Ok! ``` diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl index 512d379687bcf..be4004f5904cc 100644 --- a/compiler/rustc_hir_analysis/messages.ftl +++ b/compiler/rustc_hir_analysis/messages.ftl @@ -353,7 +353,13 @@ hir_analysis_missing_type_params = [one] reference *[other] references } to {$parameters} - .note = because of the default `Self` reference, type parameters must be specified on object types + .note = because the parameter {$parameterCount -> + [one] default references + *[other] defaults reference + } `Self`, the {$parameterCount -> + [one] parameter + *[other] parameters + } must be specified on the object type hir_analysis_multiple_relaxed_default_bounds = type parameter has more than one relaxed default bound, only one is supported diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs index 72ad190df7ee1..e59ff02642cf1 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_compatibility.rs @@ -237,16 +237,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Skip `Self` .skip(1) .map(|(index, arg)| { - if arg == dummy_self.into() { + if arg.walk().any(|arg| arg == dummy_self.into()) { let param = &generics.own_params[index]; missing_type_params.push(param.name); Ty::new_misc_error(tcx).into() - } else if arg.walk().any(|arg| arg == dummy_self.into()) { - let guar = self.dcx().span_delayed_bug( - span, - "trait object trait bounds reference `Self`", - ); - replace_dummy_self_with_error(tcx, arg, guar) } else { arg } diff --git a/tests/ui/dyn-compatibility/default-param-self-projection.rs b/tests/ui/dyn-compatibility/default-param-self-projection.rs new file mode 100644 index 0000000000000..a440cd735daba --- /dev/null +++ b/tests/ui/dyn-compatibility/default-param-self-projection.rs @@ -0,0 +1,17 @@ +trait A::E> {} + +trait D { + type E; +} + +impl A<()> for () {} +impl D for () { + type E = (); +} + +fn f() { + let B: &dyn A = &(); + //~^ ERROR the type parameter `C` must be explicitly specified +} + +fn main() {} diff --git a/tests/ui/dyn-compatibility/default-param-self-projection.stderr b/tests/ui/dyn-compatibility/default-param-self-projection.stderr new file mode 100644 index 0000000000000..ea252a99b0480 --- /dev/null +++ b/tests/ui/dyn-compatibility/default-param-self-projection.stderr @@ -0,0 +1,18 @@ +error[E0393]: the type parameter `C` must be explicitly specified + --> $DIR/default-param-self-projection.rs:13:17 + | +LL | trait A::E> {} + | --------------------------- type parameter `C` must be specified for this +... +LL | let B: &dyn A = &(); + | ^ + | + = note: because the parameter default references `Self`, the parameter must be specified on the object type +help: set the type parameter to the desired type + | +LL | let B: &dyn A = &(); + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0393`. diff --git a/tests/ui/error-codes/E0393.stderr b/tests/ui/error-codes/E0393.stderr index 489398b7be59e..4847aa2508dad 100644 --- a/tests/ui/error-codes/E0393.stderr +++ b/tests/ui/error-codes/E0393.stderr @@ -7,7 +7,7 @@ LL | LL | fn together_we_will_rule_the_galaxy(son: &dyn A) {} | ^ | - = note: because of the default `Self` reference, type parameters must be specified on object types + = note: because the parameter default references `Self`, the parameter must be specified on the object type help: set the type parameter to the desired type | LL | fn together_we_will_rule_the_galaxy(son: &dyn A) {} diff --git a/tests/ui/issues/issue-22370.stderr b/tests/ui/issues/issue-22370.stderr index 3dc060963f920..b02d867eb7dd9 100644 --- a/tests/ui/issues/issue-22370.stderr +++ b/tests/ui/issues/issue-22370.stderr @@ -7,7 +7,7 @@ LL | LL | fn f(a: &dyn A) {} | ^ | - = note: because of the default `Self` reference, type parameters must be specified on object types + = note: because the parameter default references `Self`, the parameter must be specified on the object type help: set the type parameter to the desired type | LL | fn f(a: &dyn A) {} diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs index 6dcfc754448b6..6fcd67b4950f7 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.rs @@ -10,6 +10,7 @@ fn w<'a, T: 'a, F: Fn(&'a T)>() { let b: &dyn FromResidual = &(); //~^ ERROR: the trait `FromResidual` is not dyn compatible //~| ERROR: the trait `FromResidual` is not dyn compatible + //~| ERROR the type parameter `R` must be explicitly specified } fn main() {} diff --git a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr index 7040c067f5c20..ae3762704c6ac 100644 --- a/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr +++ b/tests/ui/traits/object/canonicalize-fresh-infer-vars-issue-103626.stderr @@ -1,3 +1,18 @@ +error[E0393]: the type parameter `R` must be explicitly specified + --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:17 + | +LL | trait FromResidual::Residual> { + | ----------------------------------------------- type parameter `R` must be specified for this +... +LL | let b: &dyn FromResidual = &(); + | ^^^^^^^^^^^^ + | + = note: because the parameter default references `Self`, the parameter must be specified on the object type +help: set the type parameter to the desired type + | +LL | let b: &dyn FromResidual = &(); + | +++ + error[E0038]: the trait `FromResidual` is not dyn compatible --> $DIR/canonicalize-fresh-infer-vars-issue-103626.rs:10:32 | @@ -45,6 +60,7 @@ help: alternatively, consider constraining `from_residual` so it does not apply LL | fn from_residual(residual: R) -> Self where Self: Sized; | +++++++++++++++++ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0038`. +Some errors have detailed explanations: E0038, E0393. +For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/unspecified-self-in-trait-ref.stderr b/tests/ui/traits/unspecified-self-in-trait-ref.stderr index 22dceadc10de9..6f5ae786de6bc 100644 --- a/tests/ui/traits/unspecified-self-in-trait-ref.stderr +++ b/tests/ui/traits/unspecified-self-in-trait-ref.stderr @@ -97,7 +97,7 @@ LL | pub trait Bar { LL | let e = Bar::::lol(); | ^^^^^^^^^^^^ missing reference to `A` | - = note: because of the default `Self` reference, type parameters must be specified on object types + = note: because the parameter default references `Self`, the parameter must be specified on the object type error: aborting due to 5 previous errors; 5 warnings emitted diff --git a/tests/ui/type/type-parameter-defaults-referencing-Self.stderr b/tests/ui/type/type-parameter-defaults-referencing-Self.stderr index c81405f03f8fa..23f10c9262c7b 100644 --- a/tests/ui/type/type-parameter-defaults-referencing-Self.stderr +++ b/tests/ui/type/type-parameter-defaults-referencing-Self.stderr @@ -7,7 +7,7 @@ LL | trait Foo { LL | fn foo(x: &dyn Foo) { } | ^^^ | - = note: because of the default `Self` reference, type parameters must be specified on object types + = note: because the parameter default references `Self`, the parameter must be specified on the object type help: set the type parameter to the desired type | LL | fn foo(x: &dyn Foo) { } From c9ae0bbffb86d45e313bfe9515af513ce6ab49c9 Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Fri, 24 Jan 2025 01:41:00 -0500 Subject: [PATCH 02/10] Fix `FormattingOptions` instantiation with `Default` The `fill` value by default should be set to `' '` (space), but the current implementation uses `#[derive(Default)]` which sets it to `\0` --- library/core/src/fmt/mod.rs | 11 ++++++++++- library/core/tests/fmt/mod.rs | 6 ++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index a033b8bd30514..a1bf3a4d7a706 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -288,7 +288,7 @@ pub enum DebugAsHex { /// /// `FormattingOptions` is a [`Formatter`] without an attached [`Write`] trait. /// It is mainly used to construct `Formatter` instances. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[unstable(feature = "formatting_options", issue = "118117")] pub struct FormattingOptions { flags: u32, @@ -508,6 +508,15 @@ impl FormattingOptions { } } +#[unstable(feature = "formatting_options", issue = "118117")] +impl Default for FormattingOptions { + /// Same as [`FormattingOptions::new()`]. + fn default() -> Self { + // The `#[derive(Default)]` implementation would set `fill` to `\0` instead of space. + Self::new() + } +} + /// Configuration for formatting. /// /// A `Formatter` represents various options related to formatting. Users do not diff --git a/library/core/tests/fmt/mod.rs b/library/core/tests/fmt/mod.rs index 2c93a9bc80db9..025c69c4f6236 100644 --- a/library/core/tests/fmt/mod.rs +++ b/library/core/tests/fmt/mod.rs @@ -51,6 +51,12 @@ fn test_maybe_uninit_short() { assert_eq!(format!("{x:?}"), "MaybeUninit"); } +#[test] +fn formatting_options_ctor() { + use core::fmt::FormattingOptions; + assert_eq!(FormattingOptions::new(), FormattingOptions::default()); +} + #[test] fn formatting_options_flags() { use core::fmt::*; From 8175bf3ed3b4c5f8d4f59f8c83fdd284a24e4dac Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 24 Jan 2025 21:34:15 +1100 Subject: [PATCH 03/10] Rename test to `unresolvable-upvar-issue-87987.rs` This also suppresses an irrelevant warning, to avoid having to re-bless the output snapshot. --- src/tools/tidy/src/issues.txt | 1 - .../2229_closure_analysis/issue-87987.stderr | 14 -------------- ...-87987.rs => unresolvable-upvar-issue-87987.rs} | 3 ++- 3 files changed, 2 insertions(+), 16 deletions(-) delete mode 100644 tests/ui/closures/2229_closure_analysis/issue-87987.stderr rename tests/ui/closures/2229_closure_analysis/{issue-87987.rs => unresolvable-upvar-issue-87987.rs} (83%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index de3380502bfcd..d746b4551b4cc 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -409,7 +409,6 @@ ui/closure_context/issue-26046-fn-once.rs ui/closure_context/issue-42065.rs ui/closures/2229_closure_analysis/issue-118144.rs ui/closures/2229_closure_analysis/issue-87378.rs -ui/closures/2229_closure_analysis/issue-87987.rs ui/closures/2229_closure_analysis/issue-88118-2.rs ui/closures/2229_closure_analysis/issue-88476.rs ui/closures/2229_closure_analysis/issue-89606.rs diff --git a/tests/ui/closures/2229_closure_analysis/issue-87987.stderr b/tests/ui/closures/2229_closure_analysis/issue-87987.stderr deleted file mode 100644 index 5696a010c3f80..0000000000000 --- a/tests/ui/closures/2229_closure_analysis/issue-87987.stderr +++ /dev/null @@ -1,14 +0,0 @@ -warning: fields `field_1` and `field_2` are never read - --> $DIR/issue-87987.rs:5:5 - | -LL | struct Props { - | ----- fields in this struct -LL | field_1: u32, - | ^^^^^^^ -LL | field_2: u32, - | ^^^^^^^ - | - = note: `#[warn(dead_code)]` on by default - -warning: 1 warning emitted - diff --git a/tests/ui/closures/2229_closure_analysis/issue-87987.rs b/tests/ui/closures/2229_closure_analysis/unresolvable-upvar-issue-87987.rs similarity index 83% rename from tests/ui/closures/2229_closure_analysis/issue-87987.rs rename to tests/ui/closures/2229_closure_analysis/unresolvable-upvar-issue-87987.rs index f79a8f1b57100..03cbe53cbec69 100644 --- a/tests/ui/closures/2229_closure_analysis/issue-87987.rs +++ b/tests/ui/closures/2229_closure_analysis/unresolvable-upvar-issue-87987.rs @@ -1,8 +1,9 @@ //@ run-pass //@ edition:2021 +#[expect(dead_code)] struct Props { - field_1: u32, //~ WARNING: fields `field_1` and `field_2` are never read + field_1: u32, field_2: u32, } From 6c7e8fefa30688f2a750f738bb78da517c4ffc00 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 20 Jan 2025 17:05:54 +1100 Subject: [PATCH 04/10] Add some notes and test some more pattern variants --- .../unresolvable-upvar-issue-87987.rs | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/tests/ui/closures/2229_closure_analysis/unresolvable-upvar-issue-87987.rs b/tests/ui/closures/2229_closure_analysis/unresolvable-upvar-issue-87987.rs index 03cbe53cbec69..c501e034c97db 100644 --- a/tests/ui/closures/2229_closure_analysis/unresolvable-upvar-issue-87987.rs +++ b/tests/ui/closures/2229_closure_analysis/unresolvable-upvar-issue-87987.rs @@ -1,3 +1,13 @@ +//! When a closure syntactically captures a place, but doesn't actually capture +//! it, make sure MIR building doesn't ICE when handling that place. +//! +//! Under the Rust 2021 disjoint capture rules, this sort of non-capture can +//! occur when a place is only inspected by infallible non-binding patterns. + +// FIXME(#135985): On its own, this test should probably just be check-pass. +// But there are few/no other tests that use non-binding array patterns and +// invoke the later parts of the compiler, so building/running has some value. + //@ run-pass //@ edition:2021 @@ -20,8 +30,16 @@ fn main() { let mref = &mut arr; + // These array patterns don't need to inspect the array, so the array + // isn't captured. let _c = || match arr { - [_, _, _, _] => println!("A"), + [_, _, _, _] => println!("C"), + }; + let _d = || match arr { + [_, .., _] => println!("D"), + }; + let _e = || match arr { + [_, ..] => println!("E"), }; println!("{:#?}", mref); From e170c9dec043e8f51bf1dfd3709f25e9bbe5a0fd Mon Sep 17 00:00:00 2001 From: Huang Qi Date: Fri, 24 Jan 2025 21:17:49 +0800 Subject: [PATCH 05/10] Fix set_name in thread mod for NuttX Replace `pthread_set_name_np` with `pthread_setname_np` for NuttX in the `set_name` function, this change aligns the implementation with the correct API available on NuttX This patch ensures thread naming works correctly on NuttX platforms. Signed-off-by: Huang Qi --- library/std/src/sys/pal/unix/thread.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index f657f82e6e368..356669980c7d9 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -130,7 +130,12 @@ impl Thread { } } - #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly"))] + #[cfg(any( + target_os = "linux", + target_os = "freebsd", + target_os = "dragonfly", + target_os = "nuttx" + ))] pub fn set_name(name: &CStr) { unsafe { cfg_if::cfg_if! { @@ -139,7 +144,7 @@ impl Thread { const TASK_COMM_LEN: usize = 16; let name = truncate_cstr::<{ TASK_COMM_LEN }>(name); } else { - // FreeBSD and DragonFly BSD do not enforce length limits. + // FreeBSD, DragonFly, FreeBSD and NuttX do not enforce length limits. } }; // Available since glibc 2.12, musl 1.1.16, and uClibc 1.0.20 for Linux, @@ -150,7 +155,7 @@ impl Thread { } } - #[cfg(any(target_os = "openbsd", target_os = "nuttx"))] + #[cfg(target_os = "openbsd")] pub fn set_name(name: &CStr) { unsafe { libc::pthread_set_name_np(libc::pthread_self(), name.as_ptr()); From 571f3ed0c49353a6ceec040bb406a4b364b3766f Mon Sep 17 00:00:00 2001 From: clubby789 Date: Fri, 24 Jan 2025 16:56:00 +0000 Subject: [PATCH 06/10] bootstrap: Handle bootstrap lockfile race condition better --- src/bootstrap/src/bin/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs index b65527741952e..8ebd6b8aa54cd 100644 --- a/src/bootstrap/src/bin/main.rs +++ b/src/bootstrap/src/bin/main.rs @@ -57,7 +57,9 @@ fn main() { } err => { drop(err); - if let Ok(pid) = pid { + // #135972: We can reach this point when the lock has been taken, + // but the locker has not yet written its PID to the file + if let Some(pid) = pid.ok().filter(|pid| !pid.is_empty()) { println!("WARNING: build directory locked by process {pid}, waiting for lock"); } else { println!("WARNING: build directory locked, waiting for lock"); From 91b759354c3a0f8496af6ae72b1b27fd2f880055 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 24 Jan 2025 17:49:25 +0000 Subject: [PATCH 07/10] Use short ty string for move errors ``` error[E0382]: use of moved value: `x` --> bay.rs:14:14 | 12 | fn foo(x: D) { | - move occurs because `x` has type `(((..., ..., ..., ...), ..., ..., ...), ..., ..., ...)`, which does not implement the `Copy` trait 13 | let _a = x; | - value moved here 14 | let _b = x; //~ ERROR use of moved value | ^ value used here after move | = note: the full type name has been written to 'bay.long-type-14349227078439097973.txt' = note: consider using `--verbose` to print the full type name to the console help: consider cloning the value if the performance cost is acceptable | 13 | let _a = x.clone(); | ++++++++ ``` --- compiler/rustc_borrowck/messages.ftl | 3 +++ .../src/diagnostics/conflict_errors.rs | 7 +++++ .../src/diagnostics/move_errors.rs | 27 ++++++++++++++++--- .../rustc_borrowck/src/session_diagnostics.rs | 13 ++++++--- compiler/rustc_mir_build/messages.ftl | 2 ++ compiler/rustc_mir_build/src/errors.rs | 8 ++++-- .../src/thir/pattern/check_match.rs | 4 +++ .../diagnostic-width/non-copy-type-moved.rs | 17 ++++++++++++ .../non-copy-type-moved.stderr | 20 ++++++++++++++ 9 files changed, 93 insertions(+), 8 deletions(-) create mode 100644 tests/ui/diagnostic-width/non-copy-type-moved.rs create mode 100644 tests/ui/diagnostic-width/non-copy-type-moved.stderr diff --git a/compiler/rustc_borrowck/messages.ftl b/compiler/rustc_borrowck/messages.ftl index ada20e5c614f8..c00e6dde91965 100644 --- a/compiler/rustc_borrowck/messages.ftl +++ b/compiler/rustc_borrowck/messages.ftl @@ -92,6 +92,9 @@ borrowck_lifetime_constraints_error = borrowck_limitations_implies_static = due to current limitations in the borrow checker, this implies a `'static` lifetime +borrowck_long_type_consider_verbose = consider using `--verbose` to print the full type name to the console +borrowck_long_type_full_path = the full type name has been written to '{$path}' + borrowck_move_closure_suggestion = consider adding 'move' keyword before the nested closure diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index d020244bf55e4..07dcbba019ade 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -289,6 +289,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { None => "value".to_owned(), }; if needs_note { + let mut path = None; + let ty = self.infcx.tcx.short_ty_string(ty, &mut path); if let Some(local) = place.as_local() { let span = self.body.local_decls[local].source_info.span; err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { @@ -304,6 +306,11 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { place: ¬e_msg, }); }; + if let Some(path) = path { + err.subdiagnostic(crate::session_diagnostics::LongTypePath { + path: path.display().to_string(), + }); + } } if let UseSpans::FnSelfUse { diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index beacbdbd3fa7b..14a900f38e922 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -596,12 +596,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning(err, place_ty, expr, None); } + let mut path = None; + let ty = self.infcx.tcx.short_ty_string(place_ty, &mut path); err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, - ty: place_ty, + ty, place: &place_desc, span, }); + if let Some(path) = path { + err.subdiagnostic(crate::session_diagnostics::LongTypePath { + path: path.display().to_string(), + }); + } } else { binds_to.sort(); binds_to.dedup(); @@ -628,12 +635,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning(err, place_ty, expr, Some(use_spans)); } + let mut path = None; + let ty = self.infcx.tcx.short_ty_string(place_ty, &mut path); err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, - ty: place_ty, + ty, place: &place_desc, span: use_span, }); + if let Some(path) = path { + err.subdiagnostic(crate::session_diagnostics::LongTypePath { + path: path.display().to_string(), + }); + } use_spans.args_subdiag(err, |args_span| { crate::session_diagnostics::CaptureArgLabel::MoveOutPlace { @@ -831,12 +845,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { self.suggest_cloning(err, bind_to.ty, expr, None); } + let mut path = None; + let ty = self.infcx.tcx.short_ty_string(bind_to.ty, &mut path); err.subdiagnostic(crate::session_diagnostics::TypeNoCopy::Label { is_partial_move: false, - ty: bind_to.ty, + ty, place: place_desc, span: binding_span, }); + if let Some(path) = path { + err.subdiagnostic(crate::session_diagnostics::LongTypePath { + path: path.display().to_string(), + }); + } } } diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index 4be5d0dbf4284..2c37d2bc12362 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -459,17 +459,24 @@ pub(crate) enum OnClosureNote<'a> { } #[derive(Subdiagnostic)] -pub(crate) enum TypeNoCopy<'a, 'tcx> { +#[note(borrowck_long_type_full_path)] +#[note(borrowck_long_type_consider_verbose)] +pub(crate) struct LongTypePath { + pub(crate) path: String, +} + +#[derive(Subdiagnostic)] +pub(crate) enum TypeNoCopy<'a> { #[label(borrowck_ty_no_impl_copy)] Label { is_partial_move: bool, - ty: Ty<'tcx>, + ty: String, place: &'a str, #[primary_span] span: Span, }, #[note(borrowck_ty_no_impl_copy)] - Note { is_partial_move: bool, ty: Ty<'tcx>, place: &'a str }, + Note { is_partial_move: bool, ty: String, place: &'a str }, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index ffdb721fb18b4..053775b493789 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -25,6 +25,8 @@ mir_build_borrow_of_moved_value = borrow of moved value .occurs_because_label = move occurs because `{$name}` has type `{$ty}`, which does not implement the `Copy` trait .value_borrowed_label = value borrowed here after move .suggestion = borrow this binding in the pattern to avoid moving the value + .full_type_name = the full type name has been written to '{$path}' + .consider_verbose = consider using `--verbose` to print the full type name to the console mir_build_call_to_deprecated_safe_fn_requires_unsafe = call to deprecated safe function `{$function}` is unsafe and requires unsafe block diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 83aec9ccdefc6..c3bf5868eecde 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -790,7 +790,7 @@ pub(crate) struct IrrefutableLetPatternsWhileLet { #[derive(Diagnostic)] #[diag(mir_build_borrow_of_moved_value)] -pub(crate) struct BorrowOfMovedValue<'tcx> { +pub(crate) struct BorrowOfMovedValue { #[primary_span] #[label] #[label(mir_build_occurs_because_label)] @@ -798,9 +798,13 @@ pub(crate) struct BorrowOfMovedValue<'tcx> { #[label(mir_build_value_borrowed_label)] pub(crate) conflicts_ref: Vec, pub(crate) name: Symbol, - pub(crate) ty: Ty<'tcx>, + pub(crate) ty: String, #[suggestion(code = "ref ", applicability = "machine-applicable")] pub(crate) suggest_borrowing: Option, + #[note(mir_build_full_type_name)] + #[note(mir_build_consider_verbose)] + pub(crate) has_path: bool, + pub(crate) path: String, } #[derive(Diagnostic)] diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index b5b7b54a1cc39..d8b04398d9a51 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -795,12 +795,16 @@ fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, 'tcx>, pat: } }); if !conflicts_ref.is_empty() { + let mut path = None; + let ty = cx.tcx.short_ty_string(ty, &mut path); sess.dcx().emit_err(BorrowOfMovedValue { binding_span: pat.span, conflicts_ref, name, ty, suggest_borrowing: Some(pat.span.shrink_to_lo()), + has_path: path.is_some(), + path: path.map(|p| p.display().to_string()).unwrap_or_default(), }); } return; diff --git a/tests/ui/diagnostic-width/non-copy-type-moved.rs b/tests/ui/diagnostic-width/non-copy-type-moved.rs new file mode 100644 index 0000000000000..a5593ad7b2a3d --- /dev/null +++ b/tests/ui/diagnostic-width/non-copy-type-moved.rs @@ -0,0 +1,17 @@ +//@ compile-flags: --diagnostic-width=60 -Zwrite-long-types-to-disk=yes +//@ normalize-stderr: "long-type-\d+" -> "long-type-hash" +type A = (String, String, String, String); +type B = (A, A, A, A); +type C = (B, B, B, B); +type D = (C, C, C, C); + +trait Trait {} + +fn require_trait() {} + +fn foo(x: D) { + let _a = x; + let _b = x; //~ ERROR use of moved value +} + +fn main() {} diff --git a/tests/ui/diagnostic-width/non-copy-type-moved.stderr b/tests/ui/diagnostic-width/non-copy-type-moved.stderr new file mode 100644 index 0000000000000..da9385a5b4dcd --- /dev/null +++ b/tests/ui/diagnostic-width/non-copy-type-moved.stderr @@ -0,0 +1,20 @@ +error[E0382]: use of moved value: `x` + --> $DIR/non-copy-type-moved.rs:14:14 + | +LL | fn foo(x: D) { + | - move occurs because `x` has type `((..., ..., ..., ...), ..., ..., ...)`, which does not implement the `Copy` trait +LL | let _a = x; + | - value moved here +LL | let _b = x; + | ^ value used here after move + | + = note: the full type name has been written to '$TEST_BUILD_DIR/diagnostic-width/non-copy-type-moved/non-copy-type-moved.long-type-hash.txt' + = note: consider using `--verbose` to print the full type name to the console +help: consider cloning the value if the performance cost is acceptable + | +LL | let _a = x.clone(); + | ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0382`. From ab7793d4d4d35551480cb2b6823903974316a9fa Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Fri, 24 Jan 2025 22:05:30 +0000 Subject: [PATCH 08/10] Don't move ownership of job object --- src/bootstrap/bootstrap.py | 3 -- src/bootstrap/src/utils/job.rs | 51 +++------------------------------- 2 files changed, 4 insertions(+), 50 deletions(-) diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 74923af155585..01a9792f1b375 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -1310,9 +1310,6 @@ def bootstrap(args): args = [build.bootstrap_binary()] args.extend(sys.argv[1:]) env = os.environ.copy() - # The Python process ID is used when creating a Windows job object - # (see src\bootstrap\src\utils\job.rs) - env["BOOTSTRAP_PARENT_ID"] = str(os.getpid()) env["BOOTSTRAP_PYTHON"] = sys.executable run(args, env=env, verbose=build.verbose, is_bootstrap=True) diff --git a/src/bootstrap/src/utils/job.rs b/src/bootstrap/src/utils/job.rs index fb69d331d27e1..10efed130d624 100644 --- a/src/bootstrap/src/utils/job.rs +++ b/src/bootstrap/src/utils/job.rs @@ -42,9 +42,9 @@ pub unsafe fn setup(build: &mut crate::Build) { #[cfg(windows)] mod for_windows { use std::ffi::c_void; - use std::{env, io, mem}; + use std::{io, mem}; - use windows::Win32::Foundation::{CloseHandle, DUPLICATE_SAME_ACCESS, DuplicateHandle, HANDLE}; + use windows::Win32::Foundation::CloseHandle; use windows::Win32::System::Diagnostics::Debug::{ SEM_NOGPFAULTERRORBOX, SetErrorMode, THREAD_ERROR_MODE, }; @@ -53,9 +53,7 @@ mod for_windows { JOB_OBJECT_LIMIT_PRIORITY_CLASS, JOBOBJECT_EXTENDED_LIMIT_INFORMATION, JobObjectExtendedLimitInformation, SetInformationJobObject, }; - use windows::Win32::System::Threading::{ - BELOW_NORMAL_PRIORITY_CLASS, GetCurrentProcess, OpenProcess, PROCESS_DUP_HANDLE, - }; + use windows::Win32::System::Threading::{BELOW_NORMAL_PRIORITY_CLASS, GetCurrentProcess}; use windows::core::PCWSTR; use crate::Build; @@ -95,49 +93,8 @@ mod for_windows { return; } - // If we've got a parent process (e.g., the python script that called us) - // then move ownership of this job object up to them. That way if the python - // script is killed (e.g., via ctrl-c) then we'll all be torn down. - // - // If we don't have a parent (e.g., this was run directly) then we - // intentionally leak the job object handle. When our process exits + // Note: we intentionally leak the job object handle. When our process exits // (normally or abnormally) it will close the handle implicitly, causing all // processes in the job to be cleaned up. - let pid = match env::var("BOOTSTRAP_PARENT_ID") { - Ok(s) => s, - Err(..) => return, - }; - - let parent = match OpenProcess(PROCESS_DUP_HANDLE, false, pid.parse().unwrap()).ok() { - Some(parent) => parent, - _ => { - // If we get a null parent pointer here, it is possible that either - // we have an invalid pid or the parent process has been closed. - // Since the first case rarely happens - // (only when wrongly setting the environmental variable), - // it might be better to improve the experience of the second case - // when users have interrupted the parent process and we haven't finish - // duplicating the handle yet. - return; - } - }; - - let mut parent_handle = HANDLE::default(); - // If this fails, well at least we tried! An example of DuplicateHandle - // failing in the past has been when the wrong python2 package spawned this - // build system (e.g., the `python2` package in MSYS instead of - // `mingw-w64-x86_64-python2`). Not sure why it failed, but the "failure - // mode" here is that we only clean everything up when the build system - // dies, not when the python parent does, so not too bad. - let _ = DuplicateHandle( - GetCurrentProcess(), - job, - parent, - &mut parent_handle, - 0, - false, - DUPLICATE_SAME_ACCESS, - ); - CloseHandle(parent).ok(); } } From 8873c1871aee825d8dfe929e63f7f5d7bbed7484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 24 Jan 2025 22:08:39 +0000 Subject: [PATCH 09/10] Skip suggestions in `derive`d code Do not suggest ``` help: use parentheses to call these | 5 | (callback: Rc)(), | + +++ ``` Skip all "call function for this binop" suggestions when in a derive context. Fix #135989. --- .../rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 3 +++ .../do-not-suggest-calling-fn-in-derive-macro.rs | 8 ++++++++ ...o-not-suggest-calling-fn-in-derive-macro.stderr | 14 ++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.rs create mode 100644 tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 16294970f0531..928010c03c2ee 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -185,6 +185,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rhs_ty: Ty<'tcx>, can_satisfy: impl FnOnce(Ty<'tcx>, Ty<'tcx>) -> bool, ) -> bool { + if lhs_expr.span.in_derive_expansion() || rhs_expr.span.in_derive_expansion() { + return false; + } let Some((_, lhs_output_ty, lhs_inputs)) = self.extract_callable_info(lhs_ty) else { return false; }; diff --git a/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.rs b/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.rs new file mode 100644 index 0000000000000..76b93c0c947cb --- /dev/null +++ b/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.rs @@ -0,0 +1,8 @@ +use std::rc::Rc; + +#[derive(PartialEq)] //~ NOTE in this expansion +pub struct Function { + callback: Rc, //~ ERROR binary operation `==` cannot be applied to type `Rc` +} + +fn main() {} diff --git a/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.stderr b/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.stderr new file mode 100644 index 0000000000000..40464a49c3438 --- /dev/null +++ b/tests/ui/deriving/do-not-suggest-calling-fn-in-derive-macro.stderr @@ -0,0 +1,14 @@ +error[E0369]: binary operation `==` cannot be applied to type `Rc` + --> $DIR/do-not-suggest-calling-fn-in-derive-macro.rs:5:5 + | +LL | #[derive(PartialEq)] + | --------- in this derive macro expansion +LL | pub struct Function { +LL | callback: Rc, + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0369`. From 5f8bcec6c8e006f0b73b9bff076299f77d6c166c Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Fri, 24 Jan 2025 19:08:32 -0500 Subject: [PATCH 10/10] fix(bootstrap): deserialize null as `f64::NAN` When doing optimized build through opt-dist, I've often run into errors like `invalid type: null, expected f64`. This is likely because some f64 fields might actually bet set null. Unfortunately, serde_json doesn't handle null <-> NaN well. This commit addresses it by having a custom deserialize method, so null is always be deserialized to `f64:NAN`. See: * https://rust-lang.zulipchat.com/#narrow/channel/242791-t-infra/topic/opt-dist.3A.20.60invalid.20type.3A.20null.2C.20expect.20f64.60.20failure * https://github.com/serde-rs/json/issues/202 --- src/build_helper/src/metrics.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/build_helper/src/metrics.rs b/src/build_helper/src/metrics.rs index 2d0c66a8f3339..538c33e9b1591 100644 --- a/src/build_helper/src/metrics.rs +++ b/src/build_helper/src/metrics.rs @@ -16,6 +16,7 @@ pub struct JsonInvocation { // // This is necessary to easily correlate this invocation with logs or other data. pub start_time: u64, + #[serde(deserialize_with = "null_as_f64_nan")] pub duration_including_children_sec: f64, pub children: Vec, } @@ -28,6 +29,7 @@ pub enum JsonNode { type_: String, debug_repr: String, + #[serde(deserialize_with = "null_as_f64_nan")] duration_excluding_children_sec: f64, system_stats: JsonStepSystemStats, @@ -88,5 +90,11 @@ pub struct JsonInvocationSystemStats { #[derive(Serialize, Deserialize)] #[serde(rename_all = "snake_case")] pub struct JsonStepSystemStats { + #[serde(deserialize_with = "null_as_f64_nan")] pub cpu_utilization_percent: f64, } + +fn null_as_f64_nan<'de, D: serde::Deserializer<'de>>(d: D) -> Result { + use serde::Deserialize as _; + Option::::deserialize(d).map(|f| f.unwrap_or(f64::NAN)) +}