diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.cc b/gcc/rust/resolve/rust-finalize-imports-2.0.cc index 5ce05a9c6240..71916ae432bd 100644 --- a/gcc/rust/resolve/rust-finalize-imports-2.0.cc +++ b/gcc/rust/resolve/rust-finalize-imports-2.0.cc @@ -37,32 +37,32 @@ void GlobbingVisitor::visit (AST::Module &module) { if (module.get_visibility ().is_public ()) - ctx.insert_shadowable (module.get_name (), module.get_node_id (), - Namespace::Types); + ctx.insert_globbed (module.get_name (), module.get_node_id (), + Namespace::Types); } void GlobbingVisitor::visit (AST::MacroRulesDefinition ¯o) { if (macro.get_visibility ().is_public ()) - ctx.insert_shadowable (macro.get_rule_name (), macro.get_node_id (), - Namespace::Macros); + ctx.insert_globbed (macro.get_rule_name (), macro.get_node_id (), + Namespace::Macros); } void GlobbingVisitor::visit (AST::Function &function) { if (function.get_visibility ().is_public ()) - ctx.insert_shadowable (function.get_function_name (), - function.get_node_id (), Namespace::Values); + ctx.insert_globbed (function.get_function_name (), function.get_node_id (), + Namespace::Values); } void GlobbingVisitor::visit (AST::StaticItem &static_item) { if (static_item.get_visibility ().is_public ()) - ctx.insert_shadowable (static_item.get_identifier (), - static_item.get_node_id (), Namespace::Values); + ctx.insert_globbed (static_item.get_identifier (), + static_item.get_node_id (), Namespace::Values); } void @@ -70,11 +70,11 @@ GlobbingVisitor::visit (AST::StructStruct &struct_item) { if (struct_item.get_visibility ().is_public ()) { - ctx.insert_shadowable (struct_item.get_identifier (), - struct_item.get_node_id (), Namespace::Types); + ctx.insert_globbed (struct_item.get_identifier (), + struct_item.get_node_id (), Namespace::Types); if (struct_item.is_unit_struct ()) - ctx.insert_shadowable (struct_item.get_identifier (), - struct_item.get_node_id (), Namespace::Values); + ctx.insert_globbed (struct_item.get_identifier (), + struct_item.get_node_id (), Namespace::Values); } } @@ -83,11 +83,11 @@ GlobbingVisitor::visit (AST::TupleStruct &tuple_struct) { if (tuple_struct.get_visibility ().is_public ()) { - ctx.insert_shadowable (tuple_struct.get_identifier (), - tuple_struct.get_node_id (), Namespace::Types); + ctx.insert_globbed (tuple_struct.get_identifier (), + tuple_struct.get_node_id (), Namespace::Types); - ctx.insert_shadowable (tuple_struct.get_identifier (), - tuple_struct.get_node_id (), Namespace::Values); + ctx.insert_globbed (tuple_struct.get_identifier (), + tuple_struct.get_node_id (), Namespace::Values); } } @@ -95,24 +95,24 @@ void GlobbingVisitor::visit (AST::Enum &enum_item) { if (enum_item.get_visibility ().is_public ()) - ctx.insert_shadowable (enum_item.get_identifier (), - enum_item.get_node_id (), Namespace::Types); + ctx.insert_globbed (enum_item.get_identifier (), enum_item.get_node_id (), + Namespace::Types); } void GlobbingVisitor::visit (AST::Union &union_item) { if (union_item.get_visibility ().is_public ()) - ctx.insert_shadowable (union_item.get_identifier (), - union_item.get_node_id (), Namespace::Values); + ctx.insert_globbed (union_item.get_identifier (), union_item.get_node_id (), + Namespace::Values); } void GlobbingVisitor::visit (AST::ConstantItem &const_item) { if (const_item.get_visibility ().is_public ()) - ctx.insert_shadowable (const_item.get_identifier (), - const_item.get_node_id (), Namespace::Values); + ctx.insert_globbed (const_item.get_identifier (), const_item.get_node_id (), + Namespace::Values); } void diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h index 72b96bff3b3f..2dcabc2c66df 100644 --- a/gcc/rust/resolve/rust-forever-stack.h +++ b/gcc/rust/resolve/rust-forever-stack.h @@ -452,6 +452,22 @@ template class ForeverStack tl::expected insert_shadowable (Identifier name, NodeId id); + /** + * Insert a new glob-originated definition in the innermost `Rib` in this + * stack + * + * @param name The name of the definition + * @param id Its NodeId + * + * @return `DuplicateNameError` if that node was already present in the Rib, + * the node's `NodeId` otherwise. + * + * @aborts if there are no `Rib`s inserted in the current map, this function + * aborts the program. + */ + tl::expected insert_globbed (Identifier name, + NodeId id); + /** * Insert a new definition at the root of this stack * diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx index 2c3cba594484..9aa2f89907ee 100644 --- a/gcc/rust/resolve/rust-forever-stack.hxx +++ b/gcc/rust/resolve/rust-forever-stack.hxx @@ -131,6 +131,16 @@ ForeverStack::insert_shadowable (Identifier name, NodeId node) Rib::Definition::Shadowable (node)); } +template +tl::expected +ForeverStack::insert_globbed (Identifier name, NodeId node) +{ + auto &innermost_rib = peek (); + + return insert_inner (innermost_rib, name.as_string (), + Rib::Definition::Globbed (node)); +} + template tl::expected ForeverStack::insert_at_root (Identifier name, NodeId node) @@ -474,9 +484,17 @@ ForeverStack::dfs (ForeverStack::Node &starting_point, NodeId to_find) auto values = starting_point.rib.get_values (); for (auto &kv : values) - for (auto id : kv.second.ids) - if (id == to_find) - return {{starting_point, kv.first}}; + { + for (auto id : kv.second.ids_shadowable) + if (id == to_find) + return {{starting_point, kv.first}}; + for (auto id : kv.second.ids_non_shadowable) + if (id == to_find) + return {{starting_point, kv.first}}; + for (auto id : kv.second.ids_globbed) + if (id == to_find) + return {{starting_point, kv.first}}; + } for (auto &child : starting_point.children) { diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc index 9472d8c59c93..5cb97670b65b 100644 --- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc +++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc @@ -154,8 +154,8 @@ Late::visit (AST::IdentifierPattern &identifier) // do we insert functions in labels as well? // We do want to ignore duplicated data because some situations rely on it. - std::ignore - = ctx.values.insert (identifier.get_ident (), identifier.get_node_id ()); + std::ignore = ctx.values.insert_shadowable (identifier.get_ident (), + identifier.get_node_id ()); } void diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc b/gcc/rust/resolve/rust-name-resolution-context.cc index 1bf7ee2f29e7..28907dca6d22 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.cc +++ b/gcc/rust/resolve/rust-name-resolution-context.cc @@ -64,6 +64,24 @@ NameResolutionContext::insert_shadowable (Identifier name, NodeId id, } } +tl::expected +NameResolutionContext::insert_globbed (Identifier name, NodeId id, Namespace ns) +{ + switch (ns) + { + case Namespace::Values: + return values.insert_globbed (name, id); + case Namespace::Types: + return types.insert_globbed (name, id); + case Namespace::Macros: + return macros.insert_globbed (name, id); + case Namespace::Labels: + default: + // return labels.insert (name, id); + rust_unreachable (); + } +} + void NameResolutionContext::map_usage (Usage usage, Definition definition) { diff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h index f17cd0ae8e13..34800baad91b 100644 --- a/gcc/rust/resolve/rust-name-resolution-context.h +++ b/gcc/rust/resolve/rust-name-resolution-context.h @@ -175,6 +175,9 @@ class NameResolutionContext tl::expected insert_shadowable (Identifier name, NodeId id, Namespace ns); + tl::expected + insert_globbed (Identifier name, NodeId id, Namespace ns); + /** * Run a lambda in a "scoped" context, meaning that a new `Rib` will be pushed * before executing the lambda and then popped. This is useful for all kinds diff --git a/gcc/rust/resolve/rust-rib.cc b/gcc/rust/resolve/rust-rib.cc index 945e1c333caf..34abbffb1330 100644 --- a/gcc/rust/resolve/rust-rib.cc +++ b/gcc/rust/resolve/rust-rib.cc @@ -22,26 +22,51 @@ namespace Rust { namespace Resolver2_0 { -Rib::Definition::Definition (NodeId id, bool shadowable) - : ids ({id}), shadowable (shadowable) -{} +Rib::Definition::Definition (NodeId id, Mode mode) +{ + switch (mode) + { + case Mode::SHADOWABLE: + ids_shadowable.push_back (id); + return; + case Mode::NON_SHADOWABLE: + ids_non_shadowable.push_back (id); + return; + case Mode::GLOBBED: + ids_globbed.push_back (id); + return; + default: + gcc_unreachable (); + } +} bool Rib::Definition::is_ambiguous () const { - return shadowable && ids.size () > 1; + if (!ids_shadowable.empty ()) + return false; + else if (!ids_non_shadowable.empty ()) + return ids_non_shadowable.size () > 1; + else + return ids_globbed.size () > 1; } std::string Rib::Definition::to_string () const { std::stringstream out; - out << (shadowable ? "(S)" : "(NS)") << "["; - std::string sep; - for (auto id : ids) + const char *headers[3] = {"(S)[", "] (NS)[", "] (G)["}; + const std::vector *id_lists[3] + = {&ids_shadowable, &ids_non_shadowable, &ids_globbed}; + for (int i = 0; i < 3; i++) { - out << sep << id; - sep = ","; + out << headers[i]; + std::string sep; + for (auto id : *id_lists[i]) + { + out << sep << id; + sep = ","; + } } out << "]"; return out.str (); @@ -50,13 +75,19 @@ Rib::Definition::to_string () const Rib::Definition Rib::Definition::Shadowable (NodeId id) { - return Definition (id, true); + return Definition (id, Mode::SHADOWABLE); } Rib::Definition Rib::Definition::NonShadowable (NodeId id) { - return Definition (id, false); + return Definition (id, Mode::NON_SHADOWABLE); +} + +Rib::Definition +Rib::Definition::Globbed (NodeId id) +{ + return Definition (id, Mode::GLOBBED); } DuplicateNameError::DuplicateNameError (std::string name, NodeId existing) @@ -85,29 +116,53 @@ Rib::insert (std::string name, Definition def) /* No old value */ values[name] = def; } - else if (it->second.shadowable && def.shadowable) - { /* Both shadowable */ + else if (it->second.ids_non_shadowable.empty () + || def.ids_non_shadowable.empty ()) + { /* No non-shadowable conflict */ auto ¤t = values[name]; - for (auto id : def.ids) + for (auto id : def.ids_non_shadowable) { - if (std::find (current.ids.cbegin (), current.ids.cend (), id) - == current.ids.cend ()) - current.ids.push_back (id); + if (std::find (current.ids_non_shadowable.cbegin (), + current.ids_non_shadowable.cend (), id) + == current.ids_non_shadowable.cend ()) + current.ids_non_shadowable.push_back (id); else + // TODO: should this produce an error? + return tl::make_unexpected (DuplicateNameError (name, id)); + } + for (auto id : def.ids_shadowable) + { + if (std::find (current.ids_shadowable.cbegin (), + current.ids_shadowable.cend (), id) + == current.ids_shadowable.cend ()) + current.ids_shadowable.push_back (id); + else + // TODO: should this produce an error? + return tl::make_unexpected (DuplicateNameError (name, id)); + } + for (auto id : def.ids_globbed) + { + if (std::find (current.ids_globbed.cbegin (), + current.ids_globbed.cend (), id) + == current.ids_globbed.cend ()) + current.ids_globbed.push_back (id); + else + // TODO: should this produce an error? return tl::make_unexpected (DuplicateNameError (name, id)); } } - else if (it->second.shadowable) - { /* Only old shadowable : replace value */ - values[name] = def; - } - else /* Neither are shadowable */ + else /* Multiple non-shadowable */ { return tl::make_unexpected ( - DuplicateNameError (name, it->second.ids.back ())); + DuplicateNameError (name, it->second.ids_non_shadowable.back ())); } - return def.ids.back (); + if (!def.ids_shadowable.empty ()) + return def.ids_shadowable.back (); + else if (!def.ids_non_shadowable.empty ()) + return def.ids_non_shadowable.back (); + rust_assert (!def.ids_globbed.empty ()); + return def.ids_globbed.back (); } tl::optional diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h index 53881a92020a..9a046b2bef0d 100644 --- a/gcc/rust/resolve/rust-rib.h +++ b/gcc/rust/resolve/rust-rib.h @@ -113,9 +113,16 @@ class Rib public: static Definition NonShadowable (NodeId id); static Definition Shadowable (NodeId id); + static Definition Globbed (NodeId id); - std::vector ids; - bool shadowable; + // checked shadowable -> non_shadowable -> globbed + // we have shadowable *and* globbed in order to control + // resolution priority + // we *could* use a single vector with 2 indices here + // but it's probably not worth it for now + std::vector ids_shadowable; + std::vector ids_non_shadowable; + std::vector ids_globbed; Definition () = default; @@ -126,14 +133,29 @@ class Rib NodeId get_node_id () const { + if (!ids_shadowable.empty ()) + return ids_shadowable.back (); + rust_assert (!is_ambiguous ()); - return ids[0]; + + if (!ids_non_shadowable.empty ()) + return ids_non_shadowable.back (); + + rust_assert (!ids_globbed.empty ()); + return ids_globbed.back (); } std::string to_string () const; private: - Definition (NodeId id, bool shadowable); + enum class Mode + { + SHADOWABLE, + NON_SHADOWABLE, + GLOBBED + }; + + Definition (NodeId id, Mode mode); }; enum class Kind diff --git a/gcc/testsuite/rust/compile/nr2/exclude b/gcc/testsuite/rust/compile/nr2/exclude index dec3bdd4d18e..f254c56eb526 100644 --- a/gcc/testsuite/rust/compile/nr2/exclude +++ b/gcc/testsuite/rust/compile/nr2/exclude @@ -194,7 +194,6 @@ redef_error6.rs rustc_attr1.rs self-path1.rs self-path2.rs -shadow1.rs sizeof-stray-infer-var-bug.rs specify-crate-name.rs stmt_with_block_dot.rs