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 -- Gcc-rust mailing list Gcc-rust@gcc.gnu.org https://gcc.gnu.org/mailman/listinfo/gcc-rust