about summary refs log tree commit diff
diff options
context:
space:
mode:
authorScott McMurray <scottmcm@users.noreply.github.com>2025-02-14 22:59:19 -0800
committerScott McMurray <scottmcm@users.noreply.github.com>2025-02-14 22:59:19 -0800
commit7add35831955f8fc5ba08dcdb93921cd8de17841 (patch)
treefbb7f7eb8c9bd79473c95192897dbad8c82006ed
parent39118d6181df1ffef6e4407bbf273542ae5efe3c (diff)
downloadrust-7add35831955f8fc5ba08dcdb93921cd8de17841.tar.gz
rust-7add35831955f8fc5ba08dcdb93921cd8de17841.zip
Add real safety comments
-rw-r--r--library/core/src/slice/iter/macros.rs15
1 files changed, 14 insertions, 1 deletions
diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs
index c4b8583b75f..b1456a1bc1d 100644
--- a/library/core/src/slice/iter/macros.rs
+++ b/library/core/src/slice/iter/macros.rs
@@ -159,20 +159,33 @@ macro_rules! iterator {
 
                 let ptr = self.ptr;
                 let end_or_len = self.end_or_len;
-                // SAFETY: Type invariants.
+                // SAFETY: See inner comments. (For some reason having multiple
+                // block breaks inlining this -- if you can fix that please do!)
                 unsafe {
                     if T::IS_ZST {
                         let len = end_or_len.addr();
                         if len == 0 {
                             return None;
                         }
+                        // SAFETY: just checked that it's not zero, so subtracting one
+                        // cannot wrap.  (Ideally this would be `checked_sub`, which
+                        // does the same thing internally, but as of 2025-02 that
+                        // doesn't optimize quite as small in MIR.)
                         self.end_or_len = without_provenance_mut(len.unchecked_sub(1));
                     } else {
+                        // SAFETY: by type invariant, the `end_or_len` field is always
+                        // non-null for a non-ZST pointee.  (This transmute ensures we
+                        // get `!nonnull` metadata on the load of the field.)
                         if ptr == crate::intrinsics::transmute::<$ptr, NonNull<T>>(end_or_len) {
                             return None;
                         }
+                        // SAFETY: since it's not empty, per the check above, moving
+                        // forward one keeps us inside the slice, and this is valid.
                         self.ptr = ptr.add(1);
                     }
+                    // SAFETY: Now that we know it wasn't empty and we've moved past
+                    // the first one (to avoid giving a duplicate `&mut` next time),
+                    // we can give out a reference to it.
                     Some({ptr}.$into_ref())
                 }
             }