Re: [PATCH 6/9] rust: list: add iterators

From: Benno Lossin
Date: Thu Apr 04 2024 - 10:52:54 EST


On 04.04.24 16:41, Alice Ryhl wrote:
> On Thu, Apr 4, 2024 at 4:36 PM Benno Lossin <benno.lossin@xxxxxxxxx> wrote:
>>
>> On 02.04.24 14:17, Alice Ryhl wrote:
>>> +/// the end of the list. The `stop` pointer points at the first value in the same list, or it is
>>> +/// null if the list is empty.
>>> +#[derive(Clone)]
>>> +pub struct Iter<'a, T: ?Sized + ListItem<ID>, const ID: u64 = 0> {
>>> + current: *mut ListLinksFields,
>>> + stop: *mut ListLinksFields,
>>> + _ty: PhantomData<&'a ListArc<T, ID>>,
>>> +}
>>> +
>>> +impl<'a, T: ?Sized + ListItem<ID>, const ID: u64> Iterator for Iter<'a, T, ID> {
>>> + type Item = ArcBorrow<'a, T>;
>>> +
>>> + fn next(&mut self) -> Option<ArcBorrow<'a, T>> {
>>> + if self.current.is_null() {
>>> + return None;
>>> + }
>>> +
>>> + let current = self.current;
>>> +
>>> + // SAFETY: We just checked that `current` is not null, so it is in a list, and hence not
>>> + // dangling. There's no race because the iterator holds an immutable borrow to the list.
>>
>> This (that the iterator holds an immutable borrow) is not true (there
>> is no `&List` field in `Iter`), but you can make that an invariant
>> instead.
>
> What I mean is that the borrow-checker will consider the `List` to be
> borrowed by `Iter`. Whether or not there is a real reference or not
> doesn't matter.

Yes, but that is implementation detail of the safe function
`List::iter`, so I think it must also be captured by an invariant.

--
Cheers,
Benno