public inbox for gcc-rust@gcc.gnu.org
 help / color / mirror / Atom feed
From: Mark Wielaard <mark@klomp.org>
To: gcc-rust@gcc.gnu.org
Cc: Mark Wielaard <mark@klomp.org>
Subject: [PATCH 2/3] Resolve Enums and EnumItems
Date: Mon,  6 Sep 2021 00:48:10 +0200	[thread overview]
Message-ID: <20210905224811.69432-2-mark@klomp.org> (raw)
In-Reply-To: <20210905224811.69432-1-mark@klomp.org>

Generate paths for Enum and EnumItem AST NodeIds and resolve the types
of tuple and struct enum items.

EnumItems always have the Enum as prefix. To make this work for
ResolveStms (declaration statements are not given a canonical path) we
add an enum_prefix to be used when resolving EnumItems.

For ResolveType the tuple and struct fields get resolved using the
Enum type scope.

Add tests for toplevel or stmt enums with duplicate variant names. And
adjust the tuple_enum_variants.rs testcase to expect unused name
warnings.
---
 gcc/rust/resolve/rust-ast-resolve-item.h      |  36 ++++++
 gcc/rust/resolve/rust-ast-resolve-stmt.h      | 105 +++++++++++++++++-
 gcc/rust/resolve/rust-ast-resolve-toplevel.h  |  69 ++++++++++++
 gcc/testsuite/rust/compile/bad_stmt_enums.rs  |  22 ++++
 .../rust/compile/bad_toplevel_enums.rs        |  19 ++++
 .../compile/torture/tuple_enum_variants.rs    |   7 +-
 6 files changed, 254 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/bad_stmt_enums.rs
 create mode 100644 gcc/testsuite/rust/compile/bad_toplevel_enums.rs

diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h
index d3c053b609f..2a2f956a385 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.h
+++ b/gcc/rust/resolve/rust-ast-resolve-item.h
@@ -260,6 +260,42 @@ public:
     resolver->get_type_scope ().pop ();
   }
 
+  void visit (AST::Enum &enum_decl) override
+  {
+    NodeId scope_node_id = enum_decl.get_node_id ();
+    resolver->get_type_scope ().push (scope_node_id);
+
+    if (enum_decl.has_generics ())
+      {
+	for (auto &generic : enum_decl.get_generic_params ())
+	  {
+	    ResolveGenericParam::go (generic.get (), enum_decl.get_node_id ());
+	  }
+      }
+
+    /* The actual fields are inside the variants.  */
+    for (auto &variant : enum_decl.get_variants ())
+      ResolveItem::go (variant.get ());
+
+    resolver->get_type_scope ().pop ();
+  }
+
+  /* EnumItem doesn't need to be handled, no fields.  */
+
+  void visit (AST::EnumItemTuple &item) override
+  {
+    for (auto &field : item.get_tuple_fields ())
+      ResolveType::go (field.get_field_type ().get (), item.get_node_id ());
+  }
+
+  void visit (AST::EnumItemStruct &item) override
+  {
+    for (auto &field : item.get_struct_fields ())
+      ResolveType::go (field.get_field_type ().get (), item.get_node_id ());
+  }
+
+  /* EnumItemDiscriminant doesn't need to be handled, no fields.  */
+
   void visit (AST::StructStruct &struct_decl) override
   {
     NodeId scope_node_id = struct_decl.get_node_id ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h
index b6044327b27..43bf0a421d6 100644
--- a/gcc/rust/resolve/rust-ast-resolve-stmt.h
+++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h
@@ -33,9 +33,11 @@ class ResolveStmt : public ResolverBase
   using Rust::Resolver::ResolverBase::visit;
 
 public:
-  static void go (AST::Stmt *stmt, NodeId parent)
+  static void go (AST::Stmt *stmt, NodeId parent,
+		  const CanonicalPath &enum_prefix
+		  = CanonicalPath::create_empty ())
   {
-    ResolveStmt resolver (parent);
+    ResolveStmt resolver (parent, enum_prefix);
     stmt->accept_vis (resolver);
   };
 
@@ -98,6 +100,97 @@ public:
     resolver->get_type_scope ().pop ();
   }
 
+  void visit (AST::Enum &enum_decl) override
+  {
+    auto enum_path = CanonicalPath::new_seg (enum_decl.get_node_id (),
+					     enum_decl.get_identifier ());
+    resolver->get_type_scope ().insert (
+      enum_path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
+      [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+	RichLocation r (enum_decl.get_locus ());
+	r.add_range (locus);
+	rust_error_at (r, "redefined multiple times");
+      });
+
+    NodeId scope_node_id = enum_decl.get_node_id ();
+    resolver->get_type_scope ().push (scope_node_id);
+
+    if (enum_decl.has_generics ())
+      {
+	for (auto &generic : enum_decl.get_generic_params ())
+	  {
+	    ResolveGenericParam::go (generic.get (), enum_decl.get_node_id ());
+	  }
+      }
+
+    for (auto &variant : enum_decl.get_variants ())
+      ResolveStmt::go (variant.get (), parent, enum_path);
+
+    resolver->get_type_scope ().pop ();
+  }
+
+  void visit (AST::EnumItem &item) override
+  {
+    auto path = enum_prefix.append (
+      CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+    resolver->get_type_scope ().insert (
+      path, item.get_node_id (), item.get_locus (), false,
+      [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+	RichLocation r (item.get_locus ());
+	r.add_range (locus);
+	rust_error_at (r, "redefined multiple times");
+      });
+
+    // Done, no fields.
+  }
+
+  void visit (AST::EnumItemTuple &item) override
+  {
+    auto path = enum_prefix.append (
+      CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+    resolver->get_type_scope ().insert (
+      path, item.get_node_id (), item.get_locus (), false,
+      [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+	RichLocation r (item.get_locus ());
+	r.add_range (locus);
+	rust_error_at (r, "redefined multiple times");
+      });
+
+    for (auto &field : item.get_tuple_fields ())
+      ResolveType::go (field.get_field_type ().get (), item.get_node_id ());
+  }
+
+  void visit (AST::EnumItemStruct &item) override
+  {
+    auto path = enum_prefix.append (
+      CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+    resolver->get_type_scope ().insert (
+      path, item.get_node_id (), item.get_locus (), false,
+      [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+	RichLocation r (item.get_locus ());
+	r.add_range (locus);
+	rust_error_at (r, "redefined multiple times");
+      });
+
+    for (auto &field : item.get_struct_fields ())
+      ResolveType::go (field.get_field_type ().get (), item.get_node_id ());
+  }
+
+  void visit (AST::EnumItemDiscriminant &item) override
+  {
+    auto path = enum_prefix.append (
+      CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+    resolver->get_type_scope ().insert (
+      path, item.get_node_id (), item.get_locus (), false,
+      [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+	RichLocation r (item.get_locus ());
+	r.add_range (locus);
+	rust_error_at (r, "redefined multiple times");
+      });
+
+    // Done, no fields.
+  }
+
   void visit (AST::StructStruct &struct_decl) override
   {
     auto path = CanonicalPath::new_seg (struct_decl.get_node_id (),
@@ -219,7 +312,13 @@ public:
   }
 
 private:
-  ResolveStmt (NodeId parent) : ResolverBase (parent) {}
+  ResolveStmt (NodeId parent, const CanonicalPath &enum_prefix)
+    : ResolverBase (parent), enum_prefix (enum_prefix)
+  {}
+
+  /* item declaration statements are not given a canonical path, but enum items
+   * (variants) do inherit the enum path/identifier name.  */
+  const CanonicalPath &enum_prefix;
 };
 
 } // namespace Resolver
diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
index 12392067be7..6f802a5b6e8 100644
--- a/gcc/rust/resolve/rust-ast-resolve-toplevel.h
+++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h
@@ -88,6 +88,75 @@ public:
       });
   }
 
+  void visit (AST::Enum &enum_decl) override
+  {
+    auto path
+      = prefix.append (CanonicalPath::new_seg (enum_decl.get_node_id (),
+					       enum_decl.get_identifier ()));
+    resolver->get_type_scope ().insert (
+      path, enum_decl.get_node_id (), enum_decl.get_locus (), false,
+      [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+	RichLocation r (enum_decl.get_locus ());
+	r.add_range (locus);
+	rust_error_at (r, "redefined multiple times");
+      });
+
+    for (auto &variant : enum_decl.get_variants ())
+      ResolveTopLevel::go (variant.get (), path);
+  }
+
+  void visit (AST::EnumItem &item) override
+  {
+    auto path = prefix.append (
+      CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+    resolver->get_type_scope ().insert (
+      path, item.get_node_id (), item.get_locus (), false,
+      [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+	RichLocation r (item.get_locus ());
+	r.add_range (locus);
+	rust_error_at (r, "redefined multiple times");
+      });
+  }
+
+  void visit (AST::EnumItemTuple &item) override
+  {
+    auto path = prefix.append (
+      CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+    resolver->get_type_scope ().insert (
+      path, item.get_node_id (), item.get_locus (), false,
+      [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+	RichLocation r (item.get_locus ());
+	r.add_range (locus);
+	rust_error_at (r, "redefined multiple times");
+      });
+  }
+
+  void visit (AST::EnumItemStruct &item) override
+  {
+    auto path = prefix.append (
+      CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+    resolver->get_type_scope ().insert (
+      path, item.get_node_id (), item.get_locus (), false,
+      [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+	RichLocation r (item.get_locus ());
+	r.add_range (locus);
+	rust_error_at (r, "redefined multiple times");
+      });
+  }
+
+  void visit (AST::EnumItemDiscriminant &item) override
+  {
+    auto path = prefix.append (
+      CanonicalPath::new_seg (item.get_node_id (), item.get_identifier ()));
+    resolver->get_type_scope ().insert (
+      path, item.get_node_id (), item.get_locus (), false,
+      [&] (const CanonicalPath &, NodeId, Location locus) -> void {
+	RichLocation r (item.get_locus ());
+	r.add_range (locus);
+	rust_error_at (r, "redefined multiple times");
+      });
+  }
+
   void visit (AST::StructStruct &struct_decl) override
   {
     auto path
diff --git a/gcc/testsuite/rust/compile/bad_stmt_enums.rs b/gcc/testsuite/rust/compile/bad_stmt_enums.rs
new file mode 100644
index 00000000000..7b09a94fd27
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_stmt_enums.rs
@@ -0,0 +1,22 @@
+fn main ()
+{
+  enum EE
+    {
+      Alpha { alpha: i32 },
+      pub Beta (u8),
+      pub Gamma,
+      Gamma { gamma: u32 } // { dg-error "redefined" }
+    }
+
+  struct EE2 { }
+  enum EE2 { } // { dg-error "redefined" }
+
+  enum EE1
+    {
+      pub Alpha,
+      Beta = 41,
+      Beta = 42, // { dg-error "redefined" }
+      pub Gamma = 3,
+      D,
+    }
+}
diff --git a/gcc/testsuite/rust/compile/bad_toplevel_enums.rs b/gcc/testsuite/rust/compile/bad_toplevel_enums.rs
new file mode 100644
index 00000000000..b655e30a93d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/bad_toplevel_enums.rs
@@ -0,0 +1,19 @@
+pub enum E
+{
+  pub A { a: i32 },
+  B (u8),
+  pub C,
+  B // { dg-error "redefined" }
+}
+
+enum E2 { }
+struct E2 { } // { dg-error "redefined" }
+
+enum E1
+{
+  A,
+  pub B = 42,
+  C = 3,
+  A { a: u8 }, // { dg-error "redefined" }
+  pub D
+}
diff --git a/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs b/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs
index 26e3e5d0a71..f65bd3b5c69 100644
--- a/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs
+++ b/gcc/testsuite/rust/compile/torture/tuple_enum_variants.rs
@@ -1,4 +1,9 @@
-enum E { T0(), T1(i32), T2(i32,u32) }
+enum E        // { dg-warning "unused name" }
+{
+  T0(),       // { dg-warning "unused name" }
+  T1(i32),    // { dg-warning "unused name" }
+  T2(i32,u32) // { dg-warning "unused name" }
+}
 
 /* The following doesn't parse yet...
 fn f(e0: E, e1: E, e2: E) -> (E,E,E,())
-- 
2.32.0


  reply	other threads:[~2021-09-05 22:48 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-05 22:48 [PATCH 1/3] Parse optional visibility for enum item Mark Wielaard
2021-09-05 22:48 ` Mark Wielaard [this message]
2021-09-05 22:48 ` [PATCH 3/3] Add EnumItem HIR lowering Mark Wielaard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210905224811.69432-2-mark@klomp.org \
    --to=mark@klomp.org \
    --cc=gcc-rust@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).