[gcc r14-7538] gccrs: qualified path syntax is used to disambiguate predicates

Arthur Cohen cohenarthur@gcc.gnu.org
Tue Jan 16 17:42:39 GMT 2024


https://gcc.gnu.org/g:04877f1096b9afe9d27552ffd0cc76388bbc6c03

commit r14-7538-g04877f1096b9afe9d27552ffd0cc76388bbc6c03
Author: Philip Herron <herron.philip@googlemail.com>
Date:   Thu Apr 20 17:10:15 2023 +0100

    gccrs: qualified path syntax is used to disambiguate predicates
    
    When resolving a qualified path we need to use the predicate to lookup the
    relevant assoicated impl block where possible. The issue here is that
    it might not have one due to a valid error in the impl block or it might
    be used within a trait this is a valid case. Generally we will be able to
    resolve to an impl block then it can grab that type and move on.
    
    Fixes #2135
    
    gcc/rust/ChangeLog:
    
            * typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::visit): use the predicate
            (TypeCheckExpr::resolve_segments): cleanup
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/issue-2135.rs: New test.
    
    Signed-off-by: Philip Herron <herron.philip@googlemail.com>

Diff:
---
 gcc/rust/typecheck/rust-hir-type-check-path.cc | 82 +++++++++++++++-----------
 gcc/testsuite/rust/compile/issue-2135.rs       | 19 ++++++
 2 files changed, 66 insertions(+), 35 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index dd7bc9aee6e..9b5c6fee101 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -69,49 +69,63 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
   // inherit the bound
   root->inherit_bounds ({specified_bound});
 
-  // setup the associated types
-  const TraitReference *specified_bound_ref = specified_bound.get ();
-  auto candidates = TypeBoundsProbe::Probe (root);
-  AssociatedImplTrait *associated_impl_trait = nullptr;
-  for (auto &probed_bound : candidates)
+  // lookup the associated item from the specified bound
+  HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
+  HIR::PathIdentSegment item_seg_identifier = item_seg.get_segment ();
+  TyTy::TypeBoundPredicateItem item
+    = specified_bound.lookup_associated_item (item_seg_identifier.as_string ());
+  if (item.is_error ())
     {
-      const TraitReference *bound_trait_ref = probed_bound.first;
-      const HIR::ImplBlock *associated_impl = probed_bound.second;
-
-      HirId impl_block_id = associated_impl->get_mappings ().get_hirid ();
-      AssociatedImplTrait *associated = nullptr;
-      bool found_impl_trait
-	= context->lookup_associated_trait_impl (impl_block_id, &associated);
-      if (found_impl_trait)
+      rust_error_at (item_seg.get_locus (), "unknown associated item");
+      return;
+    }
+
+  // we try to look for the real impl item if possible
+  HIR::ImplItem *impl_item = nullptr;
+
+  // lookup the associated impl trait for this if we can (it might be generic)
+  AssociatedImplTrait *associated_impl_trait
+    = lookup_associated_impl_block (specified_bound, root);
+  if (associated_impl_trait != nullptr)
+    {
+      for (auto &i :
+	   associated_impl_trait->get_impl_block ()->get_impl_items ())
 	{
-	  bool found_trait = specified_bound_ref->is_equal (*bound_trait_ref);
-	  bool found_self = associated->get_self ()->can_eq (root, false);
-	  if (found_trait && found_self)
+	  bool found = i->get_impl_item_name ().compare (
+			 item_seg_identifier.as_string ())
+		       == 0;
+	  if (found)
 	    {
-	      associated_impl_trait = associated;
+	      impl_item = i.get ();
 	      break;
 	    }
 	}
     }
 
-  if (associated_impl_trait != nullptr)
+  NodeId root_resolved_node_id = UNKNOWN_NODEID;
+  if (impl_item == nullptr)
     {
-      associated_impl_trait->setup_associated_types (root, specified_bound);
+      // this may be valid as there could be a default trait implementation here
+      // and we dont need to worry if the trait item is actually implemented or
+      // not because this will have already been validated as part of the trait
+      // impl block
+      infered = item.get_tyty_for_receiver (root);
+      root_resolved_node_id
+	= item.get_raw_item ()->get_mappings ().get_nodeid ();
     }
-
-  // lookup the associated item from the specified bound
-  HIR::PathExprSegment &item_seg = expr.get_segments ().at (0);
-  HIR::PathIdentSegment item_seg_identifier = item_seg.get_segment ();
-  TyTy::TypeBoundPredicateItem item
-    = specified_bound.lookup_associated_item (item_seg_identifier.as_string ());
-  if (item.is_error ())
+  else
     {
-      rust_error_at (item_seg.get_locus (), "unknown associated item");
-      return;
-    }
+      HirId impl_item_id = impl_item->get_impl_mappings ().get_hirid ();
+      bool ok = query_type (impl_item_id, &infered);
+      if (!ok)
+	{
+	  // FIXME
+	  // I think query_type should error if required here anyway
+	  return;
+	}
 
-  // infer the root type
-  infered = item.get_tyty_for_receiver (root);
+      root_resolved_node_id = impl_item->get_impl_mappings ().get_nodeid ();
+    }
 
   // turbo-fish segment path::<ty>
   if (item_seg.has_generic_args ())
@@ -129,10 +143,7 @@ TypeCheckExpr::visit (HIR::QualifiedPathInExpression &expr)
     }
 
   // continue on as a path-in-expression
-  const TraitItemReference *trait_item_ref = item.get_raw_item ();
-  NodeId root_resolved_node_id = trait_item_ref->get_mappings ().get_nodeid ();
   bool fully_resolved = expr.get_segments ().size () <= 1;
-
   if (fully_resolved)
     {
       resolver->insert_resolved_name (expr.get_mappings ().get_nodeid (),
@@ -321,7 +332,8 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
       // candidate is found then we search extensions from traits
       auto candidates
 	= PathProbeType::Probe (prev_segment, seg.get_segment (), probe_impls,
-				false, true /*ignore_mandatory_trait_items*/);
+				false /*probe_bounds*/,
+				true /*ignore_mandatory_trait_items*/);
       if (candidates.size () == 0)
 	{
 	  candidates
diff --git a/gcc/testsuite/rust/compile/issue-2135.rs b/gcc/testsuite/rust/compile/issue-2135.rs
new file mode 100644
index 00000000000..563345efee3
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-2135.rs
@@ -0,0 +1,19 @@
+pub trait Foo<A> {
+    fn foo(self, _: A) -> u16;
+}
+
+impl Foo<u16> for u16 {
+    fn foo(self, _: u16) -> u16 {
+        self
+    }
+}
+
+impl Foo<u8> for u16 {
+    fn foo(self, _: u8) -> u16 {
+        self
+    }
+}
+
+pub fn bar() -> u16 {
+    <u16 as Foo<u16>>::foo(0u16, 0u16)
+}


More information about the Gcc-cvs mailing list