aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/resolve/rust-rib.cc
diff options
context:
space:
mode:
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>2024-01-16 13:55:02 +0100
committerArthur Cohen <arthur.cohen@embecosm.com>2024-08-01 16:52:26 +0200
commitf085a67ebb079431a202df822a15315e440ed456 (patch)
treef23c41a923c3bea2864a40bc3dbfd54e8724653c /gcc/rust/resolve/rust-rib.cc
parent16e00f3b14cf5a36624c287cfcded74a38b55212 (diff)
downloadgcc-f085a67ebb079431a202df822a15315e440ed456.zip
gcc-f085a67ebb079431a202df822a15315e440ed456.tar.gz
gcc-f085a67ebb079431a202df822a15315e440ed456.tar.bz2
gccrs: Add support for ambiguous use declarations
Glob use declarations may lead to ambiguous situation where two definitions with the same name are imported in a given scope. The compiler now handles shadowable items inserted after non shadowable items. An error is now thrown when multiple shadowable items are imported and used in the same rib. gcc/rust/ChangeLog: * resolve/rust-early-name-resolver-2.0.cc (Early::visit): Adapt resolved type to the new API. (Early::visit_attributes): Retrieve the node id from the definition. * resolve/rust-forever-stack.h: Change the return type of getter functions. Those functions now return a definition type instead of a node id. * resolve/rust-forever-stack.hxx: Change member function implementation in the forever stack to accomodate it's API changes. * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Use internal node id. Emit an error when resolving multiple ambiguous values. * resolve/rust-rib.cc (Rib::Definition::Definition): Add a default constructor. (Rib::Definition::is_ambiguous): Add a new function to determine whether a function definition is ambiguous or not. (Rib::Definition::to_string): Add a member function to convert a given definition to a string. (Rib::insert): Add new rules for value insertion in a rib. Insertion order does not impact the result anymore: inserting a shadowable value after a non shadowable one does not trigger an error anymore. All shadowable values inserted in a rib are kepts until being replaced by a non shadowable one. (Rib::get): Return a definition instead of a node id. * resolve/rust-rib.h: Update function prototypes. * resolve/rust-toplevel-name-resolver-2.0.cc (TopLevel::handle_use_glob): Update return value container to match the new function's prototype. (TopLevel::handle_use_dec): Likewise. (flatten_glob): Likewise. Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Diffstat (limited to 'gcc/rust/resolve/rust-rib.cc')
-rw-r--r--gcc/rust/resolve/rust-rib.cc69
1 files changed, 54 insertions, 15 deletions
diff --git a/gcc/rust/resolve/rust-rib.cc b/gcc/rust/resolve/rust-rib.cc
index dee3a09..a73e2bd 100644
--- a/gcc/rust/resolve/rust-rib.cc
+++ b/gcc/rust/resolve/rust-rib.cc
@@ -23,9 +23,30 @@ namespace Rust {
namespace Resolver2_0 {
Rib::Definition::Definition (NodeId id, bool shadowable)
- : id (id), shadowable (shadowable)
+ : ids ({id}), shadowable (shadowable)
{}
+bool
+Rib::Definition::is_ambiguous () const
+{
+ return shadowable && ids.size () > 1;
+}
+
+std::string
+Rib::Definition::to_string () const
+{
+ std::stringstream out;
+ out << (shadowable ? "(S)" : "(NS)") << "[";
+ std::string sep;
+ for (auto id : ids)
+ {
+ out << sep << id;
+ sep = ",";
+ }
+ out << "]";
+ return out.str ();
+}
+
Rib::Definition
Rib::Definition::Shadowable (NodeId id)
{
@@ -58,28 +79,46 @@ Rib::Rib (Kind kind, std::unordered_map<std::string, NodeId> to_insert)
tl::expected<NodeId, DuplicateNameError>
Rib::insert (std::string name, Definition def)
{
- auto res = values.insert ({name, def});
- auto inserted_id = res.first->second.id;
- auto existed = !res.second;
-
- // if we couldn't insert, the element already exists - exit with an error,
- // unless shadowing is allowed
- if (existed && !def.shadowable)
- return tl::make_unexpected (DuplicateNameError (name, inserted_id));
-
- // return the NodeId
- return inserted_id;
+ auto it = values.find (name);
+ if (it == values.end ())
+ {
+ /* No old value */
+ values[name] = def;
+ }
+ else if (it->second.shadowable && def.shadowable)
+ { /* Both shadowable */
+ auto &current = values[name];
+ for (auto id : def.ids)
+ {
+ if (std::find (current.ids.cbegin (), current.ids.cend (), id)
+ == current.ids.cend ())
+ {
+ current.ids.push_back (id);
+ }
+ }
+ }
+ else if (it->second.shadowable)
+ { /* Only old shadowable : replace value */
+ values[name] = def;
+ }
+ else /* Neither are shadowable */
+ {
+ return tl::make_unexpected (
+ DuplicateNameError (name, it->second.ids.back ()));
+ }
+
+ return def.ids.back ();
}
-tl::optional<NodeId>
+tl::optional<Rib::Definition>
Rib::get (const std::string &name)
{
auto it = values.find (name);
if (it == values.end ())
- return {};
+ return tl::nullopt;
- return it->second.id;
+ return it->second;
}
const std::unordered_map<std::string, Rib::Definition> &