Skip to content

core::slice::Iter and core::slice::IterMut could be replaced with safe code #120438

Closed
@HomelikeBrick42

Description

@HomelikeBrick42

The title says it, i dont see any reason why the current unsafe implementation using pointers is necessary when it could be written entirely in safe code without too much hassle

use core::{iter::FusedIterator, mem::take};

struct IterMut<'a, T> {
    slice: &'a mut [T],
}

impl<'a, T> Iterator for IterMut<'a, T> {
    type Item = &'a mut T;

    fn next(&mut self) -> Option<Self::Item> {
        let [first, rest @ ..] = take(&mut self.slice) else {
            return None;
        };
        self.slice = rest;
        Some(first)
    }

    fn size_hint(&self) -> (usize, Option<usize>) {
        (self.slice.len(), Some(self.slice.len()))
    }

    fn count(self) -> usize
    where
        Self: Sized,
    {
        self.slice.len()
    }

    fn last(mut self) -> Option<Self::Item>
    where
        Self: Sized,
    {
        self.next_back()
    }

    fn nth(&mut self, n: usize) -> Option<Self::Item> {
        let Some([value, rest @ ..]) = take(&mut self.slice).get_mut(n..) else {
            return None;
        };
        self.slice = rest;
        Some(value)
    }
}

impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
    fn next_back(&mut self) -> Option<Self::Item> {
        let [rest @ .., last] = take(&mut self.slice) else {
            return None;
        };
        self.slice = rest;
        Some(last)
    }

    fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
        let Some(new_end) = self.slice.len().checked_sub(n) else {
            self.slice = &mut [];
            return None;
        };

        let Some([rest @ .., last]) = take(&mut self.slice).get_mut(..new_end) else {
            return None;
        };
        self.slice = rest;
        Some(last)
    }
}

impl<'a, T> FusedIterator for IterMut<'a, T> {}
impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-iteratorsArea: IteratorsC-discussionCategory: Discussion or questions that doesn't represent real issues.T-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions