aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOwen Avery <powerboat9.gamer@gmail.com>2024-10-04 17:33:42 -0400
committerP-E-P <32375388+P-E-P@users.noreply.github.com>2024-10-09 09:05:29 +0000
commit14994668b56073e143274fcc159187a5c653d424 (patch)
tree95401638a511326717ff02e92bc25a28b34ae5db
parentaf0f0e3f5384457cecb74608476caf2acd1c5ebc (diff)
downloadgcc-14994668b56073e143274fcc159187a5c653d424.zip
gcc-14994668b56073e143274fcc159187a5c653d424.tar.gz
gcc-14994668b56073e143274fcc159187a5c653d424.tar.bz2
Improve Rib::Definition shadowing
gcc/rust/ChangeLog: * resolve/rust-finalize-imports-2.0.cc (GlobbingVisitor::visit): Replace calls to insert_shadowable with insert_globbed. * resolve/rust-forever-stack.h (ForeverStack::insert_globbed): Add. * resolve/rust-forever-stack.hxx (ForeverStack::insert_globbed): Add. (ForeverStack::dfs): Handle modifications to Rib::Definition fields. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Make IdentifierPattern-based declarations shadowable. * resolve/rust-name-resolution-context.cc (NameResolutionContext::insert_globbed): Add. * resolve/rust-name-resolution-context.h (NameResolutionContext::insert_globbed): Add. * resolve/rust-rib.cc (Rib::Definition::Definition): Use Rib::Definition::Mode to indicate shadowing mode instead of boolean, handle modifications to Rib::Definition fields. (Rib::Definition::is_ambiguous): Handle modifications to Rib::Definition fields. (Rib::Definition::to_string): Likewise. (Rib::Definition::Shadowable): Handle changed constructor signature. (Rib::Definition::NonShadowable): Likewise. (Rib::Definition::Globbed): Add. (Rib::insert): Handle changes to Rib::Definition fields. * resolve/rust-rib.h (Rib::Definition::Globbed): Add. (Rib::Definition::ids): Remove. (Rib::Definition::ids_shadowable): Add. (Rib::Definition::ids_non_shadowable): Add. (Rib::Definition::ids_globbed): Add. (Rib::Definition::get_node_id): Handle modifications to Rib::Definition fields. (Rib::Definition::Mode): Add. (Rib::Definition::Definition): Use Rib::Definition::Mode to indicate shadowing mode instead of boolean. gcc/testsuite/ChangeLog: * rust/compile/nr2/exclude: Remove shadow1.rs. Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
-rw-r--r--gcc/rust/resolve/rust-finalize-imports-2.0.cc44
-rw-r--r--gcc/rust/resolve/rust-forever-stack.h16
-rw-r--r--gcc/rust/resolve/rust-forever-stack.hxx24
-rw-r--r--gcc/rust/resolve/rust-late-name-resolver-2.0.cc4
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.cc18
-rw-r--r--gcc/rust/resolve/rust-name-resolution-context.h3
-rw-r--r--gcc/rust/resolve/rust-rib.cc103
-rw-r--r--gcc/rust/resolve/rust-rib.h30
-rw-r--r--gcc/testsuite/rust/compile/nr2/exclude1
9 files changed, 187 insertions, 56 deletions
diff --git a/gcc/rust/resolve/rust-finalize-imports-2.0.cc b/gcc/rust/resolve/rust-finalize-imports-2.0.cc
index 5ce05a9..71916ae 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 &macro)
{
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 72b96bf..2dcabc2 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -453,6 +453,22 @@ public:
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<NodeId, DuplicateNameError> insert_globbed (Identifier name,
+ NodeId id);
+
+ /**
* Insert a new definition at the root of this stack
*
* @param name The name of the definition
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx
index 2c3cba5..9aa2f89 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -133,6 +133,16 @@ ForeverStack<N>::insert_shadowable (Identifier name, NodeId node)
template <Namespace N>
tl::expected<NodeId, DuplicateNameError>
+ForeverStack<N>::insert_globbed (Identifier name, NodeId node)
+{
+ auto &innermost_rib = peek ();
+
+ return insert_inner (innermost_rib, name.as_string (),
+ Rib::Definition::Globbed (node));
+}
+
+template <Namespace N>
+tl::expected<NodeId, DuplicateNameError>
ForeverStack<N>::insert_at_root (Identifier name, NodeId node)
{
auto &root_rib = root.rib;
@@ -474,9 +484,17 @@ ForeverStack<N>::dfs (ForeverStack<N>::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 9472d8c..5cb9767 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 1bf7ee2..28907dc 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<NodeId, DuplicateNameError>
+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 f17cd0a..34800ba 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -175,6 +175,9 @@ public:
tl::expected<NodeId, DuplicateNameError>
insert_shadowable (Identifier name, NodeId id, Namespace ns);
+ tl::expected<NodeId, DuplicateNameError>
+ 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 945e1c3..34abbff 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<NodeId> *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 &current = 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<Rib::Definition>
diff --git a/gcc/rust/resolve/rust-rib.h b/gcc/rust/resolve/rust-rib.h
index 53881a9..9a046b2 100644
--- a/gcc/rust/resolve/rust-rib.h
+++ b/gcc/rust/resolve/rust-rib.h
@@ -113,9 +113,16 @@ public:
public:
static Definition NonShadowable (NodeId id);
static Definition Shadowable (NodeId id);
+ static Definition Globbed (NodeId id);
- std::vector<NodeId> 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<NodeId> ids_shadowable;
+ std::vector<NodeId> ids_non_shadowable;
+ std::vector<NodeId> ids_globbed;
Definition () = default;
@@ -126,14 +133,29 @@ public:
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 dec3bdd..f254c56 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