Skip to content

Commit

Permalink
Improve Rib::Definition shadowing
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
powerboat9 authored and P-E-P committed Oct 9, 2024
1 parent af0f0e3 commit 1499466
Show file tree
Hide file tree
Showing 9 changed files with 187 additions and 56 deletions.
44 changes: 22 additions & 22 deletions gcc/rust/resolve/rust-finalize-imports-2.0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,44 +37,44 @@ 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
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);
}
}

Expand All @@ -83,36 +83,36 @@ 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);
}
}

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
Expand Down
16 changes: 16 additions & 0 deletions gcc/rust/resolve/rust-forever-stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,22 @@ template <Namespace N> class ForeverStack
tl::expected<NodeId, DuplicateNameError> 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<NodeId, DuplicateNameError> insert_globbed (Identifier name,
NodeId id);

/**
* Insert a new definition at the root of this stack
*
Expand Down
24 changes: 21 additions & 3 deletions gcc/rust/resolve/rust-forever-stack.hxx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,16 @@ ForeverStack<N>::insert_shadowable (Identifier name, NodeId node)
Rib::Definition::Shadowable (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)
Expand Down Expand Up @@ -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)
{
Expand Down
4 changes: 2 additions & 2 deletions gcc/rust/resolve/rust-late-name-resolver-2.0.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
18 changes: 18 additions & 0 deletions gcc/rust/resolve/rust-name-resolution-context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down
3 changes: 3 additions & 0 deletions gcc/rust/resolve/rust-name-resolution-context.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ class NameResolutionContext
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
Expand Down
103 changes: 79 additions & 24 deletions gcc/rust/resolve/rust-rib.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 ();
Expand All @@ -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)
Expand Down Expand Up @@ -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>
Expand Down
Loading

0 comments on commit 1499466

Please sign in to comment.