1
+ use crate :: fmt;
1
2
use crate :: iter:: { FusedIterator , TrustedLen , UncheckedIterator } ;
2
- use crate :: mem:: ManuallyDrop ;
3
+ use crate :: mem:: { self , MaybeUninit } ;
3
4
use crate :: num:: NonZero ;
4
5
5
6
/// Creates a new iterator that repeats a single element a given number of times.
@@ -58,14 +59,12 @@ use crate::num::NonZero;
58
59
#[ inline]
59
60
#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
60
61
pub fn repeat_n < T : Clone > ( element : T , count : usize ) -> RepeatN < T > {
61
- let mut element = ManuallyDrop :: new ( element) ;
62
-
63
- if count == 0 {
64
- // SAFETY: we definitely haven't dropped it yet, since we only just got
65
- // passed it in, and because the count is zero the instance we're about
66
- // to create won't drop it, so to avoid leaking we need to now.
67
- unsafe { ManuallyDrop :: drop ( & mut element) } ;
68
- }
62
+ let element = if count == 0 {
63
+ // `element` gets dropped eagerly.
64
+ MaybeUninit :: uninit ( )
65
+ } else {
66
+ MaybeUninit :: new ( element)
67
+ } ;
69
68
70
69
RepeatN { element, count }
71
70
}
@@ -74,31 +73,60 @@ pub fn repeat_n<T: Clone>(element: T, count: usize) -> RepeatN<T> {
74
73
///
75
74
/// This `struct` is created by the [`repeat_n()`] function.
76
75
/// See its documentation for more.
77
- #[ derive( Clone , Debug ) ]
78
76
#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
79
77
pub struct RepeatN < A > {
80
78
count : usize ,
81
- // Invariant: has been dropped iff count == 0.
82
- element : ManuallyDrop < A > ,
79
+ // Invariant: uninit iff count == 0.
80
+ element : MaybeUninit < A > ,
83
81
}
84
82
85
83
impl < A > RepeatN < A > {
84
+ /// Returns the element if it hasn't been dropped already.
85
+ fn element_ref ( & self ) -> Option < & A > {
86
+ if self . count > 0 {
87
+ // SAFETY: The count is non-zero, so it must be initialized.
88
+ Some ( unsafe { self . element . assume_init_ref ( ) } )
89
+ } else {
90
+ None
91
+ }
92
+ }
86
93
/// If we haven't already dropped the element, return it in an option.
87
94
///
88
95
/// Clears the count so it won't be dropped again later.
89
96
#[ inline]
90
97
fn take_element ( & mut self ) -> Option < A > {
91
98
if self . count > 0 {
92
99
self . count = 0 ;
100
+ let element = mem:: replace ( & mut self . element , MaybeUninit :: uninit ( ) ) ;
93
101
// SAFETY: We just set count to zero so it won't be dropped again,
94
102
// and it used to be non-zero so it hasn't already been dropped.
95
- unsafe { Some ( ManuallyDrop :: take ( & mut self . element ) ) }
103
+ unsafe { Some ( element. assume_init ( ) ) }
96
104
} else {
97
105
None
98
106
}
99
107
}
100
108
}
101
109
110
+ #[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
111
+ impl < A : Clone > Clone for RepeatN < A > {
112
+ fn clone ( & self ) -> RepeatN < A > {
113
+ RepeatN {
114
+ count : self . count ,
115
+ element : self . element_ref ( ) . cloned ( ) . map_or_else ( MaybeUninit :: uninit, MaybeUninit :: new) ,
116
+ }
117
+ }
118
+ }
119
+
120
+ #[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
121
+ impl < A : fmt:: Debug > fmt:: Debug for RepeatN < A > {
122
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
123
+ f. debug_struct ( "RepeatN" )
124
+ . field ( "count" , & self . count )
125
+ . field ( "element" , & self . element_ref ( ) )
126
+ . finish ( )
127
+ }
128
+ }
129
+
102
130
#[ stable( feature = "iter_repeat_n" , since = "1.82.0" ) ]
103
131
impl < A > Drop for RepeatN < A > {
104
132
fn drop ( & mut self ) {
@@ -194,9 +222,11 @@ impl<A: Clone> UncheckedIterator for RepeatN<A> {
194
222
// SAFETY: the check above ensured that the count used to be non-zero,
195
223
// so element hasn't been dropped yet, and we just lowered the count to
196
224
// zero so it won't be dropped later, and thus it's okay to take it here.
197
- unsafe { ManuallyDrop :: take ( & mut self . element ) }
225
+ unsafe { mem :: replace ( & mut self . element , MaybeUninit :: uninit ( ) ) . assume_init ( ) }
198
226
} else {
199
- A :: clone ( & self . element )
227
+ // SAFETY: the count is non-zero, so it must have not been dropped yet.
228
+ let element = unsafe { self . element . assume_init_ref ( ) } ;
229
+ A :: clone ( element)
200
230
}
201
231
}
202
232
}
0 commit comments