From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id 28CE53858C2C; Tue, 28 Feb 2023 22:36:34 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 28CE53858C2C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1677623794; bh=n5YkcBso9y7oUTr1HBeW2+n4si24t6s7EAHmzXTdwtQ=; h=From:To:Subject:Date:From; b=dv2OkEkKH2mPptdZRK/VhHr9jRO42Ry+XwSUSo8IIYyhN1wTaT0Fnea6JzWqmjr5t KA83ER/XArduMUCbxrLPZG+uoUNdsWw6OyQdf96PBeQrWko+UQvvE9/3KC4bH1C8PE QKlgIyShvkSuVVW6i/QM2sM+m5xmDL1MSTrcLSEQ= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] parser: Parse `default` impl Functions and Methods X-Act-Checkin: gcc X-Git-Author: Arthur Cohen X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: 0d4a4475e9fbd972bdbcf8e0bcf6f3be3db2f00f X-Git-Newrev: ce43f55e9976929f9ff2388c8971a65afd24e26d Message-Id: <20230228223634.28CE53858C2C@sourceware.org> Date: Tue, 28 Feb 2023 22:36:34 +0000 (GMT) List-Id: https://gcc.gnu.org/g:ce43f55e9976929f9ff2388c8971a65afd24e26d commit ce43f55e9976929f9ff2388c8971a65afd24e26d Author: Arthur Cohen Date: Thu Feb 23 15:11:04 2023 +0100 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. Diff: --- gcc/rust/ast/rust-item.h | 22 +++- gcc/rust/parse/rust-parse-impl.h | 127 ++++++++------------- gcc/testsuite/rust/compile/default_not_a_kw.rs | 2 + .../rust/compile/parse_invalid_specialization.rs | 4 + gcc/testsuite/rust/compile/parse_specialization.rs | 11 ++ 5 files changed, 80 insertions(+), 86 deletions(-) diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index ab7d323607b..065ca1ed58a 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -743,6 +743,7 @@ class Method : public InherentImplItem, public TraitImplItem std::unique_ptr function_body; Location locus; NodeId node_id; + bool is_default; public: // Returns whether the method is in an error state. @@ -783,7 +784,8 @@ public: SelfParam self_param, std::vector function_params, std::unique_ptr return_type, WhereClause where_clause, std::unique_ptr function_body, Visibility vis, - std::vector outer_attrs, Location locus) + std::vector outer_attrs, Location locus, + bool is_default = false) : outer_attrs (std::move (outer_attrs)), vis (std::move (vis)), qualifiers (std::move (qualifiers)), method_name (std::move (method_name)), @@ -793,7 +795,8 @@ public: return_type (std::move (return_type)), where_clause (std::move (where_clause)), function_body (std::move (function_body)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ()->get_next_node_id ()), + is_default (is_default) {} // TODO: add constructor with less fields @@ -803,7 +806,8 @@ public: : outer_attrs (other.outer_attrs), vis (other.vis), qualifiers (other.qualifiers), method_name (other.method_name), self_param (other.self_param), function_params (other.function_params), - where_clause (other.where_clause), locus (other.locus) + where_clause (other.where_clause), locus (other.locus), + is_default (other.is_default) { // guard to prevent null dereference (always required) if (other.return_type != nullptr) @@ -831,6 +835,7 @@ public: function_params = other.function_params; where_clause = other.where_clause; locus = other.locus; + is_default = other.is_default; // guard to prevent null dereference (always required) if (other.return_type != nullptr) @@ -1526,6 +1531,7 @@ class Function : public VisItem, public InherentImplItem, public TraitImplItem WhereClause where_clause; std::unique_ptr function_body; Location locus; + bool is_default; public: std::string as_string () const override; @@ -1548,7 +1554,8 @@ public: std::vector function_params, std::unique_ptr return_type, WhereClause where_clause, std::unique_ptr function_body, Visibility vis, - std::vector outer_attrs, Location locus) + std::vector outer_attrs, Location locus, + bool is_default = false) : VisItem (std::move (vis), std::move (outer_attrs)), qualifiers (std::move (qualifiers)), function_name (std::move (function_name)), @@ -1556,7 +1563,8 @@ public: function_params (std::move (function_params)), return_type (std::move (return_type)), where_clause (std::move (where_clause)), - function_body (std::move (function_body)), locus (locus) + function_body (std::move (function_body)), locus (locus), + is_default (is_default) {} // TODO: add constructor with less fields @@ -1566,7 +1574,8 @@ public: : VisItem (other), qualifiers (other.qualifiers), function_name (other.function_name), function_params (other.function_params), - where_clause (other.where_clause), locus (other.locus) + where_clause (other.where_clause), locus (other.locus), + is_default (other.is_default) { // guard to prevent null dereference (always required) if (other.return_type != nullptr) @@ -1592,6 +1601,7 @@ public: // visibility = other.visibility->clone_visibility(); // outer_attrs = other.outer_attrs; locus = other.locus; + is_default = other.is_default; // guard to prevent null dereference (always required) if (other.return_type != nullptr) diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 0841db4dc92..7807d750ba2 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -1086,6 +1086,13 @@ Parser::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::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::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::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::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::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::parse_trait_impl_function_or_method ( // do actual if instead of ternary for return value optimisation if (is_method) { - return std::unique_ptr ( - 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 (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 ( - 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 (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)); } } diff --git a/gcc/testsuite/rust/compile/default_not_a_kw.rs b/gcc/testsuite/rust/compile/default_not_a_kw.rs new file mode 100644 index 00000000000..b79b39dba30 --- /dev/null +++ b/gcc/testsuite/rust/compile/default_not_a_kw.rs @@ -0,0 +1,2 @@ +// allowed +pub fn default() {} diff --git a/gcc/testsuite/rust/compile/parse_invalid_specialization.rs b/gcc/testsuite/rust/compile/parse_invalid_specialization.rs new file mode 100644 index 00000000000..1ce73848d0a --- /dev/null +++ b/gcc/testsuite/rust/compile/parse_invalid_specialization.rs @@ -0,0 +1,4 @@ +default fn f() { + // { dg-error ".default. is only allowed on items within .impl. blocks" "" { target *-*-* } .-1 } + // { dg-error "failed to parse item in crate" "" { target *-*-* } .-2 } +} diff --git a/gcc/testsuite/rust/compile/parse_specialization.rs b/gcc/testsuite/rust/compile/parse_specialization.rs new file mode 100644 index 00000000000..5de1f6a6f96 --- /dev/null +++ b/gcc/testsuite/rust/compile/parse_specialization.rs @@ -0,0 +1,11 @@ +// { dg-additional-options "-fsyntax-only" } + +trait Foo { + fn bar(); +} + +struct S; + +impl Foo for S { + default fn bar() {} +}