about summary refs log tree commit diff
path: root/compiler/rustc_lint/src/ptr_nulls.rs
diff options
context:
space:
mode:
authorLuigi Sartor Piucco <luigipiucco@gmail.com>2025-04-20 18:43:54 -0300
committerLuigi Sartor Piucco <luigipiucco@gmail.com>2025-07-18 13:41:34 -0300
commit8a8717e971dbdc6155506a4332e9ce8ef9151caa (patch)
tree48e29535f42dbde0b4c37a1981c74eca3d06b693 /compiler/rustc_lint/src/ptr_nulls.rs
parentbf5e6cc7a7a7eb03e3ed9b875d76530eddd47d5f (diff)
downloadrust-8a8717e971dbdc6155506a4332e9ce8ef9151caa.tar.gz
rust-8a8717e971dbdc6155506a4332e9ce8ef9151caa.zip
fix: don't panic on volatile access to null
According to
https://discourse.llvm.org/t/rfc-volatile-access-to-non-dereferenceable-memory-may-be-well-defined/86303/4,
LLVM allows volatile operations on null and handles it correctly. This
should be allowed in Rust as well, because I/O memory may be hard-coded
to address 0 in some cases, like the AVR chip ATtiny1626.

A test case that ensured a failure when passing null to volatile was
removed, since it's now valid.

Due to the addition of `maybe_is_aligned` to `ub_checks`,
`maybe_is_aligned_and_not_null` was refactored to use it.

docs: revise restrictions on volatile operations

A distinction between usage on Rust memory vs. non-Rust memory was
introduced. Documentation was reworded to explain what that means, and
make explicit that:

- No trapping can occur from volatile operations;
- On Rust memory, all safety rules must be respected;
- On Rust memory, the primary difference from regular access is that
  volatile always involves a memory dereference;
- On Rust memory, the only data affected by an operation is the one
  pointed to in the argument(s) of the function;
- On Rust memory, provenance follows the same rules as non-volatile
  access;
- On non-Rust memory, any address known to not contain Rust memory is
  valid (including 0 and usize::MAX);
- On non-Rust memory, no Rust memory may be affected (it is implicit
  that any other non-Rust memory may be affected, though, even if not
  referenced by the pointer). This should be relevant when, for example,
  reading register A causes a flag to change in register B, or writing
  to A causes B to change in some way. Everything affected mustn't be
  inside an allocation.
- On non-Rust memory, provenance is irrelevant and a pointer with none
  can be used in a valid way.

fix: don't lint null as UB for volatile

Also remove a now-unneeded `allow` line.

fix: additional wording nits
Diffstat (limited to 'compiler/rustc_lint/src/ptr_nulls.rs')
-rw-r--r--compiler/rustc_lint/src/ptr_nulls.rs4
1 files changed, 1 insertions, 3 deletions
diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs
index 826bce2c315..b2fa0fba76d 100644
--- a/compiler/rustc_lint/src/ptr_nulls.rs
+++ b/compiler/rustc_lint/src/ptr_nulls.rs
@@ -160,12 +160,10 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks {
                 let (arg_indices, are_zsts_allowed): (&[_], _) = match diag_name {
                     sym::ptr_read
                     | sym::ptr_read_unaligned
-                    | sym::ptr_read_volatile
                     | sym::ptr_replace
                     | sym::ptr_write
                     | sym::ptr_write_bytes
-                    | sym::ptr_write_unaligned
-                    | sym::ptr_write_volatile => (&[0], true),
+                    | sym::ptr_write_unaligned => (&[0], true),
                     sym::slice_from_raw_parts | sym::slice_from_raw_parts_mut => (&[0], false),
                     sym::ptr_copy
                     | sym::ptr_copy_nonoverlapping