@@ -159,20 +159,33 @@ macro_rules! iterator {
159
159
160
160
let ptr = self . ptr;
161
161
let end_or_len = self . end_or_len;
162
- // SAFETY: Type invariants.
162
+ // SAFETY: See inner comments. (For some reason having multiple
163
+ // block breaks inlining this -- if you can fix that please do!)
163
164
unsafe {
164
165
if T :: IS_ZST {
165
166
let len = end_or_len. addr( ) ;
166
167
if len == 0 {
167
168
return None ;
168
169
}
170
+ // SAFETY: just checked that it's not zero, so subtracting one
171
+ // cannot wrap. (Ideally this would be `checked_sub`, which
172
+ // does the same thing internally, but as of 2025-02 that
173
+ // doesn't optimize quite as small in MIR.)
169
174
self . end_or_len = without_provenance_mut( len. unchecked_sub( 1 ) ) ;
170
175
} else {
176
+ // SAFETY: by type invariant, the `end_or_len` field is always
177
+ // non-null for a non-ZST pointee. (This transmute ensures we
178
+ // get `!nonnull` metadata on the load of the field.)
171
179
if ptr == crate :: intrinsics:: transmute:: <$ptr, NonNull <T >>( end_or_len) {
172
180
return None ;
173
181
}
182
+ // SAFETY: since it's not empty, per the check above, moving
183
+ // forward one keeps us inside the slice, and this is valid.
174
184
self . ptr = ptr. add( 1 ) ;
175
185
}
186
+ // SAFETY: Now that we know it wasn't empty and we've moved past
187
+ // the first one (to avoid giving a duplicate `&mut` next time),
188
+ // we can give out a reference to it.
176
189
Some ( { ptr} . $into_ref( ) )
177
190
}
178
191
}
0 commit comments