[COMMITTED 26/83] gccrs: New PathProbExpr to simplify path in expression to be more targeted

arthur.cohen@opensrcsec.com arthur.cohen@opensrcsec.com
Wed Sep 16 12:29:45 GMT 2026


From: Philip Herron <herron.philip@googlemail.com>

The logic is much like PathProbeType but we are looking for fns/const exprs
since we dont care about types in that path. We should really prefer trait
position items where we can but there was regressions there which we can
revisit later.

gcc/rust/ChangeLog:

	* typecheck/rust-hir-path-probe-expr.cc (PathProbeExpr::Probe): simpler interface
	(PathProbeExpr::probe): based of the receiver
	(PathProbeExpr::visit): no longer needed
	(PathProbeExpr::probe_adt_impls): new probe
	(PathProbeExpr::probe_fallback_impls): fallback to iterate impls
	(PathProbeExpr::process_enum_item_for_candiates): removed
	(PathProbeExpr::process_enum_item_for_candidates): likewise
	(PathProbeExpr::process_impl_items_for_candidates): likewise
	(PathProbeExpr::process_impl_item_candidate): likewise
	(PathProbeExpr::probe_bounds): fall back to the impl iter
	(PathProbeExpr::insert_candidate): acumulate
	* typecheck/rust-hir-path-probe-expr.h (class PathProbeExpr): new interface
	* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::TypeCheckExpr): likewise
	* typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_segments): likewise

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
---
 .../typecheck/rust-hir-path-probe-expr.cc     | 299 +++++++-----------
 gcc/rust/typecheck/rust-hir-path-probe-expr.h |  45 +--
 .../typecheck/rust-hir-type-check-expr.cc     |   2 -
 .../typecheck/rust-hir-type-check-path.cc     |  24 +-
 4 files changed, 126 insertions(+), 244 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-path-probe-expr.cc b/gcc/rust/typecheck/rust-hir-path-probe-expr.cc
index 690e3e35c87..4177e376038 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-path-probe-expr.cc
@@ -24,155 +24,78 @@
 namespace Rust {
 namespace Resolver {
 
-// PathProbeExpr
-
 PathProbeExpr::PathProbeExpr (TyTy::BaseType *receiver,
-			      const HIR::PathIdentSegment &query,
-			      DefId specific_trait_id)
-  : TypeCheckBase (), receiver (receiver), search (query),
-    current_impl (nullptr), specific_trait_id (specific_trait_id)
+			      const HIR::PathIdentSegment &query)
+  : TypeCheckBase (), receiver (receiver), search (query)
 {}
 
 std::set<PathProbeCandidate>
 PathProbeExpr::Probe (TyTy::BaseType *receiver,
-		      const HIR::PathIdentSegment &segment_name,
-		      bool probe_impls, bool probe_bounds,
-		      bool ignore_mandatory_trait_items,
-		      DefId specific_trait_id)
+		      const HIR::PathIdentSegment &segment_name)
 {
-  Analysis::Mappings &mappings = Analysis::Mappings::get ();
-
-  PathProbeExpr probe (receiver, segment_name, specific_trait_id);
-  if (probe_impls)
-    {
-      if (receiver->get_kind () == TyTy::TypeKind::ADT)
-	{
-	  const TyTy::ADTType *adt
-	    = static_cast<const TyTy::ADTType *> (receiver);
-	  if (adt->is_enum ())
-	    probe.process_enum_item_for_candiates (adt);
-	}
-
-      probe.process_impl_items_for_candidates ();
-    }
-
-  if (!probe_bounds)
-    return probe.candidates;
+  PathProbeExpr probe (receiver, segment_name);
+  return probe.probe ();
+}
 
-  if (!probe.is_receiver_generic ())
+std::set<PathProbeCandidate>
+PathProbeExpr::probe ()
+{
+  switch (receiver->get_kind ())
     {
-      HIR::Trait *associated_trait = nullptr;
-      if (specific_trait_id != UNKNOWN_DEFID)
-	{
-	  auto item_lookup = mappings.lookup_defid (specific_trait_id);
-	  if (item_lookup.has_value ())
-	    {
-	      HIR::Item *item = item_lookup.value ();
-	      rust_assert (item->get_item_kind ()
-			   == HIR::Item::ItemKind::Trait);
-	      associated_trait = static_cast<HIR::Trait *> (item);
-	    }
-	}
+    case TyTy::TypeKind::PARAM:
+      probe_bounds ();
+      return std::move (candidates);
+
+    case TyTy::TypeKind::ADT:
+      {
+	auto *adt = static_cast<TyTy::ADTType *> (receiver);
+	if (adt->is_enum ())
+	  process_enum_item_for_candidates (adt);
+	probe_adt_impls (adt);
+	break;
+      }
 
-      auto probed_bounds = TypeBoundsProbe::Probe (receiver, associated_trait);
-      for (auto &candidate : probed_bounds)
-	{
-	  const TraitReference *trait_ref = candidate.first;
-	  if (specific_trait_id != UNKNOWN_DEFID)
-	    {
-	      if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
-		continue;
-	    }
-
-	  HIR::ImplBlock *impl = candidate.second;
-	  probe.process_associated_trait_for_candidates (
-	    trait_ref, impl, ignore_mandatory_trait_items);
-	}
+    default:
+      probe_fallback_impls ();
+      break;
     }
 
-  for (const TyTy::TypeBoundPredicate &predicate :
-       receiver->get_specified_bounds ())
-    {
-      const TraitReference *trait_ref = predicate.get ();
-      if (specific_trait_id != UNKNOWN_DEFID)
-	{
-	  if (trait_ref->get_mappings ().get_defid () != specific_trait_id)
-	    continue;
-	}
-
-      probe.process_predicate_for_candidates (predicate,
-					      ignore_mandatory_trait_items);
-    }
+  if (candidates.empty ())
+    probe_bounds ();
 
-  return probe.candidates;
+  return std::move (candidates);
 }
 
 void
-PathProbeExpr::visit (HIR::TypeAlias &alias)
+PathProbeExpr::probe_adt_impls (TyTy::ADTType *adt)
 {
-  Identifier name = alias.get_new_type_name ();
-  if (search.to_string ().compare (name.as_string ()) == 0)
+  auto adt_item = mappings.lookup_defid (adt->get_id ());
+  if (!adt_item.has_value ())
     {
-      HirId tyid = alias.get_mappings ().get_hirid ();
-      TyTy::BaseType *ty = nullptr;
-      if (!query_type (tyid, &ty))
-	return;
-
-      PathProbeCandidate::ImplItemCandidate impl_item_candidate{&alias,
-								current_impl};
-      PathProbeCandidate candidate{
-	PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS, ty,
-	alias.get_locus (), impl_item_candidate};
-      candidates.insert (std::move (candidate));
+      probe_fallback_impls ();
+      return;
     }
-}
 
-void
-PathProbeExpr::visit (HIR::ConstantItem &constant)
-{
-  Identifier name = constant.get_identifier ();
-  if (search.to_string ().compare (name.as_string ()) == 0)
-    {
-      HirId tyid = constant.get_mappings ().get_hirid ();
-      TyTy::BaseType *ty = nullptr;
-      if (!query_type (tyid, &ty))
-	return;
-
-      PathProbeCandidate::ImplItemCandidate impl_item_candidate{&constant,
-								current_impl};
-      PathProbeCandidate candidate{
-	PathProbeCandidate::CandidateType::IMPL_CONST, ty,
-	constant.get_locus (), impl_item_candidate};
-      candidates.insert (std::move (candidate));
-    }
+  NodeId adt_node_id = adt_item.value ()->get_mappings ().get_nodeid ();
+  mappings.iterate_adt_impl_items (
+    adt_node_id,
+    [this] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) -> bool {
+      return process_impl_item_candidate (id, item, impl);
+    });
 }
 
 void
-PathProbeExpr::visit (HIR::Function &function)
+PathProbeExpr::probe_fallback_impls ()
 {
-  Identifier name = function.get_function_name ();
-  if (search.to_string ().compare (name.as_string ()) == 0)
-    {
-      HirId tyid = function.get_mappings ().get_hirid ();
-      TyTy::BaseType *ty = nullptr;
-      if (!query_type (tyid, &ty))
-	return;
-
-      PathProbeCandidate::ImplItemCandidate impl_item_candidate{&function,
-								current_impl};
-      PathProbeCandidate candidate{PathProbeCandidate::CandidateType::IMPL_FUNC,
-				   ty, function.get_locus (),
-				   impl_item_candidate};
-      candidates.insert (std::move (candidate));
-    }
+  mappings.iterate_impl_items (
+    [this] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) -> bool {
+      return process_impl_item_candidate (id, item, impl);
+    });
 }
 
 void
-PathProbeExpr::process_enum_item_for_candiates (const TyTy::ADTType *adt)
+PathProbeExpr::process_enum_item_for_candidates (const TyTy::ADTType *adt)
 {
-  if (specific_trait_id != UNKNOWN_DEFID)
-    return;
-
   TyTy::VariantDef *v;
   if (!adt->lookup_variant (search.to_string (), &v))
     return;
@@ -185,65 +108,76 @@ PathProbeExpr::process_enum_item_for_candiates (const TyTy::ADTType *adt)
   candidates.insert (std::move (candidate));
 }
 
-void
-PathProbeExpr::process_impl_items_for_candidates ()
-{
-  if (auto *adt = receiver->try_as<TyTy::ADTType> ())
-    {
-      auto adt_item = mappings.lookup_defid (adt->get_id ());
-      if (adt_item.has_value ())
-	{
-	  NodeId adt_node_id = adt_item.value ()->get_mappings ().get_nodeid ();
-	  mappings.iterate_adt_impl_items (
-	    adt_node_id,
-	    [&] (HirId id, HIR::ImplItem *item,
-		 HIR::ImplBlock *impl) mutable -> bool {
-	      process_impl_item_candidate (id, item, impl);
-	      return true;
-	    });
-	  return;
-	}
-    }
-
-  mappings.iterate_impl_items (
-    [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
-      process_impl_item_candidate (id, item, impl);
-      return true;
-    });
-}
-
-void
+bool
 PathProbeExpr::process_impl_item_candidate (HirId id, HIR::ImplItem *item,
 					    HIR::ImplBlock *impl)
 {
-  current_impl = impl;
+  if (search.to_string () != item->get_impl_item_name ())
+    return true;
+
   HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
   TyTy::BaseType *impl_block_ty = nullptr;
   if (!query_type (impl_ty_id, &impl_block_ty))
-    return;
+    return true;
 
   if (!types_compatable (TyTy::TyWithLocation (receiver),
 			 TyTy::TyWithLocation (impl_block_ty),
 			 impl->get_locus (), false))
-    return;
+    return true;
+
+  PathProbeCandidate::CandidateType candidate_type;
+  switch (item->get_impl_item_type ())
+    {
+    case HIR::ImplItem::FUNCTION:
+      candidate_type = PathProbeCandidate::CandidateType::IMPL_FUNC;
+      break;
+    case HIR::ImplItem::CONSTANT:
+      candidate_type = PathProbeCandidate::CandidateType::IMPL_CONST;
+      break;
+    case HIR::ImplItem::TYPE_ALIAS:
+    default:
+      return true;
+    }
+
+  TyTy::BaseType *item_ty = nullptr;
+  if (!query_type (id, &item_ty))
+    return true;
+
+  PathProbeCandidate::ImplItemCandidate impl_candidate{item, impl};
+  insert_candidate (
+    {candidate_type, item_ty, item->get_locus (), impl_candidate});
+
+  return true;
+}
+
+void
+PathProbeExpr::probe_bounds ()
+{
+  if (!is_receiver_generic ())
+    {
+      auto probed_bounds = TypeBoundsProbe::Probe (receiver);
+      for (auto &candidate : probed_bounds)
+	{
+	  const TraitReference *trait_ref = candidate.first;
+	  process_associated_trait_for_candidates (trait_ref, candidate.second);
+	}
+    }
 
-  // lets visit the impl_item
-  item->accept_vis (*this);
+  for (const TyTy::TypeBoundPredicate &predicate :
+       receiver->get_specified_bounds ())
+    {
+      process_predicate_for_candidates (predicate);
+    }
 }
 
 void
 PathProbeExpr::process_associated_trait_for_candidates (
-  const TraitReference *trait_ref, HIR::ImplBlock *impl,
-  bool ignore_mandatory_trait_items)
+  const TraitReference *trait_ref, HIR::ImplBlock *impl)
 {
   const TraitItemReference *trait_item_ref = nullptr;
   if (!trait_ref->lookup_trait_item (search.to_string (), &trait_item_ref))
     return;
 
-  bool trait_item_needs_implementation = !trait_item_ref->is_optional ();
-  if (ignore_mandatory_trait_items && trait_item_needs_implementation)
-    return;
-
   PathProbeCandidate::CandidateType candidate_type;
   switch (trait_item_ref->get_trait_item_type ())
     {
@@ -254,8 +188,7 @@ PathProbeExpr::process_associated_trait_for_candidates (
       candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
       break;
     case TraitItemReference::TraitItemType::TYPE:
-      candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
-      break;
+      return;
 
     case TraitItemReference::TraitItemType::ERROR:
     default:
@@ -277,12 +210,12 @@ PathProbeExpr::process_associated_trait_for_candidates (
   PathProbeCandidate candidate{candidate_type, trait_item_tyty,
 			       trait_item_ref->get_locus (),
 			       trait_item_candidate};
-  candidates.insert (std::move (candidate));
+  insert_candidate (std::move (candidate));
 }
 
 void
 PathProbeExpr::process_predicate_for_candidates (
-  const TyTy::TypeBoundPredicate &predicate, bool ignore_mandatory_trait_items)
+  const TyTy::TypeBoundPredicate &predicate)
 {
   const TraitReference *trait_ref = predicate.get ();
 
@@ -291,9 +224,6 @@ PathProbeExpr::process_predicate_for_candidates (
   if (!item.has_value ())
     return;
 
-  if (ignore_mandatory_trait_items && item->needs_implementation ())
-    return;
-
   const TraitItemReference *trait_item_ref = item->get_raw_item ();
   PathProbeCandidate::CandidateType candidate_type;
   switch (trait_item_ref->get_trait_item_type ())
@@ -305,8 +235,7 @@ PathProbeExpr::process_predicate_for_candidates (
       candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
       break;
     case TraitItemReference::TraitItemType::TYPE:
-      candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
-      break;
+      return;
 
     case TraitItemReference::TraitItemType::ERROR:
     default:
@@ -324,31 +253,17 @@ PathProbeExpr::process_predicate_for_candidates (
   PathProbeCandidate candidate{candidate_type, trait_item_tyty,
 			       trait_item_ref->get_locus (),
 			       trait_item_candidate};
-  candidates.insert (std::move (candidate));
+  insert_candidate (std::move (candidate));
 }
 
-std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
-PathProbeExpr::union_bounds (
-  const std::vector<std::pair</*const*/ TraitReference *, HIR::ImplBlock *>> a,
-  const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> b)
-  const
+void
+PathProbeExpr::insert_candidate (PathProbeCandidate candidate)
 {
-  std::map<DefId, std::pair<const TraitReference *, HIR::ImplBlock *>> mapper;
-  for (auto &ref : a)
-    {
-      mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
-    }
-  for (auto &ref : b)
-    {
-      mapper.insert ({ref.first->get_mappings ().get_defid (), ref});
-    }
-
-  std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> union_set;
-
-  for (auto it = mapper.begin (); it != mapper.end (); it++)
-    union_set.emplace_back (it->second.first, it->second.second);
-
-  return union_set;
+  bool is_type
+    = candidate.type == PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS
+      || candidate.type == PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
+  if (!candidate.is_error () && !is_type)
+    candidates.insert (std::move (candidate));
 }
 
 bool
diff --git a/gcc/rust/typecheck/rust-hir-path-probe-expr.h b/gcc/rust/typecheck/rust-hir-path-probe-expr.h
index e824da66785..2b843a25813 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe-expr.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe-expr.h
@@ -24,53 +24,38 @@
 namespace Rust {
 namespace Resolver {
 
-class PathProbeExpr : public TypeCheckBase, public HIR::HIRImplVisitor
+class PathProbeExpr : public TypeCheckBase
 {
 public:
   static std::set<PathProbeCandidate>
-  Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name,
-	 bool probe_impls, bool probe_bounds, bool ignore_mandatory_trait_items,
-	 DefId specific_trait_id = UNKNOWN_DEFID);
+  Probe (TyTy::BaseType *receiver, const HIR::PathIdentSegment &segment_name);
 
-  void visit (HIR::TypeAlias &alias) override;
-  void visit (HIR::ConstantItem &constant) override;
-  void visit (HIR::Function &function) override;
+private:
+  std::set<PathProbeCandidate> probe ();
+  void probe_adt_impls (TyTy::ADTType *adt);
+  void probe_fallback_impls ();
+  void probe_bounds ();
 
-protected:
-  void process_enum_item_for_candiates (const TyTy::ADTType *adt);
+  void process_enum_item_for_candidates (const TyTy::ADTType *adt);
 
-  void process_impl_items_for_candidates ();
-
-  void process_impl_item_candidate (HirId id, HIR::ImplItem *item,
+  bool process_impl_item_candidate (HirId id, HIR::ImplItem *item,
 				    HIR::ImplBlock *impl);
 
-  void
-  process_associated_trait_for_candidates (const TraitReference *trait_ref,
-					   HIR::ImplBlock *impl,
-					   bool ignore_mandatory_trait_items);
+  void process_associated_trait_for_candidates (const TraitReference *trait_ref,
+						HIR::ImplBlock *impl);
 
   void
-  process_predicate_for_candidates (const TyTy::TypeBoundPredicate &predicate,
-				    bool ignore_mandatory_trait_items);
+  process_predicate_for_candidates (const TyTy::TypeBoundPredicate &predicate);
 
-protected:
-  PathProbeExpr (TyTy::BaseType *receiver, const HIR::PathIdentSegment &query,
-		 DefId specific_trait_id);
-
-  std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
-  union_bounds (
-    const std::vector<std::pair</*const*/ TraitReference *, HIR::ImplBlock *>>
-      a,
-    const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> b)
-    const;
+  PathProbeExpr (TyTy::BaseType *receiver, const HIR::PathIdentSegment &query);
 
   bool is_receiver_generic () const;
 
+  void insert_candidate (PathProbeCandidate candidate);
+
   TyTy::BaseType *receiver;
   const HIR::PathIdentSegment &search;
   std::set<PathProbeCandidate> candidates;
-  HIR::ImplBlock *current_impl;
-  DefId specific_trait_id;
 };
 
 } // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 1c24c7c936b..48145c8df73 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -44,8 +44,6 @@ namespace Resolver {
 
 TypeCheckExpr::TypeCheckExpr () : TypeCheckBase (), infered (nullptr) {}
 
-// Perform type checking on expr. Also runs type unification algorithm.
-// Returns the unified type of expr
 TyTy::BaseType *
 TypeCheckExpr::Resolve (HIR::Expr &expr)
 {
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 4c7a796d77d..52c6e66b2bf 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -418,28 +418,12 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
   for (size_t i = offset; i < segments.size (); i++)
     {
       HIR::PathExprSegment &seg = segments.at (i);
-      bool probe_impls = !receiver_is_generic;
-
-      // probe the path is done in two parts one where we search impls if no
-      // candidate is found then we search extensions from traits
-      auto candidates
-	= PathProbeExpr::Probe (prev_segment, seg.get_segment (), probe_impls,
-				false /*probe_bounds*/,
-				true /*ignore_mandatory_trait_items*/);
+      auto candidates = PathProbeExpr::Probe (prev_segment, seg.get_segment ());
       if (candidates.size () == 0)
 	{
-	  candidates
-	    = PathProbeExpr::Probe (prev_segment, seg.get_segment (), false,
-				    true /*probe_bounds*/,
-				    false /*ignore_mandatory_trait_items*/);
-
-	  if (candidates.size () == 0)
-	    {
-	      rust_error_at (
-		seg.get_locus (),
-		"failed to resolve path segment using an impl Probe");
-	      return;
-	    }
+	  rust_error_at (seg.get_locus (),
+			 "failed to resolve path segment using an impl Probe");
+	  return;
 	}
 
       if (candidates.size () > 1)
-- 
2.50.1



More information about the Gcc-rust mailing list