@@ -2654,33 +2654,88 @@ declare_lint! {
2654
2654
///
2655
2655
/// ### Example
2656
2656
///
2657
+ /// ```rust
2658
+ /// #![feature(strict_provenance)]
2659
+ /// #![warn(fuzzy_provenance_casts)]
2660
+ ///
2657
2661
/// fn main() {
2658
- /// let my_ref = &0;
2659
- /// let my_addr = my_ref as usize;
2662
+ /// let _dangling = 16_usize as *const u8;
2660
2663
/// }
2661
2664
/// ```
2662
2665
///
2663
2666
/// {{produces}}
2664
2667
///
2665
2668
/// ### Explanation
2666
2669
///
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).
2672
2680
///
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`].
2675
2685
///
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
2678
2689
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;
2684
2739
}
2685
2740
2686
2741
declare_lint ! {
@@ -3137,6 +3192,7 @@ declare_lint_pass! {
3137
3192
INCOMPLETE_INCLUDE ,
3138
3193
CENUM_IMPL_DROP_CAST ,
3139
3194
FUZZY_PROVENANCE_CASTS ,
3195
+ LOSSY_PROVENANCE_CASTS ,
3140
3196
CONST_EVALUATABLE_UNCHECKED ,
3141
3197
INEFFECTIVE_UNSTABLE_TRAIT_IMPL ,
3142
3198
MUST_NOT_SUSPEND ,
0 commit comments