[COMMITTED 3/9] gccrs: Fix rebinding imports
arthur.cohen@embecosm.com
arthur.cohen@embecosm.com
Wed Feb 21 13:15:21 GMT 2024
From: Owen Avery <powerboat9.gamer@gmail.com>
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 <powerboat9.gamer@gmail.com>
---
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(-)
create mode 100644 gcc/testsuite/rust/compile/use_2.rs
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc b/gcc/rust/resolve/rust-ast-resolve-item.cc
index e69b945407c..743657bc421 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<AST::SimplePath> &paths);
+flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports);
static void
-flatten_rebind (const AST::UseTreeRebind &glob,
- std::vector<AST::SimplePath> &paths);
+flatten_rebind (const AST::UseTreeRebind &glob, std::vector<Import> &imports);
static void
-flatten_list (const AST::UseTreeList &glob,
- std::vector<AST::SimplePath> &paths);
+flatten_list (const AST::UseTreeList &glob, std::vector<Import> &imports);
static void
-flatten (const AST::UseTree *tree, std::vector<AST::SimplePath> &paths)
+flatten (const AST::UseTree *tree, std::vector<Import> &imports)
{
switch (tree->get_kind ())
{
case AST::UseTree::Glob: {
auto glob = static_cast<const AST::UseTreeGlob *> (tree);
- flatten_glob (*glob, paths);
+ flatten_glob (*glob, imports);
break;
}
case AST::UseTree::Rebind: {
auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
- flatten_rebind (*rebind, paths);
+ flatten_rebind (*rebind, imports);
break;
}
case AST::UseTree::List: {
auto list = static_cast<const AST::UseTreeList *> (tree);
- flatten_list (*list, paths);
+ flatten_list (*list, imports);
break;
}
break;
@@ -858,36 +855,28 @@ flatten (const AST::UseTree *tree, std::vector<AST::SimplePath> &paths)
}
static void
-flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths)
+flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &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<AST::SimplePath> &paths)
+flatten_rebind (const AST::UseTreeRebind &rebind, std::vector<Import> &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<AST::SimplePath> &paths)
+flatten_list (const AST::UseTreeList &list, std::vector<Import> &imports)
{
auto prefix = AST::SimplePath::create_empty ();
if (list.has_path ())
@@ -895,21 +884,25 @@ flatten_list (const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths)
for (const auto &tree : list.get_trees ())
{
- auto sub_paths = std::vector<AST::SimplePath> ();
- 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<AST::SimplePath> &paths)
* Finally in the third case, we want to create two SimplePaths to resolve:
* [some::path::one, some::path::two]
*/
-static std::vector<AST::SimplePath>
-flatten_use_dec_to_paths (const AST::UseDeclaration &use_item)
+static std::vector<Import>
+flatten_use_dec_to_imports (const AST::UseDeclaration &use_item)
{
- auto paths = std::vector<AST::SimplePath> ();
+ auto imports = std::vector<Import> ();
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<AST::SimplePath> to_resolve = flatten_use_dec_to_paths (use_item);
+ std::vector<Import> 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::AST::SimplePath> ();
- Rust::Resolver::flatten_glob (glob, paths);
+ auto imports = std::vector<Rust::Resolver::Import> ();
+ 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::AST::SimplePath> ();
- Rust::Resolver::flatten_glob (glob, paths);
+ auto imports = std::vector<Rust::Resolver::Import> ();
+ 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::AST::SimplePath> ();
- Rust::Resolver::flatten_rebind (rebind, paths);
+ auto imports = std::vector<Rust::Resolver::Import> ();
+ 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::AST::SimplePath> ();
- Rust::Resolver::flatten_rebind (rebind, paths);
+ auto imports = std::vector<Rust::Resolver::Import> ();
+ 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::AST::SimplePath> ();
- 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::Import> ();
+ 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::AST::SimplePath> ();
- 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::Import> ();
+ 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 0c7b7527c44..e397ffdfe8b 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 00000000000..b89ff82caaa
--- /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" }
--
2.42.1
More information about the Gcc-patches
mailing list