Skip to content

Commit cc661d8

Browse files
powerboat9CohenArthur
authored andcommitted
Improve Optional<T> implementation
gcc/rust/ChangeLog: * util/rust-optional.h (class Optional<T>): Improve inner state. Signed-off-by: Owen Avery <[email protected]>
1 parent ee5b590 commit cc661d8

File tree

1 file changed

+52
-28
lines changed

1 file changed

+52
-28
lines changed

gcc/rust/util/rust-optional.h

+52-28
Original file line numberDiff line numberDiff line change
@@ -74,48 +74,72 @@ namespace Rust {
7474
template <typename T> class Optional
7575
{
7676
private:
77-
struct Empty
77+
struct tag_some
7878
{
7979
};
80-
81-
enum Kind
80+
struct tag_none
8281
{
83-
Some,
84-
None
85-
} kind;
82+
};
8683

87-
union Content
84+
bool field_is_some;
85+
86+
union
8887
{
89-
Empty empty;
9088
T value;
89+
};
9190

92-
Content () = default;
93-
} content;
91+
Optional (tag_some, const T &value) : field_is_some (true), value (value) {}
92+
Optional (tag_some, T &&value) : field_is_some (true), value (value) {}
9493

95-
Optional<T> (Kind kind, Content content) : kind (kind), content (content) {}
94+
Optional (tag_none) : field_is_some (false) {}
9695

9796
public:
98-
Optional (const Optional &other) = default;
99-
Optional &operator= (const Optional &other) = default;
100-
Optional (Optional &&other) = default;
97+
Optional (const Optional &other)
98+
{
99+
if ((field_is_some = other.field_is_some))
100+
new (&value) T (other.value);
101+
}
101102

102-
static Optional<T> some (T value)
103+
Optional (Optional &&other)
103104
{
104-
Content content;
105-
content.value = value;
105+
if ((field_is_some = other.field_is_some))
106+
new (&value) T (other.value);
107+
}
106108

107-
return Optional (Kind::Some, content);
109+
Optional &operator= (const Optional &other)
110+
{
111+
if (is_some ())
112+
value.~T ();
113+
if ((field_is_some = other.field_is_some))
114+
new (&value) T (other.value);
115+
return *this;
108116
}
109117

110-
static Optional<T> none ()
118+
Optional &operator= (Optional &&other)
111119
{
112-
Content content;
113-
content.empty = Empty ();
120+
if (is_some ())
121+
value.~T ();
122+
if ((field_is_some = other.field_is_some))
123+
new (&value) T (other.value);
124+
return *this;
125+
}
114126

115-
return Optional (Kind::None, content);
127+
~Optional ()
128+
{
129+
if (is_some ())
130+
value.~T ();
116131
}
117132

118-
bool is_some () const { return kind == Kind::Some; }
133+
static Optional some (const T &value)
134+
{
135+
return Optional (tag_some (), value);
136+
}
137+
138+
static Optional some (T &&value) { return Optional (tag_some (), value); }
139+
140+
static Optional none () { return Optional (tag_none ()); }
141+
142+
bool is_some () const { return field_is_some; }
119143
bool is_none () const { return !is_some (); }
120144

121145
/**
@@ -135,24 +159,24 @@ template <typename T> class Optional
135159
{
136160
rust_assert (is_some ());
137161

138-
return content.value;
162+
return value;
139163
}
140164

141165
T &get ()
142166
{
143167
rust_assert (is_some ());
144168

145-
return content.value;
169+
return value;
146170
}
147171

148172
T take ()
149173
{
150174
rust_assert (is_some ());
151175

152-
auto to_return = std::move (content.value);
176+
T to_return = std::move (value);
177+
value.~T ();
153178

154-
content.empty = Empty ();
155-
kind = Kind::None;
179+
field_is_some = false;
156180

157181
return to_return;
158182
}

0 commit comments

Comments
 (0)