about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--library/core/src/slice/iter/macros.rs16
-rw-r--r--tests/codegen/slice-iter-nonnull.rs42
2 files changed, 48 insertions, 10 deletions
diff --git a/library/core/src/slice/iter/macros.rs b/library/core/src/slice/iter/macros.rs
index 0a30033778b..d2d0dd3387f 100644
--- a/library/core/src/slice/iter/macros.rs
+++ b/library/core/src/slice/iter/macros.rs
@@ -124,12 +124,10 @@ macro_rules! iterator {
             fn next(&mut self) -> Option<$elem> {
                 // could be implemented with slices, but this avoids bounds checks
 
-                // SAFETY: `assume` calls are safe since a slice's start pointer
-                // must be non-null, and slices over non-ZSTs must also have a
-                // non-null end pointer. The call to `next_unchecked!` is safe
-                // since we check if the iterator is empty first.
+                // SAFETY: `assume` call is safe because slices over non-ZSTs must
+                // have a non-null end pointer. The call to `next_unchecked!` is
+                // safe since we check if the iterator is empty first.
                 unsafe {
-                    assume(!self.ptr.as_ptr().is_null());
                     if !<T>::IS_ZST {
                         assume(!self.end.is_null());
                     }
@@ -339,12 +337,10 @@ macro_rules! iterator {
             fn next_back(&mut self) -> Option<$elem> {
                 // could be implemented with slices, but this avoids bounds checks
 
-                // SAFETY: `assume` calls are safe since a slice's start pointer must be non-null,
-                // and slices over non-ZSTs must also have a non-null end pointer.
-                // The call to `next_back_unchecked!` is safe since we check if the iterator is
-                // empty first.
+                // SAFETY: `assume` call is safe because slices over non-ZSTs must
+                // have a non-null end pointer. The call to `next_back_unchecked!`
+                // is safe since we check if the iterator is empty first.
                 unsafe {
-                    assume(!self.ptr.as_ptr().is_null());
                     if !<T>::IS_ZST {
                         assume(!self.end.is_null());
                     }
diff --git a/tests/codegen/slice-iter-nonnull.rs b/tests/codegen/slice-iter-nonnull.rs
new file mode 100644
index 00000000000..392e4338076
--- /dev/null
+++ b/tests/codegen/slice-iter-nonnull.rs
@@ -0,0 +1,42 @@
+// no-system-llvm
+// compile-flags: -O
+// ignore-debug (these add extra checks that make it hard to verify)
+#![crate_type = "lib"]
+
+// The slice iterator used to `assume` that the `start` pointer was non-null.
+// That ought to be unneeded, though, since the type is `NonNull`, so this test
+// confirms that the appropriate metadata is included to denote that.
+
+// CHECK-LABEL: @slice_iter_next(
+#[no_mangle]
+pub fn slice_iter_next<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
+    // CHECK: %[[ENDP:.+]] = getelementptr{{.+}}ptr %it,{{.+}} 1
+    // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: %[[START:.+]] = load ptr, ptr %it,
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: icmp eq ptr %[[START]], %[[END]]
+
+    // CHECK: store ptr{{.+}}, ptr %it,
+
+    it.next()
+}
+
+// CHECK-LABEL: @slice_iter_next_back(
+#[no_mangle]
+pub fn slice_iter_next_back<'a>(it: &mut std::slice::Iter<'a, u32>) -> Option<&'a u32> {
+    // CHECK: %[[ENDP:.+]] = getelementptr{{.+}}ptr %it,{{.+}} 1
+    // CHECK: %[[END:.+]] = load ptr, ptr %[[ENDP]]
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: %[[START:.+]] = load ptr, ptr %it,
+    // CHECK-SAME: !nonnull
+    // CHECK-SAME: !noundef
+    // CHECK: icmp eq ptr %[[START]], %[[END]]
+
+    // CHECK: store ptr{{.+}}, ptr %[[ENDP]],
+
+    it.next_back()
+}