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
{
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);
}
}
{
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);
}
}
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
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
*
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)
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)
{
// 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
}
}
+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)
{
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
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 ();
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)
/* 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<Rib::Definition>
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;
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
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