Auto merge of #130145 - fee1-dead-contrib:repeatn, r=lcnr,workingjubilee · qinheping/verify-rust-std@8a5922f (original) (raw)

``

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 {

`

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 {

`

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 {

`

80

78

`count: usize,

`

81

``

`-

// Invariant: has been dropped iff count == 0.

`

82

``

`-

element: ManuallyDrop,

`

``

79

`+

// Invariant: uninit iff count == 0.

`

``

80

`+

element: MaybeUninit,

`

83

81

`}

`

84

82

``

85

83

`impl RepeatN {

`

``

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 {

`

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 {

`

``

112

`+

fn clone(&self) -> RepeatN {

`

``

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 {

`

``

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 Drop for RepeatN {

`

104

132

`fn drop(&mut self) {

`

`@@ -194,9 +222,11 @@ impl<A: Clone> UncheckedIterator for RepeatN {

`

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

`}

`