From 186ea6e1e6cbd0edf35ae6aca4abf441856f168f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Thu, 7 Aug 2025 10:41:43 +0200 Subject: [PATCH 01/15] Only run the pull workflow once per week --- src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml b/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml index 04d6469aeaa42..5ff3118960da6 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/rustc-pull.yml @@ -3,8 +3,8 @@ name: rustc-pull on: workflow_dispatch: schedule: - # Run at 04:00 UTC every Monday and Thursday - - cron: '0 4 * * 1,4' + # Run at 04:00 UTC every Monday + - cron: '0 4 * * 1' jobs: pull: From 9ade653e956e25c7a41d156d22b0de2cdd9ecb71 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Fri, 8 Aug 2025 15:58:53 -0700 Subject: [PATCH 02/15] Remove mentions of Discord. The official Discord server is no longer active (cannot be posted to). --- src/doc/rustc-dev-guide/src/about-this-guide.md | 1 - .../src/diagnostics/error-codes.md | 2 +- src/doc/rustc-dev-guide/src/getting-started.md | 17 +++++++---------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/about-this-guide.md b/src/doc/rustc-dev-guide/src/about-this-guide.md index 057e4a4cceed3..f3957724967c3 100644 --- a/src/doc/rustc-dev-guide/src/about-this-guide.md +++ b/src/doc/rustc-dev-guide/src/about-this-guide.md @@ -74,7 +74,6 @@ You might also find the following sites useful: of the team procedures, active working groups, and the team calendar. - [std-dev-guide] -- a similar guide for developing the standard library. - [The t-compiler zulip][z] -- `#contribute` and `#wg-rustup` on [Discord](https://discord.gg/rust-lang). - The [Rust Internals forum][rif], a place to ask questions and discuss Rust's internals - The [Rust reference][rr], even though it doesn't specifically talk about diff --git a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md index 1b6b87e4c8d50..1693432b90de7 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/error-codes.md @@ -20,7 +20,7 @@ explanations should help users understand why their code cannot be accepted by the compiler. Rust prides itself on helpful error messages and long-form explanations are no exception. However, before error explanations are overhauled[^new-explanations] it is a bit open as to how exactly they should be -written, as always: ask your reviewer or ask around on the Rust Discord or Zulip. +written, as always: ask your reviewer or ask around on the Rust Zulip. [^new-explanations]: See the draft RFC [here][new-explanations-rfc]. diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index 04d2e37732fa9..a4272a401d1b3 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -11,7 +11,6 @@ quick guide for the most useful things. For more information, [see this chapter on how to build and run the compiler](./building/how-to-build-and-run.md). [internals]: https://internals.rust-lang.org -[rust-discord]: http://discord.gg/rust-lang [rust-zulip]: https://rust-lang.zulipchat.com [coc]: https://www.rust-lang.org/policies/code-of-conduct [walkthrough]: ./walkthrough.md @@ -20,8 +19,7 @@ chapter on how to build and run the compiler](./building/how-to-build-and-run.md ## Asking Questions If you have questions, please make a post on the [Rust Zulip server][rust-zulip] or -[internals.rust-lang.org][internals]. If you are contributing to Rustup, be aware they are not on -Zulip - you can ask questions in `#wg-rustup` [on Discord][rust-discord]. +[internals.rust-lang.org][internals]. See the [list of teams and working groups][governance] and [the Community page][community] on the official website for more resources. @@ -30,10 +28,12 @@ official website for more resources. As a reminder, all contributors are expected to follow our [Code of Conduct][coc]. -The compiler team (or `t-compiler`) usually hangs out in Zulip [in this -"stream"][z]; it will be easiest to get questions answered there. +The compiler team (or `t-compiler`) usually hangs out in Zulip in +[the #t-compiler channel][z-t-compiler]; +questions about how the compiler works can go in [#t-compiler/help][z-help]. -[z]: https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler +[z-t-compiler]: https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler +[z-help]: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp **Please ask questions!** A lot of people report feeling that they are "wasting expert time", but nobody on `t-compiler` feels this way. Contributors are @@ -162,15 +162,12 @@ incredibly helpful: - [Triaging issues][triage]: categorizing, replicating, and minimizing issues is very helpful to the Rust maintainers. - [Working groups][wg]: there are a bunch of working groups on a wide variety of rust-related things. -- Answer questions in the _Get Help!_ channels on the [Rust Discord - server][rust-discord], on [users.rust-lang.org][users], or on - [StackOverflow][so]. +- Answer questions on [users.rust-lang.org][users], or on [Stack Overflow][so]. - Participate in the [RFC process](https://github.com/rust-lang/rfcs). - Find a [requested community library][community-library], build it, and publish it to [Crates.io](http://crates.io). Easier said than done, but very, very valuable! -[rust-discord]: https://discord.gg/rust-lang [users]: https://users.rust-lang.org/ [so]: http://stackoverflow.com/questions/tagged/rust [community-library]: https://github.com/rust-lang/rfcs/labels/A-community-library From c12f83e3acf3873876f0efdc4897d6012988a879 Mon Sep 17 00:00:00 2001 From: yukang Date: Mon, 11 Aug 2025 10:41:00 +0800 Subject: [PATCH 03/15] add a tip for english writing --- src/doc/rustc-dev-guide/src/getting-started.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/getting-started.md b/src/doc/rustc-dev-guide/src/getting-started.md index a4272a401d1b3..87e26d3796881 100644 --- a/src/doc/rustc-dev-guide/src/getting-started.md +++ b/src/doc/rustc-dev-guide/src/getting-started.md @@ -36,13 +36,15 @@ questions about how the compiler works can go in [#t-compiler/help][z-help]. [z-help]: https://rust-lang.zulipchat.com/#narrow/channel/182449-t-compiler.2Fhelp **Please ask questions!** A lot of people report feeling that they are "wasting -expert time", but nobody on `t-compiler` feels this way. Contributors are +expert's time", but nobody on `t-compiler` feels this way. Contributors are important to us. Also, if you feel comfortable, prefer public topics, as this means others can see the questions and answers, and perhaps even integrate them back into this guide :) +**Tip**: If you're not a native English speaker and feel unsure about writing, try using a translator to help. But avoid using LLM tools that generate long, complex words. In daily teamwork, **simple and clear words** are best for easy understanding. Even small typos or grammar mistakes can make you seem more human, and people connect better with humans. + ### Experts Not all `t-compiler` members are experts on all parts of `rustc`; it's a From 97564bd0707fb6928cea73ed7c61ffda87d1fb3a Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 11 Aug 2025 09:15:33 +0200 Subject: [PATCH 04/15] place link on the more suitable text Also, remove redundant word --- src/doc/rustc-dev-guide/src/git.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index 447c6fd454671..687830a723791 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -338,7 +338,7 @@ your fork with `git push --force-with-lease`. ### Keeping things up to date -The above section on [Rebasing](#rebasing) is a specific +The [above section](#rebasing) is a specific guide on rebasing work and dealing with merge conflicts. Here is some general advice about how to keep your local repo up-to-date with upstream changes: From 538299a6f5fb34239bd4992786a19e5bd728737c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 11 Aug 2025 09:20:01 +0200 Subject: [PATCH 05/15] fix grammar --- src/doc/rustc-dev-guide/src/git.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/git.md b/src/doc/rustc-dev-guide/src/git.md index 687830a723791..8f0511a4548af 100644 --- a/src/doc/rustc-dev-guide/src/git.md +++ b/src/doc/rustc-dev-guide/src/git.md @@ -344,7 +344,7 @@ Here is some general advice about how to keep your local repo up-to-date with upstream changes: Using `git pull upstream master` while on your local master branch regularly -will keep it up-to-date. You will also want to rebase your feature branches +will keep it up-to-date. You will also want to keep your feature branches up-to-date as well. After pulling, you can checkout the feature branches and rebase them: From a3510c7199806c153f927f25e2bff2c095aa60df Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Mon, 18 Aug 2025 04:22:18 +0000 Subject: [PATCH 06/15] Prepare for merging from rust-lang/rust This updates the rust-version file to 425a9c0a0e365c0b8c6cfd00c2ded83a73bed9a0. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 6ec700b9b4dc1..a399b5cd77e54 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -6bcdcc73bd11568fd85f5a38b58e1eda054ad1cd +425a9c0a0e365c0b8c6cfd00c2ded83a73bed9a0 From 06eb782c4e727c33d8548a791998a0a2cbedceae Mon Sep 17 00:00:00 2001 From: Connor Tsui Date: Fri, 22 Aug 2025 14:58:42 -0400 Subject: [PATCH 07/15] modify `LazyLock` poison panic message Fixes an issue where if the underlying `Once` panics because it is poisoned, the panic displays the wrong message. Signed-off-by: Connor Tsui --- library/std/src/sync/lazy_lock.rs | 9 ++-- library/std/tests/sync/lazy_lock.rs | 84 ++++++++++++++++++----------- 2 files changed, 59 insertions(+), 34 deletions(-) diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index a40e29a772a9c..3231125f7a13a 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -244,7 +244,11 @@ impl T> LazyLock { #[inline] #[stable(feature = "lazy_cell", since = "1.80.0")] pub fn force(this: &LazyLock) -> &T { - this.once.call_once(|| { + this.once.call_once_force(|state| { + if state.is_poisoned() { + panic_poisoned(); + } + // SAFETY: `call_once` only runs this closure once, ever. let data = unsafe { &mut *this.data.get() }; let f = unsafe { ManuallyDrop::take(&mut data.f) }; @@ -257,8 +261,7 @@ impl T> LazyLock { // * the closure was called and initialized `value`. // * the closure was called and panicked, so this point is never reached. // * the closure was not called, but a previous call initialized `value`. - // * the closure was not called because the Once is poisoned, so this point - // is never reached. + // * the closure was not called because the Once is poisoned, which we handled above. // So `value` has definitely been initialized and will not be modified again. unsafe { &*(*this.data.get()).value } } diff --git a/library/std/tests/sync/lazy_lock.rs b/library/std/tests/sync/lazy_lock.rs index 6c14b79f2ce7c..68aeea834b4fa 100644 --- a/library/std/tests/sync/lazy_lock.rs +++ b/library/std/tests/sync/lazy_lock.rs @@ -33,16 +33,6 @@ fn lazy_default() { assert_eq!(CALLED.load(SeqCst), 1); } -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn lazy_poisoning() { - let x: LazyCell = LazyCell::new(|| panic!("kaboom")); - for _ in 0..2 { - let res = panic::catch_unwind(panic::AssertUnwindSafe(|| x.len())); - assert!(res.is_err()); - } -} - #[test] #[cfg_attr(any(target_os = "emscripten", target_os = "wasi"), ignore)] // no threads fn sync_lazy_new() { @@ -123,16 +113,6 @@ fn static_sync_lazy_via_fn() { assert_eq!(xs(), &vec![1, 2, 3]); } -#[test] -#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] -fn sync_lazy_poisoning() { - let x: LazyLock = LazyLock::new(|| panic!("kaboom")); - for _ in 0..2 { - let res = panic::catch_unwind(|| x.len()); - assert!(res.is_err()); - } -} - // Check that we can infer `T` from closure's type. #[test] fn lazy_type_inference() { @@ -145,17 +125,6 @@ fn is_sync_send() { assert_traits::>(); } -#[test] -#[should_panic = "has previously been poisoned"] -fn lazy_force_mut_panic() { - let mut lazy = LazyLock::::new(|| panic!()); - panic::catch_unwind(panic::AssertUnwindSafe(|| { - let _ = LazyLock::force_mut(&mut lazy); - })) - .unwrap_err(); - let _ = &*lazy; -} - #[test] fn lazy_force_mut() { let s = "abc".to_owned(); @@ -165,3 +134,56 @@ fn lazy_force_mut() { p.clear(); LazyLock::force_mut(&mut lazy); } + +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +fn lazy_poisoning() { + let x: LazyCell = LazyCell::new(|| panic!("kaboom")); + for _ in 0..2 { + let res = panic::catch_unwind(panic::AssertUnwindSafe(|| x.len())); + assert!(res.is_err()); + } +} + +/// Verifies that when a `LazyLock` is poisoned, it panics with the correct error message ("LazyLock +/// instance has previously been poisoned") instead of the underlying `Once` error message. +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +#[should_panic(expected = "LazyLock instance has previously been poisoned")] +fn lazy_lock_deref_panic() { + let lazy: LazyLock = LazyLock::new(|| panic!("initialization failed")); + + // First access will panic during initialization. + let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { + let _ = &*lazy; + })); + + // Second access should panic with the poisoned message. + let _ = &*lazy; +} + +#[test] +#[should_panic(expected = "LazyLock instance has previously been poisoned")] +fn lazy_lock_deref_mut_panic() { + let mut lazy: LazyLock = LazyLock::new(|| panic!("initialization failed")); + + // First access will panic during initialization. + let _ = panic::catch_unwind(panic::AssertUnwindSafe(|| { + let _ = LazyLock::force_mut(&mut lazy); + })); + + // Second access should panic with the poisoned message. + let _ = &*lazy; +} + +/// Verifies that when the initialization closure panics with a custom message, that message is +/// preserved and not overridden by `LazyLock`. +#[test] +#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")] +#[should_panic(expected = "custom panic message from closure")] +fn lazy_lock_preserves_closure_panic_message() { + let lazy: LazyLock = LazyLock::new(|| panic!("custom panic message from closure")); + + // This should panic with the original message from the closure. + let _ = &*lazy; +} From 10fde9eafe95650eca9452e960a891ec3ee35565 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Mon, 28 Jul 2025 16:13:07 -0500 Subject: [PATCH 08/15] Implement some more checks for `ptr_guaranteed_cmp` in consteval: Pointers with different residues modulo their least common allocation alignment are never equal. Pointers to the same static allocation are equal if and only if they have the same offset. Strictly in-bounds (in-bounds and not one-past-the-end) pointers to different static allocations are always unequal. A pointer cannot be equal to an integer if `ptr-int` cannot be null. Also adds more tests for `ptr_guaranteed_cmp`. Co-authored-by: Ralf Jung --- .../src/const_eval/machine.rs | 118 +++++++-- tests/ui/consts/ptr_comparisons.rs | 238 +++++++++++++++--- 2 files changed, 311 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index a18ae79f318df..a682f4a19cf22 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -280,22 +280,110 @@ impl<'tcx> CompileTimeInterpCx<'tcx> { interp_ok(match (a, b) { // Comparisons between integers are always known. (Scalar::Int(a), Scalar::Int(b)) => (a == b) as u8, - // Comparisons of null with an arbitrary scalar can be known if `scalar_may_be_null` - // indicates that the scalar can definitely *not* be null. - (Scalar::Int(int), ptr) | (ptr, Scalar::Int(int)) - if int.is_null() && !self.scalar_may_be_null(ptr)? => - { - 0 + // Comparing a pointer `ptr` with an integer `int` is equivalent to comparing + // `ptr-int` with null, so we can reduce this case to a `scalar_may_be_null` test. + (Scalar::Int(int), Scalar::Ptr(ptr, _)) | (Scalar::Ptr(ptr, _), Scalar::Int(int)) => { + let int = int.to_target_usize(*self.tcx); + // The `wrapping_neg` here may produce a value that is not + // a valid target usize any more... but `wrapping_offset` handles that correctly. + let offset_ptr = ptr.wrapping_offset(Size::from_bytes(int.wrapping_neg()), self); + if !self.scalar_may_be_null(Scalar::from_pointer(offset_ptr, self))? { + // `ptr.wrapping_sub(int)` is definitely not equal to `0`, so `ptr != int` + 0 + } else { + // `ptr.wrapping_sub(int)` could be equal to `0`, but might not be, + // so we cannot know for sure if `ptr == int` or not + 2 + } + } + (Scalar::Ptr(a, _), Scalar::Ptr(b, _)) => { + let (a_prov, a_offset) = a.prov_and_relative_offset(); + let (b_prov, b_offset) = b.prov_and_relative_offset(); + let a_allocid = a_prov.alloc_id(); + let b_allocid = b_prov.alloc_id(); + let a_info = self.get_alloc_info(a_allocid); + let b_info = self.get_alloc_info(b_allocid); + + // Check if the pointers cannot be equal due to alignment + if a_info.align > Align::ONE && b_info.align > Align::ONE { + let min_align = Ord::min(a_info.align.bytes(), b_info.align.bytes()); + let a_residue = a_offset.bytes() % min_align; + let b_residue = b_offset.bytes() % min_align; + if a_residue != b_residue { + // If the two pointers have a different residue modulo their + // common alignment, they cannot be equal. + return interp_ok(0); + } + // The pointers have the same residue modulo their common alignment, + // so they could be equal. Try the other checks. + } + + if let (Some(GlobalAlloc::Static(a_did)), Some(GlobalAlloc::Static(b_did))) = ( + self.tcx.try_get_global_alloc(a_allocid), + self.tcx.try_get_global_alloc(b_allocid), + ) { + if a_allocid == b_allocid { + debug_assert_eq!( + a_did, b_did, + "different static item DefIds had same AllocId? {a_allocid:?} == {b_allocid:?}, {a_did:?} != {b_did:?}" + ); + // Comparing two pointers into the same static. As per + // https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.intro + // a static cannot be duplicated, so if two pointers are into the same + // static, they are equal if and only if their offsets are equal. + (a_offset == b_offset) as u8 + } else { + debug_assert_ne!( + a_did, b_did, + "same static item DefId had two different AllocIds? {a_allocid:?} != {b_allocid:?}, {a_did:?} == {b_did:?}" + ); + // Comparing two pointers into the different statics. + // We can never determine for sure that two pointers into different statics + // are *equal*, but we can know that they are *inequal* if they are both + // strictly in-bounds (i.e. in-bounds and not one-past-the-end) of + // their respective static, as different non-zero-sized statics cannot + // overlap or be deduplicated as per + // https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.intro + // (non-deduplication), and + // https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.storage-disjointness + // (non-overlapping). + if a_offset < a_info.size && b_offset < b_info.size { + 0 + } else { + // Otherwise, conservatively say we don't know. + // There are some cases we could still return `0` for, e.g. + // if the pointers being equal would require their statics to overlap + // one or more bytes, but for simplicity we currently only check + // strictly in-bounds pointers. + 2 + } + } + } else { + // All other cases we conservatively say we don't know. + // + // For comparing statics to non-statics, as per https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.storage-disjointness + // immutable statics can overlap with other kinds of allocations sometimes. + // + // FIXME: We could be more decisive for (non-zero-sized) mutable statics, + // which cannot overlap with other kinds of allocations. + // + // Functions and vtables can be duplicated and deduplicated, so we + // cannot be sure of runtime equality of pointers to the same one, or the + // runtime inequality of pointers to different ones (see e.g. #73722), + // so comparing those should return 2, whether they are the same allocation + // or not. + // + // `GlobalAlloc::TypeId` exists mostly to prevent consteval from comparing + // `TypeId`s, so comparing those should always return 2, whether they are the + // same allocation or not. + // + // FIXME: We could revisit comparing pointers into the same + // `GlobalAlloc::Memory` once https://github.com/rust-lang/rust/issues/128775 + // is fixed (but they can be deduplicated, so comparing pointers into different + // ones should return 2). + 2 + } } - // Other ways of comparing integers and pointers can never be known for sure. - (Scalar::Int { .. }, Scalar::Ptr(..)) | (Scalar::Ptr(..), Scalar::Int { .. }) => 2, - // FIXME: return a `1` for when both sides are the same pointer, *except* that - // some things (like functions and vtables) do not have stable addresses - // so we need to be careful around them (see e.g. #73722). - // FIXME: return `0` for at least some comparisons where we can reliably - // determine the result of runtime inequality tests at compile-time. - // Examples include comparison of addresses in different static items. - (Scalar::Ptr(..), Scalar::Ptr(..)) => 2, }) } } diff --git a/tests/ui/consts/ptr_comparisons.rs b/tests/ui/consts/ptr_comparisons.rs index e142ab3a754a4..0682184e5567c 100644 --- a/tests/ui/consts/ptr_comparisons.rs +++ b/tests/ui/consts/ptr_comparisons.rs @@ -1,43 +1,221 @@ //@ compile-flags: --crate-type=lib //@ check-pass +//@ edition: 2024 +#![feature(const_raw_ptr_comparison)] +#![feature(fn_align)] +// Generally: +// For any `Some` return, `None` would also be valid, unless otherwise noted. +// For any `None` return, only `None` is valid, unless otherwise noted. -#![feature( - core_intrinsics, - const_raw_ptr_comparison, -)] +macro_rules! do_test { + ($a:expr, $b:expr, $expected:pat) => { + const _: () = { + let a: *const _ = $a; + let b: *const _ = $b; + assert!(matches!(<*const u8>::guaranteed_eq(a.cast(), b.cast()), $expected)); + }; + }; +} -const FOO: &usize = &42; +#[repr(align(2))] +struct T(#[allow(unused)] u16); -macro_rules! check { - (eq, $a:expr, $b:expr) => { - pub const _: () = - assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 1); - }; - (ne, $a:expr, $b:expr) => { - pub const _: () = - assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 0); +#[repr(align(2))] +struct AlignedZst; + +static A: T = T(42); +static B: T = T(42); +static mut MUT_STATIC: T = T(42); +static ZST: () = (); +static ALIGNED_ZST: AlignedZst = AlignedZst; +static LARGE_WORD_ALIGNED: [usize; 2] = [0, 1]; +static mut MUT_LARGE_WORD_ALIGNED: [usize; 2] = [0, 1]; + +const FN_PTR: *const () = { + fn foo() {} + unsafe { std::mem::transmute(foo as fn()) } +}; + +const ALIGNED_FN_PTR: *const () = { + #[rustc_align(2)] + fn aligned_foo() {} + unsafe { std::mem::transmute(aligned_foo as fn()) } +}; + +// Only on armv5te-* and armv4t-* +#[cfg(all( + target_arch = "arm", + not(target_feature = "v6"), +))] +const ALIGNED_THUMB_FN_PTR: *const () = { + #[rustc_align(2)] + #[instruction_set(arm::t32)] + fn aligned_thumb_foo() {} + unsafe { std::mem::transmute(aligned_thumb_foo as fn()) } +}; + +trait Trait { + #[allow(unused)] + fn method(&self) -> u8; +} +impl Trait for u32 { + fn method(&self) -> u8 { 1 } +} +impl Trait for i32 { + fn method(&self) -> u8 { 2 } +} + +const VTABLE_PTR_1: *const () = { + let [_data, vtable] = unsafe { + std::mem::transmute::<&dyn Trait, [*const (); 2]>(&42_u32 as &dyn Trait) }; - (!, $a:expr, $b:expr) => { - pub const _: () = - assert!(std::intrinsics::ptr_guaranteed_cmp($a as *const u8, $b as *const u8) == 2); + vtable +}; +const VTABLE_PTR_2: *const () = { + let [_data, vtable] = unsafe { + std::mem::transmute::<&dyn Trait, [*const (); 2]>(&42_i32 as &dyn Trait) }; -} + vtable +}; -check!(eq, 0, 0); -check!(ne, 0, 1); -check!(ne, FOO as *const _, 0); -check!(ne, unsafe { (FOO as *const usize).offset(1) }, 0); -check!(ne, unsafe { (FOO as *const usize as *const u8).offset(3) }, 0); +// Cannot be `None`: `is_null` is stable with strong guarantees about integer-valued pointers. +do_test!(0 as *const u8, 0 as *const u8, Some(true)); +do_test!(0 as *const u8, 1 as *const u8, Some(false)); -// We want pointers to be equal to themselves, but aren't checking this yet because -// there are some open questions (e.g. whether function pointers to the same function -// compare equal: they don't necessarily do at runtime). -check!(!, FOO as *const _, FOO as *const _); +// Integer-valued pointers can always be compared. +do_test!(1 as *const u8, 1 as *const u8, Some(true)); +do_test!(1 as *const u8, 2 as *const u8, Some(false)); + +// Cannot be `None`: `static`s' addresses, references, (and within and one-past-the-end of those), +// and `fn` pointers cannot be null, and `is_null` is stable with strong guarantees, and +// `is_null` is implemented using `guaranteed_cmp`. +do_test!(&A, 0 as *const u8, Some(false)); +do_test!((&raw const A).cast::().wrapping_add(1), 0 as *const u8, Some(false)); +do_test!((&raw const A).wrapping_add(1), 0 as *const u8, Some(false)); +do_test!(&ZST, 0 as *const u8, Some(false)); +do_test!(&(), 0 as *const u8, Some(false)); +do_test!(const { &() }, 0 as *const u8, Some(false)); +do_test!(FN_PTR, 0 as *const u8, Some(false)); + +// This pointer is out-of-bounds, but still cannot be equal to 0 because of alignment. +do_test!((&raw const A).cast::().wrapping_add(size_of::() + 1), 0 as *const u8, Some(false)); // aside from 0, these pointers might end up pretty much anywhere. -check!(!, FOO as *const _, 1); // this one could be `ne` by taking into account alignment -check!(!, FOO as *const _, 1024); +do_test!(&A, align_of::() as *const u8, None); +do_test!((&raw const A).wrapping_byte_add(1), (align_of::() + 1) as *const u8, None); + +// except that they must still be aligned +do_test!(&A, 1 as *const u8, Some(false)); +do_test!((&raw const A).wrapping_byte_add(1), align_of::() as *const u8, Some(false)); + +// If `ptr.wrapping_sub(int)` cannot be null (because it is in-bounds or one-past-the-end of +// `ptr`'s allocation, or because it is misaligned from `ptr`'s allocation), then we know that +// `ptr != int`, even if `ptr` itself is out-of-bounds or one-past-the-end of its allocation. +do_test!((&raw const A).wrapping_byte_add(1), 1 as *const u8, Some(false)); +do_test!((&raw const A).wrapping_byte_add(2), 2 as *const u8, Some(false)); +do_test!((&raw const A).wrapping_byte_add(3), 1 as *const u8, Some(false)); +do_test!((&raw const ZST).wrapping_byte_add(1), 1 as *const u8, Some(false)); +do_test!(VTABLE_PTR_1.wrapping_byte_add(1), 1 as *const u8, Some(false)); +do_test!(FN_PTR.wrapping_byte_add(1), 1 as *const u8, Some(false)); +do_test!(&A, size_of::().wrapping_neg() as *const u8, Some(false)); +do_test!(&LARGE_WORD_ALIGNED, size_of::().wrapping_neg() as *const u8, Some(false)); +// (`ptr - int != 0` due to misalignment) +do_test!((&raw const A).wrapping_byte_add(2), 1 as *const u8, Some(false)); +do_test!((&raw const ALIGNED_ZST).wrapping_byte_add(2), 1 as *const u8, Some(false)); // When pointers go out-of-bounds, they *might* become null, so these comparions cannot work. -check!(!, unsafe { (FOO as *const usize).wrapping_add(2) }, 0); -check!(!, unsafe { (FOO as *const usize).wrapping_sub(1) }, 0); +do_test!((&raw const A).wrapping_add(2), 0 as *const u8, None); +do_test!((&raw const A).wrapping_sub(1), 0 as *const u8, None); + +// Statics cannot be duplicated +do_test!(&A, &A, Some(true)); + +// Two non-ZST statics cannot have the same address +do_test!(&A, &B, Some(false)); +do_test!(&A, &raw const MUT_STATIC, Some(false)); + +// One-past-the-end of one static can be equal to the address of another static. +do_test!(&A, (&raw const B).wrapping_add(1), None); + +// Cannot know if ZST static is at the same address with anything non-null (if alignment allows). +do_test!(&A, &ZST, None); +do_test!(&A, &ALIGNED_ZST, None); + +// Unclear if ZST statics can be placed "in the middle of" non-ZST statics. +// For now, we conservatively say they could, and return None here. +do_test!(&ZST, (&raw const A).wrapping_byte_add(1), None); + +// As per https://doc.rust-lang.org/nightly/reference/items/static-items.html#r-items.static.storage-disjointness +// immutable statics are allowed to overlap with const items and promoteds. +do_test!(&A, &T(42), None); +do_test!(&A, const { &T(42) }, None); +do_test!(&A, { const X: T = T(42); &X }, None); + +// These could return Some(false), since only immutable statics can overlap with const items +// and promoteds. +do_test!(&raw const MUT_STATIC, &T(42), None); +do_test!(&raw const MUT_STATIC, const { &T(42) }, None); +do_test!(&raw const MUT_STATIC, { const X: T = T(42); &X }, None); + +// An odd offset from a 2-aligned allocation can never be equal to an even offset from a +// 2-aligned allocation, even if the offsets are out-of-bounds. +do_test!(&A, (&raw const B).wrapping_byte_add(1), Some(false)); +do_test!(&A, (&raw const B).wrapping_byte_add(5), Some(false)); +do_test!(&A, (&raw const ALIGNED_ZST).wrapping_byte_add(1), Some(false)); +do_test!(&ALIGNED_ZST, (&raw const A).wrapping_byte_add(1), Some(false)); +do_test!(&A, (&T(42) as *const T).wrapping_byte_add(1), Some(false)); +do_test!(&A, (const { &T(42) } as *const T).wrapping_byte_add(1), Some(false)); +do_test!(&A, ({ const X: T = T(42); &X } as *const T).wrapping_byte_add(1), Some(false)); + +// We could return `Some(false)` for these, as pointers to different statics can never be equal if +// that would require the statics to overlap, even if the pointers themselves are offset out of +// bounds or one-past-the-end. We currently only check strictly in-bounds pointers when comparing +// pointers to different statics, however. +do_test!((&raw const A).wrapping_add(1), (&raw const B).wrapping_add(1), None); +do_test!( + (&raw const LARGE_WORD_ALIGNED).cast::().wrapping_add(2), + (&raw const MUT_LARGE_WORD_ALIGNED).cast::().wrapping_add(1), + None +); + +// Pointers into the same static are equal if and only if their offset is the same, +// even if either is out-of-bounds. +do_test!(&A, &A, Some(true)); +do_test!(&A, &A.0, Some(true)); +do_test!(&A, (&raw const A).wrapping_byte_add(1), Some(false)); +do_test!(&A, (&raw const A).wrapping_byte_add(2), Some(false)); +do_test!(&A, (&raw const A).wrapping_byte_add(51), Some(false)); +do_test!((&raw const A).wrapping_byte_add(51), (&raw const A).wrapping_byte_add(51), Some(true)); + +// Pointers to the same fn may be unequal, since `fn`s can be duplicated. +do_test!(FN_PTR, FN_PTR, None); +do_test!(ALIGNED_FN_PTR, ALIGNED_FN_PTR, None); + +// Pointers to different fns may be equal, since `fn`s can be deduplicated. +do_test!(FN_PTR, ALIGNED_FN_PTR, None); + +// Pointers to the same vtable may be unequal, since vtables can be duplicated. +do_test!(VTABLE_PTR_1, VTABLE_PTR_1, None); + +// Pointers to different vtables may be equal, since vtables can be deduplicated. +do_test!(VTABLE_PTR_1, VTABLE_PTR_2, None); + +// Function pointers to aligned function allocations are not necessarily actually aligned, +// due to platform-specific semantics. +// See https://github.com/rust-lang/rust/issues/144661 +// FIXME: This could return `Some` on platforms where function pointers' addresses actually +// correspond to function addresses including alignment, or on ARM if t32 function pointers +// have their low bit set for consteval. +do_test!(ALIGNED_FN_PTR, ALIGNED_FN_PTR.wrapping_byte_offset(1), None); +#[cfg(all( + target_arch = "arm", + not(target_feature = "v6"), +))] +do_test!(ALIGNED_THUMB_FN_PTR, ALIGNED_THUMB_FN_PTR.wrapping_byte_offset(1), None); + +// Conservatively say we don't know. +do_test!(FN_PTR, VTABLE_PTR_1, None); +do_test!((&raw const LARGE_WORD_ALIGNED).cast::().wrapping_add(1), VTABLE_PTR_1, None); +do_test!((&raw const MUT_LARGE_WORD_ALIGNED).cast::().wrapping_add(1), VTABLE_PTR_1, None); +do_test!((&raw const LARGE_WORD_ALIGNED).cast::().wrapping_add(1), FN_PTR, None); +do_test!((&raw const MUT_LARGE_WORD_ALIGNED).cast::().wrapping_add(1), FN_PTR, None); From 399f5e244cfb77b2c3addaeeae6007df5618bb9d Mon Sep 17 00:00:00 2001 From: Ada Alakbarova <58857108+ada4a@users.noreply.github.com> Date: Sat, 23 Aug 2025 23:05:30 +0200 Subject: [PATCH 09/15] std/src/lib.rs: mention "search button" instead of "search bar" --- library/std/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index ab417b6c72f9b..f0de03c9a2806 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -15,7 +15,7 @@ //! //! If you already know the name of what you are looking for, the fastest way to //! find it is to use the search -//! bar at the top of the page. +//! button at the top of the page. //! //! Otherwise, you may want to jump to one of these useful sections: //! From d4cbd9a440d0106fed53cc173dd539492f95f382 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 27 Jul 2025 12:56:02 +0200 Subject: [PATCH 10/15] Add lint against integer to pointer transmutes --- compiler/rustc_lint/messages.ftl | 8 ++ compiler/rustc_lint/src/lints.rs | 42 +++++++ compiler/rustc_lint/src/transmute.rs | 92 +++++++++++++- tests/ui/lint/int_to_ptr.fixed | 47 ++++++++ tests/ui/lint/int_to_ptr.rs | 47 ++++++++ tests/ui/lint/int_to_ptr.stderr | 171 +++++++++++++++++++++++++++ 6 files changed, 406 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/int_to_ptr.fixed create mode 100644 tests/ui/lint/int_to_ptr.rs create mode 100644 tests/ui/lint/int_to_ptr.stderr diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl index 940a07c94df87..417e5a97069c3 100644 --- a/compiler/rustc_lint/messages.ftl +++ b/compiler/rustc_lint/messages.ftl @@ -462,6 +462,14 @@ lint_invalid_reference_casting_note_book = for more information, visit + .help_exposed_provenance = for more information about exposed provenance, see + .suggestion_with_exposed_provenance = use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance + .suggestion_without_provenance_mut = if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + lint_legacy_derive_helpers = derive helper attribute is used before it is introduced .label = the attribute is introduced here diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 6c50973462684..5c91b36133bea 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1,3 +1,5 @@ +// ignore-tidy-filelength + #![allow(rustc::untranslatable_diagnostic)] use std::num::NonZero; @@ -1542,6 +1544,46 @@ impl<'a> LintDiagnostic<'a, ()> for DropGlue<'_> { } } +// transmute.rs +#[derive(LintDiagnostic)] +#[diag(lint_int_to_ptr_transmutes)] +#[note] +#[note(lint_note_exposed_provenance)] +#[help(lint_suggestion_without_provenance_mut)] +#[help(lint_help_transmute)] +#[help(lint_help_exposed_provenance)] +pub(crate) struct IntegerToPtrTransmutes<'tcx> { + #[subdiagnostic] + pub suggestion: IntegerToPtrTransmutesSuggestion<'tcx>, +} + +#[derive(Subdiagnostic)] +pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { + #[multipart_suggestion( + lint_suggestion_with_exposed_provenance, + applicability = "machine-applicable" + )] + ToPtr { + dst: Ty<'tcx>, + suffix: &'static str, + #[suggestion_part(code = "std::ptr::with_exposed_provenance{suffix}::<{dst}>(")] + start_call: Span, + }, + #[multipart_suggestion( + lint_suggestion_with_exposed_provenance, + applicability = "machine-applicable" + )] + ToRef { + dst: Ty<'tcx>, + suffix: &'static str, + ref_mutbl: &'static str, + #[suggestion_part( + code = "&{ref_mutbl}*std::ptr::with_exposed_provenance{suffix}::<{dst}>(" + )] + start_call: Span, + }, +} + // types.rs #[derive(LintDiagnostic)] #[diag(lint_range_endpoint_out_of_range)] diff --git a/compiler/rustc_lint/src/transmute.rs b/compiler/rustc_lint/src/transmute.rs index bc1d4587d076e..239c864904163 100644 --- a/compiler/rustc_lint/src/transmute.rs +++ b/compiler/rustc_lint/src/transmute.rs @@ -1,3 +1,4 @@ +use rustc_ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; @@ -7,6 +8,7 @@ use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint, impl_lint_pass}; use rustc_span::sym; +use crate::lints::{IntegerToPtrTransmutes, IntegerToPtrTransmutesSuggestion}; use crate::{LateContext, LateLintPass}; declare_lint! { @@ -67,9 +69,44 @@ declare_lint! { "detects transmutes that can also be achieved by other operations" } +declare_lint! { + /// The `integer_to_ptr_transmutes` lint detects integer to pointer + /// transmutes where the resulting pointers are undefined behavior to dereference. + /// + /// ### Example + /// + /// ```rust + /// fn foo(a: usize) -> *const u8 { + /// unsafe { + /// std::mem::transmute::(a) + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Any attempt to use the resulting pointers are undefined behavior as the resulting + /// pointers won't have any provenance. + /// + /// Alternatively, [`std::ptr::with_exposed_provenance`] should be used, as they do not + /// carry the provenance requirement. If wanting to create pointers without provenance + /// [`std::ptr::without_provenance`] should be used instead. + /// + /// See [`std::mem::transmute`] in the reference for more details. + /// + /// [`std::mem::transmute`]: https://doc.rust-lang.org/std/mem/fn.transmute.html + /// [`std::ptr::with_exposed_provenance`]: https://doc.rust-lang.org/std/ptr/fn.with_exposed_provenance.html + /// [`std::ptr::without_provenance`]: https://doc.rust-lang.org/std/ptr/fn.without_provenance.html + pub INTEGER_TO_PTR_TRANSMUTES, + Warn, + "detects integer to pointer transmutes", +} + pub(crate) struct CheckTransmutes; -impl_lint_pass!(CheckTransmutes => [PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS, UNNECESSARY_TRANSMUTES]); +impl_lint_pass!(CheckTransmutes => [PTR_TO_INTEGER_TRANSMUTE_IN_CONSTS, UNNECESSARY_TRANSMUTES, INTEGER_TO_PTR_TRANSMUTES]); impl<'tcx> LateLintPass<'tcx> for CheckTransmutes { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'tcx>) { @@ -94,9 +131,62 @@ impl<'tcx> LateLintPass<'tcx> for CheckTransmutes { check_ptr_transmute_in_const(cx, expr, body_owner_def_id, const_context, src, dst); check_unnecessary_transmute(cx, expr, callee, arg, const_context, src, dst); + check_int_to_ptr_transmute(cx, expr, arg, src, dst); } } +/// Check for transmutes from integer to pointers (*const/*mut and &/&mut). +/// +/// Using the resulting pointers would be undefined behavior. +fn check_int_to_ptr_transmute<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx hir::Expr<'tcx>, + arg: &'tcx hir::Expr<'tcx>, + src: Ty<'tcx>, + dst: Ty<'tcx>, +) { + if !matches!(src.kind(), ty::Uint(_) | ty::Int(_)) { + return; + } + let (ty::Ref(_, inner_ty, mutbl) | ty::RawPtr(inner_ty, mutbl)) = dst.kind() else { + return; + }; + // bail-out if the argument is literal 0 as we have other lints for those cases + if matches!(arg.kind, hir::ExprKind::Lit(hir::Lit { node: LitKind::Int(v, _), .. }) if v == 0) { + return; + } + // bail-out if the inner type is a ZST + let Ok(layout_inner_ty) = cx.tcx.layout_of(cx.typing_env().as_query_input(*inner_ty)) else { + return; + }; + if layout_inner_ty.is_1zst() { + return; + } + + let suffix = if mutbl.is_mut() { "_mut" } else { "" }; + cx.tcx.emit_node_span_lint( + INTEGER_TO_PTR_TRANSMUTES, + expr.hir_id, + expr.span, + IntegerToPtrTransmutes { + suggestion: if dst.is_ref() { + IntegerToPtrTransmutesSuggestion::ToRef { + dst: *inner_ty, + suffix, + ref_mutbl: mutbl.prefix_str(), + start_call: expr.span.shrink_to_lo().until(arg.span), + } + } else { + IntegerToPtrTransmutesSuggestion::ToPtr { + dst: *inner_ty, + suffix, + start_call: expr.span.shrink_to_lo().until(arg.span), + } + }, + }, + ); +} + /// Check for transmutes that exhibit undefined behavior. /// For example, transmuting pointers to integers in a const context. /// diff --git a/tests/ui/lint/int_to_ptr.fixed b/tests/ui/lint/int_to_ptr.fixed new file mode 100644 index 0000000000000..8f373492e6fb8 --- /dev/null +++ b/tests/ui/lint/int_to_ptr.fixed @@ -0,0 +1,47 @@ +// Checks for the `integer_to_pointer_transmutes` lint + +//@ check-pass +//@ run-rustfix + +#![allow(unused_unsafe)] +#![allow(dead_code)] + +unsafe fn should_lint(a: usize) { + let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::(a) }; + //~^ WARN transmuting an integer to a pointer + + let _ptr = unsafe { std::ptr::with_exposed_provenance::(42usize) }; + //~^ WARN transmuting an integer to a pointer + let _ptr = unsafe { std::ptr::with_exposed_provenance::(a + a) }; + //~^ WARN transmuting an integer to a pointer +} + +const unsafe fn should_lintin_const(a: usize) { + let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::(a) }; + //~^ WARN transmuting an integer to a pointer + + let _ptr = unsafe { std::ptr::with_exposed_provenance::(42usize) }; + //~^ WARN transmuting an integer to a pointer + let _ptr = unsafe { std::ptr::with_exposed_provenance::(a + a) }; + //~^ WARN transmuting an integer to a pointer +} + +unsafe fn should_not_lint(a: usize) { + let _ptr = unsafe { std::mem::transmute::(0usize) }; // linted by other lints + let _ptr = unsafe { std::mem::transmute::(a) }; // inner type is a ZST + let _ptr = unsafe { std::mem::transmute::(a) }; // omit fn-ptr for now +} + +fn main() {} diff --git a/tests/ui/lint/int_to_ptr.rs b/tests/ui/lint/int_to_ptr.rs new file mode 100644 index 0000000000000..7f60da47b85d8 --- /dev/null +++ b/tests/ui/lint/int_to_ptr.rs @@ -0,0 +1,47 @@ +// Checks for the `integer_to_pointer_transmutes` lint + +//@ check-pass +//@ run-rustfix + +#![allow(unused_unsafe)] +#![allow(dead_code)] + +unsafe fn should_lint(a: usize) { + let _ptr: *const u8 = unsafe { std::mem::transmute::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ptr: *mut u8 = unsafe { std::mem::transmute::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ref: &'static u8 = unsafe { std::mem::transmute::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ref: &'static mut u8 = unsafe { std::mem::transmute::(a) }; + //~^ WARN transmuting an integer to a pointer + + let _ptr = unsafe { std::mem::transmute::(42usize) }; + //~^ WARN transmuting an integer to a pointer + let _ptr = unsafe { std::mem::transmute::(a + a) }; + //~^ WARN transmuting an integer to a pointer +} + +const unsafe fn should_lintin_const(a: usize) { + let _ptr: *const u8 = unsafe { std::mem::transmute::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ptr: *mut u8 = unsafe { std::mem::transmute::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ref: &'static u8 = unsafe { std::mem::transmute::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ref: &'static mut u8 = unsafe { std::mem::transmute::(a) }; + //~^ WARN transmuting an integer to a pointer + + let _ptr = unsafe { std::mem::transmute::(42usize) }; + //~^ WARN transmuting an integer to a pointer + let _ptr = unsafe { std::mem::transmute::(a + a) }; + //~^ WARN transmuting an integer to a pointer +} + +unsafe fn should_not_lint(a: usize) { + let _ptr = unsafe { std::mem::transmute::(0usize) }; // linted by other lints + let _ptr = unsafe { std::mem::transmute::(a) }; // inner type is a ZST + let _ptr = unsafe { std::mem::transmute::(a) }; // omit fn-ptr for now +} + +fn main() {} diff --git a/tests/ui/lint/int_to_ptr.stderr b/tests/ui/lint/int_to_ptr.stderr new file mode 100644 index 0000000000000..437f644239766 --- /dev/null +++ b/tests/ui/lint/int_to_ptr.stderr @@ -0,0 +1,171 @@ +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr.rs:10:36 + | +LL | let _ptr: *const u8 = unsafe { std::mem::transmute::(a) }; + | ----------------------------------------^^ + | | + | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance::(` + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + = note: `#[warn(integer_to_ptr_transmutes)]` on by default + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr.rs:12:34 + | +LL | let _ptr: *mut u8 = unsafe { std::mem::transmute::(a) }; + | --------------------------------------^^ + | | + | help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance_mut::(` + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr.rs:14:38 + | +LL | let _ref: &'static u8 = unsafe { std::mem::transmute::(a) }; + | ------------------------------------------^^ + | | + | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `&*std::ptr::with_exposed_provenance::(` + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr.rs:16:42 + | +LL | let _ref: &'static mut u8 = unsafe { std::mem::transmute::(a) }; + | ----------------------------------------------^^ + | | + | help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance: `&mut *std::ptr::with_exposed_provenance_mut::(` + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr.rs:19:25 + | +LL | let _ptr = unsafe { std::mem::transmute::(42usize) }; + | ----------------------------------------^^^^^^^^ + | | + | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance::(` + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr.rs:21:25 + | +LL | let _ptr = unsafe { std::mem::transmute::(a + a) }; + | ----------------------------------------^^^^^^ + | | + | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance::(` + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr.rs:26:36 + | +LL | let _ptr: *const u8 = unsafe { std::mem::transmute::(a) }; + | ----------------------------------------^^ + | | + | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance::(` + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr.rs:28:34 + | +LL | let _ptr: *mut u8 = unsafe { std::mem::transmute::(a) }; + | --------------------------------------^^ + | | + | help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance_mut::(` + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr.rs:30:38 + | +LL | let _ref: &'static u8 = unsafe { std::mem::transmute::(a) }; + | ------------------------------------------^^ + | | + | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `&*std::ptr::with_exposed_provenance::(` + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr.rs:32:42 + | +LL | let _ref: &'static mut u8 = unsafe { std::mem::transmute::(a) }; + | ----------------------------------------------^^ + | | + | help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance: `&mut *std::ptr::with_exposed_provenance_mut::(` + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr.rs:35:25 + | +LL | let _ptr = unsafe { std::mem::transmute::(42usize) }; + | ----------------------------------------^^^^^^^^ + | | + | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance::(` + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr.rs:37:25 + | +LL | let _ptr = unsafe { std::mem::transmute::(a + a) }; + | ----------------------------------------^^^^^^ + | | + | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance::(` + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + +warning: 12 warnings emitted + From f25bf37f1f9a254db517f48ced9553bb990dcd14 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 27 Jul 2025 13:20:46 +0200 Subject: [PATCH 11/15] Allow `integer_to_ptr_transmutes` in core --- library/core/src/ptr/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs index f5c490ca7cea3..6fc85a83e179e 100644 --- a/library/core/src/ptr/mod.rs +++ b/library/core/src/ptr/mod.rs @@ -914,6 +914,7 @@ pub const fn dangling() -> *const T { #[must_use] #[stable(feature = "strict_provenance", since = "1.84.0")] #[rustc_const_stable(feature = "strict_provenance", since = "1.84.0")] +#[allow(integer_to_ptr_transmutes)] // Expected semantics here. pub const fn without_provenance_mut(addr: usize) -> *mut T { // An int-to-pointer transmute currently has exactly the intended semantics: it creates a // pointer without provenance. Note that this is *not* a stable guarantee about transmute From 3c664785c12a5b32b4489d0791cf8cc77fd1b3f6 Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 27 Jul 2025 13:41:10 +0200 Subject: [PATCH 12/15] Allow `integer_to_ptr_transmutes` in tests --- src/tools/miri/tests/fail/branchless-select-i128-pointer.rs | 2 ++ src/tools/miri/tests/fail/provenance/provenance_transmute.rs | 2 ++ src/tools/miri/tests/fail/validity/dangling_ref1.rs | 3 +++ src/tools/miri/tests/panic/transmute_fat2.rs | 2 ++ src/tools/miri/tests/pass/binops.rs | 1 + src/tools/miri/tests/pass/too-large-primval-write-problem.rs | 2 ++ tests/ui/binop/binops.rs | 1 + 7 files changed, 13 insertions(+) diff --git a/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs b/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs index 2b861e5447b03..7147813c4b6c1 100644 --- a/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs +++ b/src/tools/miri/tests/fail/branchless-select-i128-pointer.rs @@ -1,3 +1,5 @@ +#![allow(integer_to_ptr_transmutes)] + use std::mem::transmute; #[cfg(target_pointer_width = "32")] diff --git a/src/tools/miri/tests/fail/provenance/provenance_transmute.rs b/src/tools/miri/tests/fail/provenance/provenance_transmute.rs index d72f10530d7ab..60cb9a7f6bfb1 100644 --- a/src/tools/miri/tests/fail/provenance/provenance_transmute.rs +++ b/src/tools/miri/tests/fail/provenance/provenance_transmute.rs @@ -1,5 +1,7 @@ //@compile-flags: -Zmiri-permissive-provenance +#![allow(integer_to_ptr_transmutes)] + use std::mem; // This is the example from diff --git a/src/tools/miri/tests/fail/validity/dangling_ref1.rs b/src/tools/miri/tests/fail/validity/dangling_ref1.rs index fc3a9f344638f..57ba1117e765e 100644 --- a/src/tools/miri/tests/fail/validity/dangling_ref1.rs +++ b/src/tools/miri/tests/fail/validity/dangling_ref1.rs @@ -1,5 +1,8 @@ // Make sure we catch this even without Stacked Borrows //@compile-flags: -Zmiri-disable-stacked-borrows + +#![allow(integer_to_ptr_transmutes)] + use std::mem; fn main() { diff --git a/src/tools/miri/tests/panic/transmute_fat2.rs b/src/tools/miri/tests/panic/transmute_fat2.rs index e695ff2d57ba5..7441f25d03ea7 100644 --- a/src/tools/miri/tests/panic/transmute_fat2.rs +++ b/src/tools/miri/tests/panic/transmute_fat2.rs @@ -1,3 +1,5 @@ +#![allow(integer_to_ptr_transmutes)] + fn main() { #[cfg(all(target_endian = "little", target_pointer_width = "64"))] let bad = unsafe { std::mem::transmute::(42) }; diff --git a/src/tools/miri/tests/pass/binops.rs b/src/tools/miri/tests/pass/binops.rs index 0aff7acb29d44..fcbe6c85b7b8f 100644 --- a/src/tools/miri/tests/pass/binops.rs +++ b/src/tools/miri/tests/pass/binops.rs @@ -32,6 +32,7 @@ fn test_bool() { assert_eq!(true ^ true, false); } +#[allow(integer_to_ptr_transmutes)] fn test_ptr() { unsafe { let p1: *const u8 = ::std::mem::transmute(0_usize); diff --git a/src/tools/miri/tests/pass/too-large-primval-write-problem.rs b/src/tools/miri/tests/pass/too-large-primval-write-problem.rs index f4c418bd78a99..00882b7ecca6e 100644 --- a/src/tools/miri/tests/pass/too-large-primval-write-problem.rs +++ b/src/tools/miri/tests/pass/too-large-primval-write-problem.rs @@ -7,6 +7,8 @@ // // This is just intended as a regression test to make sure we don't reintroduce this problem. +#![allow(integer_to_ptr_transmutes)] + #[cfg(target_pointer_width = "32")] fn main() { use std::mem::transmute; diff --git a/tests/ui/binop/binops.rs b/tests/ui/binop/binops.rs index 7142190a45b9a..702e9a61345b7 100644 --- a/tests/ui/binop/binops.rs +++ b/tests/ui/binop/binops.rs @@ -35,6 +35,7 @@ fn test_bool() { assert_eq!(true ^ true, false); } +#[allow(integer_to_ptr_transmutes)] fn test_ptr() { unsafe { let p1: *const u8 = ::std::mem::transmute(0_usize); From 02a67cc4a535fdb226a57a3d8d3ef32d68fd347c Mon Sep 17 00:00:00 2001 From: Urgau Date: Sun, 27 Jul 2025 21:21:49 +0200 Subject: [PATCH 13/15] Adjust clippy lints for rustc `integer_to_ptr_transmutes` lint --- .../src/transmute/useless_transmute.rs | 12 +---- src/tools/clippy/tests/ui/transmute.rs | 3 +- src/tools/clippy/tests/ui/transmute.stderr | 46 +++++++------------ .../transmutes_expressible_as_ptr_casts.fixed | 3 -- .../ui/transmutes_expressible_as_ptr_casts.rs | 3 -- ...transmutes_expressible_as_ptr_casts.stderr | 32 ++++++------- 6 files changed, 32 insertions(+), 67 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs index ec5fb2793f976..b898920baefc2 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/useless_transmute.rs @@ -49,17 +49,7 @@ pub(super) fn check<'tcx>( true }, (ty::Int(_) | ty::Uint(_), ty::RawPtr(_, _)) => { - span_lint_and_then( - cx, - USELESS_TRANSMUTE, - e.span, - "transmute from an integer to a pointer", - |diag| { - if let Some(arg) = sugg::Sugg::hir_opt(cx, arg) { - diag.span_suggestion(e.span, "try", arg.as_ty(to_ty.to_string()), Applicability::Unspecified); - } - }, - ); + // Handled by the upstream rustc `integer_to_ptr_transmutes` lint true }, _ => false, diff --git a/src/tools/clippy/tests/ui/transmute.rs b/src/tools/clippy/tests/ui/transmute.rs index e968e7a59244d..e7099104f942d 100644 --- a/src/tools/clippy/tests/ui/transmute.rs +++ b/src/tools/clippy/tests/ui/transmute.rs @@ -4,6 +4,7 @@ dead_code, clippy::borrow_as_ptr, unnecessary_transmutes, + integer_to_ptr_transmutes, clippy::needless_lifetimes, clippy::missing_transmute_annotations )] @@ -60,12 +61,10 @@ fn useless() { //~^ useless_transmute let _: *const usize = std::mem::transmute(5_isize); - //~^ useless_transmute let _ = std::ptr::dangling::(); let _: *const usize = std::mem::transmute(1 + 1usize); - //~^ useless_transmute let _ = (1 + 1_usize) as *const usize; } diff --git a/src/tools/clippy/tests/ui/transmute.stderr b/src/tools/clippy/tests/ui/transmute.stderr index 79528ec06f1bf..9478db09481a8 100644 --- a/src/tools/clippy/tests/ui/transmute.stderr +++ b/src/tools/clippy/tests/ui/transmute.stderr @@ -1,5 +1,5 @@ error: transmute from a reference to a pointer - --> tests/ui/transmute.rs:33:27 + --> tests/ui/transmute.rs:34:27 | LL | let _: *const T = core::mem::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T` @@ -8,61 +8,49 @@ LL | let _: *const T = core::mem::transmute(t); = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]` error: transmute from a reference to a pointer - --> tests/ui/transmute.rs:36:25 + --> tests/ui/transmute.rs:37:25 | LL | let _: *mut T = core::mem::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *mut T` error: transmute from a reference to a pointer - --> tests/ui/transmute.rs:39:27 + --> tests/ui/transmute.rs:40:27 | LL | let _: *const U = core::mem::transmute(t); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `t as *const T as *const U` error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:47:27 + --> tests/ui/transmute.rs:48:27 | LL | let _: Vec = core::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:50:27 + --> tests/ui/transmute.rs:51:27 | LL | let _: Vec = core::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:53:27 + --> tests/ui/transmute.rs:54:27 | LL | let _: Vec = std::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:56:27 + --> tests/ui/transmute.rs:57:27 | LL | let _: Vec = std::mem::transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`std::vec::Vec`) to itself - --> tests/ui/transmute.rs:59:27 + --> tests/ui/transmute.rs:60:27 | LL | let _: Vec = my_transmute(my_vec()); | ^^^^^^^^^^^^^^^^^^^^^^ -error: transmute from an integer to a pointer - --> tests/ui/transmute.rs:62:31 - | -LL | let _: *const usize = std::mem::transmute(5_isize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize` - -error: transmute from an integer to a pointer - --> tests/ui/transmute.rs:67:31 - | -LL | let _: *const usize = std::mem::transmute(1 + 1usize); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize` - error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`) - --> tests/ui/transmute.rs:99:24 + --> tests/ui/transmute.rs:98:24 | LL | let _: Usize = core::mem::transmute(int_const_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -71,25 +59,25 @@ LL | let _: Usize = core::mem::transmute(int_const_ptr); = help: to override `-D warnings` add `#[allow(clippy::crosspointer_transmute)]` error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`) - --> tests/ui/transmute.rs:102:24 + --> tests/ui/transmute.rs:101:24 | LL | let _: Usize = core::mem::transmute(int_mut_ptr); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`) - --> tests/ui/transmute.rs:105:31 + --> tests/ui/transmute.rs:104:31 | LL | let _: *const Usize = core::mem::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`) - --> tests/ui/transmute.rs:108:29 + --> tests/ui/transmute.rs:107:29 | LL | let _: *mut Usize = core::mem::transmute(my_int()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: transmute from a `u8` to a `bool` - --> tests/ui/transmute.rs:115:28 + --> tests/ui/transmute.rs:114:28 | LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0` @@ -98,7 +86,7 @@ LL | let _: bool = unsafe { std::mem::transmute(0_u8) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_int_to_bool)]` error: transmute from a `&[u8]` to a `&str` - --> tests/ui/transmute.rs:122:28 + --> tests/ui/transmute.rs:121:28 | LL | let _: &str = unsafe { std::mem::transmute(B) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(B).unwrap()` @@ -107,16 +95,16 @@ LL | let _: &str = unsafe { std::mem::transmute(B) }; = help: to override `-D warnings` add `#[allow(clippy::transmute_bytes_to_str)]` error: transmute from a `&mut [u8]` to a `&mut str` - --> tests/ui/transmute.rs:125:32 + --> tests/ui/transmute.rs:124:32 | LL | let _: &mut str = unsafe { std::mem::transmute(mb) }; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()` error: transmute from a `&[u8]` to a `&str` - --> tests/ui/transmute.rs:128:30 + --> tests/ui/transmute.rs:127:30 | LL | const _: &str = unsafe { std::mem::transmute(B) }; | ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_unchecked(B)` -error: aborting due to 18 previous errors +error: aborting due to 16 previous errors diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed index e7ad2a1cbbcb1..02f67f79e2b19 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.fixed @@ -13,9 +13,6 @@ fn main() { // We should see an error message for each transmute, and no error messages for // the casts, since the casts are the recommended fixes. - // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast - let _ptr_i32_transmute = unsafe { usize::MAX as *const i32 }; - //~^ useless_transmute let ptr_i32 = usize::MAX as *const i32; // e has type *T, U is *U_0, and either U_0: Sized ... diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs index 42a81777a8267..c5e156405ebca 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.rs @@ -13,9 +13,6 @@ fn main() { // We should see an error message for each transmute, and no error messages for // the casts, since the casts are the recommended fixes. - // e is an integer and U is *U_0, while U_0: Sized; addr-ptr-cast - let _ptr_i32_transmute = unsafe { transmute::(usize::MAX) }; - //~^ useless_transmute let ptr_i32 = usize::MAX as *const i32; // e has type *T, U is *U_0, and either U_0: Sized ... diff --git a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr index 7746f087cc714..f39a64d57eb49 100644 --- a/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr +++ b/src/tools/clippy/tests/ui/transmutes_expressible_as_ptr_casts.stderr @@ -1,14 +1,5 @@ -error: transmute from an integer to a pointer - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:17:39 - | -LL | let _ptr_i32_transmute = unsafe { transmute::(usize::MAX) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `usize::MAX as *const i32` - | - = note: `-D clippy::useless-transmute` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]` - error: transmute from a pointer to a pointer - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:22:38 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:19:38 | LL | let _ptr_i8_transmute = unsafe { transmute::<*const i32, *const i8>(ptr_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +13,7 @@ LL + let _ptr_i8_transmute = unsafe { ptr_i32.cast::() }; | error: transmute from a pointer to a pointer - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:29:46 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:26:46 | LL | let _ptr_to_unsized_transmute = unsafe { transmute::<*const [i32], *const [u32]>(slice_ptr) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -34,7 +25,7 @@ LL + let _ptr_to_unsized_transmute = unsafe { slice_ptr as *const [u32] }; | error: transmute from `*const i32` to `usize` which could be expressed as a pointer cast instead - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:36:50 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:33:50 | LL | let _usize_from_int_ptr_transmute = unsafe { transmute::<*const i32, usize>(ptr_i32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr_i32 as usize` @@ -43,40 +34,43 @@ LL | let _usize_from_int_ptr_transmute = unsafe { transmute::<*const i32, us = help: to override `-D warnings` add `#[allow(clippy::transmutes_expressible_as_ptr_casts)]` error: transmute from a reference to a pointer - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:43:41 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:40:41 | LL | let _array_ptr_transmute = unsafe { transmute::<&[i32; 4], *const [i32; 4]>(array_ref) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `array_ref as *const [i32; 4]` + | + = note: `-D clippy::useless-transmute` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::useless_transmute)]` error: transmute from `fn(usize) -> u8` to `*const usize` which could be expressed as a pointer cast instead - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:52:41 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:49:41 | LL | let _usize_ptr_transmute = unsafe { transmute:: u8, *const usize>(foo) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as *const usize` error: transmute from `fn(usize) -> u8` to `usize` which could be expressed as a pointer cast instead - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:57:49 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:54:49 | LL | let _usize_from_fn_ptr_transmute = unsafe { transmute:: u8, usize>(foo) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `foo as usize` error: transmute from `*const u32` to `usize` which could be expressed as a pointer cast instead - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:61:36 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:58:36 | LL | let _usize_from_ref = unsafe { transmute::<*const u32, usize>(&1u32) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&1u32 as *const u32 as usize` error: transmute from a reference to a pointer - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:73:14 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:70:14 | LL | unsafe { transmute::<&[i32; 1], *const u8>(in_param) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `in_param as *const [i32; 1] as *const u8` error: transmute from `fn()` to `*const u8` which could be expressed as a pointer cast instead - --> tests/ui/transmutes_expressible_as_ptr_casts.rs:92:28 + --> tests/ui/transmutes_expressible_as_ptr_casts.rs:89:28 | LL | let _x: u8 = unsafe { *std::mem::transmute::(f) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(f as *const u8)` -error: aborting due to 10 previous errors +error: aborting due to 9 previous errors From 1da4959e54eaee2b3770301fe4902b65f7b97e9f Mon Sep 17 00:00:00 2001 From: Urgau Date: Sat, 16 Aug 2025 11:17:19 +0200 Subject: [PATCH 14/15] Prefer verbose suggestions for `integer_to_ptr_transmutes` lint --- compiler/rustc_lint/src/lints.rs | 6 +- tests/ui/lint/int_to_ptr.stderr | 108 ++++++++++++++++++++----------- 2 files changed, 76 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 5c91b36133bea..426500dda4a72 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -1561,7 +1561,8 @@ pub(crate) struct IntegerToPtrTransmutes<'tcx> { pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { #[multipart_suggestion( lint_suggestion_with_exposed_provenance, - applicability = "machine-applicable" + applicability = "machine-applicable", + style = "verbose" )] ToPtr { dst: Ty<'tcx>, @@ -1571,7 +1572,8 @@ pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { }, #[multipart_suggestion( lint_suggestion_with_exposed_provenance, - applicability = "machine-applicable" + applicability = "machine-applicable", + style = "verbose" )] ToRef { dst: Ty<'tcx>, diff --git a/tests/ui/lint/int_to_ptr.stderr b/tests/ui/lint/int_to_ptr.stderr index 437f644239766..4035bda8fb2cf 100644 --- a/tests/ui/lint/int_to_ptr.stderr +++ b/tests/ui/lint/int_to_ptr.stderr @@ -2,9 +2,7 @@ warning: transmuting an integer to a pointer creates a pointer without provenanc --> $DIR/int_to_ptr.rs:10:36 | LL | let _ptr: *const u8 = unsafe { std::mem::transmute::(a) }; - | ----------------------------------------^^ - | | - | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance::(` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance @@ -12,160 +10,198 @@ LL | let _ptr: *const u8 = unsafe { std::mem::transmute::( = help: for more information about transmute, see = help: for more information about exposed provenance, see = note: `#[warn(integer_to_ptr_transmutes)]` on by default +help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance + | +LL - let _ptr: *const u8 = unsafe { std::mem::transmute::(a) }; +LL + let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::(a) }; + | warning: transmuting an integer to a pointer creates a pointer without provenance --> $DIR/int_to_ptr.rs:12:34 | LL | let _ptr: *mut u8 = unsafe { std::mem::transmute::(a) }; - | --------------------------------------^^ - | | - | help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance_mut::(` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see +help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance + | +LL - let _ptr: *mut u8 = unsafe { std::mem::transmute::(a) }; +LL + let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::(a) }; + | warning: transmuting an integer to a pointer creates a pointer without provenance --> $DIR/int_to_ptr.rs:14:38 | LL | let _ref: &'static u8 = unsafe { std::mem::transmute::(a) }; - | ------------------------------------------^^ - | | - | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `&*std::ptr::with_exposed_provenance::(` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see +help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance + | +LL - let _ref: &'static u8 = unsafe { std::mem::transmute::(a) }; +LL + let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::(a) }; + | warning: transmuting an integer to a pointer creates a pointer without provenance --> $DIR/int_to_ptr.rs:16:42 | LL | let _ref: &'static mut u8 = unsafe { std::mem::transmute::(a) }; - | ----------------------------------------------^^ - | | - | help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance: `&mut *std::ptr::with_exposed_provenance_mut::(` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see +help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance + | +LL - let _ref: &'static mut u8 = unsafe { std::mem::transmute::(a) }; +LL + let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::(a) }; + | warning: transmuting an integer to a pointer creates a pointer without provenance --> $DIR/int_to_ptr.rs:19:25 | LL | let _ptr = unsafe { std::mem::transmute::(42usize) }; - | ----------------------------------------^^^^^^^^ - | | - | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance::(` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see +help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance + | +LL - let _ptr = unsafe { std::mem::transmute::(42usize) }; +LL + let _ptr = unsafe { std::ptr::with_exposed_provenance::(42usize) }; + | warning: transmuting an integer to a pointer creates a pointer without provenance --> $DIR/int_to_ptr.rs:21:25 | LL | let _ptr = unsafe { std::mem::transmute::(a + a) }; - | ----------------------------------------^^^^^^ - | | - | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance::(` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see +help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance + | +LL - let _ptr = unsafe { std::mem::transmute::(a + a) }; +LL + let _ptr = unsafe { std::ptr::with_exposed_provenance::(a + a) }; + | warning: transmuting an integer to a pointer creates a pointer without provenance --> $DIR/int_to_ptr.rs:26:36 | LL | let _ptr: *const u8 = unsafe { std::mem::transmute::(a) }; - | ----------------------------------------^^ - | | - | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance::(` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see +help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance + | +LL - let _ptr: *const u8 = unsafe { std::mem::transmute::(a) }; +LL + let _ptr: *const u8 = unsafe { std::ptr::with_exposed_provenance::(a) }; + | warning: transmuting an integer to a pointer creates a pointer without provenance --> $DIR/int_to_ptr.rs:28:34 | LL | let _ptr: *mut u8 = unsafe { std::mem::transmute::(a) }; - | --------------------------------------^^ - | | - | help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance_mut::(` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see +help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance + | +LL - let _ptr: *mut u8 = unsafe { std::mem::transmute::(a) }; +LL + let _ptr: *mut u8 = unsafe { std::ptr::with_exposed_provenance_mut::(a) }; + | warning: transmuting an integer to a pointer creates a pointer without provenance --> $DIR/int_to_ptr.rs:30:38 | LL | let _ref: &'static u8 = unsafe { std::mem::transmute::(a) }; - | ------------------------------------------^^ - | | - | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `&*std::ptr::with_exposed_provenance::(` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see +help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance + | +LL - let _ref: &'static u8 = unsafe { std::mem::transmute::(a) }; +LL + let _ref: &'static u8 = unsafe { &*std::ptr::with_exposed_provenance::(a) }; + | warning: transmuting an integer to a pointer creates a pointer without provenance --> $DIR/int_to_ptr.rs:32:42 | LL | let _ref: &'static mut u8 = unsafe { std::mem::transmute::(a) }; - | ----------------------------------------------^^ - | | - | help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance: `&mut *std::ptr::with_exposed_provenance_mut::(` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see +help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance + | +LL - let _ref: &'static mut u8 = unsafe { std::mem::transmute::(a) }; +LL + let _ref: &'static mut u8 = unsafe { &mut *std::ptr::with_exposed_provenance_mut::(a) }; + | warning: transmuting an integer to a pointer creates a pointer without provenance --> $DIR/int_to_ptr.rs:35:25 | LL | let _ptr = unsafe { std::mem::transmute::(42usize) }; - | ----------------------------------------^^^^^^^^ - | | - | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance::(` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see +help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance + | +LL - let _ptr = unsafe { std::mem::transmute::(42usize) }; +LL + let _ptr = unsafe { std::ptr::with_exposed_provenance::(42usize) }; + | warning: transmuting an integer to a pointer creates a pointer without provenance --> $DIR/int_to_ptr.rs:37:25 | LL | let _ptr = unsafe { std::mem::transmute::(a + a) }; - | ----------------------------------------^^^^^^ - | | - | help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance: `std::ptr::with_exposed_provenance::(` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see +help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance + | +LL - let _ptr = unsafe { std::mem::transmute::(a + a) }; +LL + let _ptr = unsafe { std::ptr::with_exposed_provenance::(a + a) }; + | warning: 12 warnings emitted From e4557f0ea4f7e015b3108dc509bce562f64528bc Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 23 Aug 2025 20:54:02 +0000 Subject: [PATCH 15/15] Use unnamed lifetime spans as primary spans for MISMATCHED_LIFETIME_SYNTAXES --- compiler/rustc_lint/src/lifetime_syntax.rs | 8 +- src/tools/clippy/tests/ui/ptr_arg.stderr | 4 +- .../type-dependent/issue-71348.full.stderr | 4 +- .../rpit-assoc-pair-with-lifetime.stderr | 4 +- .../example-from-issue48686.stderr | 4 +- .../missing-lifetime-kind.stderr | 16 +- .../not-tied-to-crate.stderr | 8 +- .../static.stderr | 16 +- .../lifetimes/mismatched-lifetime-syntaxes.rs | 6 +- .../mismatched-lifetime-syntaxes.stderr | 153 +++++++++--------- .../ignore-non-reference-lifetimes.stderr | 8 +- tests/ui/self/self_lifetime-async.stderr | 8 +- tests/ui/self/self_lifetime.stderr | 8 +- 13 files changed, 122 insertions(+), 125 deletions(-) diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index 464f4fc34b966..413525eb6e514 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs @@ -214,9 +214,9 @@ impl LifetimeSyntaxCategories> { } } - pub fn flatten(&self) -> impl Iterator { - let Self { hidden, elided, named } = self; - [hidden.iter(), elided.iter(), named.iter()].into_iter().flatten() + pub fn iter_unnamed(&self) -> impl Iterator { + let Self { hidden, elided, named: _ } = self; + [hidden.iter(), elided.iter()].into_iter().flatten() } } @@ -495,7 +495,7 @@ fn emit_mismatch_diagnostic<'tcx>( cx.emit_span_lint( MISMATCHED_LIFETIME_SYNTAXES, - inputs.flatten().copied().collect::>(), + inputs.iter_unnamed().chain(outputs.iter_unnamed()).copied().collect::>(), lints::MismatchedLifetimeSyntaxes { inputs, outputs, suggestions }, ); } diff --git a/src/tools/clippy/tests/ui/ptr_arg.stderr b/src/tools/clippy/tests/ui/ptr_arg.stderr index 87235057349e3..f32e83d8b8184 100644 --- a/src/tools/clippy/tests/ui/ptr_arg.stderr +++ b/src/tools/clippy/tests/ui/ptr_arg.stderr @@ -268,10 +268,10 @@ LL | fn barbar(_x: &mut Vec, y: &mut String) { | ^^^^^^^^^^^ help: change this to: `&mut str` error: eliding a lifetime that's named elsewhere is confusing - --> tests/ui/ptr_arg.rs:314:36 + --> tests/ui/ptr_arg.rs:314:56 | LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { - | ^^ ^^ ---- the same lifetime is elided here + | -- -- ^^^^ the same lifetime is elided here | | | | | the lifetime is named here | the lifetime is named here diff --git a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr index 32fa46b92b306..299ae68009385 100644 --- a/tests/ui/const-generics/type-dependent/issue-71348.full.stderr +++ b/tests/ui/const-generics/type-dependent/issue-71348.full.stderr @@ -1,8 +1,8 @@ warning: hiding a lifetime that's named elsewhere is confusing - --> $DIR/issue-71348.rs:18:40 + --> $DIR/issue-71348.rs:18:56 | LL | fn ask<'a, const N: &'static str>(&'a self) -> &'a >::Target - | ^^ -- ------------------------ the same lifetime is hidden here + | -- -- ^^^^^^^^^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | | | the same lifetime is named here | the lifetime is named here diff --git a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr index 3651226e0c39d..7a9254bac608e 100644 --- a/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr +++ b/tests/ui/impl-trait/rpit-assoc-pair-with-lifetime.stderr @@ -1,8 +1,8 @@ warning: eliding a lifetime that's named elsewhere is confusing - --> $DIR/rpit-assoc-pair-with-lifetime.rs:3:31 + --> $DIR/rpit-assoc-pair-with-lifetime.rs:3:82 | LL | pub fn iter<'a>(v: Vec<(u32, &'a u32)>) -> impl DoubleEndedIterator { - | ^^ the lifetime is named here ---- the same lifetime is elided here + | -- the lifetime is named here ^^^^ the same lifetime is elided here | = help: the same lifetime is referred to in inconsistent ways, making the signature confusing = note: `#[warn(mismatched_lifetime_syntaxes)]` on by default diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr index 5a7a5a6ebf95c..2b7d6a6da2751 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/example-from-issue48686.stderr @@ -1,8 +1,8 @@ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/example-from-issue48686.rs:6:21 + --> $DIR/example-from-issue48686.rs:6:50 | LL | pub fn get_mut(&'static self, x: &mut u8) -> &mut u8 { - | ^^^^^^^ ------- the same lifetime is elided here + | ------- ^^^^^^^ the same lifetime is elided here | | | the lifetime is named here | diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr index af56a0a0ea5a4..c4d6e78d78729 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/missing-lifetime-kind.stderr @@ -1,8 +1,8 @@ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/missing-lifetime-kind.rs:3:22 + --> $DIR/missing-lifetime-kind.rs:3:32 | LL | fn ampersand<'a>(x: &'a u8) -> &u8 { - | ^^ --- the same lifetime is elided here + | -- ^^^ the same lifetime is elided here | | | the lifetime is named here | @@ -18,10 +18,10 @@ LL | fn ampersand<'a>(x: &'a u8) -> &'a u8 { | ++ error: hiding a lifetime that's named elsewhere is confusing - --> $DIR/missing-lifetime-kind.rs:10:21 + --> $DIR/missing-lifetime-kind.rs:10:31 | LL | fn brackets<'a>(x: &'a u8) -> Brackets { - | ^^ -------- the same lifetime is hidden here + | -- ^^^^^^^^ the same lifetime is hidden here | | | the lifetime is named here | @@ -32,10 +32,10 @@ LL | fn brackets<'a>(x: &'a u8) -> Brackets<'a> { | ++++ error: hiding a lifetime that's named elsewhere is confusing - --> $DIR/missing-lifetime-kind.rs:17:18 + --> $DIR/missing-lifetime-kind.rs:17:28 | LL | fn comma<'a>(x: &'a u8) -> Comma { - | ^^ --------- the same lifetime is hidden here + | -- ^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is named here | @@ -46,10 +46,10 @@ LL | fn comma<'a>(x: &'a u8) -> Comma<'a, u8> { | +++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/missing-lifetime-kind.rs:22:23 + --> $DIR/missing-lifetime-kind.rs:22:34 | LL | fn underscore<'a>(x: &'a u8) -> &'_ u8 { - | ^^ -- the same lifetime is elided here + | -- ^^ the same lifetime is elided here | | | the lifetime is named here | diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr index cf0a29678fada..28de809faab43 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/not-tied-to-crate.stderr @@ -1,8 +1,8 @@ warning: eliding a lifetime that's named elsewhere is confusing - --> $DIR/not-tied-to-crate.rs:8:16 + --> $DIR/not-tied-to-crate.rs:8:31 | LL | fn bar(x: &'static u8) -> &u8 { - | ^^^^^^^ --- the same lifetime is elided here + | ------- ^^^ the same lifetime is elided here | | | the lifetime is named here | @@ -18,10 +18,10 @@ LL | fn bar(x: &'static u8) -> &'static u8 { | +++++++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/not-tied-to-crate.rs:14:16 + --> $DIR/not-tied-to-crate.rs:14:31 | LL | fn baz(x: &'static u8) -> &u8 { - | ^^^^^^^ --- the same lifetime is elided here + | ------- ^^^ the same lifetime is elided here | | | the lifetime is named here | diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr index d60bec6f7e492..5f21a2877a71b 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/static.stderr @@ -1,8 +1,8 @@ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/static.rs:16:18 + --> $DIR/static.rs:16:33 | LL | fn ampersand(x: &'static u8) -> &u8 { - | ^^^^^^^ --- the same lifetime is elided here + | ------- ^^^ the same lifetime is elided here | | | the lifetime is named here | @@ -18,10 +18,10 @@ LL | fn ampersand(x: &'static u8) -> &'static u8 { | +++++++ error: hiding a lifetime that's named elsewhere is confusing - --> $DIR/static.rs:23:17 + --> $DIR/static.rs:23:32 | LL | fn brackets(x: &'static u8) -> Brackets { - | ^^^^^^^ -------- the same lifetime is hidden here + | ------- ^^^^^^^^ the same lifetime is hidden here | | | the lifetime is named here | @@ -32,10 +32,10 @@ LL | fn brackets(x: &'static u8) -> Brackets<'static> { | +++++++++ error: hiding a lifetime that's named elsewhere is confusing - --> $DIR/static.rs:30:14 + --> $DIR/static.rs:30:29 | LL | fn comma(x: &'static u8) -> Comma { - | ^^^^^^^ --------- the same lifetime is hidden here + | ------- ^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is named here | @@ -46,10 +46,10 @@ LL | fn comma(x: &'static u8) -> Comma<'static, u8> { | ++++++++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/static.rs:35:19 + --> $DIR/static.rs:35:35 | LL | fn underscore(x: &'static u8) -> &'_ u8 { - | ^^^^^^^ -- the same lifetime is elided here + | ------- ^^ the same lifetime is elided here | | | the lifetime is named here | diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs index f6260c4720296..f404c4163a9fa 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.rs @@ -36,8 +36,8 @@ fn explicit_bound_path_to_implicit_path<'a>(v: ContainsLifetime<'a>) -> Contains fn explicit_bound_path_to_explicit_anonymous_path<'a>( v: ContainsLifetime<'a>, - //~^ ERROR eliding a lifetime that's named elsewhere is confusing ) -> ContainsLifetime<'_> { + //~^ ERROR eliding a lifetime that's named elsewhere is confusing v } @@ -188,8 +188,8 @@ mod impl_trait { fn explicit_bound_path_to_impl_trait_precise_capture<'a>( v: ContainsLifetime<'a>, - //~^ ERROR eliding a lifetime that's named elsewhere is confusing ) -> impl FnOnce() + use<'_> { + //~^ ERROR eliding a lifetime that's named elsewhere is confusing move || _ = v } } @@ -208,8 +208,8 @@ mod dyn_trait { fn explicit_bound_path_to_dyn_trait_bound<'a>( v: ContainsLifetime<'a>, - //~^ ERROR hiding a lifetime that's named elsewhere is confusing ) -> Box + '_> { + //~^ ERROR hiding a lifetime that's named elsewhere is confusing Box::new(iter::once(v)) } } diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr index 20b7561c594c5..89768fc764a41 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes.stderr @@ -1,8 +1,8 @@ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:10:47 + --> $DIR/mismatched-lifetime-syntaxes.rs:10:57 | LL | fn explicit_bound_ref_to_implicit_ref<'a>(v: &'a u8) -> &u8 { - | ^^ --- the same lifetime is elided here + | -- ^^^ the same lifetime is elided here | | | the lifetime is named here | @@ -18,10 +18,10 @@ LL | fn explicit_bound_ref_to_implicit_ref<'a>(v: &'a u8) -> &'a u8 { | ++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:15:57 + --> $DIR/mismatched-lifetime-syntaxes.rs:15:68 | LL | fn explicit_bound_ref_to_explicit_anonymous_ref<'a>(v: &'a u8) -> &'_ u8 { - | ^^ -- the same lifetime is elided here + | -- ^^ the same lifetime is elided here | | | the lifetime is named here | @@ -36,7 +36,7 @@ error: hiding a lifetime that's elided elsewhere is confusing --> $DIR/mismatched-lifetime-syntaxes.rs:22:48 | LL | fn implicit_path_to_explicit_anonymous_path(v: ContainsLifetime) -> ContainsLifetime<'_> { - | ^^^^^^^^^^^^^^^^ -- the same lifetime is elided here + | ^^^^^^^^^^^^^^^^ ^^ the same lifetime is elided here | | | the lifetime is hidden here | @@ -50,7 +50,7 @@ error: hiding a lifetime that's elided elsewhere is confusing --> $DIR/mismatched-lifetime-syntaxes.rs:27:65 | LL | fn explicit_anonymous_path_to_implicit_path(v: ContainsLifetime<'_>) -> ContainsLifetime { - | ^^ ---------------- the same lifetime is hidden here + | ^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is elided here | @@ -61,10 +61,10 @@ LL | fn explicit_anonymous_path_to_implicit_path(v: ContainsLifetime<'_>) -> Con | ++++ error: hiding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:32:65 + --> $DIR/mismatched-lifetime-syntaxes.rs:32:73 | LL | fn explicit_bound_path_to_implicit_path<'a>(v: ContainsLifetime<'a>) -> ContainsLifetime { - | ^^ ---------------- the same lifetime is hidden here + | -- ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is named here | @@ -75,13 +75,12 @@ LL | fn explicit_bound_path_to_implicit_path<'a>(v: ContainsLifetime<'a>) -> Con | ++++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:38:25 + --> $DIR/mismatched-lifetime-syntaxes.rs:39:23 | LL | v: ContainsLifetime<'a>, - | ^^ the lifetime is named here -LL | + | -- the lifetime is named here LL | ) -> ContainsLifetime<'_> { - | -- the same lifetime is elided here + | ^^ the same lifetime is elided here | = help: the same lifetime is referred to in inconsistent ways, making the signature confusing help: consistently use `'a` @@ -94,7 +93,7 @@ error: hiding a lifetime that's elided elsewhere is confusing --> $DIR/mismatched-lifetime-syntaxes.rs:46:37 | LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime { - | ^^^ ---------------- the same lifetime is hidden here + | ^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is elided here | @@ -108,7 +107,7 @@ error: hiding a lifetime that's elided elsewhere is confusing --> $DIR/mismatched-lifetime-syntaxes.rs:51:48 | LL | fn explicit_anonymous_ref_to_implicit_path(v: &'_ u8) -> ContainsLifetime { - | ^^ ---------------- the same lifetime is hidden here + | ^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is elided here | @@ -119,10 +118,10 @@ LL | fn explicit_anonymous_ref_to_implicit_path(v: &'_ u8) -> ContainsLifetime<' | ++++ error: hiding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:56:48 + --> $DIR/mismatched-lifetime-syntaxes.rs:56:58 | LL | fn explicit_bound_ref_to_implicit_path<'a>(v: &'a u8) -> ContainsLifetime { - | ^^ ---------------- the same lifetime is hidden here + | -- ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is named here | @@ -133,10 +132,10 @@ LL | fn explicit_bound_ref_to_implicit_path<'a>(v: &'a u8) -> ContainsLifetime<' | ++++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:61:58 + --> $DIR/mismatched-lifetime-syntaxes.rs:61:85 | LL | fn explicit_bound_ref_to_explicit_anonymous_path<'a>(v: &'a u8) -> ContainsLifetime<'_> { - | ^^ -- the same lifetime is elided here + | -- ^^ the same lifetime is elided here | | | the lifetime is named here | @@ -151,7 +150,7 @@ error: hiding a lifetime that's elided elsewhere is confusing --> $DIR/mismatched-lifetime-syntaxes.rs:68:37 | LL | fn implicit_path_to_implicit_ref(v: ContainsLifetime) -> &u8 { - | ^^^^^^^^^^^^^^^^ --- the same lifetime is elided here + | ^^^^^^^^^^^^^^^^ ^^^ the same lifetime is elided here | | | the lifetime is hidden here | @@ -165,7 +164,7 @@ error: hiding a lifetime that's elided elsewhere is confusing --> $DIR/mismatched-lifetime-syntaxes.rs:73:47 | LL | fn implicit_path_to_explicit_anonymous_ref(v: ContainsLifetime) -> &'_ u8 { - | ^^^^^^^^^^^^^^^^ -- the same lifetime is elided here + | ^^^^^^^^^^^^^^^^ ^^ the same lifetime is elided here | | | the lifetime is hidden here | @@ -176,10 +175,10 @@ LL | fn implicit_path_to_explicit_anonymous_ref(v: ContainsLifetime<'_>) -> &'_ | ++++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:78:64 + --> $DIR/mismatched-lifetime-syntaxes.rs:78:72 | LL | fn explicit_bound_path_to_implicit_ref<'a>(v: ContainsLifetime<'a>) -> &u8 { - | ^^ --- the same lifetime is elided here + | -- ^^^ the same lifetime is elided here | | | the lifetime is named here | @@ -190,10 +189,10 @@ LL | fn explicit_bound_path_to_implicit_ref<'a>(v: ContainsLifetime<'a>) -> &'a | ++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:83:74 + --> $DIR/mismatched-lifetime-syntaxes.rs:83:83 | LL | fn explicit_bound_path_to_explicit_anonymous_ref<'a>(v: ContainsLifetime<'a>) -> &'_ u8 { - | ^^ -- the same lifetime is elided here + | -- ^^ the same lifetime is elided here | | | the lifetime is named here | @@ -205,10 +204,10 @@ LL + fn explicit_bound_path_to_explicit_anonymous_ref<'a>(v: ContainsLifetime<'a | error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:89:55 + --> $DIR/mismatched-lifetime-syntaxes.rs:89:67 | LL | fn method_explicit_bound_ref_to_implicit_ref<'a>(&'a self) -> &u8 { - | ^^ --- the same lifetime is elided here + | -- ^^^ the same lifetime is elided here | | | the lifetime is named here | @@ -219,10 +218,10 @@ LL | fn method_explicit_bound_ref_to_implicit_ref<'a>(&'a self) -> &'a u8 { | ++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:94:65 + --> $DIR/mismatched-lifetime-syntaxes.rs:94:78 | LL | fn method_explicit_bound_ref_to_explicit_anonymous_ref<'a>(&'a self) -> &'_ u8 { - | ^^ -- the same lifetime is elided here + | -- ^^ the same lifetime is elided here | | | the lifetime is named here | @@ -237,7 +236,7 @@ error: hiding a lifetime that's elided elsewhere is confusing --> $DIR/mismatched-lifetime-syntaxes.rs:101:56 | LL | fn method_explicit_anonymous_ref_to_implicit_path(&'_ self) -> ContainsLifetime { - | ^^ ---------------- the same lifetime is hidden here + | ^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is elided here | @@ -248,10 +247,10 @@ LL | fn method_explicit_anonymous_ref_to_implicit_path(&'_ self) -> Contains | ++++ error: hiding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:106:56 + --> $DIR/mismatched-lifetime-syntaxes.rs:106:68 | LL | fn method_explicit_bound_ref_to_implicit_path<'a>(&'a self) -> ContainsLifetime { - | ^^ ---------------- the same lifetime is hidden here + | -- ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is named here | @@ -262,10 +261,10 @@ LL | fn method_explicit_bound_ref_to_implicit_path<'a>(&'a self) -> Contains | ++++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:111:66 + --> $DIR/mismatched-lifetime-syntaxes.rs:111:95 | LL | fn method_explicit_bound_ref_to_explicit_anonymous_path<'a>(&'a self) -> ContainsLifetime<'_> { - | ^^ -- the same lifetime is elided here + | -- ^^ the same lifetime is elided here | | | the lifetime is named here | @@ -277,10 +276,10 @@ LL + fn method_explicit_bound_ref_to_explicit_anonymous_path<'a>(&'a self) - | error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:126:39 + --> $DIR/mismatched-lifetime-syntaxes.rs:126:54 | LL | fn static_ref_to_implicit_ref(v: &'static u8) -> &u8 { - | ^^^^^^^ --- the same lifetime is elided here + | ------- ^^^ the same lifetime is elided here | | | the lifetime is named here | @@ -291,10 +290,10 @@ LL | fn static_ref_to_implicit_ref(v: &'static u8) -> &'static u8 { | +++++++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:131:49 + --> $DIR/mismatched-lifetime-syntaxes.rs:131:65 | LL | fn static_ref_to_explicit_anonymous_ref(v: &'static u8) -> &'_ u8 { - | ^^^^^^^ -- the same lifetime is elided here + | ------- ^^ the same lifetime is elided here | | | the lifetime is named here | @@ -306,10 +305,10 @@ LL + fn static_ref_to_explicit_anonymous_ref(v: &'static u8) -> &'static u8 | error: hiding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:136:40 + --> $DIR/mismatched-lifetime-syntaxes.rs:136:55 | LL | fn static_ref_to_implicit_path(v: &'static u8) -> ContainsLifetime { - | ^^^^^^^ ---------------- the same lifetime is hidden here + | ------- ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is named here | @@ -320,10 +319,10 @@ LL | fn static_ref_to_implicit_path(v: &'static u8) -> ContainsLifetime<'sta | +++++++++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:141:50 + --> $DIR/mismatched-lifetime-syntaxes.rs:141:82 | LL | fn static_ref_to_explicit_anonymous_path(v: &'static u8) -> ContainsLifetime<'_> { - | ^^^^^^^ -- the same lifetime is elided here + | ------- ^^ the same lifetime is elided here | | | the lifetime is named here | @@ -335,10 +334,10 @@ LL + fn static_ref_to_explicit_anonymous_path(v: &'static u8) -> ContainsLif | error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:147:40 + --> $DIR/mismatched-lifetime-syntaxes.rs:147:57 | LL | fn static_ref_to_implicit_ref(&'static self) -> &u8 { - | ^^^^^^^ --- the same lifetime is elided here + | ------- ^^^ the same lifetime is elided here | | | the lifetime is named here | @@ -349,10 +348,10 @@ LL | fn static_ref_to_implicit_ref(&'static self) -> &'static u8 { | +++++++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:152:50 + --> $DIR/mismatched-lifetime-syntaxes.rs:152:68 | LL | fn static_ref_to_explicit_anonymous_ref(&'static self) -> &'_ u8 { - | ^^^^^^^ -- the same lifetime is elided here + | ------- ^^ the same lifetime is elided here | | | the lifetime is named here | @@ -364,10 +363,10 @@ LL + fn static_ref_to_explicit_anonymous_ref(&'static self) -> &'static | error: hiding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:157:41 + --> $DIR/mismatched-lifetime-syntaxes.rs:157:58 | LL | fn static_ref_to_implicit_path(&'static self) -> ContainsLifetime { - | ^^^^^^^ ---------------- the same lifetime is hidden here + | ------- ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is named here | @@ -378,10 +377,10 @@ LL | fn static_ref_to_implicit_path(&'static self) -> ContainsLifetime<' | +++++++++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:162:51 + --> $DIR/mismatched-lifetime-syntaxes.rs:162:85 | LL | fn static_ref_to_explicit_anonymous_path(&'static self) -> ContainsLifetime<'_> { - | ^^^^^^^ -- the same lifetime is elided here + | ------- ^^ the same lifetime is elided here | | | the lifetime is named here | @@ -393,10 +392,10 @@ LL + fn static_ref_to_explicit_anonymous_path(&'static self) -> Contains | error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:174:55 + --> $DIR/mismatched-lifetime-syntaxes.rs:174:81 | LL | fn explicit_bound_ref_to_impl_trait_bound<'a>(v: &'a u8) -> impl FnOnce() + '_ { - | ^^ -- the same lifetime is elided here + | -- ^^ the same lifetime is elided here | | | the lifetime is named here | @@ -408,10 +407,10 @@ LL + fn explicit_bound_ref_to_impl_trait_bound<'a>(v: &'a u8) -> impl FnOnce | error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:179:65 + --> $DIR/mismatched-lifetime-syntaxes.rs:179:95 | LL | fn explicit_bound_ref_to_impl_trait_precise_capture<'a>(v: &'a u8) -> impl FnOnce() + use<'_> { - | ^^ the lifetime is named here -- the same lifetime is elided here + | -- the lifetime is named here ^^ the same lifetime is elided here | = help: the same lifetime is referred to in inconsistent ways, making the signature confusing help: consistently use `'a` @@ -421,10 +420,10 @@ LL + fn explicit_bound_ref_to_impl_trait_precise_capture<'a>(v: &'a u8) -> i | error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:184:72 + --> $DIR/mismatched-lifetime-syntaxes.rs:184:96 | LL | fn explicit_bound_path_to_impl_trait_bound<'a>(v: ContainsLifetime<'a>) -> impl FnOnce() + '_ { - | ^^ -- the same lifetime is elided here + | -- ^^ the same lifetime is elided here | | | the lifetime is named here | @@ -436,13 +435,12 @@ LL + fn explicit_bound_path_to_impl_trait_bound<'a>(v: ContainsLifetime<'a>) | error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:190:29 + --> $DIR/mismatched-lifetime-syntaxes.rs:191:30 | LL | v: ContainsLifetime<'a>, - | ^^ the lifetime is named here -LL | + | -- the lifetime is named here LL | ) -> impl FnOnce() + use<'_> { - | -- the same lifetime is elided here + | ^^ the same lifetime is elided here | = help: the same lifetime is referred to in inconsistent ways, making the signature confusing help: consistently use `'a` @@ -452,10 +450,10 @@ LL + ) -> impl FnOnce() + use<'a> { | error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:204:54 + --> $DIR/mismatched-lifetime-syntaxes.rs:204:88 | LL | fn explicit_bound_ref_to_dyn_trait_bound<'a>(v: &'a u8) -> Box + '_> { - | ^^ the lifetime is named here --- the same lifetime is elided here + | -- the lifetime is named here ^^^ the same lifetime is elided here | = help: the same lifetime is referred to in inconsistent ways, making the signature confusing help: consistently use `'a` @@ -464,13 +462,12 @@ LL | fn explicit_bound_ref_to_dyn_trait_bound<'a>(v: &'a u8) -> Box $DIR/mismatched-lifetime-syntaxes.rs:210:29 + --> $DIR/mismatched-lifetime-syntaxes.rs:211:34 | LL | v: ContainsLifetime<'a>, - | ^^ the lifetime is named here -LL | + | -- the lifetime is named here LL | ) -> Box + '_> { - | ---------------- the same lifetime is hidden here + | ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | = help: the same lifetime is referred to in inconsistent ways, making the signature confusing help: consistently use `'a` @@ -479,10 +476,10 @@ LL | ) -> Box> + '_> { | ++++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:222:33 + --> $DIR/mismatched-lifetime-syntaxes.rs:222:52 | LL | fn multiple_inputs<'a>(v: (&'a u8, &'a u8)) -> &u8 { - | ^^ ^^ --- the same lifetime is elided here + | -- -- ^^^ the same lifetime is elided here | | | | | the lifetime is named here | the lifetime is named here @@ -494,10 +491,10 @@ LL | fn multiple_inputs<'a>(v: (&'a u8, &'a u8)) -> &'a u8 { | ++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:227:33 + --> $DIR/mismatched-lifetime-syntaxes.rs:227:44 | LL | fn multiple_outputs<'a>(v: &'a u8) -> (&u8, &u8) { - | ^^ --- --- the same lifetime is elided here + | -- ^^^ ^^^ the same lifetime is elided here | | | | | the same lifetime is elided here | the lifetime is named here @@ -509,10 +506,10 @@ LL | fn multiple_outputs<'a>(v: &'a u8) -> (&'a u8, &'a u8) { | ++ ++ error: hiding or eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:232:53 + --> $DIR/mismatched-lifetime-syntaxes.rs:232:62 | LL | fn all_three_categories<'a>(v: ContainsLifetime<'a>) -> (&u8, ContainsLifetime) { - | ^^ --- ---------------- the same lifetime is hidden here + | -- ^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | | | the same lifetime is elided here | the lifetime is named here @@ -524,10 +521,10 @@ LL | fn all_three_categories<'a>(v: ContainsLifetime<'a>) -> (&'a u8, Contai | ++ ++++ error: eliding a lifetime that's named elsewhere is confusing - --> $DIR/mismatched-lifetime-syntaxes.rs:237:38 + --> $DIR/mismatched-lifetime-syntaxes.rs:237:49 | LL | fn explicit_bound_output<'a>(v: &'a u8) -> (&u8, &'a u8, ContainsLifetime<'a>) { - | ^^ --- -- -- the same lifetime is named here + | -- ^^^ -- -- the same lifetime is named here | | | | | | | the same lifetime is named here | | the same lifetime is elided here @@ -543,7 +540,7 @@ error: hiding a lifetime that's elided elsewhere is confusing --> $DIR/mismatched-lifetime-syntaxes.rs:250:45 | LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime; - | ^^^ ---------------- the same lifetime is hidden here + | ^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is elided here | @@ -557,7 +554,7 @@ error: hiding a lifetime that's elided elsewhere is confusing --> $DIR/mismatched-lifetime-syntaxes.rs:253:49 | LL | fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime; - | ^^^^^ ---------------- the same lifetime is hidden here + | ^^^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is elided here | @@ -571,7 +568,7 @@ error: hiding a lifetime that's elided elsewhere is confusing --> $DIR/mismatched-lifetime-syntaxes.rs:258:45 | LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime { - | ^^^ ---------------- the same lifetime is hidden here + | ^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is elided here | @@ -585,7 +582,7 @@ error: hiding a lifetime that's elided elsewhere is confusing --> $DIR/mismatched-lifetime-syntaxes.rs:263:49 | LL | fn method_implicit_ref_to_implicit_path(&self) -> ContainsLifetime { - | ^^^^^ ---------------- the same lifetime is hidden here + | ^^^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is elided here | @@ -599,7 +596,7 @@ error: hiding a lifetime that's elided elsewhere is confusing --> $DIR/mismatched-lifetime-syntaxes.rs:277:45 | LL | fn implicit_ref_to_implicit_path(v: &u8) -> ContainsLifetime; - | ^^^ ---------------- the same lifetime is hidden here + | ^^^ ^^^^^^^^^^^^^^^^ the same lifetime is hidden here | | | the lifetime is elided here | diff --git a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr index 7108fa1a2908b..1a5c87114d476 100644 --- a/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr +++ b/tests/ui/self/elision/ignore-non-reference-lifetimes.stderr @@ -1,8 +1,8 @@ warning: eliding a lifetime that's named elsewhere is confusing - --> $DIR/ignore-non-reference-lifetimes.rs:6:30 + --> $DIR/ignore-non-reference-lifetimes.rs:6:41 | LL | fn a<'a>(self: Self, a: &'a str) -> &str { - | ^^ ---- the same lifetime is elided here + | -- ^^^^ the same lifetime is elided here | | | the lifetime is named here | @@ -14,10 +14,10 @@ LL | fn a<'a>(self: Self, a: &'a str) -> &'a str { | ++ warning: eliding a lifetime that's named elsewhere is confusing - --> $DIR/ignore-non-reference-lifetimes.rs:10:33 + --> $DIR/ignore-non-reference-lifetimes.rs:10:44 | LL | fn b<'a>(self: Foo<'b>, a: &'a str) -> &str { - | ^^ ---- the same lifetime is elided here + | -- ^^^^ the same lifetime is elided here | | | the lifetime is named here | diff --git a/tests/ui/self/self_lifetime-async.stderr b/tests/ui/self/self_lifetime-async.stderr index 43dc96abdc2ed..78cc610fd0436 100644 --- a/tests/ui/self/self_lifetime-async.stderr +++ b/tests/ui/self/self_lifetime-async.stderr @@ -1,8 +1,8 @@ warning: eliding a lifetime that's named elsewhere is confusing - --> $DIR/self_lifetime-async.rs:6:29 + --> $DIR/self_lifetime-async.rs:6:44 | LL | async fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } - | ^^ --- the same lifetime is elided here + | -- ^^^ the same lifetime is elided here | | | the lifetime is named here | @@ -14,10 +14,10 @@ LL | async fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } | ++ warning: eliding a lifetime that's named elsewhere is confusing - --> $DIR/self_lifetime-async.rs:12:42 + --> $DIR/self_lifetime-async.rs:12:52 | LL | async fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } - | ^^ --- the same lifetime is elided here + | -- ^^^ the same lifetime is elided here | | | the lifetime is named here | diff --git a/tests/ui/self/self_lifetime.stderr b/tests/ui/self/self_lifetime.stderr index 4f9b2fcd2ad05..84f6345463306 100644 --- a/tests/ui/self/self_lifetime.stderr +++ b/tests/ui/self/self_lifetime.stderr @@ -1,8 +1,8 @@ warning: eliding a lifetime that's named elsewhere is confusing - --> $DIR/self_lifetime.rs:7:23 + --> $DIR/self_lifetime.rs:7:38 | LL | fn foo<'b>(self: &'b Foo<'a>) -> &() { self.0 } - | ^^ --- the same lifetime is elided here + | -- ^^^ the same lifetime is elided here | | | the lifetime is named here | @@ -14,10 +14,10 @@ LL | fn foo<'b>(self: &'b Foo<'a>) -> &'b () { self.0 } | ++ warning: eliding a lifetime that's named elsewhere is confusing - --> $DIR/self_lifetime.rs:13:36 + --> $DIR/self_lifetime.rs:13:46 | LL | fn bar<'a>(self: &Alias, arg: &'a ()) -> &() { arg } - | ^^ --- the same lifetime is elided here + | -- ^^^ the same lifetime is elided here | | | the lifetime is named here |