From e2c983138876cc29d89c9320b05a6614607d11c7 Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas) Chirananthavat" Date: Thu, 12 Sep 2024 23:39:45 +0700 Subject: [PATCH 01/16] Document subtleties of `ManuallyDrop` --- library/core/src/mem/manually_drop.rs | 126 +++++++++++++++++++++++--- 1 file changed, 115 insertions(+), 11 deletions(-) diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index be5cee2e85267..f4b56c9f13e73 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -1,20 +1,19 @@ use crate::ops::{Deref, DerefMut, DerefPure}; use crate::ptr; -/// A wrapper to inhibit the compiler from automatically calling `T`’s destructor. -/// This wrapper is 0-cost. +/// A wrapper to inhibit the compiler from automatically calling `T`’s +/// destructor. This wrapper is 0-cost. /// /// `ManuallyDrop` is guaranteed to have the same layout and bit validity as -/// `T`, and is subject to the same layout optimizations as `T`. As a consequence, -/// it has *no effect* on the assumptions that the compiler makes about its -/// contents. For example, initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`] -/// is undefined behavior. If you need to handle uninitialized data, use -/// [`MaybeUninit`] instead. +/// `T`, and is subject to the same layout optimizations as `T`. As a +/// consequence, it has *no effect* on the assumptions that the compiler makes +/// about its contents. For example, initializing a `ManuallyDrop<&mut T>` with +/// [`mem::zeroed`] is undefined behavior. If you need to handle uninitialized +/// data, use [`MaybeUninit`] instead. /// -/// Note that accessing the value inside a `ManuallyDrop` is safe. -/// This means that a `ManuallyDrop` whose content has been dropped must not -/// be exposed through a public safe API. -/// Correspondingly, `ManuallyDrop::drop` is unsafe. +/// Note that accessing the value inside a `ManuallyDrop` is safe. This means +/// that a `ManuallyDrop` whose content has been dropped must not be exposed +/// through a public safe API. Correspondingly, `ManuallyDrop::drop` is unsafe. /// /// # `ManuallyDrop` and drop order. /// @@ -40,9 +39,114 @@ use crate::ptr; /// } /// ``` /// +/// # Interaction with `Box`. +/// +/// Currently, once the `Box` inside a `ManuallyDrop>` is dropped, +/// moving the `ManuallyDrop>` is [considered to be undefined +/// behavior](https://github.com/rust-lang/unsafe-code-guidelines/issues/245). +/// That is, the following code causes undefined behavior: +/// +/// ```no_run +/// use std::mem::ManuallyDrop; +/// +/// let mut x = ManuallyDrop::new(Box::new(42)); +/// unsafe { +/// ManuallyDrop::drop(&mut x); +/// } +/// let y = x; // Undefined behavior! +/// ``` +/// +/// This may change in the future. In the meantime, consider using +/// [`MaybeUninit`] instead. +/// +/// # Safety hazards when storing `ManuallyDrop` in a struct / enum. +/// +/// Special care is needed when all of the conditions below are met: +/// * A field of a struct or enum is a `ManuallyDrop` or contains a +/// `ManuallyDrop`, without the `ManuallyDrop` being inside a `union`. +/// * The struct or enum is part of public API, or is stored in a struct or enum +/// that is part of public API. +/// * There is code outside of a `Drop` implementation that calls +/// [`ManuallyDrop::drop`] or [`ManuallyDrop::take`] on the `ManuallyDrop` +/// field. +/// +/// In particular, the following hazards can occur: +/// +/// #### Storing generic types +/// +/// If the `ManuallyDrop` contains a client-supplied generic type, the client +/// might provide a `Box`, causing undefined behavior when the struct / enum is +/// later moved, as mentioned above. For example, the following code causes +/// undefined behavior: +/// +/// ```no_run +/// use std::mem::ManuallyDrop; +/// +/// pub struct BadOption { +/// // Invariant: Has been dropped iff `is_some` is false. +/// value: ManuallyDrop, +/// is_some: bool, +/// } +/// impl BadOption { +/// pub fn new(value: T) -> Self { +/// Self { value: ManuallyDrop::new(value), is_some: true } +/// } +/// pub fn change_to_none(&mut self) { +/// if self.is_some { +/// self.is_some = false; +/// unsafe { +/// // SAFETY: `value` hasn't been dropped yet, as per the invariant +/// // (This is actually unsound!) +/// ManuallyDrop::drop(&mut self.value); +/// } +/// } +/// } +/// } +/// +/// // In another crate: +/// +/// let mut option = BadOption::new(Box::new(42)); +/// option.change_to_none(); +/// let option2 = option; // Undefined behavior! +/// ``` +/// +/// #### Deriving traits +/// +/// Deriving `Debug`, `Clone`, `PartialEq`, `PartialOrd`, `Ord`, or `Hash` on +/// the struct / enum could be unsound, since the derived implementations of +/// these traits would access the `ManuallyDrop` field. For example, the +/// following code causes undefined behavior: +/// +/// ```no_run +/// use std::mem::ManuallyDrop; +/// +/// #[derive(Debug)] // This is unsound! +/// pub struct Foo { +/// value: ManuallyDrop, +/// } +/// impl Foo { +/// pub fn new() -> Self { +/// let mut temp = Self { +/// value: ManuallyDrop::new(String::from("Unsafe rust is hard")) +/// }; +/// unsafe { +/// // SAFETY: `value` hasn't been dropped yet. +/// ManuallyDrop::drop(&mut temp.value); +/// } +/// temp +/// } +/// } +/// +/// // In another crate: +/// +/// let foo = Foo::new(); +/// println!("{:?}", foo); // Undefined behavior! +/// ``` +/// /// [drop order]: https://doc.rust-lang.org/reference/destructors.html /// [`mem::zeroed`]: crate::mem::zeroed /// [`MaybeUninit`]: crate::mem::MaybeUninit +/// [`MaybeUninit`]: crate::mem::MaybeUninit #[stable(feature = "manually_drop", since = "1.20.0")] #[lang = "manually_drop"] #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] From 6fa092a1024d6fc47926bb8eed9e2df075c2ff2f Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas) Chirananthavat" Date: Fri, 13 Sep 2024 21:26:39 +0700 Subject: [PATCH 02/16] Address WaffleLapkin's comments --- library/core/src/mem/manually_drop.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index f4b56c9f13e73..24d95f939000a 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -15,7 +15,7 @@ use crate::ptr; /// that a `ManuallyDrop` whose content has been dropped must not be exposed /// through a public safe API. Correspondingly, `ManuallyDrop::drop` is unsafe. /// -/// # `ManuallyDrop` and drop order. +/// # `ManuallyDrop` and drop order /// /// Rust has a well-defined [drop order] of values. To make sure that fields or /// locals are dropped in a specific order, reorder the declarations such that @@ -39,7 +39,7 @@ use crate::ptr; /// } /// ``` /// -/// # Interaction with `Box`. +/// # Interaction with `Box` /// /// Currently, once the `Box` inside a `ManuallyDrop>` is dropped, /// moving the `ManuallyDrop>` is [considered to be undefined @@ -56,16 +56,17 @@ use crate::ptr; /// let y = x; // Undefined behavior! /// ``` /// -/// This may change in the future. In the meantime, consider using -/// [`MaybeUninit`] instead. +/// This is [likely to change in the +/// future](https://rust-lang.github.io/rfcs/3336-maybe-dangling.html). In the +/// meantime, consider using [`MaybeUninit`] instead. /// -/// # Safety hazards when storing `ManuallyDrop` in a struct / enum. +/// # Safety hazards when storing `ManuallyDrop` in a struct or an enum. /// /// Special care is needed when all of the conditions below are met: /// * A field of a struct or enum is a `ManuallyDrop` or contains a /// `ManuallyDrop`, without the `ManuallyDrop` being inside a `union`. -/// * The struct or enum is part of public API, or is stored in a struct or enum -/// that is part of public API. +/// * The struct or enum is part of public API, or is stored in a struct or an +/// enum that is part of public API. /// * There is code outside of a `Drop` implementation that calls /// [`ManuallyDrop::drop`] or [`ManuallyDrop::take`] on the `ManuallyDrop` /// field. @@ -120,14 +121,15 @@ use crate::ptr; /// ```no_run /// use std::mem::ManuallyDrop; /// -/// #[derive(Debug)] // This is unsound! +/// // This derive is unsound in combination with the `ManuallyDrop::drop` call. +/// #[derive(Debug)] /// pub struct Foo { /// value: ManuallyDrop, /// } /// impl Foo { /// pub fn new() -> Self { /// let mut temp = Self { -/// value: ManuallyDrop::new(String::from("Unsafe rust is hard")) +/// value: ManuallyDrop::new(String::from("Unsafe rust is hard.")) /// }; /// unsafe { /// // SAFETY: `value` hasn't been dropped yet. From f604ed631baa3428fcc8370402985a56fc0fc459 Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas) Chirananthavat" Date: Fri, 13 Sep 2024 22:02:07 +0700 Subject: [PATCH 03/16] Fix awkward wording. --- library/core/src/mem/manually_drop.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 24d95f939000a..8dea3539e4639 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -63,22 +63,21 @@ use crate::ptr; /// # Safety hazards when storing `ManuallyDrop` in a struct or an enum. /// /// Special care is needed when all of the conditions below are met: -/// * A field of a struct or enum is a `ManuallyDrop` or contains a -/// `ManuallyDrop`, without the `ManuallyDrop` being inside a `union`. +/// * A struct or enum contains a `ManuallyDrop`. +/// * The `ManuallyDrop` is not inside a `union`. /// * The struct or enum is part of public API, or is stored in a struct or an /// enum that is part of public API. -/// * There is code outside of a `Drop` implementation that calls -/// [`ManuallyDrop::drop`] or [`ManuallyDrop::take`] on the `ManuallyDrop` -/// field. +/// * There is code that drops the contents of the `ManuallyDrop` field, and +/// this code is outside the struct or enum's `Drop` implementation. /// -/// In particular, the following hazards can occur: +/// In particular, the following hazards may occur: /// /// #### Storing generic types /// /// If the `ManuallyDrop` contains a client-supplied generic type, the client -/// might provide a `Box`, causing undefined behavior when the struct / enum is -/// later moved, as mentioned above. For example, the following code causes -/// undefined behavior: +/// might provide a `Box` as that type. This would cause undefined behavior when +/// the struct or enum is later moved, as mentioned in the previous section. For +/// example, the following code causes undefined behavior: /// /// ```no_run /// use std::mem::ManuallyDrop; @@ -114,7 +113,7 @@ use crate::ptr; /// #### Deriving traits /// /// Deriving `Debug`, `Clone`, `PartialEq`, `PartialOrd`, `Ord`, or `Hash` on -/// the struct / enum could be unsound, since the derived implementations of +/// the struct or enum could be unsound, since the derived implementations of /// these traits would access the `ManuallyDrop` field. For example, the /// following code causes undefined behavior: /// From 4788e8c34ac900f3595e7fe6070f0cf210851cf7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 18 Sep 2024 14:48:30 +0000 Subject: [PATCH 04/16] Add the library workspace to the suggested rust-analyzer config --- src/bootstrap/src/core/build_steps/setup.rs | 1 + src/etc/rust_analyzer_settings.json | 1 + 2 files changed, 2 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/setup.rs b/src/bootstrap/src/core/build_steps/setup.rs index f7b26712cabd6..eb7f29ee23d76 100644 --- a/src/bootstrap/src/core/build_steps/setup.rs +++ b/src/bootstrap/src/core/build_steps/setup.rs @@ -46,6 +46,7 @@ static SETTINGS_HASHES: &[&str] = &[ "47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923", "b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a", "828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000", + "811fb3b063c739d261fd8590dd30242e117908f5a095d594fa04585daa18ec4d", ]; static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json"); diff --git a/src/etc/rust_analyzer_settings.json b/src/etc/rust_analyzer_settings.json index d329fe997cd79..a20105f0ef378 100644 --- a/src/etc/rust_analyzer_settings.json +++ b/src/etc/rust_analyzer_settings.json @@ -10,6 +10,7 @@ ], "rust-analyzer.linkedProjects": [ "Cargo.toml", + "library/Cargo.toml", "src/tools/x/Cargo.toml", "src/bootstrap/Cargo.toml", "src/tools/rust-analyzer/Cargo.toml", From de2eba18263855871522cb967bfa82ac1ef22d5e Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas) Chirananthavat" Date: Sat, 21 Sep 2024 12:38:38 +0700 Subject: [PATCH 05/16] Reword ManuallyDrop+Box interaction --- library/core/src/mem/manually_drop.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/src/mem/manually_drop.rs b/library/core/src/mem/manually_drop.rs index 8dea3539e4639..86eac7724cf3a 100644 --- a/library/core/src/mem/manually_drop.rs +++ b/library/core/src/mem/manually_drop.rs @@ -41,8 +41,9 @@ use crate::ptr; /// /// # Interaction with `Box` /// -/// Currently, once the `Box` inside a `ManuallyDrop>` is dropped, -/// moving the `ManuallyDrop>` is [considered to be undefined +/// Currently, if you have a `ManuallyDrop`, where the type `T` is a `Box` or +/// contains a `Box` inside, then dropping the `T` followed by moving the +/// `ManuallyDrop` is [considered to be undefined /// behavior](https://github.com/rust-lang/unsafe-code-guidelines/issues/245). /// That is, the following code causes undefined behavior: /// From 986e20d5bb5df4274b390b4148aab0058081a241 Mon Sep 17 00:00:00 2001 From: Virginia Senioria <91khr@users.noreply.github.com> Date: Wed, 25 Sep 2024 07:34:53 +0000 Subject: [PATCH 06/16] Fixed diagnostics for coroutines with () as input. --- .../traits/fulfillment_errors.rs | 72 +++++++++---------- .../arg-count-mismatch-on-unit-input.rs | 11 +++ .../arg-count-mismatch-on-unit-input.stderr | 15 ++++ 3 files changed, 61 insertions(+), 37 deletions(-) create mode 100644 tests/ui/coroutine/arg-count-mismatch-on-unit-input.rs create mode 100644 tests/ui/coroutine/arg-count-mismatch-on-unit-input.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 19e2679ae4da7..969f2528836d4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2635,49 +2635,47 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // This shouldn't be common unless manually implementing one of the // traits manually, but don't make it more confusing when it does // happen. - Ok( - if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait() - && not_tupled - { - self.report_and_explain_type_error( - TypeTrace::trait_refs( - &obligation.cause, - true, - expected_trait_ref, - found_trait_ref, - ), - ty::error::TypeError::Mismatch, - ) - } else if found.len() == expected.len() { - self.report_closure_arg_mismatch( - span, - found_span, - found_trait_ref, - expected_trait_ref, - obligation.cause.code(), - found_node, - obligation.param_env, - ) - } else { - let (closure_span, closure_arg_span, found) = found_did - .and_then(|did| { - let node = self.tcx.hir().get_if_local(did)?; - let (found_span, closure_arg_span, found) = - self.get_fn_like_arguments(node)?; - Some((Some(found_span), closure_arg_span, found)) - }) - .unwrap_or((found_span, None, found)); - - self.report_arg_count_mismatch( + if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait() && not_tupled + { + return Ok(self.report_and_explain_type_error( + TypeTrace::trait_refs(&obligation.cause, true, expected_trait_ref, found_trait_ref), + ty::error::TypeError::Mismatch, + )); + } + if found.len() != expected.len() { + let (closure_span, closure_arg_span, found) = found_did + .and_then(|did| { + let node = self.tcx.hir().get_if_local(did)?; + let (found_span, closure_arg_span, found) = self.get_fn_like_arguments(node)?; + Some((Some(found_span), closure_arg_span, found)) + }) + .unwrap_or((found_span, None, found)); + + // If the coroutine take a single () as its argument, + // the trait argument would found the coroutine take 0 arguments, + // but get_fn_like_arguments would give 1 argument. + // This would result in "Expected to take 1 argument, but it takes 1 argument". + // Check again to avoid this. + if found.len() != expected.len() { + return Ok(self.report_arg_count_mismatch( span, closure_span, expected, found, found_trait_ty.is_closure(), closure_arg_span, - ) - }, - ) + )); + } + } + Ok(self.report_closure_arg_mismatch( + span, + found_span, + found_trait_ref, + expected_trait_ref, + obligation.cause.code(), + found_node, + obligation.param_env, + )) } /// Given some node representing a fn-like thing in the HIR map, diff --git a/tests/ui/coroutine/arg-count-mismatch-on-unit-input.rs b/tests/ui/coroutine/arg-count-mismatch-on-unit-input.rs new file mode 100644 index 0000000000000..448c7100df657 --- /dev/null +++ b/tests/ui/coroutine/arg-count-mismatch-on-unit-input.rs @@ -0,0 +1,11 @@ +#![feature(coroutines, coroutine_trait, stmt_expr_attributes)] + +use std::ops::Coroutine; + +fn foo() -> impl Coroutine { + //~^ ERROR type mismatch in coroutine arguments + #[coroutine] + |_: ()| {} +} + +fn main() { } diff --git a/tests/ui/coroutine/arg-count-mismatch-on-unit-input.stderr b/tests/ui/coroutine/arg-count-mismatch-on-unit-input.stderr new file mode 100644 index 0000000000000..c7d6507fd7940 --- /dev/null +++ b/tests/ui/coroutine/arg-count-mismatch-on-unit-input.stderr @@ -0,0 +1,15 @@ +error[E0631]: type mismatch in coroutine arguments + --> $DIR/arg-count-mismatch-on-unit-input.rs:5:13 + | +LL | fn foo() -> impl Coroutine { + | ^^^^^^^^^^^^^^^^^^ expected due to this +... +LL | |_: ()| {} + | ------- found signature defined here + | + = note: expected coroutine signature `fn(u8) -> _` + found coroutine signature `fn(()) -> _` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0631`. From 8f1ed9b2e2930ded9c273fec566131519205a866 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 25 Sep 2024 19:45:37 +0200 Subject: [PATCH 07/16] Utf8Chunks: add link to Utf8Chunk --- library/core/src/str/lossy.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index 3f31107acf050..e7677c8317a9f 100644 --- a/library/core/src/str/lossy.rs +++ b/library/core/src/str/lossy.rs @@ -8,6 +8,8 @@ impl [u8] { /// Creates an iterator over the contiguous valid UTF-8 ranges of this /// slice, and the non-UTF-8 fragments in between. /// + /// See the [`Utf8Chunk`] type for documenation of the items yielded by this iterator. + /// /// # Examples /// /// This function formats arbitrary but mostly-UTF-8 bytes into Rust source @@ -148,6 +150,8 @@ impl fmt::Debug for Debug<'_> { /// If you want a simple conversion from UTF-8 byte slices to string slices, /// [`from_utf8`] is easier to use. /// +/// See the [`Utf8Chunk`] type for documenation of the items yielded by this iterator. +/// /// [byteslice]: slice /// [`from_utf8`]: super::from_utf8 /// From afb7eef79aa6bfaa9249fe2a0dc7033a44eff063 Mon Sep 17 00:00:00 2001 From: Aleksei Romanov Date: Wed, 25 Sep 2024 22:44:54 +0300 Subject: [PATCH 08/16] Pass Module Analysis Manager to Standard Instrumentations --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 165fb7aa6c3d3..8f0b1b8127657 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -732,12 +732,7 @@ extern "C" LLVMRustResult LLVMRustOptimize( PTO.SLPVectorization = SLPVectorize; PTO.MergeFunctions = MergeFunctions; - // FIXME: We may want to expose this as an option. - bool DebugPassManager = false; - PassInstrumentationCallbacks PIC; - StandardInstrumentations SI(TheModule->getContext(), DebugPassManager); - SI.registerCallbacks(PIC); if (LlvmSelfProfiler) { LLVMSelfProfileInitializeCallbacks(PIC, LlvmSelfProfiler, @@ -784,6 +779,12 @@ extern "C" LLVMRustResult LLVMRustOptimize( CGSCCAnalysisManager CGAM; ModuleAnalysisManager MAM; + // FIXME: We may want to expose this as an option. + bool DebugPassManager = false; + + StandardInstrumentations SI(TheModule->getContext(), DebugPassManager); + SI.registerCallbacks(PIC, &MAM); + if (LLVMPluginsLen) { auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen); SmallVector Plugins; From a51b0a2adf0197dbe569f1eb83dbf1caa11096ca Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 25 Sep 2024 16:40:50 -0700 Subject: [PATCH 09/16] Use `mem::offset_of!` for `sockaddr_un.sun_path` --- library/std/src/os/unix/net/addr.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 79f2c365025b7..dcc1b5999dc67 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -18,12 +18,7 @@ mod libc { pub struct sockaddr_un; } -fn sun_path_offset(addr: &libc::sockaddr_un) -> usize { - // Work with an actual instance of the type since using a null pointer is UB - let base = (addr as *const libc::sockaddr_un).addr(); - let path = core::ptr::addr_of!(addr.sun_path).addr(); - path - base -} +const SUN_PATH_OFFSET: usize = mem::offset_of!(libc::sockaddr_un, sun_path); pub(super) fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> { // SAFETY: All zeros is a valid representation for `sockaddr_un`. @@ -53,7 +48,7 @@ pub(super) fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::s ptr::copy_nonoverlapping(bytes.as_ptr(), addr.sun_path.as_mut_ptr().cast(), bytes.len()) }; - let mut len = sun_path_offset(&addr) + bytes.len(); + let mut len = SUN_PATH_OFFSET + bytes.len(); match bytes.get(0) { Some(&0) | None => {} Some(_) => len += 1, @@ -114,13 +109,13 @@ impl SocketAddr { let sun_path: &[u8] = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&addr.sun_path) }; len = core::slice::memchr::memchr(0, sun_path) - .map_or(len, |new_len| (new_len + sun_path_offset(&addr)) as libc::socklen_t); + .map_or(len, |new_len| (new_len + SUN_PATH_OFFSET) as libc::socklen_t); } if len == 0 { // When there is a datagram from unnamed unix socket // linux returns zero bytes of address - len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address + len = SUN_PATH_OFFSET as libc::socklen_t; // i.e., zero-length address } else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t { return Err(io::const_io_error!( io::ErrorKind::InvalidInput, @@ -238,7 +233,7 @@ impl SocketAddr { } fn address(&self) -> AddressKind<'_> { - let len = self.len as usize - sun_path_offset(&self.addr); + let len = self.len as usize - SUN_PATH_OFFSET; let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) }; // macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses @@ -287,7 +282,7 @@ impl linux_ext::addr::SocketAddrExt for SocketAddr { addr.sun_path.as_mut_ptr().add(1) as *mut u8, name.len(), ); - let len = (sun_path_offset(&addr) + 1 + name.len()) as libc::socklen_t; + let len = (SUN_PATH_OFFSET + 1 + name.len()) as libc::socklen_t; SocketAddr::from_parts(addr, len) } } From 58921874cb2bc9ac1eb1ebcd6635d3611c0b6bb1 Mon Sep 17 00:00:00 2001 From: makai410 Date: Thu, 26 Sep 2024 10:18:18 +0800 Subject: [PATCH 10/16] Fix the misleading diagnostic for let_underscore_drop on type without Drop implementation --- compiler/rustc_lint/messages.ftl | 2 +- compiler/rustc_lint/src/let_underscore.rs | 2 +- tests/ui/lint/let_underscore/issue-119696-err-on-fn.rs | 2 +- tests/ui/lint/let_underscore/issue-119696-err-on-fn.stderr | 2 +- tests/ui/lint/let_underscore/issue-119697-extra-let.rs | 4 ++-- tests/ui/lint/let_underscore/issue-119697-extra-let.stderr | 4 ++-- tests/ui/lint/let_underscore/let_underscore_drop.rs | 2 +- tests/ui/lint/let_underscore/let_underscore_drop.stderr | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 375cfccbe9f71..a286ccb22c7a6 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -531,7 +531,7 @@ lint_non_binding_let_multi_suggestion = consider immediately dropping the value lint_non_binding_let_on_drop_type = - non-binding let on a type that implements `Drop` + non-binding let on a type that has a destructor lint_non_binding_let_on_sync_lock = non-binding let on a synchronization lock .label = this lock is not assigned to a binding and is immediately dropped diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs index a12a97ee5730e..abee9ee786993 100644 --- a/compiler/rustc_lint/src/let_underscore.rs +++ b/compiler/rustc_lint/src/let_underscore.rs @@ -51,7 +51,7 @@ declare_lint! { /// intent. pub LET_UNDERSCORE_DROP, Allow, - "non-binding let on a type that implements `Drop`" + "non-binding let on a type that has a destructor" } declare_lint! { diff --git a/tests/ui/lint/let_underscore/issue-119696-err-on-fn.rs b/tests/ui/lint/let_underscore/issue-119696-err-on-fn.rs index b885352dfd949..0973e2f1637d9 100644 --- a/tests/ui/lint/let_underscore/issue-119696-err-on-fn.rs +++ b/tests/ui/lint/let_underscore/issue-119696-err-on-fn.rs @@ -2,7 +2,7 @@ #![deny(let_underscore_drop)] fn main() { - let _ = foo(); //~ ERROR non-binding let on a type that implements `Drop` + let _ = foo(); //~ ERROR non-binding let on a type that has a destructor } async fn from_config(_: Config) {} diff --git a/tests/ui/lint/let_underscore/issue-119696-err-on-fn.stderr b/tests/ui/lint/let_underscore/issue-119696-err-on-fn.stderr index 86e521580b87a..70f9979556a3a 100644 --- a/tests/ui/lint/let_underscore/issue-119696-err-on-fn.stderr +++ b/tests/ui/lint/let_underscore/issue-119696-err-on-fn.stderr @@ -1,4 +1,4 @@ -error: non-binding let on a type that implements `Drop` +error: non-binding let on a type that has a destructor --> $DIR/issue-119696-err-on-fn.rs:5:5 | LL | let _ = foo(); diff --git a/tests/ui/lint/let_underscore/issue-119697-extra-let.rs b/tests/ui/lint/let_underscore/issue-119697-extra-let.rs index 1dc80a123f613..84abb933911f5 100644 --- a/tests/ui/lint/let_underscore/issue-119697-extra-let.rs +++ b/tests/ui/lint/let_underscore/issue-119697-extra-let.rs @@ -12,9 +12,9 @@ pub fn ice_cold(beverage: Tait) { // Must destructure at least one field of `Foo` let Foo { field } = beverage; // boom - _ = field; //~ ERROR non-binding let on a type that implements `Drop` + _ = field; //~ ERROR non-binding let on a type that has a destructor - let _ = field; //~ ERROR non-binding let on a type that implements `Drop` + let _ = field; //~ ERROR non-binding let on a type that has a destructor } diff --git a/tests/ui/lint/let_underscore/issue-119697-extra-let.stderr b/tests/ui/lint/let_underscore/issue-119697-extra-let.stderr index 16df2c720eaf2..e4b1872bba55a 100644 --- a/tests/ui/lint/let_underscore/issue-119697-extra-let.stderr +++ b/tests/ui/lint/let_underscore/issue-119697-extra-let.stderr @@ -1,4 +1,4 @@ -error: non-binding let on a type that implements `Drop` +error: non-binding let on a type that has a destructor --> $DIR/issue-119697-extra-let.rs:15:5 | LL | _ = field; @@ -18,7 +18,7 @@ help: consider immediately dropping the value LL | drop(field); | ~~~~~ + -error: non-binding let on a type that implements `Drop` +error: non-binding let on a type that has a destructor --> $DIR/issue-119697-extra-let.rs:17:5 | LL | let _ = field; diff --git a/tests/ui/lint/let_underscore/let_underscore_drop.rs b/tests/ui/lint/let_underscore/let_underscore_drop.rs index 58988ec05d79f..f5a5e4299a1ac 100644 --- a/tests/ui/lint/let_underscore/let_underscore_drop.rs +++ b/tests/ui/lint/let_underscore/let_underscore_drop.rs @@ -10,7 +10,7 @@ impl Drop for NontrivialDrop { } fn main() { - let _ = NontrivialDrop; //~WARNING non-binding let on a type that implements `Drop` + let _ = NontrivialDrop; //~WARNING non-binding let on a type that has a destructor let (_, _) = (NontrivialDrop, NontrivialDrop); // This should be ignored. } diff --git a/tests/ui/lint/let_underscore/let_underscore_drop.stderr b/tests/ui/lint/let_underscore/let_underscore_drop.stderr index 7b7de202e4626..09f2587063bb9 100644 --- a/tests/ui/lint/let_underscore/let_underscore_drop.stderr +++ b/tests/ui/lint/let_underscore/let_underscore_drop.stderr @@ -1,4 +1,4 @@ -warning: non-binding let on a type that implements `Drop` +warning: non-binding let on a type that has a destructor --> $DIR/let_underscore_drop.rs:13:5 | LL | let _ = NontrivialDrop; From 1bef68c4cb5e84ebcca5ed636a1a38460eb412dd Mon Sep 17 00:00:00 2001 From: Taiki Endo Date: Thu, 26 Sep 2024 12:52:35 +0900 Subject: [PATCH 11/16] Update FIXME comment in s390x_unknown_linux_*.rs --- .../rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs | 5 ++--- .../src/spec/targets/s390x_unknown_linux_musl.rs | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs index a8163e228e690..3efbb46483613 100644 --- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs @@ -6,9 +6,8 @@ pub(crate) fn target() -> Target { base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM base.cpu = "z10".into(); - // FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector - // ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we - // also strip v128 from the data_layout below to match the older LLVM's expectation. + // FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector + // ABI. Pass the -vector feature string to LLVM to respect this assumption. base.features = "-vector".into(); base.max_atomic_width = Some(128); base.min_global_align = Some(16); diff --git a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs index e52bcc987f9ba..65b5c1167bdd8 100644 --- a/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs +++ b/compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs @@ -6,9 +6,8 @@ pub(crate) fn target() -> Target { base.endian = Endian::Big; // z10 is the oldest CPU supported by LLVM base.cpu = "z10".into(); - // FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector - // ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we - // also strip v128 from the data_layout below to match the older LLVM's expectation. + // FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector + // ABI. Pass the -vector feature string to LLVM to respect this assumption. base.features = "-vector".into(); base.max_atomic_width = Some(128); base.min_global_align = Some(16); From cdd3371bb4fceb9931be48700f5a70de7819df7c Mon Sep 17 00:00:00 2001 From: zopsicle <50083900+zopsicle@users.noreply.github.com> Date: Thu, 26 Sep 2024 01:44:06 +0200 Subject: [PATCH 12/16] rustdoc: do not animate when user prefers reduced motion This accessibility improvement gates the target flashing and tooltip fade-out behind an inverted prefers-reduced-motion media query. --- src/librustdoc/html/static/css/rustdoc.css | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index ae9727a4d4f57..61e32aa5d3097 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1687,7 +1687,12 @@ instead, we check that it's not a "finger" cursor. padding-right: 3px; background-color: var(--target-background-color); border-right: 3px solid var(--target-border-color); - animation: 0.65s cubic-bezier(0, 0, 0.1, 1.0) 0.1s targetfadein; +} + +@media not (prefers-reduced-motion) { + :target { + animation: 0.65s cubic-bezier(0, 0, 0.1, 1.0) 0.1s targetfadein; + } } .code-header a.tooltip { @@ -1712,12 +1717,14 @@ a.tooltip:hover::after { content: "\00a0"; } -/* This animation is layered onto the mistake-proofing delay for dismissing - a hovered tooltip, to ensure it feels responsive even with the delay. - */ -.fade-out { - opacity: 0; - transition: opacity 0.45s cubic-bezier(0, 0, 0.1, 1.0); +@media not (prefers-reduced-motion) { + /* This animation is layered onto the mistake-proofing delay for dismissing + a hovered tooltip, to ensure it feels responsive even with the delay. + */ + .fade-out { + opacity: 0; + transition: opacity 0.45s cubic-bezier(0, 0, 0.1, 1.0); + } } .popover.tooltip .content { From ef87a7f663826b67cf47e147546ada7e1d081c46 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 26 Sep 2024 15:42:37 +0200 Subject: [PATCH 13/16] add missing FIXME(const-hack) --- library/core/src/ptr/alignment.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index ceb5906d226ef..50706fca5b0f8 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -155,7 +155,7 @@ impl Alignment { !(unsafe { self.as_usize().unchecked_sub(1) }) } - // Remove me once `Ord::max` is usable in const + // FIXME(const-hack) Remove me once `Ord::max` is usable in const pub(crate) const fn max(a: Self, b: Self) -> Self { if a.as_usize() > b.as_usize() { a } else { b } } From 9431d1ab4e7613a21790d7e95616e52f3b679957 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 26 Sep 2024 09:33:30 -0700 Subject: [PATCH 14/16] Add `sun_path` to the fake doc `sockaddr_un` --- library/std/src/os/unix/net/addr.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index dcc1b5999dc67..e0f3aea42b67b 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -15,7 +15,9 @@ mod libc { pub type socklen_t = u32; pub struct sockaddr; #[derive(Clone)] - pub struct sockaddr_un; + pub struct sockaddr_un { + pub sun_path: [u8; 1], + } } const SUN_PATH_OFFSET: usize = mem::offset_of!(libc::sockaddr_un, sun_path); From e29ff8c058d3bca10ae810de924417e96ed51b04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 26 Sep 2024 13:25:52 +0200 Subject: [PATCH 15/16] Pass correct HirId to late_bound_vars in diagnostic code --- .../src/fn_ctxt/suggestions.rs | 3 ++- tests/crashes/125655.rs | 8 ------ .../binder/closure-return-type-mismatch.rs | 15 +++++++++++ .../closure-return-type-mismatch.stderr | 25 +++++++++++++++++++ .../closures/closure-return-type-mismatch.rs | 4 +++ .../closure-return-type-mismatch.stderr | 10 +++++++- 6 files changed, 55 insertions(+), 10 deletions(-) delete mode 100644 tests/crashes/125655.rs create mode 100644 tests/ui/closures/binder/closure-return-type-mismatch.rs create mode 100644 tests/ui/closures/binder/closure-return-type-mismatch.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 5f89f7dedc2cc..487cc7e55cd9e 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -882,7 +882,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let ty = self.lowerer().lower_ty(hir_ty); debug!(?ty, "return type (lowered)"); debug!(?expected, "expected type"); - let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into()); + let bound_vars = + self.tcx.late_bound_vars(self.tcx.local_def_id_to_hir_id(fn_id)); let ty = Binder::bind_with_vars(ty, bound_vars); let ty = self.normalize(hir_ty.span, ty); let ty = self.tcx.instantiate_bound_regions_with_erased(ty); diff --git a/tests/crashes/125655.rs b/tests/crashes/125655.rs deleted file mode 100644 index fbf92ca22be7e..0000000000000 --- a/tests/crashes/125655.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ known-bug: rust-lang/rust#125655 - -fn main() { - static foo: dyn Fn() -> u32 = || -> u32 { - ... - 0 - }; -} diff --git a/tests/ui/closures/binder/closure-return-type-mismatch.rs b/tests/ui/closures/binder/closure-return-type-mismatch.rs new file mode 100644 index 0000000000000..398a4c43ee2eb --- /dev/null +++ b/tests/ui/closures/binder/closure-return-type-mismatch.rs @@ -0,0 +1,15 @@ +// We used to bind the closure return type `&'a ()` with the late-bound vars of +// the owner (here `main` & `env` resp.) instead of the ones of the enclosing +// function-like / closure inside diagnostic code which was incorrect. + +#![feature(closure_lifetime_binder)] + +// issue: rust-lang/rust#130391 +fn main() { + let _ = for<'a> |x: &'a u8| -> &'a () { x }; //~ ERROR mismatched types +} + +// issue: rust-lang/rust#130663 +fn env<'r>() { + let _ = for<'a> |x: &'a u8| -> &'a () { x }; //~ ERROR mismatched types +} diff --git a/tests/ui/closures/binder/closure-return-type-mismatch.stderr b/tests/ui/closures/binder/closure-return-type-mismatch.stderr new file mode 100644 index 0000000000000..67045654f995b --- /dev/null +++ b/tests/ui/closures/binder/closure-return-type-mismatch.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/closure-return-type-mismatch.rs:9:45 + | +LL | let _ = for<'a> |x: &'a u8| -> &'a () { x }; + | ------ ^ expected `&()`, found `&u8` + | | + | expected `&'a ()` because of return type + | + = note: expected reference `&'a ()` + found reference `&'a u8` + +error[E0308]: mismatched types + --> $DIR/closure-return-type-mismatch.rs:14:45 + | +LL | let _ = for<'a> |x: &'a u8| -> &'a () { x }; + | ------ ^ expected `&()`, found `&u8` + | | + | expected `&'a ()` because of return type + | + = note: expected reference `&'a ()` + found reference `&'a u8` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/closures/closure-return-type-mismatch.rs b/tests/ui/closures/closure-return-type-mismatch.rs index 1631bb303e54e..e5cda1659de40 100644 --- a/tests/ui/closures/closure-return-type-mismatch.rs +++ b/tests/ui/closures/closure-return-type-mismatch.rs @@ -15,3 +15,7 @@ fn main() { b }; } + +// issue: rust-lang/rust#130858 rust-lang/rust#125655 +static FOO: fn() -> bool = || -> bool { 1 }; +//~^ ERROR mismatched types diff --git a/tests/ui/closures/closure-return-type-mismatch.stderr b/tests/ui/closures/closure-return-type-mismatch.stderr index 3a2f098d1efb3..052bbbb5ed579 100644 --- a/tests/ui/closures/closure-return-type-mismatch.stderr +++ b/tests/ui/closures/closure-return-type-mismatch.stderr @@ -1,3 +1,11 @@ +error[E0308]: mismatched types + --> $DIR/closure-return-type-mismatch.rs:20:41 + | +LL | static FOO: fn() -> bool = || -> bool { 1 }; + | ---- ^ expected `bool`, found integer + | | + | expected `bool` because of return type + error[E0308]: mismatched types --> $DIR/closure-return-type-mismatch.rs:7:9 | @@ -19,6 +27,6 @@ LL | if false { LL | return "hello" | ^^^^^^^ expected `bool`, found `&str` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0308`. From 5b5848188d4b3e0652267d56d8e0ec8de34eaa89 Mon Sep 17 00:00:00 2001 From: zopsicle Date: Thu, 26 Sep 2024 23:59:13 +0200 Subject: [PATCH 16/16] rustdoc: consolidate prefers-reduced-motion-gated rulesets --- src/librustdoc/html/static/css/rustdoc.css | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 61e32aa5d3097..40391b1b4dfee 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -1689,12 +1689,6 @@ instead, we check that it's not a "finger" cursor. border-right: 3px solid var(--target-border-color); } -@media not (prefers-reduced-motion) { - :target { - animation: 0.65s cubic-bezier(0, 0, 0.1, 1.0) 0.1s targetfadein; - } -} - .code-header a.tooltip { color: inherit; margin-right: 15px; @@ -1718,6 +1712,10 @@ a.tooltip:hover::after { } @media not (prefers-reduced-motion) { + :target { + animation: 0.65s cubic-bezier(0, 0, 0.1, 1.0) 0.1s targetfadein; + } + /* This animation is layered onto the mistake-proofing delay for dismissing a hovered tooltip, to ensure it feels responsive even with the delay. */