From: Pierre-Emmanuel Patry <[email protected]>

gcc/rust/ChangeLog:

        * parse/rust-parse-error.h (struct EnumVariant): Add error for enum
        variant.
        * parse/rust-parse-impl.hxx: Use new error type instead of nullptr.
        * parse/rust-parse.h: Update function prototype.

Signed-off-by: Pierre-Emmanuel Patry <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/488a47ff11607dda54df1b6ec112f1f9b8f9ee9a

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4450

 gcc/rust/parse/rust-parse-error.h  | 42 +++++++++++++++++++++++
 gcc/rust/parse/rust-parse-impl.hxx | 55 +++++++++++++++---------------
 gcc/rust/parse/rust-parse.h        |  3 +-
 3 files changed, 71 insertions(+), 29 deletions(-)

diff --git a/gcc/rust/parse/rust-parse-error.h 
b/gcc/rust/parse/rust-parse-error.h
index 73d42f0c0..46ac46245 100644
--- a/gcc/rust/parse/rust-parse-error.h
+++ b/gcc/rust/parse/rust-parse-error.h
@@ -27,6 +27,48 @@ namespace Rust {
 namespace Parse {
 namespace Error {
 
+struct EnumVariant
+{
+  enum class Kind
+  {
+    CHILD_ERROR,
+    NO_IDENTIFIER,
+    UNFINISHED_TUPLE_VARIANT,
+  } kind;
+
+  static tl::expected<std::unique_ptr<AST::EnumItem>, EnumVariant>
+  make_not_identifier (const_TokenPtr unexpected_token)
+  {
+    return tl::unexpected<EnumVariant> (EnumVariant (unexpected_token));
+  }
+
+  static tl::expected<std::unique_ptr<AST::EnumItem>, EnumVariant>
+  make_child_error ()
+  {
+    return tl::unexpected<EnumVariant> (EnumVariant (Kind::CHILD_ERROR));
+  }
+
+  static tl::expected<std::unique_ptr<AST::EnumItem>, EnumVariant>
+  make_unfinished_tuple_variant ()
+  {
+    return tl::unexpected<EnumVariant> (
+      EnumVariant (Kind::UNFINISHED_TUPLE_VARIANT));
+  }
+
+private:
+  EnumVariant (const_TokenPtr unexpected_token)
+    : kind (Kind::NO_IDENTIFIER), unexpected_token (unexpected_token)
+  {}
+
+  EnumVariant (Kind kind) : kind (kind), unexpected_token (nullptr)
+  {
+    rust_assert (kind != Kind::NO_IDENTIFIER);
+  }
+
+  // Only valid for missing identifier
+  const_TokenPtr unexpected_token;
+};
+
 struct Attribute
 {
   static tl::expected<AST::Attribute, Attribute> make_malformed ()
diff --git a/gcc/rust/parse/rust-parse-impl.hxx 
b/gcc/rust/parse/rust-parse-impl.hxx
index bfa545b7c..9ed5eef15 100644
--- a/gcc/rust/parse/rust-parse-impl.hxx
+++ b/gcc/rust/parse/rust-parse-impl.hxx
@@ -2750,7 +2750,7 @@ Parser<ManagedTokenSource>::parse_trait_bound ()
 
   // handle TypePath
   AST::TypePath type_path = parse_type_path ();
-  if (type_path.is_error())
+  if (type_path.is_error ())
     return nullptr;
 
   // handle closing parentheses
@@ -3353,26 +3353,26 @@ Parser<ManagedTokenSource>::parse_enum_items ()
 {
   std::vector<std::unique_ptr<AST::EnumItem>> items;
 
-  std::unique_ptr<AST::EnumItem> initial_item = parse_enum_item ();
+  auto initial_item = parse_enum_item ();
 
   // Return empty item list if no field there
-  if (initial_item == nullptr)
+  if (!initial_item)
     return items;
 
-  items.push_back (std::move (initial_item));
+  items.push_back (std::move (initial_item.value ()));
 
   while (lexer.peek_token ()->get_id () == COMMA)
     {
       lexer.skip_token ();
 
-      std::unique_ptr<AST::EnumItem> item = parse_enum_item ();
-      if (item == nullptr)
+      auto item = parse_enum_item ();
+      if (!item)
        {
          // this would occur with a trailing comma, which is allowed
          break;
        }
 
-      items.push_back (std::move (item));
+      items.push_back (std::move (item.value ()));
     }
 
   items.shrink_to_fit ();
@@ -3389,13 +3389,13 @@ Parser<ManagedTokenSource>::parse_enum_items 
(EndTokenPred is_end_tok)
 {
   std::vector<std::unique_ptr<AST::EnumItem>> items;
 
-  std::unique_ptr<AST::EnumItem> initial_item = parse_enum_item ();
+  auto initial_item = parse_enum_item ();
 
   // Return empty item list if no field there
-  if (initial_item == nullptr)
+  if (!initial_item)
     return items;
 
-  items.push_back (std::move (initial_item));
+  items.push_back (std::move (initial_item.value ()));
 
   while (lexer.peek_token ()->get_id () == COMMA)
     {
@@ -3404,8 +3404,8 @@ Parser<ManagedTokenSource>::parse_enum_items 
(EndTokenPred is_end_tok)
       if (is_end_tok (lexer.peek_token ()->get_id ()))
        break;
 
-      std::unique_ptr<AST::EnumItem> item = parse_enum_item ();
-      if (item == nullptr)
+      auto item = parse_enum_item ();
+      if (!item)
        {
          /* TODO should this ignore all successfully parsed enum items just
           * because one failed? */
@@ -3416,7 +3416,7 @@ Parser<ManagedTokenSource>::parse_enum_items 
(EndTokenPred is_end_tok)
          return {};
        }
 
-      items.push_back (std::move (item));
+      items.push_back (std::move (item.value ()));
     }
 
   items.shrink_to_fit ();
@@ -3428,7 +3428,7 @@ Parser<ManagedTokenSource>::parse_enum_items 
(EndTokenPred is_end_tok)
 /* Parses a single enum variant item in an enum definition. Does not parse
  * commas. */
 template <typename ManagedTokenSource>
-std::unique_ptr<AST::EnumItem>
+tl::expected<std::unique_ptr<AST::EnumItem>, Parse::Error::EnumVariant>
 Parser<ManagedTokenSource>::parse_enum_item ()
 {
   // parse outer attributes if they exist
@@ -3437,7 +3437,7 @@ Parser<ManagedTokenSource>::parse_enum_item ()
   // parse visibility, which may or may not exist
   auto vis_res = parse_visibility ();
   if (!vis_res)
-    return nullptr;
+    return Parse::Error::EnumVariant::make_child_error ();
   auto vis = vis_res.value ();
 
   // parse name for enum item, which is required
@@ -3445,7 +3445,7 @@ Parser<ManagedTokenSource>::parse_enum_item ()
   if (item_name_tok->get_id () != IDENTIFIER)
     {
       // this may not be an error but it means there is no enum item here
-      return nullptr;
+      return Parse::Error::EnumVariant::make_not_identifier (item_name_tok);
     }
   lexer.skip_token ();
   Identifier item_name{item_name_tok};
@@ -3469,7 +3469,7 @@ Parser<ManagedTokenSource>::parse_enum_item ()
        if (!skip_token (RIGHT_PAREN))
          {
            // skip after somewhere
-           return nullptr;
+           return Parse::Error::EnumVariant::make_unfinished_tuple_variant ();
          }
 
        return std::unique_ptr<AST::EnumItemTuple> (new AST::EnumItemTuple (
@@ -3487,7 +3487,7 @@ Parser<ManagedTokenSource>::parse_enum_item ()
        if (!skip_token (RIGHT_CURLY))
          {
            // skip after somewhere
-           return nullptr;
+           return Parse::Error::EnumVariant::make_unfinished_tuple_variant ();
          }
 
        return std::unique_ptr<AST::EnumItemStruct> (new AST::EnumItemStruct (
@@ -3501,20 +3501,19 @@ Parser<ManagedTokenSource>::parse_enum_item ()
 
        auto discriminant_expr = parse_expr ();
        if (!discriminant_expr)
-         return nullptr;
+         return Parse::Error::EnumVariant::make_child_error ();
 
-       return std::unique_ptr<AST::EnumItemDiscriminant> (
-         new AST::EnumItemDiscriminant (std::move (item_name), std::move (vis),
-                                        std::move (discriminant_expr.value ()),
-                                        std::move (outer_attrs),
-                                        item_name_tok->get_locus ()));
+       return std::make_unique<AST::EnumItemDiscriminant> (
+         std::move (item_name), std::move (vis),
+         std::move (discriminant_expr.value ()), std::move (outer_attrs),
+         item_name_tok->get_locus ());
       }
     default:
       // regular enum with just an identifier
-      return std::unique_ptr<AST::EnumItem> (
-       new AST::EnumItem (std::move (item_name), std::move (vis),
-                          std::move (outer_attrs),
-                          item_name_tok->get_locus ()));
+      return std::make_unique<AST::EnumItem> (std::move (item_name),
+                                             std::move (vis),
+                                             std::move (outer_attrs),
+                                             item_name_tok->get_locus ());
     }
 }
 
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 289018e32..96b2d091f 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -438,7 +438,8 @@ private:
   template <typename EndTokenPred>
   std::vector<std::unique_ptr<AST::EnumItem>>
   parse_enum_items (EndTokenPred is_end_token);
-  std::unique_ptr<AST::EnumItem> parse_enum_item ();
+  tl::expected<std::unique_ptr<AST::EnumItem>, Parse::Error::EnumVariant>
+  parse_enum_item ();
   std::unique_ptr<AST::Union> parse_union (AST::Visibility vis,
                                           AST::AttrVec outer_attrs);
   std::unique_ptr<AST::ConstantItem>
-- 
2.53.0

Reply via email to