aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>2023-11-15 13:02:28 +0100
committerP-E-P <32375388+P-E-P@users.noreply.github.com>2023-11-21 09:19:08 +0000
commitd2f2f68a8d9d3ce71e97fb586318445d7e7cd984 (patch)
tree4e5c221a7f334bf8ce49554925cf3303fe28b967
parent6f8b0ffd7667c81af7798c5c02eb24f7b2a79bd5 (diff)
downloadgcc-d2f2f68a8d9d3ce71e97fb586318445d7e7cd984.zip
gcc-d2f2f68a8d9d3ce71e97fb586318445d7e7cd984.tar.gz
gcc-d2f2f68a8d9d3ce71e97fb586318445d7e7cd984.tar.bz2
Report self parameter parsing error kind
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>
-rw-r--r--gcc/rust/parse/rust-parse-impl.h72
-rw-r--r--gcc/rust/parse/rust-parse.h12
2 files changed, 56 insertions, 28 deletions
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index eb52782..5a276d1 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -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)
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 08e6ce0..e873d52 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -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>