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 <powerboat9.gamer@gmail.com>
This commit is contained in:
parent
4cabeacc38
commit
17a7fd17b7
3 changed files with 114 additions and 91 deletions
|
@ -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 ();
|
||||
label = rebind.get_identifier ().as_string ();
|
||||
else
|
||||
label = path.get_final_segment ().as_string ();
|
||||
|
||||
// Add the identifier as a new path
|
||||
rebind_path.get_segments ().back ()
|
||||
= AST::SimplePathSegment (new_seg.as_string (), UNDEF_LOCATION);
|
||||
|
||||
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);
|
||||
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].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");
|
||||
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);
|
||||
auto imports = std::vector<Rust::Resolver::Import> ();
|
||||
Rust::Resolver::flatten_list (list, imports);
|
||||
|
||||
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");
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
7
gcc/testsuite/rust/compile/use_2.rs
Normal file
7
gcc/testsuite/rust/compile/use_2.rs
Normal file
|
@ -0,0 +1,7 @@
|
|||
mod foo {
|
||||
pub struct S;
|
||||
}
|
||||
|
||||
use foo::S as T;
|
||||
|
||||
const V: T = T; // { dg-warning "unused name" }
|
Loading…
Add table
Reference in a new issue