diff options
author | Arthur Cohen <arthur.cohen@embecosm.com> | 2023-02-23 15:11:04 +0100 |
---|---|---|
committer | CohenArthur <arthur.cohen@embecosm.com> | 2023-02-27 09:52:33 +0000 |
commit | ce43f55e9976929f9ff2388c8971a65afd24e26d (patch) | |
tree | 6df3152421ed8f15efbffe46b957060dcba575cd /gcc/rust/parse | |
parent | 0d4a4475e9fbd972bdbcf8e0bcf6f3be3db2f00f (diff) | |
download | gcc-ce43f55e9976929f9ff2388c8971a65afd24e26d.zip gcc-ce43f55e9976929f9ff2388c8971a65afd24e26d.tar.gz gcc-ce43f55e9976929f9ff2388c8971a65afd24e26d.tar.bz2 |
parser: Parse `default` impl Functions and Methods
gcc/rust/ChangeLog:
* ast/rust-item.h (class Method): Add `is_default` field.
(class Function): Likewise.
* parse/rust-parse-impl.h (Parser::parse_item): Add nice error when
parsing `default` outside of an `impl` block
(Parser::parse_trait_impl_item): Allow parsing functions
or methods when seeing `default`.
gcc/testsuite/ChangeLog:
* rust/compile/parse_invalid_specialization.rs: New test.
* rust/compile/parse_specialization.rs: New test.
* rust/compile/default_not_a_kw.rs: New test.
Diffstat (limited to 'gcc/rust/parse')
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 127 |
1 files changed, 47 insertions, 80 deletions
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 0841db4..7807d75 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -1086,6 +1086,13 @@ Parser<ManagedTokenSource>::parse_item (bool called_from_statement) return parse_vis_item (std::move (outer_attrs)); // or should this go straight to parsing union? } + else if (t->get_str () == "default") + { + add_error (Error (t->get_locus (), + "%qs is only allowed on items within %qs blocks", + "default", "impl")); + return nullptr; + } else if (t->get_str () == "macro_rules") { // macro_rules! macro item @@ -5538,13 +5545,14 @@ Parser<ManagedTokenSource>::parse_trait_impl_item () // parse outer attributes (if they exist) AST::AttrVec outer_attrs = parse_outer_attributes (); - // TODO: clean this function up, it is basically unreadable hacks + auto visibility = AST::Visibility::create_private (); + if (lexer.peek_token ()->get_id () == PUB) + visibility = parse_visibility (); // branch on next token: const_TokenPtr t = lexer.peek_token (); switch (t->get_id ()) { - case IDENTIFIER: case SUPER: case SELF: case CRATE: @@ -5552,67 +5560,20 @@ Parser<ManagedTokenSource>::parse_trait_impl_item () // these seem to be SimplePath tokens, so this is a macro invocation // semi return parse_macro_invocation_semi (std::move (outer_attrs)); + case IDENTIFIER: + if (lexer.peek_token ()->get_str () == "default") + return parse_trait_impl_function_or_method (visibility, + std::move (outer_attrs)); + else + return parse_macro_invocation_semi (std::move (outer_attrs)); case TYPE: - return parse_type_alias (AST::Visibility::create_private (), - std::move (outer_attrs)); - case PUB: { - // visibility, so not a macro invocation semi - must be constant, - // function, or method - AST::Visibility vis = parse_visibility (); - - // TODO: is a recursive call to parse_trait_impl_item better? - switch (lexer.peek_token ()->get_id ()) - { - case TYPE: - return parse_type_alias (std::move (vis), std::move (outer_attrs)); - case EXTERN_TOK: - case UNSAFE: - case FN_TOK: - // function or method - return parse_trait_impl_function_or_method (std::move (vis), - std::move ( - outer_attrs)); - case CONST: - // lookahead to resolve production - could be function/method or - // const item - t = lexer.peek_token (1); - - switch (t->get_id ()) - { - case IDENTIFIER: - case UNDERSCORE: - return parse_const_item (std::move (vis), - std::move (outer_attrs)); - case UNSAFE: - case EXTERN_TOK: - case FN_TOK: - return parse_trait_impl_function_or_method (std::move (vis), - std::move ( - outer_attrs)); - default: - add_error (Error (t->get_locus (), - "unexpected token %qs in some sort of const " - "item in trait impl", - t->get_token_description ())); - - lexer.skip_token (1); // TODO: is this right thing to do? - return nullptr; - } - default: - add_error (Error (t->get_locus (), - "unrecognised token %qs for item in trait impl", - t->get_token_description ())); - - // skip? - return nullptr; - } - } + return parse_type_alias (visibility, std::move (outer_attrs)); case EXTERN_TOK: case UNSAFE: case FN_TOK: // function or method - return parse_trait_impl_function_or_method ( - AST::Visibility::create_private (), std::move (outer_attrs)); + return parse_trait_impl_function_or_method (visibility, + std::move (outer_attrs)); case CONST: // lookahead to resolve production - could be function/method or const // item @@ -5622,13 +5583,12 @@ Parser<ManagedTokenSource>::parse_trait_impl_item () { case IDENTIFIER: case UNDERSCORE: - return parse_const_item (AST::Visibility::create_private (), - std::move (outer_attrs)); + return parse_const_item (visibility, std::move (outer_attrs)); case UNSAFE: case EXTERN_TOK: case FN_TOK: - return parse_trait_impl_function_or_method ( - AST::Visibility::create_private (), std::move (outer_attrs)); + return parse_trait_impl_function_or_method (visibility, + std::move (outer_attrs)); default: add_error (Error ( t->get_locus (), @@ -5640,13 +5600,14 @@ Parser<ManagedTokenSource>::parse_trait_impl_item () } gcc_unreachable (); default: - add_error (Error (t->get_locus (), - "unrecognised token %qs for item in trait impl", - t->get_token_description ())); - - // skip? - return nullptr; + break; } + add_error (Error (t->get_locus (), + "unrecognised token %qs for item in trait impl", + t->get_token_description ())); + + // skip? + return nullptr; } /* For internal use only by parse_trait_impl_item() - splits giant method into @@ -5665,6 +5626,14 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method ( // parse function or method qualifiers AST::FunctionQualifiers qualifiers = parse_function_qualifiers (); + auto is_default = false; + auto t = lexer.peek_token (); + if (t->get_id () == IDENTIFIER && t->get_str () == "default") + { + is_default = true; + lexer.skip_token (); + } + skip_token (FN_TOK); // parse function or method name @@ -5789,21 +5758,19 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method ( // do actual if instead of ternary for return value optimisation if (is_method) { - return std::unique_ptr<AST::Method> ( - new AST::Method (std::move (ident), std::move (qualifiers), - std::move (generic_params), std::move (self_param), - std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (body), - std::move (vis), std::move (outer_attrs), locus)); + return std::unique_ptr<AST::Method> (new AST::Method ( + std::move (ident), std::move (qualifiers), std::move (generic_params), + std::move (self_param), std::move (function_params), + std::move (return_type), std::move (where_clause), std::move (body), + std::move (vis), std::move (outer_attrs), locus, is_default)); } else { - return std::unique_ptr<AST::Function> ( - new AST::Function (std::move (ident), std::move (qualifiers), - std::move (generic_params), - std::move (function_params), std::move (return_type), - std::move (where_clause), std::move (body), - std::move (vis), std::move (outer_attrs), locus)); + return std::unique_ptr<AST::Function> (new AST::Function ( + std::move (ident), std::move (qualifiers), std::move (generic_params), + std::move (function_params), std::move (return_type), + std::move (where_clause), std::move (body), std::move (vis), + std::move (outer_attrs), locus, is_default)); } } |