Skip to content

Commit 62f5051

Browse files
committed
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>
1 parent c93eb30 commit 62f5051

File tree

3 files changed

+116
-93
lines changed

3 files changed

+116
-93
lines changed

gcc/rust/resolve/rust-ast-resolve-item.cc

+86-93
Original file line numberDiff line numberDiff line change
@@ -890,92 +890,85 @@ ResolveItem::resolve_extern_item (AST::ExternalItem *item)
890890
}
891891

892892
static void
893-
flatten_glob (const AST::UseTreeGlob &glob,
894-
std::vector<AST::SimplePath> &paths);
893+
flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports);
895894
static void
896-
flatten_rebind (const AST::UseTreeRebind &glob,
897-
std::vector<AST::SimplePath> &paths);
895+
flatten_rebind (const AST::UseTreeRebind &glob, std::vector<Import> &imports);
898896
static void
899-
flatten_list (const AST::UseTreeList &glob,
900-
std::vector<AST::SimplePath> &paths);
897+
flatten_list (const AST::UseTreeList &glob, std::vector<Import> &imports);
901898

902899
static void
903-
flatten (const AST::UseTree *tree, std::vector<AST::SimplePath> &paths)
900+
flatten (const AST::UseTree *tree, std::vector<Import> &imports)
904901
{
905902
switch (tree->get_kind ())
906903
{
907904
case AST::UseTree::Glob: {
908905
auto glob = static_cast<const AST::UseTreeGlob *> (tree);
909-
flatten_glob (*glob, paths);
906+
flatten_glob (*glob, imports);
910907
break;
911908
}
912909
case AST::UseTree::Rebind: {
913910
auto rebind = static_cast<const AST::UseTreeRebind *> (tree);
914-
flatten_rebind (*rebind, paths);
911+
flatten_rebind (*rebind, imports);
915912
break;
916913
}
917914
case AST::UseTree::List: {
918915
auto list = static_cast<const AST::UseTreeList *> (tree);
919-
flatten_list (*list, paths);
916+
flatten_list (*list, imports);
920917
break;
921918
}
922919
break;
923920
}
924921
}
925922

926923
static void
927-
flatten_glob (const AST::UseTreeGlob &glob, std::vector<AST::SimplePath> &paths)
924+
flatten_glob (const AST::UseTreeGlob &glob, std::vector<Import> &imports)
928925
{
929926
if (glob.has_path ())
930-
paths.emplace_back (glob.get_path ());
927+
imports.emplace_back (glob.get_path (), true, std::string ());
931928
}
932929

933930
static void
934-
flatten_rebind (const AST::UseTreeRebind &rebind,
935-
std::vector<AST::SimplePath> &paths)
931+
flatten_rebind (const AST::UseTreeRebind &rebind, std::vector<Import> &imports)
936932
{
937933
auto path = rebind.get_path ();
938-
if (rebind.has_path ())
939-
paths.emplace_back (path);
940934

941-
// FIXME: Do we want to emplace the rebind here as well?
935+
std::string label;
942936
if (rebind.has_identifier ())
943-
{
944-
auto rebind_path = path;
945-
auto new_seg = rebind.get_identifier ();
946-
947-
// Add the identifier as a new path
948-
rebind_path.get_segments ().back ()
949-
= AST::SimplePathSegment (new_seg, Location ());
937+
label = rebind.get_identifier ();
938+
else
939+
label = path.get_final_segment ().as_string ();
950940

951-
paths.emplace_back (rebind_path);
952-
}
941+
imports.emplace_back (path, false, label);
953942
}
954943

955944
static void
956-
flatten_list (const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths)
945+
flatten_list (const AST::UseTreeList &list, std::vector<Import> &imports)
957946
{
958947
auto prefix = AST::SimplePath::create_empty ();
959948
if (list.has_path ())
960949
prefix = list.get_path ();
961950

962951
for (const auto &tree : list.get_trees ())
963952
{
964-
auto sub_paths = std::vector<AST::SimplePath> ();
965-
flatten (tree.get (), sub_paths);
953+
// append imports to the main list, then modify them in-place
954+
auto start_idx = imports.size ();
955+
flatten (tree.get (), imports);
966956

967-
for (auto &sub_path : sub_paths)
968-
{
969-
auto new_path = prefix;
970-
std::copy (sub_path.get_segments ().begin (),
971-
sub_path.get_segments ().end (),
972-
std::back_inserter (new_path.get_segments ()));
973-
974-
paths.emplace_back (new_path);
975-
}
957+
for (auto import = imports.begin () + start_idx; import != imports.end ();
958+
import++)
959+
import->add_prefix (prefix);
976960
}
977961
}
978962

963+
void
964+
Import::add_prefix (AST::SimplePath prefix)
965+
{
966+
AST::SimplePath old_path (std::move (path));
967+
path = std::move (prefix);
968+
std::move (old_path.get_segments ().begin (), old_path.get_segments ().end (),
969+
std::back_inserter (path.get_segments ()));
970+
}
971+
979972
/**
980973
* Flatten a UseDeclaration's UseTree into multiple simple paths to resolve.
981974
*
@@ -996,21 +989,21 @@ flatten_list (const AST::UseTreeList &list, std::vector<AST::SimplePath> &paths)
996989
* Finally in the third case, we want to create two SimplePaths to resolve:
997990
* [some::path::one, some::path::two]
998991
*/
999-
static std::vector<AST::SimplePath>
1000-
flatten_use_dec_to_paths (const AST::UseDeclaration &use_item)
992+
static std::vector<Import>
993+
flatten_use_dec_to_imports (const AST::UseDeclaration &use_item)
1001994
{
1002-
auto paths = std::vector<AST::SimplePath> ();
995+
auto imports = std::vector<Import> ();
1003996

1004997
const auto &tree = use_item.get_tree ();
1005-
flatten (tree.get (), paths);
998+
flatten (tree.get (), imports);
1006999

1007-
return paths;
1000+
return imports;
10081001
}
10091002

10101003
void
10111004
ResolveItem::visit (AST::UseDeclaration &use_item)
10121005
{
1013-
std::vector<AST::SimplePath> to_resolve = flatten_use_dec_to_paths (use_item);
1006+
std::vector<Import> to_resolve = flatten_use_dec_to_imports (use_item);
10141007

10151008
// FIXME: I think this does not actually resolve glob use-decls and is going
10161009
// the wrong way about it. RFC #1560 specifies the following:
@@ -1022,18 +1015,20 @@ ResolveItem::visit (AST::UseDeclaration &use_item)
10221015
// Which is the opposite of what we're doing if I understand correctly?
10231016

10241017
NodeId current_module = resolver->peek_current_module_scope ();
1025-
for (auto &path : to_resolve)
1018+
for (auto &import : to_resolve)
10261019
{
1020+
auto &path = import.get_path ();
1021+
10271022
rust_debug ("resolving use-decl path: [%s]", path.as_string ().c_str ());
10281023
NodeId resolved_node_id = ResolvePath::go (&path);
10291024
bool ok = resolved_node_id != UNKNOWN_NODEID;
10301025
if (!ok)
10311026
continue;
10321027

1033-
const AST::SimplePathSegment &final_seg = path.get_final_segment ();
1028+
if (import.is_glob ())
1029+
continue;
10341030

1035-
auto decl
1036-
= CanonicalPath::new_seg (resolved_node_id, final_seg.as_string ());
1031+
auto decl = CanonicalPath::new_seg (resolved_node_id, import.get_name ());
10371032
mappings->insert_module_child_item (current_module, decl);
10381033

10391034
resolver->get_type_scope ().insert (decl, resolved_node_id,
@@ -1157,13 +1152,13 @@ rust_flatten_nested_glob (void)
11571152
= Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED,
11581153
foobar, Location ());
11591154

1160-
auto paths = std::vector<Rust::AST::SimplePath> ();
1161-
Rust::Resolver::flatten_glob (glob, paths);
1155+
auto imports = std::vector<Rust::Resolver::Import> ();
1156+
Rust::Resolver::flatten_glob (glob, imports);
11621157

1163-
ASSERT_TRUE (!paths.empty ());
1164-
ASSERT_EQ (paths.size (), 1);
1165-
ASSERT_EQ (paths[0].get_segments ()[0].as_string (), "foo");
1166-
ASSERT_EQ (paths[0].get_segments ()[1].as_string (), "bar");
1158+
ASSERT_TRUE (!imports.empty ());
1159+
ASSERT_EQ (imports.size (), 1);
1160+
ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo");
1161+
ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar");
11671162
}
11681163

11691164
static void
@@ -1175,12 +1170,12 @@ rust_flatten_glob (void)
11751170
= Rust::AST::UseTreeGlob (Rust::AST::UseTreeGlob::PathType::PATH_PREFIXED,
11761171
frob, Location ());
11771172

1178-
auto paths = std::vector<Rust::AST::SimplePath> ();
1179-
Rust::Resolver::flatten_glob (glob, paths);
1173+
auto imports = std::vector<Rust::Resolver::Import> ();
1174+
Rust::Resolver::flatten_glob (glob, imports);
11801175

1181-
ASSERT_TRUE (!paths.empty ());
1182-
ASSERT_EQ (paths.size (), 1);
1183-
ASSERT_EQ (paths[0], "frobulator");
1176+
ASSERT_TRUE (!imports.empty ());
1177+
ASSERT_EQ (imports.size (), 1);
1178+
ASSERT_EQ (imports[0].get_path (), "frobulator");
11841179
}
11851180

11861181
static void
@@ -1193,13 +1188,13 @@ rust_flatten_rebind_none (void)
11931188
auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::NONE,
11941189
foobar, Location ());
11951190

1196-
auto paths = std::vector<Rust::AST::SimplePath> ();
1197-
Rust::Resolver::flatten_rebind (rebind, paths);
1191+
auto imports = std::vector<Rust::Resolver::Import> ();
1192+
Rust::Resolver::flatten_rebind (rebind, imports);
11981193

1199-
ASSERT_TRUE (!paths.empty ());
1200-
ASSERT_EQ (paths.size (), 1);
1201-
ASSERT_EQ (paths[0].get_segments ()[0].as_string (), "foo");
1202-
ASSERT_EQ (paths[0].get_segments ()[1].as_string (), "bar");
1194+
ASSERT_TRUE (!imports.empty ());
1195+
ASSERT_EQ (imports.size (), 1);
1196+
ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo");
1197+
ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar");
12031198
}
12041199

12051200
static void
@@ -1210,13 +1205,13 @@ rust_flatten_rebind (void)
12101205
auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER,
12111206
frob, Location (), "saindoux");
12121207

1213-
auto paths = std::vector<Rust::AST::SimplePath> ();
1214-
Rust::Resolver::flatten_rebind (rebind, paths);
1208+
auto imports = std::vector<Rust::Resolver::Import> ();
1209+
Rust::Resolver::flatten_rebind (rebind, imports);
12151210

1216-
ASSERT_TRUE (!paths.empty ());
1217-
ASSERT_EQ (paths.size (), 2);
1218-
ASSERT_EQ (paths[0], "frobulator");
1219-
ASSERT_EQ (paths[1], "saindoux");
1211+
ASSERT_TRUE (!imports.empty ());
1212+
ASSERT_EQ (imports.size (), 1);
1213+
ASSERT_EQ (imports[0].get_path (), "frobulator");
1214+
ASSERT_EQ (imports[0].get_name (), "saindoux");
12201215
}
12211216

12221217
static void
@@ -1231,17 +1226,15 @@ rust_flatten_rebind_nested (void)
12311226
auto rebind = Rust::AST::UseTreeRebind (Rust::AST::UseTreeRebind::IDENTIFIER,
12321227
foo_bar_baz, Location (), "saindoux");
12331228

1234-
auto paths = std::vector<Rust::AST::SimplePath> ();
1235-
Rust::Resolver::flatten_rebind (rebind, paths);
1236-
1237-
ASSERT_TRUE (!paths.empty ());
1238-
ASSERT_EQ (paths.size (), 2);
1239-
ASSERT_EQ (paths[0].get_segments ()[0].as_string (), "foo");
1240-
ASSERT_EQ (paths[0].get_segments ()[1].as_string (), "bar");
1241-
ASSERT_EQ (paths[0].get_segments ()[2].as_string (), "baz");
1242-
ASSERT_EQ (paths[1].get_segments ()[0].as_string (), "foo");
1243-
ASSERT_EQ (paths[1].get_segments ()[1].as_string (), "bar");
1244-
ASSERT_EQ (paths[1].get_segments ()[2].as_string (), "saindoux");
1229+
auto imports = std::vector<Rust::Resolver::Import> ();
1230+
Rust::Resolver::flatten_rebind (rebind, imports);
1231+
1232+
ASSERT_TRUE (!imports.empty ());
1233+
ASSERT_EQ (imports.size (), 1);
1234+
ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo");
1235+
ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar");
1236+
ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz");
1237+
ASSERT_EQ (imports[0].get_name (), "saindoux");
12451238
}
12461239

12471240
static void
@@ -1270,17 +1263,17 @@ rust_flatten_list (void)
12701263
auto list = Rust::AST::UseTreeList (Rust::AST::UseTreeList::PATH_PREFIXED,
12711264
foo_bar, std::move (uses), Location ());
12721265

1273-
auto paths = std::vector<Rust::AST::SimplePath> ();
1274-
Rust::Resolver::flatten_list (list, paths);
1275-
1276-
ASSERT_TRUE (!paths.empty ());
1277-
ASSERT_EQ (paths.size (), 2);
1278-
ASSERT_EQ (paths[0].get_segments ()[0].as_string (), "foo");
1279-
ASSERT_EQ (paths[0].get_segments ()[1].as_string (), "bar");
1280-
ASSERT_EQ (paths[0].get_segments ()[2].as_string (), "baz");
1281-
ASSERT_EQ (paths[1].get_segments ()[0].as_string (), "foo");
1282-
ASSERT_EQ (paths[1].get_segments ()[1].as_string (), "bar");
1283-
ASSERT_EQ (paths[1].get_segments ()[2].as_string (), "bul");
1266+
auto imports = std::vector<Rust::Resolver::Import> ();
1267+
Rust::Resolver::flatten_list (list, imports);
1268+
1269+
ASSERT_TRUE (!imports.empty ());
1270+
ASSERT_EQ (imports.size (), 2);
1271+
ASSERT_EQ (imports[0].get_path ().get_segments ()[0].as_string (), "foo");
1272+
ASSERT_EQ (imports[0].get_path ().get_segments ()[1].as_string (), "bar");
1273+
ASSERT_EQ (imports[0].get_path ().get_segments ()[2].as_string (), "baz");
1274+
ASSERT_EQ (imports[1].get_path ().get_segments ()[0].as_string (), "foo");
1275+
ASSERT_EQ (imports[1].get_path ().get_segments ()[1].as_string (), "bar");
1276+
ASSERT_EQ (imports[1].get_path ().get_segments ()[2].as_string (), "bul");
12841277
}
12851278

12861279
static void

gcc/rust/resolve/rust-ast-resolve-item.h

+23
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,29 @@ class ResolveExternItem : public ResolverBase
130130
const CanonicalPath &canonical_prefix;
131131
};
132132

133+
class Import
134+
{
135+
public:
136+
Import (AST::SimplePath path, bool is_glob, std::string name)
137+
: path (path), is_glob_f (is_glob), name (name)
138+
{}
139+
140+
AST::SimplePath &get_path () { return path; }
141+
142+
const AST::SimplePath &get_path () const { return path; }
143+
144+
bool is_glob () const { return is_glob_f; }
145+
146+
const std::string &get_name () const { return name; }
147+
148+
void add_prefix (AST::SimplePath prefix);
149+
150+
private:
151+
AST::SimplePath path;
152+
bool is_glob_f;
153+
std::string name;
154+
};
155+
133156
} // namespace Resolver
134157
} // namespace Rust
135158

gcc/testsuite/rust/compile/use_2.rs

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
mod foo {
2+
pub struct S;
3+
}
4+
5+
use foo::S as T;
6+
7+
const V: T = T; // { dg-warning "unused name" }

0 commit comments

Comments
 (0)