Skip to content

Add a raw pointer iterator #91390

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -202,6 +202,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
flags.push((sym::_Self, Some("{integral}".to_owned())));
}

if let ty::RawPtr(ptr) = self_ty.kind() {
let string = match ptr.mutbl {
hir::Mutability::Mut => "*mut T",
hir::Mutability::Not => "*const T",
};
flags.push((sym::_Self, Some(string.to_owned())));
}
if let ty::Array(aty, len) = self_ty.kind() {
flags.push((sym::_Self, Some("[]".to_owned())));
flags.push((sym::_Self, Some(format!("[{}]", aty))));
4 changes: 4 additions & 0 deletions library/core/src/iter/range.rs
Original file line number Diff line number Diff line change
@@ -21,6 +21,10 @@ unsafe_impl_trusted_step![char i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usi
/// The *successor* operation moves towards values that compare greater.
/// The *predecessor* operation moves towards values that compare lesser.
#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
#[rustc_on_unimplemented(
on(_Self = "*const T", label = "use core::ptr::IterConst to iterate a range of pointers"),
on(_Self = "*mut T", label = "use core::ptr::IterMut to iterate a range of pointers")
)]
pub trait Step: Clone + PartialOrd + Sized {
/// Returns the number of *successor* steps required to get from `start` to `end`.
///
513 changes: 513 additions & 0 deletions library/core/src/ptr/iter.rs

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions library/core/src/ptr/mod.rs
Original file line number Diff line number Diff line change
@@ -90,6 +90,10 @@ pub use crate::intrinsics::copy;
#[doc(inline)]
pub use crate::intrinsics::write_bytes;

mod iter;
#[unstable(feature = "ptr_iter", issue = "none")]
pub use iter::{IterConst, IterMut};

mod metadata;
pub(crate) use metadata::PtrRepr;
#[unstable(feature = "ptr_metadata", issue = "81513")]
1 change: 1 addition & 0 deletions library/core/tests/lib.rs
Original file line number Diff line number Diff line change
@@ -63,6 +63,7 @@
#![feature(unwrap_infallible)]
#![feature(result_into_ok_or_err)]
#![cfg_attr(not(bootstrap), feature(portable_simd))]
#![feature(ptr_iter)]
#![feature(ptr_metadata)]
#![feature(once_cell)]
#![feature(unsized_tuple_coercion)]
2 changes: 2 additions & 0 deletions library/core/tests/ptr.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
mod iter;

use core::cell::RefCell;
use core::ptr;
use core::ptr::*;
97 changes: 97 additions & 0 deletions library/core/tests/ptr/iter.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
use core::ops::Range;
use core::ptr::IterConst;

#[test]
fn test_ptr_iter_empty() {
let start = &() as *const () as *const [u8; 100];
let mut iter = unsafe { IterConst::new(start, start) };
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.nth(0), None);
assert_eq!(iter.nth(1), None);
assert_eq!(iter.advance_by(0), Ok(()));
assert_eq!(iter.advance_by(1), Err(0));
assert_eq!(iter.next_back(), None);
assert_eq!(iter.nth_back(0), None);
assert_eq!(iter.nth_back(1), None);
assert_eq!(iter.advance_back_by(0), Ok(()));
assert_eq!(iter.advance_back_by(1), Err(0));
assert_eq!(iter, unsafe { IterConst::new(start, start) });
}

#[test]
fn test_ptr_iter() {
let data = [[0u8; 10]; 12];
let Range { start, end } = data.as_ptr_range();
let mut iter = unsafe { IterConst::new(start, end) };
assert_eq!(iter.size_hint(), (12, Some(12)));
assert_eq!(iter.next(), Some(&data[0] as _));
assert_eq!(iter, unsafe { IterConst::new(&data[1], end) });
assert_eq!(iter.nth(0), Some(&data[1] as _));
assert_eq!(iter, unsafe { IterConst::new(&data[2], end) });
assert_eq!(iter.nth(1), Some(&data[3] as _));
assert_eq!(iter, unsafe { IterConst::new(&data[4], end) });
assert_eq!(iter.advance_by(0), Ok(()));
assert_eq!(iter, unsafe { IterConst::new(&data[4], end) });
assert_eq!(iter.advance_by(1), Ok(()));
assert_eq!(iter, unsafe { IterConst::new(&data[5], end) });
assert_eq!(iter.next_back(), Some(&data[11] as _));
assert_eq!(iter, unsafe { IterConst::new(&data[5], &data[11]) });
assert_eq!(iter.nth_back(0), Some(&data[10] as _));
assert_eq!(iter, unsafe { IterConst::new(&data[5], &data[10]) });
assert_eq!(iter.nth_back(1), Some(&data[8] as _));
assert_eq!(iter, unsafe { IterConst::new(&data[5], &data[8]) });
assert_eq!(iter.advance_back_by(0), Ok(()));
assert_eq!(iter, unsafe { IterConst::new(&data[5], &data[8]) });
assert_eq!(iter.advance_back_by(1), Ok(()));
assert_eq!(iter, unsafe { IterConst::new(&data[5], &data[7]) });

let mut iter = unsafe { IterConst::new(start, end) };
assert_eq!(iter.nth(20), None);
assert_eq!(iter, unsafe { IterConst::new(end, end) });

let mut iter = unsafe { IterConst::new(start, end) };
assert_eq!(iter.advance_by(20), Err(12));
assert_eq!(iter, unsafe { IterConst::new(end, end) });

let mut iter = unsafe { IterConst::new(start, end) };
assert_eq!(iter.nth_back(20), None);
assert_eq!(iter, unsafe { IterConst::new(start, start) });

let mut iter = unsafe { IterConst::new(start, end) };
assert_eq!(iter.advance_back_by(20), Err(12));
assert_eq!(iter, unsafe { IterConst::new(start, start) });
}

#[test]
fn test_ptr_iter_zero_sized() {
let start = &0i32 as *const i32 as *const ();
let mut iter = unsafe { IterConst::new(start, start) };
assert_eq!(iter.size_hint(), (0, Some(0)));
assert_eq!(iter.next(), None);
assert_eq!(iter.nth(0), None);
assert_eq!(iter.nth(1), None);
assert_eq!(iter.advance_by(0), Ok(()));
assert_eq!(iter.advance_by(1), Err(0));
assert_eq!(iter.next_back(), None);
assert_eq!(iter.nth_back(0), None);
assert_eq!(iter.nth_back(1), None);
assert_eq!(iter.advance_back_by(0), Ok(()));
assert_eq!(iter.advance_back_by(1), Err(0));
assert_eq!(iter, unsafe { IterConst::new(start, start) });

let end = unsafe { start.cast::<i32>().add(1).cast::<()>() };
let mut iter = unsafe { IterConst::new(start, end) };
assert_eq!(iter.size_hint(), (usize::MAX, None));
assert_eq!(iter.next(), Some(start));
assert_eq!(iter.nth(0), Some(start));
assert_eq!(iter.nth(1), Some(start));
assert_eq!(iter.advance_by(0), Ok(()));
assert_eq!(iter.advance_by(1), Ok(()));
assert_eq!(iter.next_back(), Some(start));
assert_eq!(iter.nth_back(0), Some(start));
assert_eq!(iter.nth_back(1), Some(start));
assert_eq!(iter.advance_back_by(0), Ok(()));
assert_eq!(iter.advance_back_by(1), Ok(()));
assert_eq!(iter, unsafe { IterConst::new(start, end) });
}
5 changes: 5 additions & 0 deletions src/test/ui/iterators/ptr-range.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
fn main() {
let range = [0i32].as_ptr_range();
for _ in range {}
//~^ ERROR: the trait bound `*const i32: Step` is not satisfied
}
13 changes: 13 additions & 0 deletions src/test/ui/iterators/ptr-range.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0277]: the trait bound `*const i32: Step` is not satisfied
--> $DIR/ptr-range.rs:3:14
|
LL | for _ in range {}
| ^^^^^ use core::ptr::IterConst to iterate a range of pointers
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very nice! ❤️

|
= help: the trait `Step` is not implemented for `*const i32`
= note: required because of the requirements on the impl of `Iterator` for `std::ops::Range<*const i32>`
= note: required because of the requirements on the impl of `IntoIterator` for `std::ops::Range<*const i32>`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.