@@ -2654,33 +2654,88 @@ declare_lint! {
26542654 ///
26552655 /// ### Example
26562656 ///
2657+ /// ```rust
2658+ /// #![feature(strict_provenance)]
2659+ /// #![warn(fuzzy_provenance_casts)]
2660+ ///
26572661 /// fn main() {
2658- /// let my_ref = &0;
2659- /// let my_addr = my_ref as usize;
2662+ /// let _dangling = 16_usize as *const u8;
26602663 /// }
26612664 /// ```
26622665 ///
26632666 /// {{produces}}
26642667 ///
26652668 /// ### Explanation
26662669 ///
2667- /// Casting a pointer to an integer or an integer to a pointer is a lossy operation,
2668- /// because beyond just an *address* a pointer may be associated with a particular
2669- /// *provenance* and *segment*. This information is required by both the compiler
2670- /// and the hardware to correctly execute your code. If you need to do this kind
2671- /// of operation, use ptr::addr and ptr::with_addr.
2670+ /// This lint is part of the strict provenance effort, see [issue #95228].
2671+ /// Casting an integer to a pointer is considered bad style, as a pointer
2672+ /// contains, besides the *address* also a *provenance*, indicating what
2673+ /// memory the pointer is allowed to read/write. Casting an integer, which
2674+ /// doesn't have provenance, to a pointer requires the compiler to assign
2675+ /// (guess) provenance. The compiler assigns "all exposed valid" (see the
2676+ /// docs of [`ptr::from_exposed_addr`] for more information about this
2677+ /// "exposing"). This penalizes the optimiser and is not well suited for
2678+ /// dynamic analysis/dynamic program verification (e.g. Miri or CHERI
2679+ /// platforms).
26722680 ///
2673- /// This is a [future-incompatible] lint to transition this to a hard error
2674- /// in the future. See [issue #9999999] for more details.
2681+ /// It is much better to use [`ptr::with_addr`] instead to specify the
2682+ /// provenance you want. If using this function is not possible because the
2683+ /// code relies on exposed provenance then there is as an escape hatch
2684+ /// [`ptr::from_exposed_addr`].
26752685 ///
2676- /// [future-incompatible]: ../index.md#future-incompatible-lints
2677- /// [issue #9999999]: https://github.com/rust-lang/rust/issues/9999999
2686+ /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228
2687+ /// [`ptr::with_addr`]: https://doc.rust-lang.org/core/ptr/fn.with_addr
2688+ /// [`ptr::from_exposed_addr`]: https://doc.rust-lang.org/core/ptr/fn.from_exposed_addr
26782689 pub FUZZY_PROVENANCE_CASTS ,
2679- Warn ,
2680- "A lossy pointer-integer integer cast is used" ,
2681- @future_incompatible = FutureIncompatibleInfo {
2682- reference: "issue #9999999 <https://github.com/rust-lang/rust/issues/9999999>" ,
2683- } ;
2690+ Allow ,
2691+ "a fuzzy integer to pointer cast is used" ,
2692+ @feature_gate = sym:: strict_provenance;
2693+ }
2694+
2695+ declare_lint ! {
2696+ /// The `lossy_provenance_casts` lint detects an `as` cast between a pointer
2697+ /// and an integer.
2698+ ///
2699+ /// ### Example
2700+ ///
2701+ /// ```rust
2702+ /// #![feature(strict_provenance)]
2703+ /// #![warn(lossy_provenance_casts)]
2704+ ///
2705+ /// fn main() {
2706+ /// let x: u8 = 37;
2707+ /// let _addr: usize = &x as *const u8 as usize;
2708+ /// }
2709+ /// ```
2710+ ///
2711+ /// {{produces}}
2712+ ///
2713+ /// ### Explanation
2714+ ///
2715+ /// This lint is part of the strict provenance effort, see [issue #95228].
2716+ /// Casting a pointer to an integer is a lossy operation, because beyond
2717+ /// just an *address* a pointer may be associated with a particular
2718+ /// *provenance*. This information is used by the optimiser and for dynamic
2719+ /// analysis/dynamic program verification (e.g. Miri or CHERI platforms).
2720+ ///
2721+ /// Since this cast is lossy, it is considered good style to use the
2722+ /// [`ptr::addr`] method instead, which has a similar effect, but doesn't
2723+ /// "expose" the pointer provenance. This improves optimisation potential.
2724+ /// See the docs of [`ptr::addr`] and [`ptr::expose_addr`] for more information
2725+ /// about exposing pointer provenance.
2726+ ///
2727+ /// If your code can't comply with strict provenance and needs to expose
2728+ /// the provenance, then there is [`ptr::expose_addr`] as an escape hatch,
2729+ /// which preserves the behaviour of `as usize` casts while being explicit
2730+ /// about the semantics.
2731+ ///
2732+ /// [issue #95228]: https://github.com/rust-lang/rust/issues/95228
2733+ /// [`ptr::addr`]: https://doc.rust-lang.org/core/ptr/fn.addr
2734+ /// [`ptr::expose_addr`]: https://doc.rust-lang.org/core/ptr/fn.expose_addr
2735+ pub LOSSY_PROVENANCE_CASTS ,
2736+ Allow ,
2737+ "a lossy pointer to integer cast is used" ,
2738+ @feature_gate = sym:: strict_provenance;
26842739}
26852740
26862741declare_lint ! {
@@ -3137,6 +3192,7 @@ declare_lint_pass! {
31373192 INCOMPLETE_INCLUDE ,
31383193 CENUM_IMPL_DROP_CAST ,
31393194 FUZZY_PROVENANCE_CASTS ,
3195+ LOSSY_PROVENANCE_CASTS ,
31403196 CONST_EVALUATABLE_UNCHECKED ,
31413197 INEFFECTIVE_UNSTABLE_TRAIT_IMPL ,
31423198 MUST_NOT_SUSPEND ,
0 commit comments