public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] gccrs: qualified path syntax is used to disambiguate predicates
@ 2023-05-02  7:12 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2023-05-02  7:12 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:187f4b9eb897a08c124742e018b323c1ad6c9189

commit 187f4b9eb897a08c124742e018b323c1ad6c9189
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 d43587f6f35..67b8d24b5a9 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)
+}

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-05-02  7:12 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-05-02  7:12 [gcc/devel/rust/master] gccrs: qualified path syntax is used to disambiguate predicates Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).