@@ -84,6 +84,135 @@ impl<T, const N: usize> IntoIter<T, N> {
84
84
IntoIterator :: into_iter ( array)
85
85
}
86
86
87
+ /// Creates an iterator over the elements in a partially-initialized buffer.
88
+ ///
89
+ /// If you have a fully-initialized array, then use [`IntoIterator`].
90
+ /// But this is useful for returning partial results from unsafe code.
91
+ ///
92
+ /// # Safety
93
+ ///
94
+ /// - The `buffer[initialized]` elements must all be initialized.
95
+ /// - The range must be canonical, with `initialized.start <= initialized.end`.
96
+ /// - The range must in in-bounds for the buffer, with `initialized.end <= N`.
97
+ /// (Like how indexing `[0][100..100]` fails despite the range being empty.)
98
+ ///
99
+ /// It's sound to have more elements initialized than mentioned, though that
100
+ /// will most likely result in them being leaked.
101
+ ///
102
+ /// # Examples
103
+ ///
104
+ /// ```
105
+ /// #![feature(array_into_iter_constructors)]
106
+ ///
107
+ /// #![feature(maybe_uninit_array_assume_init)]
108
+ /// #![feature(maybe_uninit_uninit_array)]
109
+ /// use std::array::IntoIter;
110
+ /// use std::mem::MaybeUninit;
111
+ ///
112
+ /// # // Hi! Thanks for reading the code. This is restricted to `Copy` because
113
+ /// # // otherwise it could leak. A fully-general version this would need a drop
114
+ /// # // guard to handle panics from the iterator, but this works for an example.
115
+ /// fn next_chunk<T: Copy, const N: usize>(
116
+ /// it: &mut impl Iterator<Item = T>,
117
+ /// ) -> Result<[T; N], IntoIter<T, N>> {
118
+ /// let mut buffer = MaybeUninit::uninit_array();
119
+ /// let mut i = 0;
120
+ /// while i < N {
121
+ /// match it.next() {
122
+ /// Some(x) => {
123
+ /// buffer[i].write(x);
124
+ /// i += 1;
125
+ /// }
126
+ /// None => {
127
+ /// // SAFETY: We've initialized the first `i` items
128
+ /// unsafe {
129
+ /// return Err(IntoIter::new_unchecked(buffer, 0..i));
130
+ /// }
131
+ /// }
132
+ /// }
133
+ /// }
134
+ ///
135
+ /// // SAFETY: We've initialized all N items
136
+ /// unsafe { Ok(MaybeUninit::array_assume_init(buffer)) }
137
+ /// }
138
+ ///
139
+ /// let r: [_; 4] = next_chunk(&mut (10..16)).unwrap();
140
+ /// assert_eq!(r, [10, 11, 12, 13]);
141
+ /// let r: IntoIter<_, 40> = next_chunk(&mut (10..16)).unwrap_err();
142
+ /// assert_eq!(r.collect::<Vec<_>>(), vec![10, 11, 12, 13, 14, 15]);
143
+ /// ```
144
+ #[ unstable( feature = "array_into_iter_constructors" , issue = "91583" ) ]
145
+ #[ rustc_const_unstable( feature = "const_array_into_iter_constructors" , issue = "91583" ) ]
146
+ pub const unsafe fn new_unchecked (
147
+ buffer : [ MaybeUninit < T > ; N ] ,
148
+ initialized : Range < usize > ,
149
+ ) -> Self {
150
+ Self { data : buffer, alive : initialized }
151
+ }
152
+
153
+ /// Creates an iterator over `T` which returns no elements.
154
+ ///
155
+ /// If you just need an empty iterator, then use
156
+ /// [`iter::empty()`](crate::iter::empty) instead.
157
+ /// And if you need an empty array, use `[]`.
158
+ ///
159
+ /// But this is useful when you need an `array::IntoIter<T, N>` *specifically*.
160
+ ///
161
+ /// # Examples
162
+ ///
163
+ /// ```
164
+ /// #![feature(array_into_iter_constructors)]
165
+ /// use std::array::IntoIter;
166
+ ///
167
+ /// let empty = IntoIter::<i32, 3>::empty();
168
+ /// assert_eq!(empty.len(), 0);
169
+ /// assert_eq!(empty.as_slice(), &[]);
170
+ ///
171
+ /// let empty = IntoIter::<std::convert::Infallible, 200>::empty();
172
+ /// assert_eq!(empty.len(), 0);
173
+ /// ```
174
+ ///
175
+ /// `[1, 2].into_iter()` and `[].into_iter()` have different types
176
+ /// ```should_fail,edition2021
177
+ /// #![feature(array_into_iter_constructors)]
178
+ /// use std::array::IntoIter;
179
+ ///
180
+ /// pub fn get_bytes(b: bool) -> IntoIter<i8, 4> {
181
+ /// if b {
182
+ /// [1, 2, 3, 4].into_iter()
183
+ /// } else {
184
+ /// [].into_iter() // error[E0308]: mismatched types
185
+ /// }
186
+ /// }
187
+ /// ```
188
+ ///
189
+ /// But using this method you can get an empty iterator of appropriate size:
190
+ /// ```edition2021
191
+ /// #![feature(array_into_iter_constructors)]
192
+ /// use std::array::IntoIter;
193
+ ///
194
+ /// pub fn get_bytes(b: bool) -> IntoIter<i8, 4> {
195
+ /// if b {
196
+ /// [1, 2, 3, 4].into_iter()
197
+ /// } else {
198
+ /// IntoIter::empty()
199
+ /// }
200
+ /// }
201
+ ///
202
+ /// assert_eq!(get_bytes(true).collect::<Vec<_>>(), vec![1, 2, 3, 4]);
203
+ /// assert_eq!(get_bytes(false).collect::<Vec<_>>(), vec![]);
204
+ /// ```
205
+ #[ unstable( feature = "array_into_iter_constructors" , issue = "91583" ) ]
206
+ #[ rustc_const_unstable( feature = "const_array_into_iter_constructors" , issue = "91583" ) ]
207
+ pub const fn empty ( ) -> Self {
208
+ let buffer = MaybeUninit :: uninit_array ( ) ;
209
+ let initialized = 0 ..0 ;
210
+
211
+ // SAFETY: We're telling it that none of the elements are initialized,
212
+ // which is trivially true. And ∀N: usize, 0 <= N.
213
+ unsafe { Self :: new_unchecked ( buffer, initialized) }
214
+ }
215
+
87
216
/// Returns an immutable slice of all elements that have not been yielded
88
217
/// yet.
89
218
#[ stable( feature = "array_value_iter" , since = "1.51.0" ) ]
0 commit comments