From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7905) id 1F8813858C42; Wed, 21 Feb 2024 12:51:42 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 1F8813858C42 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1708519902; bh=6LgOIcpqlM+KE7mzNELsDEbgJLkor8WlM9GltpLVkv4=; h=From:To:Subject:Date:From; b=NvjoqXiLhq69OQJEFxtz1wBjB2RoF+o2mOQDB1FKmQAo7ezss7VuXeSRdLKkcRRll zKNSAZyNrwlwGlcjs2LPW5l43zWwLyFdTWpW8p0N8dyhWbplo94B089c51pt4FAV2j cHtvOhHm3359nSKVIklZBKOs1NtshI2asdssOsVI= MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: Arthur Cohen To: gcc-cvs@gcc.gnu.org Subject: [gcc r14-9108] gccrs: Fix rebinding imports X-Act-Checkin: gcc X-Git-Author: Owen Avery X-Git-Refname: refs/heads/trunk X-Git-Oldrev: 4cabeacc388b4ec8dfa41bf9c99b0dbd87d4b1f4 X-Git-Newrev: 17a7fd17b7e42e42a9165b127fb9bd5e4e81f276 Message-Id: <20240221125142.1F8813858C42@sourceware.org> Date: Wed, 21 Feb 2024 12:51:42 +0000 (GMT) List-Id: https://gcc.gnu.org/g:17a7fd17b7e42e42a9165b127fb9bd5e4e81f276 commit r14-9108-g17a7fd17b7e42e42a9165b127fb9bd5e4e81f276 Author: Owen Avery Date: Wed Jun 21 10:26:30 2023 -0400 gccrs: Fix rebinding imports gcc/rust/ChangeLog: * resolve/rust-ast-resolve-item.cc (flatten_glob): Use Import class. (flatten_rebind): Likewise. (flatten_list): Likewise. (flatten): Likewise. (flatten_use_dec_to_paths): Likewise. (flatten_use_dec_to_imports): Likewise. (ResolveItem::visit): Likewise. (Import::add_prefix): New. (rust_flatten_nested_glob): Adjust test. (rust_flatten_glob): Likewise. (rust_flatten_rebind_none): Likewise. (rust_flatten_rebind): Likewise. (rust_flatten_rebind_nested): Likewise. (rust_flatten_list): Likewise. * resolve/rust-ast-resolve-item.h (class Import): New. gcc/testsuite/ChangeLog: * rust/compile/use_2.rs: New test. Signed-off-by: Owen Avery Diff: --- gcc/rust/resolve/rust-ast-resolve-item.cc | 179 ++++++++++++++---------------- gcc/rust/resolve/rust-ast-resolve-item.h | 23 ++++ gcc/testsuite/rust/compile/use_2.rs | 7 ++ 3 files changed, 116 insertions(+), 93 deletions(-) diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc index e69b945407cf..743657bc4219 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.cc +++ b/gcc/rust/resolve/rust-ast-resolve-item.cc @@ -824,33 +824,30 @@ ResolveItem::resolve_extern_item (AST::ExternalItem *item) } static void -flatten_glob (const AST::UseTreeGlob &glob, - std::vector &paths); +flatten_glob (const AST::UseTreeGlob &glob, std::vector &imports); static void -flatten_rebind (const AST::UseTreeRebind &glob, - std::vector &paths); +flatten_rebind (const AST::UseTreeRebind &glob, std::vector &imports); static void -flatten_list (const AST::UseTreeList &glob, - std::vector &paths); +flatten_list (const AST::UseTreeList &glob, std::vector &imports); static void -flatten (const AST::UseTree *tree, std::vector &paths) +flatten (const AST::UseTree *tree, std::vector &imports) { switch (tree->get_kind ()) { case AST::UseTree::Glob: { auto glob = static_cast (tree); - flatten_glob (*glob, paths); + flatten_glob (*glob, imports); break; } case AST::UseTree::Rebind: { auto rebind = static_cast (tree); - flatten_rebind (*rebind, paths); + flatten_rebind (*rebind, imports); break; } case AST::UseTree::List: { auto list = static_cast (tree); - flatten_list (*list, paths); + flatten_list (*list, imports); break; } break; @@ -858,36 +855,28 @@ flatten (const AST::UseTree *tree, std::vector &paths) } static void -flatten_glob (const AST::UseTreeGlob &glob, std::vector &paths) +flatten_glob (const AST::UseTreeGlob &glob, std::vector &imports) { if (glob.has_path ()) - paths.emplace_back (glob.get_path ()); + imports.emplace_back (glob.get_path (), true, std::string ()); } static void -flatten_rebind (const AST::UseTreeRebind &rebind, - std::vector &paths) +flatten_rebind (const AST::UseTreeRebind &rebind, std::vector &imports) { auto path = rebind.get_path (); - if (rebind.has_path ()) - paths.emplace_back (path); - // FIXME: Do we want to emplace the rebind here as well? + std::string label; if (rebind.has_identifier ()) - { - auto rebind_path = path; - auto new_seg = rebind.get_identifier (); - - // Add the identifier as a new path - rebind_path.get_segments ().back () - = AST::SimplePathSegment (new_seg.as_string (), UNDEF_LOCATION); + label = rebind.get_identifier ().as_string (); + else + label = path.get_final_segment ().as_string (); - paths.emplace_back (rebind_path); - } + imports.emplace_back (path, false, label); } static void -flatten_list (const AST::UseTreeList &list, std::vector &paths) +flatten_list (const AST::UseTreeList &list, std::vector &imports) { auto prefix = AST::SimplePath::create_empty (); if (list.has_path ()) @@ -895,21 +884,25 @@ flatten_list (const AST::UseTreeList &list, std::vector &paths) for (const auto &tree : list.get_trees ()) { - auto sub_paths = std::vector (); - flatten (tree.get (), sub_paths); + // append imports to the main list, then modify them in-place + auto start_idx = imports.size (); + flatten (tree.get (), imports); - for (auto &sub_path : sub_paths) - { - auto new_path = prefix; - std::copy (sub_path.get_segments ().begin (), - sub_path.get_segments ().end (), - std::back_inserter (new_path.get_segments ())); - - paths.emplace_back (new_path); - } + for (auto import = imports.begin () + start_idx; import != imports.end (); + import++) + import->add_prefix (prefix); } } +void +Import::add_prefix (AST::SimplePath prefix) +{ + AST::SimplePath old_path (std::move (path)); + path = std::move (prefix); + std::move (old_path.get_segments ().begin (), old_path.get_segments ().end (), + std::back_inserter (path.get_segments ())); +} + /** * Flatten a UseDeclaration's UseTree into multiple simple paths to resolve. * @@ -930,21 +923,21 @@ flatten_list (const AST::UseTreeList &list, std::vector &paths) * Finally in the third case, we want to create two SimplePaths to resolve: * [some::path::one, some::path::two] */ -static std::vector -flatten_use_dec_to_paths (const AST::UseDeclaration &use_item) +static std::vector +flatten_use_dec_to_imports (const AST::UseDeclaration &use_item) { - auto paths = std::vector (); + auto imports = std::vector (); const auto &tree = use_item.get_tree (); - flatten (tree.get (), paths); + flatten (tree.get (), imports); - return paths; + return imports; } void ResolveItem::visit (AST::UseDeclaration &use_item) { - std::vector to_resolve = flatten_use_dec_to_paths (use_item); + std::vector to_resolve = flatten_use_dec_to_imports (use_item); // FIXME: I think this does not actually resolve glob use-decls and is going // the wrong way about it. RFC #1560 specifies the following: @@ -956,18 +949,20 @@ ResolveItem::visit (AST::UseDeclaration &use_item) // Which is the opposite of what we're doing if I understand correctly? NodeId current_module = resolver->peek_current_module_scope (); - for (auto &path : to_resolve) + for (auto &import : to_resolve) { + auto &path = import.get_path (); + rust_debug ("resolving use-decl path: [%s]", path.as_string ().c_str ()); NodeId resolved_node_id = ResolvePath::go (&path); bool ok = resolved_node_id != UNKNOWN_NODEID; if (!ok) continue; - const AST::SimplePathSegment &final_seg = path.get_segments ().back (); + if (import.is_glob ()) + continue; - auto decl - = CanonicalPath::new_seg (resolved_node_id, final_seg.as_string ()); + auto decl = CanonicalPath::new_seg (resolved_node_id, import.get_name ()); mappings->insert_module_child_item (current_module, decl); resolver->get_type_scope ().insert (decl, resolved_node_id, @@ -1079,13 +1074,13 @@ rust_flatten_nested_glob (void) = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED, foobar, UNDEF_LOCATION); - auto paths = std::vector (); - Rust::Resolver::flatten_glob (glob, paths); + auto imports = std::vector (); + Rust::Resolver::flatten_glob (glob, imports); - ASSERT_TRUE (!paths.empty ()); - ASSERT_EQ (paths.size (), 1); - ASSERT_EQ (paths[0].get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (paths[0].get_segments ()[1].as_string (), "bar"); + ASSERT_TRUE (!imports.empty ()); + ASSERT_EQ (imports.size (), 1); + ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); + ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); } static void @@ -1097,12 +1092,12 @@ rust_flatten_glob (void) = Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED, frob, UNDEF_LOCATION); - auto paths = std::vector (); - Rust::Resolver::flatten_glob (glob, paths); + auto imports = std::vector (); + Rust::Resolver::flatten_glob (glob, imports); - ASSERT_TRUE (!paths.empty ()); - ASSERT_EQ (paths.size (), 1); - ASSERT_EQ (paths[0], "frobulator"); + ASSERT_TRUE (!imports.empty ()); + ASSERT_EQ (imports.size (), 1); + ASSERT_EQ (imports[0].get_path (), "frobulator"); } static void @@ -1115,13 +1110,13 @@ rust_flatten_rebind_none (void) auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE, foobar, UNDEF_LOCATION); - auto paths = std::vector (); - Rust::Resolver::flatten_rebind (rebind, paths); + auto imports = std::vector (); + Rust::Resolver::flatten_rebind (rebind, imports); - ASSERT_TRUE (!paths.empty ()); - ASSERT_EQ (paths.size (), 1); - ASSERT_EQ (paths[0].get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (paths[0].get_segments ()[1].as_string (), "bar"); + ASSERT_TRUE (!imports.empty ()); + ASSERT_EQ (imports.size (), 1); + ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); + ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); } static void @@ -1132,13 +1127,13 @@ rust_flatten_rebind (void) auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER, frob, UNDEF_LOCATION, {"saindoux"}); - auto paths = std::vector (); - Rust::Resolver::flatten_rebind (rebind, paths); + auto imports = std::vector (); + Rust::Resolver::flatten_rebind (rebind, imports); - ASSERT_TRUE (!paths.empty ()); - ASSERT_EQ (paths.size (), 2); - ASSERT_EQ (paths[0], "frobulator"); - ASSERT_EQ (paths[1], "saindoux"); + ASSERT_TRUE (!imports.empty ()); + ASSERT_EQ (imports.size (), 1); + ASSERT_EQ (imports[0].get_path (), "frobulator"); + ASSERT_EQ (imports[0].get_name (), "saindoux"); } static void @@ -1154,17 +1149,15 @@ rust_flatten_rebind_nested (void) = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER, foo_bar_baz, UNDEF_LOCATION, {"saindoux"}); - auto paths = std::vector (); - Rust::Resolver::flatten_rebind (rebind, paths); - - ASSERT_TRUE (!paths.empty ()); - ASSERT_EQ (paths.size (), 2); - ASSERT_EQ (paths[0].get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (paths[0].get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (paths[0].get_segments ()[2].as_string (), "baz"); - ASSERT_EQ (paths[1].get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (paths[1].get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (paths[1].get_segments ()[2].as_string (), "saindoux"); + auto imports = std::vector (); + Rust::Resolver::flatten_rebind (rebind, imports); + + ASSERT_TRUE (!imports.empty ()); + ASSERT_EQ (imports.size (), 1); + ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); + ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); + ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz"); + ASSERT_EQ (imports[0].get_name (), "saindoux"); } static void @@ -1194,17 +1187,17 @@ rust_flatten_list (void) = Rust::AST::UseTreeList (Rust::AST::UseTreeList::PATH_PREFIXED, foo_bar, std::move (uses), UNDEF_LOCATION); - auto paths = std::vector (); - Rust::Resolver::flatten_list (list, paths); - - ASSERT_TRUE (!paths.empty ()); - ASSERT_EQ (paths.size (), 2); - ASSERT_EQ (paths[0].get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (paths[0].get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (paths[0].get_segments ()[2].as_string (), "baz"); - ASSERT_EQ (paths[1].get_segments ()[0].as_string (), "foo"); - ASSERT_EQ (paths[1].get_segments ()[1].as_string (), "bar"); - ASSERT_EQ (paths[1].get_segments ()[2].as_string (), "bul"); + auto imports = std::vector (); + Rust::Resolver::flatten_list (list, imports); + + ASSERT_TRUE (!imports.empty ()); + ASSERT_EQ (imports.size (), 2); + ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo"); + ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar"); + ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz"); + ASSERT_EQ (imports[1].get_path ().get_segments ()[0].as_string (), "foo"); + ASSERT_EQ (imports[1].get_path ().get_segments ()[1].as_string (), "bar"); + ASSERT_EQ (imports[1].get_path ().get_segments ()[2].as_string (), "bul"); } static void diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index 0c7b7527c44d..e397ffdfe8ba 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -124,6 +124,29 @@ private: const CanonicalPath &canonical_prefix; }; +class Import +{ +public: + Import (AST::SimplePath path, bool is_glob, std::string name) + : path (path), is_glob_f (is_glob), name (name) + {} + + AST::SimplePath &get_path () { return path; } + + const AST::SimplePath &get_path () const { return path; } + + bool is_glob () const { return is_glob_f; } + + const std::string &get_name () const { return name; } + + void add_prefix (AST::SimplePath prefix); + +private: + AST::SimplePath path; + bool is_glob_f; + std::string name; +}; + } // namespace Resolver } // namespace Rust diff --git a/gcc/testsuite/rust/compile/use_2.rs b/gcc/testsuite/rust/compile/use_2.rs new file mode 100644 index 000000000000..b89ff82caaa1 --- /dev/null +++ b/gcc/testsuite/rust/compile/use_2.rs @@ -0,0 +1,7 @@ +mod foo { + pub struct S; +} + +use foo::S as T; + +const V: T = T; // { dg-warning "unused name" }