]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Report self parameter parsing error kind
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Wed, 15 Nov 2023 12:02:28 +0000 (13:02 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 30 Jan 2024 11:36:42 +0000 (12:36 +0100)
Self parameter parsing errors may come from different situations, which
should not be handled in the same way. It is now possible to
differentiate a missing self parameter from a self pointer or a parsing
error.

gcc/rust/ChangeLog:

* parse/rust-parse-impl.h (Parser::parse_function): Early return on
unrecoverable errors.
(Parser::parse_trait_item): Likewise.
(Parser::parse_self_param): Update return type.
* parse/rust-parse.h (enum ParseSelfError): Add enumeration to describe
different self parameter parsing errors.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
gcc/rust/parse/rust-parse-impl.h
gcc/rust/parse/rust-parse.h

index 1ebe1ed442c0e74d8a165ef1e1e407053779d878..de17412c3b6848fee214080eda939c29017605c1 100644 (file)
@@ -2880,8 +2880,13 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
       return nullptr;
     }
 
-  std::unique_ptr<AST::Param> initial_param = parse_self_param ();
-  if (initial_param != nullptr)
+  auto initial_param = parse_self_param ();
+
+  if (!initial_param.has_value ()
+      && initial_param.error () != ParseSelfError::NOT_SELF)
+    return nullptr;
+
+  if (initial_param.has_value ())
     skip_token (COMMA);
 
   // parse function parameters (only if next token isn't right paren)
@@ -2891,9 +2896,9 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
     function_params
       = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
 
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
     function_params.insert (function_params.begin (),
-                           std::move (initial_param));
+                           std::move (*initial_param));
 
   if (!skip_token (RIGHT_PAREN))
     {
@@ -5063,13 +5068,15 @@ Parser<ManagedTokenSource>::parse_trait_item ()
 
        /* now for function vs method disambiguation - method has opening
         * "self" param */
-       std::unique_ptr<AST::Param> initial_param = parse_self_param ();
+       auto initial_param = parse_self_param ();
+       if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+         return nullptr;
        /* FIXME: ensure that self param doesn't accidently consume tokens for
         * a function */
        bool is_method = false;
-       if (initial_param != nullptr)
+       if (initial_param.has_value ())
          {
-           if (initial_param->is_self ())
+           if ((*initial_param)->is_self ())
              is_method = true;
 
            /* skip comma so function and method regular params can be parsed
@@ -5089,9 +5096,9 @@ Parser<ManagedTokenSource>::parse_trait_item ()
            return nullptr;
          }
 
-       if (initial_param != nullptr)
+       if (initial_param.has_value ())
          function_params.insert (function_params.begin (),
-                                 std::move (initial_param));
+                                 std::move (*initial_param));
 
        // parse return type (optional)
        std::unique_ptr<AST::Type> return_type = parse_function_return_type ();
@@ -5609,14 +5616,18 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
 
   // now for function vs method disambiguation - method has opening "self"
   // param
-  std::unique_ptr<AST::Param> initial_param = parse_self_param ();
+  auto initial_param = parse_self_param ();
+
+  if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+    return nullptr;
+
   /* FIXME: ensure that self param doesn't accidently consume tokens for a
    * function one idea is to lookahead up to 4 tokens to see whether self is
    * one of them */
   bool is_method = false;
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
     {
-      if (initial_param->is_self ())
+      if ((*initial_param)->is_self ())
        is_method = true;
 
       /* skip comma so function and method regular params can be parsed in
@@ -5629,9 +5640,9 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
   std::vector<std::unique_ptr<AST::Param>> function_params
     = parse_function_params ([] (TokenId id) { return id == RIGHT_PAREN; });
 
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
     function_params.insert (function_params.begin (),
-                           std::move (initial_param));
+                           std::move (*initial_param));
 
   if (!skip_token (RIGHT_PAREN))
     {
@@ -5817,13 +5828,17 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
 
   // now for function vs method disambiguation - method has opening "self"
   // param
-  std::unique_ptr<AST::Param> initial_param = parse_self_param ();
+  auto initial_param = parse_self_param ();
+
+  if (!initial_param.has_value () && initial_param.error () != NOT_SELF)
+    return nullptr;
+
   // FIXME: ensure that self param doesn't accidently consume tokens for a
   // function
   bool is_method = false;
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
     {
-      if (initial_param->is_self ())
+      if ((*initial_param)->is_self ())
        is_method = true;
 
       // skip comma so function and method regular params can be parsed in
@@ -5861,9 +5876,9 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
        }
     }
 
-  if (initial_param != nullptr)
+  if (initial_param.has_value ())
     function_params.insert (function_params.begin (),
-                           std::move (initial_param));
+                           std::move (*initial_param));
 
   // DEBUG
   rust_debug ("successfully parsed function params in function or method "
@@ -7112,7 +7127,7 @@ Parser<ManagedTokenSource>::parse_qualified_path_in_type ()
 
 // Parses a self param. Also handles self param not existing.
 template <typename ManagedTokenSource>
-std::unique_ptr<AST::Param>
+tl::expected<std::unique_ptr<AST::Param>, ParseSelfError>
 Parser<ManagedTokenSource>::parse_self_param ()
 {
   bool has_reference = false;
@@ -7133,8 +7148,11 @@ Parser<ManagedTokenSource>::parse_self_param ()
        if (lexer.peek_token (i)->get_id () != s[i])
          break;
       if (i == s.size ())
-       rust_error_at (lexer.peek_token ()->get_locus (),
-                      "cannot pass %<self%> by raw pointer");
+       {
+         rust_error_at (lexer.peek_token ()->get_locus (),
+                        "cannot pass %<self%> by raw pointer");
+         return tl::make_unexpected (ParseSelfError::SELF_PTR);
+       }
     }
 
   // Trying to find those patterns:
@@ -7154,7 +7172,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
       is_self = true;
 
   if (!is_self)
-    return nullptr;
+    return tl::make_unexpected (ParseSelfError::NOT_SELF);
 
   // test if self is a reference parameter
   if (lexer.peek_token ()->get_id () == AMP)
@@ -7175,7 +7193,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
              add_error (std::move (error));
 
              // skip after somewhere?
-             return nullptr;
+             return tl::make_unexpected (ParseSelfError::PARSING);
            }
        }
     }
@@ -7193,7 +7211,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
   if (self_tok->get_id () != SELF)
     {
       // skip after somewhere?
-      return nullptr;
+      return tl::make_unexpected (ParseSelfError::NOT_SELF);
     }
   lexer.skip_token ();
 
@@ -7212,7 +7230,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
          add_error (std::move (error));
 
          // skip after somewhere?
-         return nullptr;
+         return tl::make_unexpected (ParseSelfError::PARSING);
        }
     }
 
@@ -7225,7 +7243,7 @@ Parser<ManagedTokenSource>::parse_self_param ()
       add_error (std::move (error));
 
       // skip after somewhere?
-      return nullptr;
+      return tl::make_unexpected (ParseSelfError::PARSING);
     }
 
   if (has_reference)
index 08e6ce000f4dae87848d5232db6a03dc4adaf1d3..e873d5292cde9061221d4f1a70aac8a1d40dbdc8 100644 (file)
@@ -22,6 +22,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "rust-ast-full.h"
 #include "rust-diagnostics.h"
 
+#include "expected.h"
+
 namespace Rust {
 /* HACK: used to resolve the expression-or-statement problem at the end of a
  * block by allowing either to be returned (technically). Tagged union would
@@ -93,6 +95,12 @@ struct ParseRestrictions
   bool allow_close_after_expr_stmt = false;
 };
 
+enum ParseSelfError
+{
+  SELF_PTR,
+  PARSING,
+  NOT_SELF,
+};
 // Parser implementation for gccrs.
 // TODO: if updated to C++20, ManagedTokenSource would be useful as a concept
 template <typename ManagedTokenSource> class Parser
@@ -335,7 +343,9 @@ private:
   parse_trait_type (AST::AttrVec outer_attrs, AST::Visibility);
   std::unique_ptr<AST::TraitItemConst>
   parse_trait_const (AST::AttrVec outer_attrs);
-  std::unique_ptr<AST::Param> parse_self_param ();
+
+  tl::expected<std::unique_ptr<AST::Param>, ParseSelfError> parse_self_param ();
+
   std::unique_ptr<AST::Impl> parse_impl (AST::Visibility vis,
                                         AST::AttrVec outer_attrs);
   std::unique_ptr<AST::InherentImplItem>