public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] parser: Parse `default` impl Functions and Methods
@ 2023-02-28 22:36 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2023-02-28 22:36 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:ce43f55e9976929f9ff2388c8971a65afd24e26d

commit ce43f55e9976929f9ff2388c8971a65afd24e26d
Author: Arthur Cohen <arthur.cohen@embecosm.com>
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<BlockExpr> 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<FunctionParam> function_params,
 	  std::unique_ptr<Type> return_type, WhereClause where_clause,
 	  std::unique_ptr<BlockExpr> function_body, Visibility vis,
-	  std::vector<Attribute> outer_attrs, Location locus)
+	  std::vector<Attribute> 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<BlockExpr> function_body;
   Location locus;
+  bool is_default;
 
 public:
   std::string as_string () const override;
@@ -1548,7 +1554,8 @@ public:
 	    std::vector<FunctionParam> function_params,
 	    std::unique_ptr<Type> return_type, WhereClause where_clause,
 	    std::unique_ptr<BlockExpr> function_body, Visibility vis,
-	    std::vector<Attribute> outer_attrs, Location locus)
+	    std::vector<Attribute> 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<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));
     }
 }
 
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() {}
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-02-28 22:36 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-28 22:36 [gcc/devel/rust/master] parser: Parse `default` impl Functions and Methods Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).