From: Arthur Cohen <[email protected]>
Namespaces, flattening and resolved_nodes are all properly separated now and in
the files
where they should be.
gcc/rust/ChangeLog:
* resolve/rust-early-name-resolver-2.0.cc (Early::try_insert_once): Use
new
Usage -> Definition map for macros.
* resolve/rust-finalized-name-resolution-context.cc
(FinalizedNameResolutionContext::map_usage): Dispatch to proper
resolution map.
* resolve/rust-forever-stack.h (enum class LookupFinalizeError): Move
here.
* resolve/rust-forever-stack.hxx: Make resolution take a
resolve_segment lambda with
an extra namespace parameter.
* resolve/rust-name-resolution-context.hxx: Likewise.
* resolve/rust-name-resolution-context.cc (find_leaf_definition_inner):
Move here...
(NameResolutionContext::find_leaf_definition): Likewise.
(NameResolutionContext::flatten): Likewise.
* resolve/rust-name-resolution-context.h: ...from here.
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/1cdd162df75c94fd1eb3367829f7b1c364443038
The commit has NOT been mentioned in any issue.
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4551
.../resolve/rust-early-name-resolver-2.0.cc | 2 +-
.../rust-finalized-name-resolution-context.cc | 27 ++++++--
gcc/rust/resolve/rust-forever-stack.h | 39 +++++++++--
gcc/rust/resolve/rust-forever-stack.hxx | 69 +++++++++++++++++--
.../resolve/rust-name-resolution-context.cc | 69 ++-----------------
.../resolve/rust-name-resolution-context.h | 60 +++++++---------
.../resolve/rust-name-resolution-context.hxx | 41 ++++++-----
7 files changed, 177 insertions(+), 130 deletions(-)
diff --git a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
index de68bf52e..148385300 100644
--- a/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-early-name-resolver-2.0.cc
@@ -41,7 +41,7 @@ Early::Early (NameResolutionContext &ctx)
void
Early::try_insert_once (AST::MacroInvocation &invocation, NodeId resolved)
{
- auto leaf_macro = ctx.find_leaf_definition (resolved);
+ auto leaf_macro = ctx.macros.find_leaf_definition (resolved);
// Sometimes the import itself isn't resolved yet this turn of the
fixed-point
if (!leaf_macro)
diff --git a/gcc/rust/resolve/rust-finalized-name-resolution-context.cc
b/gcc/rust/resolve/rust-finalized-name-resolution-context.cc
index a8902e283..71d1269f3 100644
--- a/gcc/rust/resolve/rust-finalized-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-finalized-name-resolution-context.cc
@@ -17,6 +17,9 @@
// <http://www.gnu.org/licenses/>.
#include "rust-finalized-name-resolution-context.h"
+#include "expected.h"
+#include "optional.h"
+#include "rust-forever-stack.h"
namespace Rust {
namespace Resolver2_0 {
@@ -45,10 +48,26 @@ void
FinalizedNameResolutionContext::map_usage (Usage usage, Definition definition,
Namespace ns)
{
- auto leaf_definition
- = ctx.find_leaf_definition (definition.id).value_or (definition);
-
- ctx.map_usage (usage, leaf_definition, ns);
+ tl::expected<Definition, LookupFinalizeError> leaf_result
+ = tl::make_unexpected (LookupFinalizeError::NoDefinition);
+
+ switch (ns)
+ {
+ case Namespace::Values:
+ leaf_result = ctx.values.find_leaf_definition (definition.id);
+ break;
+ case Namespace::Types:
+ leaf_result = ctx.types.find_leaf_definition (definition.id);
+ break;
+ case Namespace::Labels:
+ leaf_result = ctx.labels.find_leaf_definition (definition.id);
+ break;
+ case Namespace::Macros:
+ leaf_result = ctx.macros.find_leaf_definition (definition.id);
+ break;
+ }
+
+ ctx.map_usage (usage, leaf_result.value_or (definition), ns);
}
tl::optional<NodeId>
diff --git a/gcc/rust/resolve/rust-forever-stack.h
b/gcc/rust/resolve/rust-forever-stack.h
index 3a2877244..a2a031ddd 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -620,6 +620,20 @@ private:
NodeId node_id;
};
+/**
+ * Error enum for finding leaf definitions in the resolved_nodes map
+ */
+enum class LookupFinalizeError
+{
+ // Impossible - we did not find any definition corresponding to a Usage.
+ // This is an internal compiler error
+ NoDefinition,
+ // There was a loop in the map, such as an import resolving to another
+ // import which eventually resolved to the original import. Report the
+ // error and stop the pipeline
+ Loop,
+};
+
template <Namespace N> class ForeverStack
{
public:
@@ -862,11 +876,12 @@ public:
Node &find_closest_module (Node &starting_point);
- tl::optional<SegIterator> find_starting_point (
- const std::vector<ResolutionPath::Segment> &segments,
- std::reference_wrapper<Node> &starting_point,
- std::function<void (Usage, Definition)> insert_segment_resolution,
- std::vector<Error> &collect_errors);
+ tl::optional<SegIterator>
+ find_starting_point (const std::vector<ResolutionPath::Segment> &segments,
+ std::reference_wrapper<Node> &starting_point,
+ std::function<void (Usage, Definition, Namespace)>
+ insert_segment_resolution,
+ std::vector<Error> &collect_errors);
/* Helper functions for forward resolution (to_canonical_path, to_rib...) */
struct DfsResult
@@ -909,7 +924,9 @@ public:
void map_usage (Usage usage, Definition definition)
{
- auto inserted = resolved_nodes.emplace (usage, definition);
+ resolved_nodes.emplace (usage, definition);
+
+ // auto inserted = resolved_nodes.emplace (usage, definition);
// is that valid?
// FIXME: Yikes
@@ -926,6 +943,16 @@ public:
return it->second.id;
}
+ tl::expected<Definition, LookupFinalizeError>
+ find_leaf_definition (const NodeId &key) const;
+
+ /**
+ * Look at NameResolutionContext::flatten - This is the inner working
function
+ * which works on one specific namespace, while
NameResolutionContext::flatten
+ * calls flatten for every namespace
+ */
+ void flatten ();
+
/* Map of "usage" nodes which have been resolved to a "definition" node */
std::map<Usage, Definition> resolved_nodes;
};
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx
b/gcc/rust/resolve/rust-forever-stack.hxx
index 9f1a2cdb5..9a21dc1ee 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -462,7 +462,7 @@ tl::optional<typename
std::vector<ResolutionPath::Segment>::const_iterator>
ForeverStack<N>::find_starting_point (
const std::vector<ResolutionPath::Segment> &segments,
std::reference_wrapper<Node> &starting_point,
- std::function<void (Usage, Definition)> insert_segment_resolution,
+ std::function<void (Usage, Definition, Namespace)> insert_segment_resolution,
std::vector<Error> &collect_errors)
{
auto iterator = segments.begin ();
@@ -485,7 +485,7 @@ ForeverStack<N>::find_starting_point (
{
starting_point = root;
insert_segment_resolution (Usage (seg.node_id),
- Definition (starting_point.get ().id));
+ Definition (starting_point.get ().id), N);
iterator++;
break;
}
@@ -494,7 +494,7 @@ ForeverStack<N>::find_starting_point (
// insert segment resolution and exit
starting_point = find_closest_module (starting_point);
insert_segment_resolution (Usage (seg.node_id),
- Definition (starting_point.get ().id));
+ Definition (starting_point.get ().id), N);
iterator++;
break;
}
@@ -513,7 +513,7 @@ ForeverStack<N>::find_starting_point (
= find_closest_module (starting_point.get ().parent.value ());
insert_segment_resolution (Usage (seg.node_id),
- Definition (starting_point.get ().id));
+ Definition (starting_point.get ().id), N);
continue;
}
@@ -733,6 +733,67 @@ ForeverStack<N>::is_module_descendant (NodeId parent,
NodeId child) const
return dfs_node (dfs_node (root, parent).value (), child).has_value ();
}
+static tl::expected<Definition, LookupFinalizeError>
+find_leaf_definition_inner (const Usage &key,
+ const std::map<Usage, Definition> &resolved_nodes,
+ std::set<Usage> &keys_seen)
+{
+ auto original_definition = resolved_nodes.find (key);
+ auto possible_import = Usage (original_definition->second.id);
+
+ if (original_definition == resolved_nodes.end ())
+ return tl::make_unexpected (LookupFinalizeError::NoDefinition);
+
+ if (!keys_seen.insert (key).second)
+ return tl::make_unexpected (LookupFinalizeError::Loop);
+
+ if (resolved_nodes.find (possible_import) == resolved_nodes.end ())
+ return original_definition->second;
+
+ // We're dealing with an import - a reference to another
+ // definition. Go through the chain and update the original key's
+ // corresponding definition.
+ return find_leaf_definition_inner (possible_import, resolved_nodes,
+ keys_seen);
+}
+
+template <Namespace N>
+tl::expected<Definition, LookupFinalizeError>
+ForeverStack<N>::find_leaf_definition (const NodeId &key) const
+{
+ std::set<Usage> keys_seen;
+
+ return find_leaf_definition_inner (Usage (key), resolved_nodes, keys_seen);
+}
+
+template <Namespace N>
+void
+ForeverStack<N>::flatten ()
+{
+ for (auto &k_v : resolved_nodes)
+ {
+ // Loop detection
+ auto keys_seen = std::set<Usage> ();
+
+ auto result
+ = find_leaf_definition_inner (k_v.first, resolved_nodes, keys_seen);
+
+ if (!result)
+ {
+ // Trigger an ICE if we haven't found a definition because that's
+ // really weird
+ rust_assert (result.error () != LookupFinalizeError::NoDefinition);
+
+ // FIXME: This needs to be improved and tested, but later
+ rust_error_at (UNDEF_LOCATION, "import loop");
+ continue;
+ }
+
+ // Replace the Definition for this Usage in the map. This may be a no-op.
+ k_v.second = result.value ();
+ }
+}
+
// FIXME: Can we add selftests?
} // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-name-resolution-context.cc
b/gcc/rust/resolve/rust-name-resolution-context.cc
index c84c34258..479d0cb46 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.cc
+++ b/gcc/rust/resolve/rust-name-resolution-context.cc
@@ -372,74 +372,13 @@ NameResolutionContext::scoped (Rib::Kind rib_kind,
Namespace ns,
}
}
-static tl::expected<Definition, NameResolutionContext::LookupFinalizeError>
-find_leaf_definition_inner (const Usage &key,
- const std::map<Usage, Definition> &resolved_nodes,
- std::set<Usage> &keys_seen)
-{
- auto original_definition = resolved_nodes.find (key);
- auto possible_import = Usage (original_definition->second.id);
-
- if (original_definition == resolved_nodes.end ())
- return tl::make_unexpected (
- NameResolutionContext::LookupFinalizeError::NoDefinition);
-
- if (!keys_seen.insert (key).second)
- return tl::make_unexpected (
- NameResolutionContext::LookupFinalizeError::Loop);
-
- if (resolved_nodes.find (possible_import) == resolved_nodes.end ())
- return original_definition->second;
-
- // We're dealing with an import - a reference to another
- // definition. Go through the chain and update the original key's
- // corresponding definition.
- return find_leaf_definition_inner (possible_import, resolved_nodes,
- keys_seen);
-}
-
-tl::expected<Definition, NameResolutionContext::LookupFinalizeError>
-NameResolutionContext::find_leaf_definition (const NodeId &key) const
-{
- std::set<Usage> keys_seen;
-
- return find_leaf_definition_inner (Usage (key), resolved_nodes, keys_seen);
-}
-
void
NameResolutionContext::flatten ()
{
- rust_debug ("[ARTHUR] FINALIZING EARLY NR!!!!");
-
- for (auto &kv : resolved_nodes)
- rust_debug ("[ARTHUR] [resolved_nodes]: %d -> %d", kv.first.id,
- kv.second.id);
-
- for (auto &k_v : resolved_nodes)
- {
- // Loop detection
- auto keys_seen = std::set<Usage> ();
-
- auto result
- = find_leaf_definition_inner (k_v.first, resolved_nodes, keys_seen);
-
- if (!result)
- {
- // Trigger an ICE if we haven't found a definition because that's
- // really weird
- rust_assert (result.error () != LookupFinalizeError::NoDefinition);
-
- rust_error_at (UNDEF_LOCATION, "import loop");
- continue;
- }
-
- // Replace the Definition for this Usage in the map. This may be a no-op.
- k_v.second = result.value ();
- }
-
- for (auto &kv : resolved_nodes)
- rust_debug ("[ARTHUR] [resolved_nodes]: %d -> %d", kv.first.id,
- kv.second.id);
+ values.flatten ();
+ types.flatten ();
+ macros.flatten ();
+ labels.flatten ();
}
} // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h
b/gcc/rust/resolve/rust-name-resolution-context.h
index fa383df37..f44fc2c5d 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -585,10 +585,9 @@ public:
resolve_path (const ResolutionPath &path, ResolutionMode mode,
std::vector<Error> &collect_errors, Namespace ns)
{
- std::function<void (Usage, Definition)> insert_segment_resolution
- = [this, ns] (Usage seg_id, Definition id) {
- if (resolved_nodes.find (seg_id) == resolved_nodes.end ())
- map_usage (seg_id, id, ns);
+ std::function<void (Usage, Definition, Namespace)>
insert_segment_resolution
+ = [this] (Usage seg_id, Definition id, Namespace ns) {
+ map_usage (seg_id, id, ns);
};
tl::optional<NamespacedDefinition> resolved = tl::nullopt;
@@ -843,20 +842,6 @@ public:
std::forward<Args> (args)...);
}
- enum class LookupFinalizeError
- {
- // Impossible - we did not find any definition corresponding to a Usage.
- // This is an internal compiler error
- NoDefinition,
- // There was a loop in the map, such as an import resolving to another
- // import which eventually resolved to the original import. Report the
- // error and stop the pipeline
- Loop,
- };
-
- tl::expected<Definition, LookupFinalizeError>
- find_leaf_definition (const NodeId &key) const;
-
/**
* We've now collected every definition and import, and errored out when
* necessary if multiple definitions are colliding. Do a final flattening of
@@ -890,31 +875,38 @@ private:
* current map, an empty one otherwise.
*/
template <Namespace N>
- tl::optional<Rib::Definition> resolve_path (
- ForeverStack<N> &stack, const ResolutionPath &path, ResolutionMode mode,
- std::function<void (Usage, Definition)> insert_segment_resolution,
- std::vector<Error> &collect_errors);
+ tl::optional<Rib::Definition>
+ resolve_path (ForeverStack<N> &stack, const ResolutionPath &path,
+ ResolutionMode mode,
+ std::function<void (Usage, Definition, Namespace)>
+ insert_segment_resolution,
+ std::vector<Error> &collect_errors);
template <Namespace N>
- tl::optional<Rib::Definition> resolve_path (
- ForeverStack<N> &stack, const ResolutionPath &path, ResolutionMode mode,
- std::function<void (Usage, Definition)> insert_segment_resolution,
- std::vector<Error> &collect_errors, NodeId starting_point_id);
+ tl::optional<Rib::Definition>
+ resolve_path (ForeverStack<N> &stack, const ResolutionPath &path,
+ ResolutionMode mode,
+ std::function<void (Usage, Definition, Namespace)>
+ insert_segment_resolution,
+ std::vector<Error> &collect_errors, NodeId starting_point_id);
template <Namespace N>
tl::optional<Rib::Definition> resolve_path (
ForeverStack<N> &stack, const ResolutionPath &path, ResolutionMode mode,
- std::function<void (Usage, Definition)> insert_segment_resolution,
+ std::function<void (Usage, Definition, Namespace)>
+ insert_segment_resolution,
std::vector<Error> &collect_errors,
std::reference_wrapper<typename ForeverStack<N>::Node> starting_point);
template <Namespace N>
- tl::optional<typename ForeverStack<N>::Node &> resolve_segments (
- ForeverStack<N> &stack, typename ForeverStack<N>::Node &starting_point,
- const std::vector<ResolutionPath::Segment> &segments,
- typename ForeverStack<N>::SegIterator iterator,
- std::function<void (Usage, Definition)> insert_segment_resolution,
- std::vector<Error> &collect_errors);
+ tl::optional<typename ForeverStack<N>::Node &>
+ resolve_segments (ForeverStack<N> &stack,
+ typename ForeverStack<N>::Node &starting_point,
+ const std::vector<ResolutionPath::Segment> &segments,
+ typename ForeverStack<N>::SegIterator iterator,
+ std::function<void (Usage, Definition, Namespace)>
+ insert_segment_resolution,
+ std::vector<Error> &collect_errors);
template <Namespace N>
tl::optional<Rib::Definition>
@@ -923,7 +915,7 @@ private:
std::string &seg_name, bool is_lower_self);
/* Map of "usage" nodes which have been resolved to a "definition" node */
- std::map<Usage, Definition> resolved_nodes;
+ // std::map<Usage, Definition> resolved_nodes;
};
} // namespace Resolver2_0
diff --git a/gcc/rust/resolve/rust-name-resolution-context.hxx
b/gcc/rust/resolve/rust-name-resolution-context.hxx
index 1492125e5..c16bae874 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.hxx
+++ b/gcc/rust/resolve/rust-name-resolution-context.hxx
@@ -32,7 +32,7 @@ template <Namespace N>
tl::optional<Rib::Definition>
NameResolutionContext::resolve_path (
ForeverStack<N> &stack, const ResolutionPath &path, ResolutionMode mode,
- std::function<void (Usage, Definition)> insert_segment_resolution,
+ std::function<void (Usage, Definition, Namespace)> insert_segment_resolution,
std::vector<Error> &collect_errors)
{
std::reference_wrapper<typename ForeverStack<N>::Node> starting_point
@@ -47,7 +47,7 @@ template <Namespace N>
tl::optional<Rib::Definition>
NameResolutionContext::resolve_path (
ForeverStack<N> &stack, const ResolutionPath &path, ResolutionMode mode,
- std::function<void (Usage, Definition)> insert_segment_resolution,
+ std::function<void (Usage, Definition, Namespace)> insert_segment_resolution,
std::vector<Error> &collect_errors, NodeId starting_point_id)
{
@@ -67,7 +67,7 @@ template <Namespace N>
tl::optional<Rib::Definition>
NameResolutionContext::resolve_path (
ForeverStack<N> &stack, const ResolutionPath &path, ResolutionMode mode,
- std::function<void (Usage, Definition)> insert_segment_resolution,
+ std::function<void (Usage, Definition, Namespace)> insert_segment_resolution,
std::vector<Error> &collect_errors,
std::reference_wrapper<typename ForeverStack<N>::Node> starting_point)
{
@@ -80,8 +80,8 @@ NameResolutionContext::resolve_path (
NodeId seg_id
= Analysis::Mappings::get ().get_lang_item_node (lang_item->first);
- insert_segment_resolution (Usage (lang_item->second),
- Definition (seg_id));
+ insert_segment_resolution (Usage (lang_item->second), Definition
(seg_id),
+ N);
if (path.get_segments ().empty ())
return Rib::Definition::NonShadowable (seg_id);
@@ -130,14 +130,15 @@ NameResolutionContext::resolve_path (
if (seg.is_crate_path_seg ())
{
insert_segment_resolution (Usage (seg.node_id),
- Definition (stack.root.id));
+ Definition (stack.root.id), N);
// TODO: does NonShadowable matter?
return Rib::Definition::NonShadowable (stack.root.id);
}
else if (seg.is_lower_self_seg ())
{
NodeId id = stack.find_closest_module (starting_point.get ()).id;
- insert_segment_resolution (Usage (seg.node_id), Definition (id));
+ insert_segment_resolution (Usage (seg.node_id), Definition (id),
+ N);
// TODO: does NonShadowable matter?
return Rib::Definition::NonShadowable (id);
}
@@ -154,7 +155,8 @@ NameResolutionContext::resolve_path (
NodeId id
= stack.find_closest_module (closest_module.parent.value ()).id;
- insert_segment_resolution (Usage (seg.node_id), Definition (id));
+ insert_segment_resolution (Usage (seg.node_id), Definition (id),
+ N);
// TODO: does NonShadowable matter?
return Rib::Definition::NonShadowable (id);
}
@@ -173,17 +175,19 @@ NameResolutionContext::resolve_path (
},
false))
{
+ // FIXME: Is the NS to insert_segment_resolution valid?
insert_segment_resolution (Usage (seg.node_id),
- Definition (kv.second.id));
+ Definition (kv.second.id), N);
return Rib::Definition::NonShadowable (kv.second.id);
}
}
}
}
+ // FIXME: Is the NS to insert_segment_resolution valid?
if (res && !res->is_ambiguous ())
insert_segment_resolution (Usage (seg.node_id),
- Definition (res->get_node_id ()));
+ Definition (res->get_node_id ()), N);
return res;
}
@@ -253,7 +257,7 @@ NameResolutionContext::resolve_path (
false))
{
insert_segment_resolution (Usage (seg.node_id),
- Definition (kv.second.id));
+ Definition (kv.second.id), N);
return Rib::Definition::NonShadowable (kv.second.id);
}
}
@@ -261,7 +265,7 @@ NameResolutionContext::resolve_path (
if (res && !res->is_ambiguous ())
insert_segment_resolution (Usage (seg.node_id),
- Definition (res->get_node_id ()));
+ Definition (res->get_node_id ()), N);
return res;
}
@@ -272,7 +276,7 @@ NameResolutionContext::resolve_segments (
ForeverStack<N> &stack, typename ForeverStack<N>::Node &starting_point,
const std::vector<ResolutionPath::Segment> &segments,
typename ForeverStack<N>::SegIterator iterator,
- std::function<void (Usage, Definition)> insert_segment_resolution,
+ std::function<void (Usage, Definition, Namespace)> insert_segment_resolution,
std::vector<Error> &collect_errors)
{
auto *current_node = &starting_point;
@@ -350,7 +354,7 @@ NameResolutionContext::resolve_segments (
.has_value ())
{
auto leaf_module
- = find_leaf_definition (rib_lookup->get_node_id ())
+ = stack.find_leaf_definition (rib_lookup->get_node_id ())
.value ()
.id;
@@ -359,9 +363,14 @@ NameResolutionContext::resolve_segments (
}
else
{
+ // FIXME: Resolve segments always resolves in the Types NS
+ // correct? If so, we should remove the template parameter for
+ // this function - and use NS::Types directly here instead of
+ // N
insert_segment_resolution (Usage (seg.node_id),
Definition (
- rib_lookup->get_node_id ()));
+ rib_lookup->get_node_id ()),
+ N);
return tl::nullopt;
}
@@ -388,7 +397,7 @@ NameResolutionContext::resolve_segments (
// the while loop above would have returned or kept looping
current_node = &child->get ();
insert_segment_resolution (Usage (seg.node_id),
- Definition (current_node->id));
+ Definition (current_node->id), N);
}
return *current_node;
--
2.54.0