Auto merge of #140859 - pietroalbini:pa-stable, r=pietroalbini

[stable] Prepare the 1.87.0 release

Preparing the stable artifacts as described in the release process.

This PR also includes the following last minute backports:

* https://github.com/rust-lang/rust/pull/140810
* https://github.com/rust-lang/rust/pull/140601
* https://github.com/rust-lang/rust/pull/140684

r? `@ghost`
This commit is contained in:
bors 2025-05-09 20:37:37 +00:00
commit 17067e9ac6
24 changed files with 551 additions and 139 deletions

View file

@ -1,3 +1,292 @@
Version 1.87.0 (2025-05-15)
==========================
<a id="1.87.0-Language"></a>
Language
--------
- [Stabilize `asm_goto` feature](https://github.com/rust-lang/rust/pull/133870)
- [Allow parsing open beginning ranges (`..EXPR`) after unary operators `!`, `~`, `-`, and `*`}](https://github.com/rust-lang/rust/pull/134900).
- [Don't require method impls for methods with `Self: Sized` bounds in `impl`s for unsized types](https://github.com/rust-lang/rust/pull/135480)
- [Stabilize `feature(precise_capturing_in_traits)` allowing `use<...>` bounds on return position `impl Trait` in `trait`s](https://github.com/rust-lang/rust/pull/138128)
<a id="1.87.0-Compiler"></a>
Compiler
--------
- [x86: make SSE2 required for i686 targets and use it to pass SIMD types](https://github.com/rust-lang/rust/pull/135408)
<a id="1.87.0-Platform-Support"></a>
Platform Support
----------------
- [Remove `i586-pc-windows-msvc` target](https://github.com/rust-lang/rust/pull/137957)
Refer to Rust's [platform support page][platform-support-doc]
for more information on Rust's tiered platform support.
[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html
<a id="1.87.0-Libraries"></a>
Libraries
---------
- [Stabilize the anonymous pipe API](https://github.com/rust-lang/rust/issues/127154)
- [Add support for unbounded left/right shift operations](https://github.com/rust-lang/rust/issues/129375)
- [Print pointer metadata in `Debug` impl of raw pointers](https://github.com/rust-lang/rust/pull/135080)
- [`Vec::with_capacity` guarantees it allocates with the amount requested, even if `Vec::capacity` returns a different number.](https://github.com/rust-lang/rust/pull/135933)
- Most `std::arch` intrinsics which don't take pointer arguments can now be called from safe code if the caller has the appropriate target features already enabled (https://github.com/rust-lang/stdarch/pull/1714, https://github.com/rust-lang/stdarch/pull/1716, https://github.com/rust-lang/stdarch/pull/1717)
- [Undeprecate `env::home_dir`](https://github.com/rust-lang/rust/pull/137327)
- [Denote `ControlFlow` as `#[must_use]`](https://github.com/rust-lang/rust/pull/137449)
- [Macros such as `assert_eq!` and `vec!` now support `const {...}` expressions](https://github.com/rust-lang/rust/pull/138162)
<a id="1.87.0-Stabilized-APIs"></a>
Stabilized APIs
---------------
- [`Vec::extract_if`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.extract_if)
- [`vec::ExtractIf`](https://doc.rust-lang.org/stable/std/vec/struct.ExtractIf.html)
- [`LinkedList::extract_if`](https://doc.rust-lang.org/stable/std/collections/struct.LinkedList.html#method.extract_if)
- [`linked_list::ExtractIf`](https://doc.rust-lang.org/stable/std/collections/linked_list/struct.ExtractIf.html)
- [`<[T]>::split_off`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off)
- [`<[T]>::split_off_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_mut)
- [`<[T]>::split_off_first`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_first)
- [`<[T]>::split_off_first_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_first_mut)
- [`<[T]>::split_off_last`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_last)
- [`<[T]>::split_off_last_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.split_off_last_mut)
- [`String::extend_from_within`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.extend_from_within)
- [`os_str::Display`](https://doc.rust-lang.org/stable/std/ffi/os_str/struct.Display.html)
- [`OsString::display`](https://doc.rust-lang.org/stable/std/ffi/struct.OsString.html#method.display)
- [`OsStr::display`](https://doc.rust-lang.org/stable/std/ffi/struct.OsStr.html#method.display)
- [`io::pipe`](https://doc.rust-lang.org/stable/std/io/fn.pipe.html)
- [`io::PipeReader`](https://doc.rust-lang.org/stable/std/io/struct.PipeReader.html)
- [`io::PipeWriter`](https://doc.rust-lang.org/stable/std/io/struct.PipeWriter.html)
- [`impl From<PipeReader> for OwnedHandle`](https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeReader%3E-for-OwnedHandle)
- [`impl From<PipeWriter> for OwnedHandle`](https://doc.rust-lang.org/stable/std/os/windows/io/struct.OwnedHandle.html#impl-From%3CPipeWriter%3E-for-OwnedHandle)
- [`impl From<PipeReader> for Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html)
- [`impl From<PipeWriter> for Stdio`](https://doc.rust-lang.org/stable/std/process/struct.Stdio.html#impl-From%3CPipeWriter%3E-for-Stdio)
- [`impl From<PipeReader> for OwnedFd`](https://doc.rust-lang.org/stable/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeReader%3E-for-OwnedFd)
- [`impl From<PipeWriter> for OwnedFd`](https://doc.rust-lang.org/stable/std/os/fd/struct.OwnedFd.html#impl-From%3CPipeWriter%3E-for-OwnedFd)
- [`Box<MaybeUninit<T>>::write`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.write)
- [`impl TryFrom<Vec<u8>> for String`](https://doc.rust-lang.org/stable/std/string/struct.String.html#impl-TryFrom%3CVec%3Cu8%3E%3E-for-String)
- [`<*const T>::offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from_unsigned)
- [`<*const T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.byte_offset_from_unsigned)
- [`<*mut T>::offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.offset_from_unsigned-1)
- [`<*mut T>::byte_offset_from_unsigned`](https://doc.rust-lang.org/stable/std/primitive.pointer.html#method.byte_offset_from_unsigned-1)
- [`NonNull::offset_from_unsigned`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.offset_from_unsigned)
- [`NonNull::byte_offset_from_unsigned`](https://doc.rust-lang.org/stable/std/ptr/struct.NonNull.html#method.byte_offset_from_unsigned)
- [`<uN>::cast_signed`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.cast_signed)
- [`NonZero::<uN>::cast_signed`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.cast_signed-5).
- [`<iN>::cast_unsigned`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.cast_unsigned).
- [`NonZero::<iN>::cast_unsigned`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.cast_unsigned-5).
- [`<uN>::is_multiple_of`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.is_multiple_of)
- [`<uN>::unbounded_shl`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.unbounded_shl)
- [`<uN>::unbounded_shr`](https://doc.rust-lang.org/stable/std/primitive.usize.html#method.unbounded_shr)
- [`<iN>::unbounded_shl`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.unbounded_shl)
- [`<iN>::unbounded_shr`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.unbounded_shr)
- [`<iN>::midpoint`](https://doc.rust-lang.org/stable/std/primitive.isize.html#method.midpoint)
- [`<str>::from_utf8`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8)
- [`<str>::from_utf8_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8_mut)
- [`<str>::from_utf8_unchecked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8_unchecked)
- [`<str>::from_utf8_unchecked_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.from_utf8_unchecked_mut)
These previously stable APIs are now stable in const contexts:
- [`core::str::from_utf8_mut`](https://doc.rust-lang.org/stable/std/str/fn.from_utf8_mut.html)
- [`<[T]>::copy_from_slice`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.copy_from_slice)
- [`SocketAddr::set_ip`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.set_ip)
- [`SocketAddr::set_port`](https://doc.rust-lang.org/stable/std/net/enum.SocketAddr.html#method.set_port),
- [`SocketAddrV4::set_ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.set_ip)
- [`SocketAddrV4::set_port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV4.html#method.set_port),
- [`SocketAddrV6::set_ip`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_ip)
- [`SocketAddrV6::set_port`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_port)
- [`SocketAddrV6::set_flowinfo`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_flowinfo)
- [`SocketAddrV6::set_scope_id`](https://doc.rust-lang.org/stable/std/net/struct.SocketAddrV6.html#method.set_scope_id)
- [`char::is_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_digit)
- [`char::is_whitespace`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_whitespace)
- [`<[[T; N]]>::as_flattened`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_flattened)
- [`<[[T; N]]>::as_flattened_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_flattened_mut)
- [`String::into_bytes`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.into_bytes)
- [`String::as_str`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_str)
- [`String::capacity`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.capacity)
- [`String::as_bytes`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_bytes)
- [`String::len`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.len)
- [`String::is_empty`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.is_empty)
- [`String::as_mut_str`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_mut_str)
- [`String::as_mut_vec`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_mut_vec)
- [`Vec::as_ptr`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_ptr)
- [`Vec::as_slice`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_slice)
- [`Vec::capacity`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.capacity)
- [`Vec::len`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.len)
- [`Vec::is_empty`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.is_empty)
- [`Vec::as_mut_slice`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_mut_slice)
- [`Vec::as_mut_ptr`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.as_mut_ptr)
<a id="1.87.0-Cargo"></a>
Cargo
-----
- [Add terminal integration via ANSI OSC 9;4 sequences](https://github.com/rust-lang/cargo/pull/14615/)
- [chore: bump openssl to v3](https://github.com/rust-lang/cargo/pull/15232/)
- [feat(package): add --exclude-lockfile flag](https://github.com/rust-lang/cargo/pull/15234/)
<a id="1.87.0-Compatibility-Notes"></a>
Compatibility Notes
-------------------
- [Rust now raises an error for macro invocations inside the `#![crate_name]` attribute](https://github.com/rust-lang/rust/pull/127581)
- [Unstable fields are now always considered to be inhabited](https://github.com/rust-lang/rust/pull/133889)
- [Macro arguments of unary operators followed by open beginning ranges may now be matched differently](https://github.com/rust-lang/rust/pull/134900)
- [Make `Debug` impl of raw pointers print metadata if present](https://github.com/rust-lang/rust/pull/135080)
- [Warn against function pointers using unsupported ABI strings in dependencies](https://github.com/rust-lang/rust/pull/135767)
- [Associated types on `dyn` types are no longer deduplicated](https://github.com/rust-lang/rust/pull/136458)
- [Forbid attributes on `..` inside of struct patterns (`let Struct { #[attribute] .. }) =`](https://github.com/rust-lang/rust/pull/136490)
- [Make `ptr_cast_add_auto_to_object` lint into hard error](https://github.com/rust-lang/rust/pull/136764)
- Many `std::arch` intrinsics are now safe to call in some contexts, there may now be new `unused_unsafe` warnings in existing codebases.
- [Limit `width` and `precision` formatting options to 16 bits on all targets](https://github.com/rust-lang/rust/pull/136932)
- [Turn order dependent trait objects future incompat warning into a hard error](https://github.com/rust-lang/rust/pull/136968)
- [Denote `ControlFlow` as `#[must_use]`](https://github.com/rust-lang/rust/pull/137449)
- [Windows: The standard library no longer links `advapi32`, except on win7.](https://github.com/rust-lang/rust/pull/138233) Code such as C libraries that were relying on this assumption may need to explicitly link advapi32.
- [Proc macros can no longer observe expanded `cfg(true)` attributes.](https://github.com/rust-lang/rust/pull/138844)
- [Start changing the internal representation of pasted tokens](https://github.com/rust-lang/rust/pull/124141). Certain invalid declarative macros that were previously accepted in obscure circumstances are now correctly rejected by the compiler. Use of a `tt` fragment specifier can often fix these macros.
- [Don't allow flattened format_args in const.](https://github.com/rust-lang/rust/pull/139624)
<a id="1.87.0-Internal-Changes"></a>
Internal Changes
----------------
These changes do not affect any public interfaces of Rust, but they represent
significant improvements to the performance or internals of rustc and related
tools.
- [Update to LLVM 20](https://github.com/rust-lang/rust/pull/135763)
Version 1.86.0 (2025-04-03)
==========================
<a id="1.86.0-Language"></a>
Language
--------
- [Stabilize upcasting trait objects to supertraits.](https://github.com/rust-lang/rust/pull/134367)
- [Allow safe functions to be marked with the `#[target_feature]` attribute.](https://github.com/rust-lang/rust/pull/134090)
- [The `missing_abi` lint now warns-by-default.](https://github.com/rust-lang/rust/pull/132397)
- Rust now lints about double negations, to catch cases that might have intended to be a prefix decrement operator (`--x`) as written in other languages. This was previously a clippy lint, `clippy::double_neg`, and is [now available directly in Rust as `double_negations`.](https://github.com/rust-lang/rust/pull/126604)
- [More pointers are now detected as definitely not-null based on their alignment in const eval.](https://github.com/rust-lang/rust/pull/133700)
- [Empty `repr()` attribute applied to invalid items are now correctly rejected.](https://github.com/rust-lang/rust/pull/133925)
- [Inner attributes `#![test]` and `#![rustfmt::skip]` are no longer accepted in more places than intended.](https://github.com/rust-lang/rust/pull/134276)
<a id="1.86.0-Compiler"></a>
Compiler
--------
- [Debug-assert that raw pointers are non-null on access.](https://github.com/rust-lang/rust/pull/134424)
- [Change `-O` to mean `-C opt-level=3` instead of `-C opt-level=2` to match Cargo's defaults.](https://github.com/rust-lang/rust/pull/135439)
- [Fix emission of `overflowing_literals` under certain macro environments.](https://github.com/rust-lang/rust/pull/136393)
<a id="1.86.0-Platform-Support"></a>
Platform Support
----------------
- [Replace `i686-unknown-redox` target with `i586-unknown-redox`.](https://github.com/rust-lang/rust/pull/136698)
- [Increase baseline CPU of `i686-unknown-hurd-gnu` to Pentium 4.](https://github.com/rust-lang/rust/pull/136700)
- New tier 3 targets:
- [`{aarch64-unknown,x86_64-pc}-nto-qnx710_iosock`](https://github.com/rust-lang/rust/pull/133631).
For supporting Neutrino QNX 7.1 with `io-socket` network stack.
- [`{aarch64-unknown,x86_64-pc}-nto-qnx800`](https://github.com/rust-lang/rust/pull/133631).
For supporting Neutrino QNX 8.0 (`no_std`-only).
- [`{x86_64,i686}-win7-windows-gnu`](https://github.com/rust-lang/rust/pull/134609).
Intended for backwards compatibility with Windows 7. `{x86_64,i686}-win7-windows-msvc` are the Windows MSVC counterparts that already exist as Tier 3 targets.
- [`amdgcn-amd-amdhsa`](https://github.com/rust-lang/rust/pull/134740).
- [`x86_64-pc-cygwin`](https://github.com/rust-lang/rust/pull/134999).
- [`{mips,mipsel}-mti-none-elf`](https://github.com/rust-lang/rust/pull/135074).
Initial bare-metal support.
- [`m68k-unknown-none-elf`](https://github.com/rust-lang/rust/pull/135085).
- [`armv7a-nuttx-{eabi,eabihf}`, `aarch64-unknown-nuttx`, and `thumbv7a-nuttx-{eabi,eabihf}`](https://github.com/rust-lang/rust/pull/135757).
Refer to Rust's [platform support page][platform-support-doc]
for more information on Rust's tiered platform support.
<a id="1.86.0-Libraries"></a>
Libraries
---------
- The type of `FromBytesWithNulError` in `CStr::from_bytes_with_nul(bytes: &[u8]) -> Result<&Self, FromBytesWithNulError>` was [changed from an opaque struct to an enum](https://github.com/rust-lang/rust/pull/134143), allowing users to examine why the conversion failed.
- [Remove `RustcDecodable` and `RustcEncodable`.](https://github.com/rust-lang/rust/pull/134272)
- [Deprecate libtest's `--logfile` option.](https://github.com/rust-lang/rust/pull/134283)
- [On recent versions of Windows, `std::fs::remove_file` will now remove read-only files.](https://github.com/rust-lang/rust/pull/134679)
<a id="1.86.0-Stabilized-APIs"></a>
Stabilized APIs
---------------
- [`{float}::next_down`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.next_down)
- [`{float}::next_up`](https://doc.rust-lang.org/stable/std/primitive.f64.html#method.next_up)
- [`<[_]>::get_disjoint_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_mut)
- [`<[_]>::get_disjoint_unchecked_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.get_disjoint_unchecked_mut)
- [`slice::GetDisjointMutError`](https://doc.rust-lang.org/stable/std/slice/enum.GetDisjointMutError.html)
- [`HashMap::get_disjoint_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.get_disjoint_mut)
- [`HashMap::get_disjoint_unchecked_mut`](https://doc.rust-lang.org/std/collections/hash_map/struct.HashMap.html#method.get_disjoint_unchecked_mut)
- [`NonZero::count_ones`](https://doc.rust-lang.org/stable/std/num/struct.NonZero.html#method.count_ones)
- [`Vec::pop_if`](https://doc.rust-lang.org/std/vec/struct.Vec.html#method.pop_if)
- [`sync::Once::wait`](https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.wait)
- [`sync::Once::wait_force`](https://doc.rust-lang.org/stable/std/sync/struct.Once.html#method.wait_force)
- [`sync::OnceLock::wait`](https://doc.rust-lang.org/stable/std/sync/struct.OnceLock.html#method.wait)
These APIs are now stable in const contexts:
- [`hint::black_box`](https://doc.rust-lang.org/stable/std/hint/fn.black_box.html)
- [`io::Cursor::get_mut`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.get_mut)
- [`io::Cursor::set_position`](https://doc.rust-lang.org/stable/std/io/struct.Cursor.html#method.set_position)
- [`str::is_char_boundary`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.is_char_boundary)
- [`str::split_at`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at)
- [`str::split_at_checked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_checked)
- [`str::split_at_mut`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_mut)
- [`str::split_at_mut_checked`](https://doc.rust-lang.org/stable/std/primitive.str.html#method.split_at_mut_checked)
<a id="1.86.0-Cargo"></a>
Cargo
-----
- [When merging, replace rather than combine configuration keys that refer to a program path and its arguments.](https://github.com/rust-lang/cargo/pull/15066/)
- [Error if both `--package` and `--workspace` are passed but the requested package is missing.](https://github.com/rust-lang/cargo/pull/15071/) This was previously silently ignored, which was considered a bug since missing packages should be reported.
- [Deprecate the token argument in `cargo login` to avoid shell history leaks.](https://github.com/rust-lang/cargo/pull/15057/)
- [Simplify the implementation of `SourceID` comparisons.](https://github.com/rust-lang/cargo/pull/14980/) This may potentially change behavior if the canonicalized URL compares differently in alternative registries.
<a id="1.86.0-Rustdoc"></a>
Rustdoc
-----
- [Add a sans-serif font setting.](https://github.com/rust-lang/rust/pull/133636)
<a id="1.86.0-Compatibility-Notes"></a>
Compatibility Notes
-------------------
- [The `wasm_c_abi` future compatibility warning is now a hard error.](https://github.com/rust-lang/rust/pull/133951)
Users of `wasm-bindgen` should upgrade to at least version 0.2.89, otherwise compilation will fail.
- [Remove long-deprecated no-op attributes `#![no_start]` and `#![crate_id]`.](https://github.com/rust-lang/rust/pull/134300)
- [The future incompatibility lint `cenum_impl_drop_cast` has been made into a hard error.](https://github.com/rust-lang/rust/pull/135964) This means it is now an error to cast a field-less enum to an integer if the enum implements `Drop`.
- [SSE2 is now required for "i686" 32-bit x86 hard-float targets; disabling it causes a warning that will become a hard error eventually.](https://github.com/rust-lang/rust/pull/137037)
To compile for pre-SSE2 32-bit x86, use a "i586" target instead.
<a id="1.86.0-Internal-Changes"></a>
Internal Changes
----------------
These changes do not affect any public interfaces of Rust, but they represent
significant improvements to the performance or internals of rustc and related
tools.
- [Build the rustc on AArch64 Linux with ThinLTO + PGO.](https://github.com/rust-lang/rust/pull/133807)
The ARM 64-bit compiler (AArch64) on Linux is now optimized with ThinLTO and PGO, similar to the optimizations we have already performed for the x86-64 compiler on Linux. This should make it up to 30% faster.
Version 1.85.1 (2025-03-18)
==========================

View file

@ -13,7 +13,7 @@ use rustc_ast_pretty::pprust;
use rustc_errors::DiagCtxtHandle;
use rustc_hir::{self as hir, AttrPath};
use rustc_span::symbol::{Ident, kw, sym};
use rustc_span::{ErrorGuaranteed, Span, Symbol};
use rustc_span::{Span, Symbol};
pub struct SegmentIterator<'a> {
offset: usize,
@ -176,7 +176,7 @@ impl<'a> ArgParser<'a> {
pub enum MetaItemOrLitParser<'a> {
MetaItemParser(MetaItemParser<'a>),
Lit(MetaItemLit),
Err(Span, ErrorGuaranteed),
Err(Span),
}
impl<'a> MetaItemOrLitParser<'a> {
@ -186,7 +186,7 @@ impl<'a> MetaItemOrLitParser<'a> {
generic_meta_item_parser.span()
}
MetaItemOrLitParser::Lit(meta_item_lit) => meta_item_lit.span,
MetaItemOrLitParser::Err(span, _) => *span,
MetaItemOrLitParser::Err(span) => *span,
}
}
@ -495,12 +495,9 @@ impl<'a> MetaItemListParserContext<'a> {
// where the macro didn't expand to a literal. An error is already given
// for this at this point, and then we do continue. This makes this path
// reachable...
let e = self.dcx.span_delayed_bug(
*span,
"expr in place where literal is expected (builtin attr parsing)",
);
return Some(MetaItemOrLitParser::Err(*span, e));
// NOTE: For backward compatibility we can't emit any error / delayed bug here (yet).
// See <https://github.com/rust-lang/rust/issues/140612>
return Some(MetaItemOrLitParser::Err(*span));
} else {
self.next_path()?
};

View file

@ -146,7 +146,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
let principal_trait = regular_traits.into_iter().next();
let mut needed_associated_types = vec![];
// A stable ordering of associated types from the principal trait and all its
// supertraits. We use this to ensure that different substitutions of a trait
// don't result in `dyn Trait` types with different projections lists, which
// can be unsound: <https://github.com/rust-lang/rust/pull/136458>.
// We achieve a stable ordering by walking over the unsubstituted principal
// trait ref.
let mut ordered_associated_types = vec![];
if let Some((principal_trait, ref spans)) = principal_trait {
let principal_trait = principal_trait.map_bound(|trait_pred| {
assert_eq!(trait_pred.polarity, ty::PredicatePolarity::Positive);
@ -171,16 +178,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
// FIXME(negative_bounds): Handle this correctly...
let trait_ref =
tcx.anonymize_bound_vars(bound_predicate.rebind(pred.trait_ref));
needed_associated_types.extend(
ordered_associated_types.extend(
tcx.associated_items(pred.trait_ref.def_id)
.in_definition_order()
// We only care about associated types.
.filter(|item| item.kind == ty::AssocKind::Type)
// No RPITITs -- they're not dyn-compatible for now.
.filter(|item| !item.is_impl_trait_in_trait())
// If the associated type has a `where Self: Sized` bound,
// we do not need to constrain the associated type.
.filter(|item| !tcx.generics_require_sized_self(item.def_id))
.map(|item| (item.def_id, trait_ref)),
);
}
@ -252,14 +256,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
}
}
// We compute the list of projection bounds taking the ordered associated types,
// and check if there was an entry in the collected `projection_bounds`. Those
// are computed by first taking the user-written associated types, then elaborating
// the principal trait ref, and only using those if there was no user-written.
// See note below about how we handle missing associated types with `Self: Sized`,
// which are not required to be provided, but are still used if they are provided.
let mut missing_assoc_types = FxIndexSet::default();
let projection_bounds: Vec<_> = needed_associated_types
let projection_bounds: Vec<_> = ordered_associated_types
.into_iter()
.filter_map(|key| {
if let Some(assoc) = projection_bounds.get(&key) {
Some(*assoc)
} else {
missing_assoc_types.insert(key);
// If the associated type has a `where Self: Sized` bound, then
// we do not need to provide the associated type. This results in
// a `dyn Trait` type that has a different number of projection
// bounds, which may lead to type mismatches.
if !tcx.generics_require_sized_self(key.0) {
missing_assoc_types.insert(key);
}
None
}
})

View file

@ -720,7 +720,10 @@ impl<'tcx> Ty<'tcx> {
repr: DynKind,
) -> Ty<'tcx> {
if cfg!(debug_assertions) {
let projection_count = obj.projection_bounds().count();
let projection_count = obj
.projection_bounds()
.filter(|item| !tcx.generics_require_sized_self(item.item_def_id()))
.count();
let expected_count: usize = obj
.principal_def_id()
.into_iter()

View file

@ -1 +1 @@
beta
stable

View file

@ -95,14 +95,13 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
return;
};
if then_search.is_key_used_and_no_copy || else_search.is_key_used_and_no_copy {
span_lint(cx, MAP_ENTRY, expr.span, lint_msg);
return;
}
if then_search.edits.is_empty() && else_search.edits.is_empty() {
// No insertions
return;
} else if then_search.is_key_used_and_no_copy || else_search.is_key_used_and_no_copy {
// If there are other uses of the key, and the key is not copy,
// we cannot perform a fix automatically, but continue to emit a lint.
None
} else if then_search.edits.is_empty() || else_search.edits.is_empty() {
// if .. { insert } else { .. } or if .. { .. } else { insert }
let ((then_str, entry_kind), else_str) = match (else_search.edits.is_empty(), contains_expr.negated) {
@ -123,10 +122,10 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
snippet_with_applicability(cx, then_expr.span, "{ .. }", &mut app),
),
};
format!(
Some(format!(
"if let {}::{entry_kind} = {map_str}.entry({key_str}) {then_str} else {else_str}",
map_ty.entry_path(),
)
))
} else {
// if .. { insert } else { insert }
let ((then_str, then_entry), (else_str, else_entry)) = if contains_expr.negated {
@ -142,13 +141,13 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
};
let indent_str = snippet_indent(cx, expr.span);
let indent_str = indent_str.as_deref().unwrap_or("");
format!(
Some(format!(
"match {map_str}.entry({key_str}) {{\n{indent_str} {entry}::{then_entry} => {}\n\
{indent_str} {entry}::{else_entry} => {}\n{indent_str}}}",
reindent_multiline(&then_str, true, Some(4 + indent_str.len())),
reindent_multiline(&else_str, true, Some(4 + indent_str.len())),
entry = map_ty.entry_path(),
)
))
}
} else {
if then_search.edits.is_empty() {
@ -163,17 +162,17 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
} else {
then_search.snippet_occupied(cx, then_expr.span, &mut app)
};
format!(
Some(format!(
"if let {}::{entry_kind} = {map_str}.entry({key_str}) {body_str}",
map_ty.entry_path(),
)
))
} else if let Some(insertion) = then_search.as_single_insertion() {
let value_str = snippet_with_context(cx, insertion.value.span, then_expr.span.ctxt(), "..", &mut app).0;
if contains_expr.negated {
if insertion.value.can_have_side_effects() {
format!("{map_str}.entry({key_str}).or_insert_with(|| {value_str});")
Some(format!("{map_str}.entry({key_str}).or_insert_with(|| {value_str});"))
} else {
format!("{map_str}.entry({key_str}).or_insert({value_str});")
Some(format!("{map_str}.entry({key_str}).or_insert({value_str});"))
}
} else {
// TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here.
@ -183,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
} else {
let block_str = then_search.snippet_closure(cx, then_expr.span, &mut app);
if contains_expr.negated {
format!("{map_str}.entry({key_str}).or_insert_with(|| {block_str});")
Some(format!("{map_str}.entry({key_str}).or_insert_with(|| {block_str});"))
} else {
// TODO: suggest using `if let Some(v) = map.get_mut(k) { .. }` here.
// This would need to be a different lint.
@ -192,7 +191,11 @@ impl<'tcx> LateLintPass<'tcx> for HashMapPass {
}
};
span_lint_and_sugg(cx, MAP_ENTRY, expr.span, lint_msg, "try", sugg, app);
if let Some(sugg) = sugg {
span_lint_and_sugg(cx, MAP_ENTRY, expr.span, lint_msg, "try", sugg, app);
} else {
span_lint(cx, MAP_ENTRY, expr.span, lint_msg);
}
}
}

View file

@ -85,7 +85,7 @@ fn is_variant_or_wildcard(cx: &LateContext<'_>, pat: &Pat<'_>, can_be_wild: bool
/// contains `Err(IDENT)`, `None` otherwise.
fn is_ok_or_err<'hir>(cx: &LateContext<'_>, pat: &Pat<'hir>) -> Option<(bool, &'hir Ident)> {
if let PatKind::TupleStruct(qpath, [arg], _) = &pat.kind
&& let PatKind::Binding(BindingMode::NONE, _, ident, _) = &arg.kind
&& let PatKind::Binding(BindingMode::NONE, _, ident, None) = &arg.kind
&& let res = cx.qpath_res(qpath, pat.hir_id)
&& let Res::Def(DefKind::Ctor(..), id) = res
&& let id @ Some(_) = cx.tcx.opt_parent(id)

View file

@ -786,9 +786,9 @@ fn check_ptr_eq<'tcx>(
}
// Remove one level of usize conversion if any
let (left, right) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
(Some(lhs), Some(rhs)) => (lhs, rhs),
_ => (left, right),
let (left, right, usize_peeled) = match (expr_as_cast_to_usize(cx, left), expr_as_cast_to_usize(cx, right)) {
(Some(lhs), Some(rhs)) => (lhs, rhs, true),
_ => (left, right, false),
};
// This lint concerns raw pointers
@ -797,10 +797,16 @@ fn check_ptr_eq<'tcx>(
return;
}
let (left_var, right_var) = (peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
let ((left_var, left_casts_peeled), (right_var, right_casts_peeled)) =
(peel_raw_casts(cx, left, left_ty), peel_raw_casts(cx, right, right_ty));
if let Some(left_snip) = left_var.span.get_source_text(cx)
&& let Some(right_snip) = right_var.span.get_source_text(cx)
if !(usize_peeled || left_casts_peeled || right_casts_peeled) {
return;
}
let mut app = Applicability::MachineApplicable;
let left_snip = Sugg::hir_with_context(cx, left_var, expr.span.ctxt(), "_", &mut app);
let right_snip = Sugg::hir_with_context(cx, right_var, expr.span.ctxt(), "_", &mut app);
{
let Some(top_crate) = std_or_core(cx) else { return };
let invert = if op == BinOpKind::Eq { "" } else { "!" };
@ -811,7 +817,7 @@ fn check_ptr_eq<'tcx>(
format!("use `{top_crate}::ptr::eq` when comparing raw pointers"),
"try",
format!("{invert}{top_crate}::ptr::eq({left_snip}, {right_snip})"),
Applicability::MachineApplicable,
app,
);
}
}
@ -819,7 +825,8 @@ fn check_ptr_eq<'tcx>(
// If the given expression is a cast to a usize, return the lhs of the cast
// E.g., `foo as *const _ as usize` returns `foo as *const _`.
fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>) -> Option<&'tcx Expr<'tcx>> {
if cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize
if !cast_expr.span.from_expansion()
&& cx.typeck_results().expr_ty(cast_expr) == cx.tcx.types.usize
&& let ExprKind::Cast(expr, _) = cast_expr.kind
{
Some(expr)
@ -828,16 +835,18 @@ fn expr_as_cast_to_usize<'tcx>(cx: &LateContext<'tcx>, cast_expr: &'tcx Expr<'_>
}
}
// Peel raw casts if the remaining expression can be coerced to it
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> &'tcx Expr<'tcx> {
if let ExprKind::Cast(inner, _) = expr.kind
// Peel raw casts if the remaining expression can be coerced to it, and whether casts have been
// peeled or not.
fn peel_raw_casts<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, expr_ty: Ty<'tcx>) -> (&'tcx Expr<'tcx>, bool) {
if !expr.span.from_expansion()
&& let ExprKind::Cast(inner, _) = expr.kind
&& let ty::RawPtr(target_ty, _) = expr_ty.kind()
&& let inner_ty = cx.typeck_results().expr_ty(inner)
&& let ty::RawPtr(inner_target_ty, _) | ty::Ref(_, inner_target_ty, _) = inner_ty.kind()
&& target_ty == inner_target_ty
{
peel_raw_casts(cx, inner, inner_ty)
(peel_raw_casts(cx, inner, inner_ty).0, true)
} else {
expr
(expr, false)
}
}

View file

@ -226,4 +226,26 @@ fn issue11976() {
}
}
mod issue14449 {
use std::collections::BTreeMap;
pub struct Meow {
map: BTreeMap<String, String>,
}
impl Meow {
fn pet(&self, _key: &str, _v: u32) -> u32 {
42
}
}
pub fn f(meow: &Meow, x: String) {
if meow.map.contains_key(&x) {
let _ = meow.pet(&x, 1);
} else {
let _ = meow.pet(&x, 0);
}
}
}
fn main() {}

View file

@ -232,4 +232,26 @@ fn issue11976() {
}
}
mod issue14449 {
use std::collections::BTreeMap;
pub struct Meow {
map: BTreeMap<String, String>,
}
impl Meow {
fn pet(&self, _key: &str, _v: u32) -> u32 {
42
}
}
pub fn f(meow: &Meow, x: String) {
if meow.map.contains_key(&x) {
let _ = meow.pet(&x, 1);
} else {
let _ = meow.pet(&x, 0);
}
}
}
fn main() {}

View file

@ -80,6 +80,11 @@ fn no_lint() {
Ok(3) => None,
Ok(v) => Some(v),
};
let _ = match funcall() {
Ok(v @ 1..) => Some(v),
_ => None,
};
}
const fn cf(x: Result<u32, &'static str>) -> Option<u32> {

View file

@ -116,6 +116,11 @@ fn no_lint() {
Ok(3) => None,
Ok(v) => Some(v),
};
let _ = match funcall() {
Ok(v @ 1..) => Some(v),
_ => None,
};
}
const fn cf(x: Result<u32, &'static str>) -> Option<u32> {

View file

@ -94,7 +94,7 @@ LL | | };
| |_____^ help: replace with: `(-S).ok()`
error: manual implementation of `ok`
--> tests/ui/manual_ok_err.rs:132:12
--> tests/ui/manual_ok_err.rs:137:12
|
LL | } else if let Ok(n) = "1".parse::<u8>() {
| ____________^

View file

@ -4,6 +4,9 @@ macro_rules! mac {
($a:expr, $b:expr) => {
$a as *const _ as usize == $b as *const _ as usize
};
(cast $a:expr) => {
$a as *const [i32; 3]
};
}
macro_rules! another_mac {
@ -20,23 +23,25 @@ fn main() {
//~^ ptr_eq
let _ = std::ptr::eq(a, b);
//~^ ptr_eq
let _ = std::ptr::eq(a.as_ptr(), b as *const _);
//~^ ptr_eq
let _ = std::ptr::eq(a.as_ptr(), b.as_ptr());
//~^ ptr_eq
// Do not lint: the rhs conversion is needed
let _ = a.as_ptr() == b as *const _;
// Do not lint: we have two raw pointers already
let _ = a.as_ptr() == b.as_ptr();
// Do not lint
let _ = mac!(a, b);
let _ = another_mac!(a, b);
let a = &mut [1, 2, 3];
let b = &mut [1, 2, 3];
let _ = std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _);
//~^ ptr_eq
let _ = std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr());
//~^ ptr_eq
// Do not lint: the rhs conversion is needed
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
// Do not lint: we have two raw pointers already
let _ = a.as_mut_ptr() == b.as_mut_ptr();
let _ = a == b;
let _ = core::ptr::eq(a, b);
@ -48,7 +53,11 @@ fn main() {
let _ = !std::ptr::eq(x, y);
//~^ ptr_eq
#[allow(clippy::eq_op)]
let _issue14337 = std::ptr::eq(main as *const (), main as *const ());
#[expect(clippy::eq_op)]
// Do not lint: casts are needed to not change type
let _issue14337 = main as *const () == main as *const ();
// Do not peel the content of macros
let _ = std::ptr::eq(mac!(cast a), mac!(cast b));
//~^ ptr_eq
}

View file

@ -4,6 +4,9 @@ macro_rules! mac {
($a:expr, $b:expr) => {
$a as *const _ as usize == $b as *const _ as usize
};
(cast $a:expr) => {
$a as *const [i32; 3]
};
}
macro_rules! another_mac {
@ -20,23 +23,25 @@ fn main() {
//~^ ptr_eq
let _ = a as *const _ == b as *const _;
//~^ ptr_eq
// Do not lint: the rhs conversion is needed
let _ = a.as_ptr() == b as *const _;
//~^ ptr_eq
// Do not lint: we have two raw pointers already
let _ = a.as_ptr() == b.as_ptr();
//~^ ptr_eq
// Do not lint
let _ = mac!(a, b);
let _ = another_mac!(a, b);
let a = &mut [1, 2, 3];
let b = &mut [1, 2, 3];
// Do not lint: the rhs conversion is needed
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
//~^ ptr_eq
// Do not lint: we have two raw pointers already
let _ = a.as_mut_ptr() == b.as_mut_ptr();
//~^ ptr_eq
let _ = a == b;
let _ = core::ptr::eq(a, b);
@ -48,7 +53,11 @@ fn main() {
let _ = x as *const u32 != y as *mut u32 as *const u32;
//~^ ptr_eq
#[allow(clippy::eq_op)]
#[expect(clippy::eq_op)]
// Do not lint: casts are needed to not change type
let _issue14337 = main as *const () == main as *const ();
// Do not peel the content of macros
let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
//~^ ptr_eq
}

View file

@ -1,5 +1,5 @@
error: use `std::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq.rs:19:13
--> tests/ui/ptr_eq.rs:22:13
|
LL | let _ = a as *const _ as usize == b as *const _ as usize;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)`
@ -8,52 +8,28 @@ LL | let _ = a as *const _ as usize == b as *const _ as usize;
= help: to override `-D warnings` add `#[allow(clippy::ptr_eq)]`
error: use `std::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq.rs:21:13
--> tests/ui/ptr_eq.rs:24:13
|
LL | let _ = a as *const _ == b as *const _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a, b)`
error: use `std::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq.rs:23:13
|
LL | let _ = a.as_ptr() == b as *const _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b as *const _)`
error: use `std::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq.rs:25:13
|
LL | let _ = a.as_ptr() == b.as_ptr();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_ptr(), b.as_ptr())`
error: use `std::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq.rs:36:13
|
LL | let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)`
error: use `std::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq.rs:38:13
|
LL | let _ = a.as_mut_ptr() == b.as_mut_ptr();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())`
error: use `std::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq.rs:45:13
--> tests/ui/ptr_eq.rs:50:13
|
LL | let _ = x as *const u32 == y as *mut u32 as *const u32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(x, y)`
error: use `std::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq.rs:48:13
--> tests/ui/ptr_eq.rs:53:13
|
LL | let _ = x as *const u32 != y as *mut u32 as *const u32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!std::ptr::eq(x, y)`
error: use `std::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq.rs:52:23
--> tests/ui/ptr_eq.rs:61:13
|
LL | let _issue14337 = main as *const () == main as *const ();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(main as *const (), main as *const ())`
LL | let _ = mac!(cast a) as *const _ == mac!(cast b) as *const _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::eq(mac!(cast a), mac!(cast b))`
error: aborting due to 9 previous errors
error: aborting due to 5 previous errors

View file

@ -32,23 +32,25 @@ fn main() {
//~^ ptr_eq
let _ = core::ptr::eq(a, b);
//~^ ptr_eq
let _ = core::ptr::eq(a.as_ptr(), b as *const _);
//~^ ptr_eq
let _ = core::ptr::eq(a.as_ptr(), b.as_ptr());
//~^ ptr_eq
// Do not lint: the rhs conversion is needed
let _ = a.as_ptr() == b as *const _;
// Do not lint: we have two raw pointers already
let _ = a.as_ptr() == b.as_ptr();
// Do not lint
let _ = mac!(a, b);
let _ = another_mac!(a, b);
let a = &mut [1, 2, 3];
let b = &mut [1, 2, 3];
let _ = core::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _);
//~^ ptr_eq
let _ = core::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr());
//~^ ptr_eq
// Do not lint: the rhs conversion is needed
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
// Do not lint: we have two raw pointers already
let _ = a.as_mut_ptr() == b.as_mut_ptr();
let _ = a == b;
let _ = core::ptr::eq(a, b);

View file

@ -32,23 +32,25 @@ fn main() {
//~^ ptr_eq
let _ = a as *const _ == b as *const _;
//~^ ptr_eq
// Do not lint: the rhs conversion is needed
let _ = a.as_ptr() == b as *const _;
//~^ ptr_eq
// Do not lint: we have two raw pointers already
let _ = a.as_ptr() == b.as_ptr();
//~^ ptr_eq
// Do not lint
let _ = mac!(a, b);
let _ = another_mac!(a, b);
let a = &mut [1, 2, 3];
let b = &mut [1, 2, 3];
// Do not lint: the rhs conversion is needed
let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
//~^ ptr_eq
// Do not lint: we have two raw pointers already
let _ = a.as_mut_ptr() == b.as_mut_ptr();
//~^ ptr_eq
let _ = a == b;
let _ = core::ptr::eq(a, b);

View file

@ -13,29 +13,5 @@ error: use `core::ptr::eq` when comparing raw pointers
LL | let _ = a as *const _ == b as *const _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a, b)`
error: use `core::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq_no_std.rs:35:13
|
LL | let _ = a.as_ptr() == b as *const _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_ptr(), b as *const _)`
error: use `core::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq_no_std.rs:37:13
|
LL | let _ = a.as_ptr() == b.as_ptr();
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_ptr(), b.as_ptr())`
error: use `core::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq_no_std.rs:48:13
|
LL | let _ = a.as_mut_ptr() == b as *mut [i32] as *mut _;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_mut_ptr(), b as *mut [i32] as *mut _)`
error: use `core::ptr::eq` when comparing raw pointers
--> tests/ui/ptr_eq_no_std.rs:50:13
|
LL | let _ = a.as_mut_ptr() == b.as_mut_ptr();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `core::ptr::eq(a.as_mut_ptr(), b.as_mut_ptr())`
error: aborting due to 6 previous errors
error: aborting due to 2 previous errors

View file

@ -0,0 +1,8 @@
extern crate proc_macro;
use proc_macro::TokenStream;
#[proc_macro_derive(Derive, attributes(arg))]
pub fn derive(_: TokenStream) -> TokenStream {
TokenStream::new()
}

View file

@ -0,0 +1,16 @@
// Regression test for <https://github.com/rust-lang/rust/issues/137687#issuecomment-2816312274>.
//@ proc-macro: derive_macro_with_helper.rs
//@ edition: 2018
//@ check-pass
macro_rules! call_macro {
($text:expr) => {
#[derive(derive_macro_with_helper::Derive)]
#[arg($text)]
pub struct Foo;
};
}
call_macro!(1 + 1);
fn main() {}

View file

@ -0,0 +1,24 @@
//@ check-pass
// Regression test for <https://github.com/rust-lang/rust/issues/140645>.
// Test that we lower impossible-to-satisfy associated type bounds, which
// may for example constrain impl parameters.
pub trait Other {}
pub trait Trait {
type Assoc
where
Self: Sized;
}
impl Other for dyn Trait {}
// `dyn Trait<Assoc = ()>` is a different "nominal type" than `dyn Trait`.
impl Other for dyn Trait<Assoc = ()> {}
//~^ WARN unnecessary associated type bound for dyn-incompatible associated type
// I hope it's clear that `dyn Trait` (w/o `Assoc`) wouldn't match this impl.
impl<T> dyn Trait<Assoc = T> {}
//~^ WARN unnecessary associated type bound for dyn-incompatible associated type
fn main() {}

View file

@ -0,0 +1,19 @@
warning: unnecessary associated type bound for dyn-incompatible associated type
--> $DIR/constrain-via-unnecessary-bound.rs:17:26
|
LL | impl Other for dyn Trait<Assoc = ()> {}
| ^^^^^^^^^^ help: remove this bound
|
= note: this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized`
= note: `#[warn(unused_associated_type_bounds)]` on by default
warning: unnecessary associated type bound for dyn-incompatible associated type
--> $DIR/constrain-via-unnecessary-bound.rs:21:19
|
LL | impl<T> dyn Trait<Assoc = T> {}
| ^^^^^^^^^ help: remove this bound
|
= note: this associated type has a `where Self: Sized` bound, and while the associated type can be specified, it cannot be used because trait objects are never `Sized`
warning: 2 warnings emitted

View file

@ -154,12 +154,12 @@ error[E0308]: mismatched types
--> $DIR/pretty.rs:41:56
|
LL | fn dyn_has_gat(x: &dyn HasGat<u8, Assoc<bool> = ()>) { x }
| - ^ expected `()`, found `&dyn HasGat<u8>`
| - ^ expected `()`, found `&dyn HasGat<u8, Assoc<bool> = ()>`
| |
| help: try adding a return type: `-> &dyn HasGat<u8>`
| help: try adding a return type: `-> &dyn HasGat<u8, Assoc<bool> = ()>`
|
= note: expected unit type `()`
found reference `&dyn HasGat<u8>`
found reference `&dyn HasGat<u8, Assoc<bool> = ()>`
error: aborting due to 14 previous errors; 1 warning emitted