]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Improve Optional<T> implementation
authorOwen Avery <powerboat9.gamer@gmail.com>
Fri, 12 May 2023 07:13:30 +0000 (03:13 -0400)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:37:20 +0000 (18:37 +0100)
gcc/rust/ChangeLog:

* util/rust-optional.h
(class Optional<T>): Improve inner state.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
gcc/rust/util/rust-optional.h

index 658d90faa87f30267139a54dc51f84dfd3db1b50..66730bd992d9b81fe350f7a93f2181186445678a 100644 (file)
@@ -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;
   }