aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>2023-11-15 13:02:28 +0100
committerArthur Cohen <arthur.cohen@embecosm.com>2024-01-30 12:36:42 +0100
commit3e450ae1bb99d0111f6ca5f34ac8d6ea308c13d6 (patch)
tree95688f50e6f4df7028fadf407c0ebb744fac187b
parentca16a3ee232dac565cb18ea5e0b84c4ad54f727e (diff)
downloadgcc-3e450ae1bb99d0111f6ca5f34ac8d6ea308c13d6.zip
gcc-3e450ae1bb99d0111f6ca5f34ac8d6ea308c13d6.tar.gz
gcc-3e450ae1bb99d0111f6ca5f34ac8d6ea308c13d6.tar.bz2
gccrs: 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 1ebe1ed..de17412 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>