diff options
author | Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com> | 2024-01-16 13:55:02 +0100 |
---|---|---|
committer | Arthur Cohen <arthur.cohen@embecosm.com> | 2024-08-01 16:52:26 +0200 |
commit | f085a67ebb079431a202df822a15315e440ed456 (patch) | |
tree | f23c41a923c3bea2864a40bc3dbfd54e8724653c /gcc/rust/resolve/rust-rib.cc | |
parent | 16e00f3b14cf5a36624c287cfcded74a38b55212 (diff) | |
download | gcc-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.cc | 69 |
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 ¤t = 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> & |