aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/util/rust-optional.h
diff options
context:
space:
mode:
authorOwen Avery <powerboat9.gamer@gmail.com>2023-05-12 03:13:30 -0400
committerArthur Cohen <arthur.cohen@embecosm.com>2024-01-16 18:37:20 +0100
commit4a71a18da8a1ea731ad69c34771bd6ee1085cc64 (patch)
tree015fe8b00eea92a9be215286389332904550da3b /gcc/rust/util/rust-optional.h
parentdfd2e26bda189f573d40eaf1f6b5a44180c31640 (diff)
downloadgcc-4a71a18da8a1ea731ad69c34771bd6ee1085cc64.zip
gcc-4a71a18da8a1ea731ad69c34771bd6ee1085cc64.tar.gz
gcc-4a71a18da8a1ea731ad69c34771bd6ee1085cc64.tar.bz2
gccrs: Improve Optional<T> implementation
gcc/rust/ChangeLog: * util/rust-optional.h (class Optional<T>): Improve inner state. Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
Diffstat (limited to 'gcc/rust/util/rust-optional.h')
-rw-r--r--gcc/rust/util/rust-optional.h80
1 files changed, 52 insertions, 28 deletions
diff --git a/gcc/rust/util/rust-optional.h b/gcc/rust/util/rust-optional.h
index 658d90f..66730bd 100644
--- a/gcc/rust/util/rust-optional.h
+++ b/gcc/rust/util/rust-optional.h
@@ -74,48 +74,72 @@ namespace Rust {
template <typename T> class Optional
{
private:
- struct Empty
+ struct tag_some
{
};
-
- enum Kind
+ struct tag_none
{
- Some,
- None
- } kind;
+ };
- union Content
+ bool field_is_some;
+
+ union
{
- Empty empty;
T value;
+ };
- Content () = default;
- } content;
+ Optional (tag_some, const T &value) : field_is_some (true), value (value) {}
+ Optional (tag_some, T &&value) : field_is_some (true), value (value) {}
- Optional<T> (Kind kind, Content content) : kind (kind), content (content) {}
+ Optional (tag_none) : field_is_some (false) {}
public:
- Optional (const Optional &other) = default;
- Optional &operator= (const Optional &other) = default;
- Optional (Optional &&other) = default;
+ Optional (const Optional &other)
+ {
+ if ((field_is_some = other.field_is_some))
+ new (&value) T (other.value);
+ }
- static Optional<T> some (T value)
+ Optional (Optional &&other)
{
- Content content;
- content.value = value;
+ if ((field_is_some = other.field_is_some))
+ new (&value) T (other.value);
+ }
- return Optional (Kind::Some, content);
+ Optional &operator= (const Optional &other)
+ {
+ if (is_some ())
+ value.~T ();
+ if ((field_is_some = other.field_is_some))
+ new (&value) T (other.value);
+ return *this;
}
- static Optional<T> none ()
+ Optional &operator= (Optional &&other)
{
- Content content;
- content.empty = Empty ();
+ if (is_some ())
+ value.~T ();
+ if ((field_is_some = other.field_is_some))
+ new (&value) T (other.value);
+ return *this;
+ }
- return Optional (Kind::None, content);
+ ~Optional ()
+ {
+ if (is_some ())
+ value.~T ();
}
- bool is_some () const { return kind == Kind::Some; }
+ static Optional some (const T &value)
+ {
+ return Optional (tag_some (), value);
+ }
+
+ static Optional some (T &&value) { return Optional (tag_some (), value); }
+
+ static Optional none () { return Optional (tag_none ()); }
+
+ bool is_some () const { return field_is_some; }
bool is_none () const { return !is_some (); }
/**
@@ -135,24 +159,24 @@ public:
{
rust_assert (is_some ());
- return content.value;
+ return value;
}
T &get ()
{
rust_assert (is_some ());
- return content.value;
+ return value;
}
T take ()
{
rust_assert (is_some ());
- auto to_return = std::move (content.value);
+ T to_return = std::move (value);
+ value.~T ();
- content.empty = Empty ();
- kind = Kind::None;
+ field_is_some = false;
return to_return;
}