public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] gccrs: Extract helper lookup_associated_impl_block
@ 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:c13032e55c0bd39557c6366729e4afca3890c6c1

commit c13032e55c0bd39557c6366729e4afca3890c6c1
Author: Philip Herron <herron.philip@googlemail.com>
Date:   Thu Apr 20 16:56:46 2023 +0100

    gccrs: Extract helper lookup_associated_impl_block
    
    This will look for a specified predicate that is associated with it so we
    might have the predicate Foo<u16, i32> which would refer to:
    
      impl Foo<i32> for u16 {}
    
    This is a general helper which can be used in several places.
    
    gcc/rust/ChangeLog:
    
            * typecheck/rust-hir-trait-reference.cc (AssociatedImplTrait::AssociatedImplTrait):
            bind the predicate
            (AssociatedImplTrait::get_trait): remove
            (AssociatedImplTrait::get_predicate): new getter
            * typecheck/rust-hir-trait-reference.h: bind predicate
            * typecheck/rust-hir-type-check-item.cc: update ctor
            * typecheck/rust-type-util.cc (lookup_associated_impl_block): new function
            * typecheck/rust-type-util.h (class BaseType): remove unused forward decl
            (lookup_associated_impl_block): new helper
            * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::is_equal): new
            * typecheck/rust-tyty-subst.cc (SubstitutionRef::lookup_associated_impl): use new helper
            (SubstitutionRef::monomorphize): update usage/error handling
            * typecheck/rust-tyty-subst.h: remove old prototype
            * typecheck/rust-tyty.h: add is_equal decl
    
    Signed-off-by: Philip Herron <herron.philip@googlemail.com>

Diff:
---
 gcc/rust/typecheck/rust-hir-trait-reference.cc |  11 +-
 gcc/rust/typecheck/rust-hir-trait-reference.h  |   6 +-
 gcc/rust/typecheck/rust-hir-type-check-item.cc |   4 +-
 gcc/rust/typecheck/rust-type-util.cc           | 108 +++++++++++++++++
 gcc/rust/typecheck/rust-type-util.h            |  10 +-
 gcc/rust/typecheck/rust-tyty-bounds.cc         |  34 ++++++
 gcc/rust/typecheck/rust-tyty-subst.cc          | 153 ++++---------------------
 gcc/rust/typecheck/rust-tyty-subst.h           |   4 -
 gcc/rust/typecheck/rust-tyty.h                 |   2 +
 9 files changed, 183 insertions(+), 149 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.cc b/gcc/rust/typecheck/rust-hir-trait-reference.cc
index a1229adc06c..f4593ce00fb 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.cc
@@ -442,16 +442,18 @@ TraitReference::satisfies_bound (const TraitReference &reference) const
 }
 
 AssociatedImplTrait::AssociatedImplTrait (TraitReference *trait,
+					  TyTy::TypeBoundPredicate predicate,
 					  HIR::ImplBlock *impl,
 					  TyTy::BaseType *self,
 					  Resolver::TypeCheckContext *context)
-  : trait (trait), impl (impl), self (self), context (context)
+  : trait (trait), predicate (predicate), impl (impl), self (self),
+    context (context)
 {}
 
-TraitReference *
-AssociatedImplTrait::get_trait ()
+TyTy::TypeBoundPredicate &
+AssociatedImplTrait::get_predicate ()
 {
-  return trait;
+  return predicate;
 }
 
 HIR::ImplBlock *
@@ -465,6 +467,7 @@ AssociatedImplTrait::get_self ()
 {
   return self;
 }
+
 const TyTy::BaseType *
 AssociatedImplTrait::get_self () const
 {
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h
index d20b2952e5b..2179d09403f 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -238,11 +238,12 @@ private:
 class AssociatedImplTrait
 {
 public:
-  AssociatedImplTrait (TraitReference *trait, HIR::ImplBlock *impl,
+  AssociatedImplTrait (TraitReference *trait,
+		       TyTy::TypeBoundPredicate predicate, HIR::ImplBlock *impl,
 		       TyTy::BaseType *self,
 		       Resolver::TypeCheckContext *context);
 
-  TraitReference *get_trait ();
+  TyTy::TypeBoundPredicate &get_predicate ();
 
   HIR::ImplBlock *get_impl_block ();
 
@@ -257,6 +258,7 @@ public:
 
 private:
   TraitReference *trait;
+  TyTy::TypeBoundPredicate predicate;
   HIR::ImplBlock *impl;
   TyTy::BaseType *self;
   Resolver::TypeCheckContext *context;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index 0e8ce6b7b78..4b9f9bce2ea 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc
@@ -607,8 +607,8 @@ TypeCheckItem::validate_trait_impl_block (
     {
       trait_reference->clear_associated_types ();
 
-      AssociatedImplTrait associated (trait_reference, &impl_block, self,
-				      context);
+      AssociatedImplTrait associated (trait_reference, specified_bound,
+				      &impl_block, self, context);
       context->insert_associated_trait_impl (
 	impl_block.get_mappings ().get_hirid (), std::move (associated));
       context->insert_associated_impl_mapping (
diff --git a/gcc/rust/typecheck/rust-type-util.cc b/gcc/rust/typecheck/rust-type-util.cc
index 578e0c4509e..d77175eedc0 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -25,6 +25,7 @@
 #include "rust-casts.h"
 #include "rust-unify.h"
 #include "rust-coercion.h"
+#include "rust-hir-type-bounds.h"
 
 namespace Rust {
 namespace Resolver {
@@ -254,5 +255,112 @@ cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to,
   return casted;
 }
 
+AssociatedImplTrait *
+lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound,
+			      const TyTy::BaseType *binding, bool *ambigious)
+{
+  auto context = TypeCheckContext::get ();
+
+  // setup any associated type mappings for the specified bonds and this
+  // type
+  auto candidates = TypeBoundsProbe::Probe (binding);
+  std::vector<AssociatedImplTrait *> associated_impl_traits;
+  for (auto &probed_bound : candidates)
+    {
+      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)
+	{
+	  // compare the bounds from here i think is what we can do:
+	  if (bound.is_equal (associated->get_predicate ()))
+	    {
+	      associated_impl_traits.push_back (associated);
+	    }
+	}
+    }
+
+  if (associated_impl_traits.empty ())
+    return nullptr;
+
+  // This code is important when you look at slices for example when
+  // you have a slice such as:
+  //
+  // let slice = &array[1..3]
+  //
+  // the higher ranked bounds will end up having an Index trait
+  // implementation for Range<usize> so we need this code to resolve
+  // that we have an integer inference variable that needs to become
+  // a usize
+  //
+  // The other complicated issue is that we might have an intrinsic
+  // which requires the :Clone or Copy bound but the libcore adds
+  // implementations for all the integral types so when there are
+  // multiple candidates we need to resolve to the default
+  // implementation for that type otherwise its an error for
+  // ambiguous type bounds
+
+  // if we have a non-general inference variable we need to be
+  // careful about the selection here
+  bool is_infer_var = binding->get_kind () == TyTy::TypeKind::INFER;
+  bool is_integer_infervar
+    = is_infer_var
+      && static_cast<const TyTy::InferType *> (binding)->get_infer_kind ()
+	   == TyTy::InferType::InferTypeKind::INTEGRAL;
+  bool is_float_infervar
+    = is_infer_var
+      && static_cast<const TyTy::InferType *> (binding)->get_infer_kind ()
+	   == TyTy::InferType::InferTypeKind::FLOAT;
+
+  AssociatedImplTrait *associate_impl_trait = nullptr;
+  if (associated_impl_traits.size () == 1)
+    {
+      // just go for it
+      associate_impl_trait = associated_impl_traits.at (0);
+    }
+  else if (is_integer_infervar)
+    {
+      TyTy::BaseType *type = nullptr;
+      bool ok = context->lookup_builtin ("i32", &type);
+      rust_assert (ok);
+
+      for (auto &impl : associated_impl_traits)
+	{
+	  bool found = impl->get_self ()->is_equal (*type);
+	  if (found)
+	    {
+	      associate_impl_trait = impl;
+	      break;
+	    }
+	}
+    }
+  else if (is_float_infervar)
+    {
+      TyTy::BaseType *type = nullptr;
+      bool ok = context->lookup_builtin ("f64", &type);
+      rust_assert (ok);
+
+      for (auto &impl : associated_impl_traits)
+	{
+	  bool found = impl->get_self ()->is_equal (*type);
+	  if (found)
+	    {
+	      associate_impl_trait = impl;
+	      break;
+	    }
+	}
+    }
+
+  if (associate_impl_trait == nullptr && ambigious != nullptr)
+    {
+      *ambigious = true;
+    }
+
+  return associate_impl_trait;
+}
+
 } // namespace Resolver
 } // namespace Rust
diff --git a/gcc/rust/typecheck/rust-type-util.h b/gcc/rust/typecheck/rust-type-util.h
index 8ecba738ff4..89e4a185a50 100644
--- a/gcc/rust/typecheck/rust-type-util.h
+++ b/gcc/rust/typecheck/rust-type-util.h
@@ -23,11 +23,6 @@
 #include "rust-tyty.h"
 
 namespace Rust {
-
-namespace TyTy {
-class BaseType;
-}
-
 namespace Resolver {
 
 bool
@@ -50,6 +45,11 @@ TyTy::BaseType *
 cast_site (HirId id, TyTy::TyWithLocation from, TyTy::TyWithLocation to,
 	   Location cast_locus);
 
+AssociatedImplTrait *
+lookup_associated_impl_block (const TyTy::TypeBoundPredicate &bound,
+			      const TyTy::BaseType *binding,
+			      bool *ambigious = nullptr);
+
 } // namespace Resolver
 } // namespace Rust
 
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index defa0ec1edf..67aa4f8fa86 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -680,6 +680,40 @@ TypeBoundPredicate::get_associated_type_items ()
   return items;
 }
 
+bool
+TypeBoundPredicate::is_equal (const TypeBoundPredicate &other) const
+{
+  // check they match the same trait reference
+  if (reference != other.reference)
+    return false;
+
+  // check that the generics match
+  if (get_num_substitutions () != other.get_num_substitutions ())
+    return false;
+
+  // then match the generics applied
+  for (size_t i = 0; i < get_num_substitutions (); i++)
+    {
+      const SubstitutionParamMapping &a = substitutions.at (i);
+      const SubstitutionParamMapping &b = other.substitutions.at (i);
+
+      const ParamType *ap = a.get_param_ty ();
+      const ParamType *bp = b.get_param_ty ();
+
+      const BaseType *apd = ap->destructure ();
+      const BaseType *bpd = bp->destructure ();
+
+      // FIXME use the unify_and infer inteface or try coerce
+      if (!apd->can_eq (bpd, false /*emit_errors*/))
+	{
+	  if (!bpd->can_eq (apd, false /*emit_errors*/))
+	    return false;
+	}
+    }
+
+  return true;
+}
+
 // trait item reference
 
 const Resolver::TraitItemReference *
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index 60bf219e26c..7d7ab7ca79a 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -21,7 +21,7 @@
 #include "rust-hir-type-check.h"
 #include "rust-substitution-mapper.h"
 #include "rust-hir-type-check-type.h"
-#include "rust-hir-type-bounds.h"
+#include "rust-type-util.h"
 
 namespace Rust {
 namespace TyTy {
@@ -831,132 +831,6 @@ SubstitutionRef::solve_mappings_from_receiver_for_self (
 				       mappings.get_locus ());
 }
 
-Resolver::AssociatedImplTrait *
-SubstitutionRef::lookup_associated_impl (const SubstitutionParamMapping &subst,
-					 const TypeBoundPredicate &bound,
-					 const TyTy::BaseType *binding,
-					 bool *error_flag) const
-{
-  auto context = Resolver::TypeCheckContext::get ();
-  const Resolver::TraitReference *specified_bound_ref = bound.get ();
-
-  // setup any associated type mappings for the specified bonds and this
-  // type
-  auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
-  std::vector<Resolver::AssociatedImplTrait *> associated_impl_traits;
-  for (auto &probed_bound : candidates)
-    {
-      const Resolver::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 ();
-      Resolver::AssociatedImplTrait *associated = nullptr;
-      bool found_impl_trait
-	= context->lookup_associated_trait_impl (impl_block_id, &associated);
-      if (found_impl_trait)
-	{
-	  bool found_trait = specified_bound_ref->is_equal (*bound_trait_ref);
-	  bool found_self = associated->get_self ()->can_eq (binding, false);
-	  if (found_trait && found_self)
-	    {
-	      associated_impl_traits.push_back (associated);
-	    }
-	}
-    }
-
-  if (associated_impl_traits.empty ())
-    return nullptr;
-
-  // This code is important when you look at slices for example when
-  // you have a slice such as:
-  //
-  // let slice = &array[1..3]
-  //
-  // the higher ranked bounds will end up having an Index trait
-  // implementation for Range<usize> so we need this code to resolve
-  // that we have an integer inference variable that needs to become
-  // a usize
-  //
-  // The other complicated issue is that we might have an intrinsic
-  // which requires the :Clone or Copy bound but the libcore adds
-  // implementations for all the integral types so when there are
-  // multiple candidates we need to resolve to the default
-  // implementation for that type otherwise its an error for
-  // ambiguous type bounds
-
-  // if we have a non-general inference variable we need to be
-  // careful about the selection here
-  bool is_infer_var = binding->get_kind () == TyTy::TypeKind::INFER;
-  bool is_integer_infervar
-    = is_infer_var
-      && static_cast<const TyTy::InferType *> (binding)->get_infer_kind ()
-	   == TyTy::InferType::InferTypeKind::INTEGRAL;
-  bool is_float_infervar
-    = is_infer_var
-      && static_cast<const TyTy::InferType *> (binding)->get_infer_kind ()
-	   == TyTy::InferType::InferTypeKind::FLOAT;
-
-  Resolver::AssociatedImplTrait *associate_impl_trait = nullptr;
-  if (associated_impl_traits.size () == 1)
-    {
-      // just go for it
-      associate_impl_trait = associated_impl_traits.at (0);
-    }
-  else if (is_integer_infervar)
-    {
-      TyTy::BaseType *type = nullptr;
-      bool ok = context->lookup_builtin ("i32", &type);
-      rust_assert (ok);
-
-      for (auto &impl : associated_impl_traits)
-	{
-	  bool found = impl->get_self ()->is_equal (*type);
-	  if (found)
-	    {
-	      associate_impl_trait = impl;
-	      break;
-	    }
-	}
-    }
-  else if (is_float_infervar)
-    {
-      TyTy::BaseType *type = nullptr;
-      bool ok = context->lookup_builtin ("f64", &type);
-      rust_assert (ok);
-
-      for (auto &impl : associated_impl_traits)
-	{
-	  bool found = impl->get_self ()->is_equal (*type);
-	  if (found)
-	    {
-	      associate_impl_trait = impl;
-	      break;
-	    }
-	}
-    }
-
-  if (associate_impl_trait == nullptr)
-    {
-      // go for the first one? or error out?
-      auto &mappings = *Analysis::Mappings::get ();
-      const auto &type_param = subst.get_generic_param ();
-      const auto *trait_ref = bound.get ();
-
-      RichLocation r (type_param.get_locus ());
-      r.add_range (bound.get_locus ());
-      r.add_range (mappings.lookup_location (binding->get_ref ()));
-
-      rust_error_at (r, "ambiguous type bound for trait %s and type %s",
-		     trait_ref->get_name ().c_str (),
-		     binding->get_name ().c_str ());
-
-      *error_flag = true;
-      return nullptr;
-    }
-
-  return associate_impl_trait;
-}
-
 void
 SubstitutionRef::prepare_higher_ranked_bounds ()
 {
@@ -987,16 +861,31 @@ SubstitutionRef::monomorphize ()
 
       for (const auto &bound : pty->get_specified_bounds ())
 	{
-	  bool error_flag = false;
+	  bool ambigious = false;
 	  auto associated
-	    = lookup_associated_impl (subst, bound, binding, &error_flag);
+	    = Resolver::lookup_associated_impl_block (bound, binding,
+						      &ambigious);
+	  if (associated == nullptr && ambigious)
+	    {
+	      // go for the first one? or error out?
+	      auto &mappings = *Analysis::Mappings::get ();
+	      const auto &type_param = subst.get_generic_param ();
+	      const auto *trait_ref = bound.get ();
+
+	      RichLocation r (type_param.get_locus ());
+	      r.add_range (bound.get_locus ());
+	      r.add_range (mappings.lookup_location (binding->get_ref ()));
+
+	      rust_error_at (r, "ambiguous type bound for trait %s and type %s",
+			     trait_ref->get_name ().c_str (),
+			     binding->get_name ().c_str ());
+	      return false;
+	    }
+
 	  if (associated != nullptr)
 	    {
 	      associated->setup_associated_types (binding, bound);
 	    }
-
-	  if (error_flag)
-	    return false;
 	}
     }
 
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h
index 639a275eea0..0bbb164b8d5 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -318,10 +318,6 @@ public:
   SubstitutionArgumentMappings get_used_arguments () const;
 
 protected:
-  Resolver::AssociatedImplTrait *lookup_associated_impl (
-    const SubstitutionParamMapping &subst, const TypeBoundPredicate &bound,
-    const TyTy::BaseType *binding, bool *error_flag) const;
-
   std::vector<SubstitutionParamMapping> substitutions;
   SubstitutionArgumentMappings used_arguments;
 };
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 550b76672ea..5daf1ca40c5 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -438,6 +438,8 @@ public:
   TypeBoundPredicateItem
   lookup_associated_type (const std::string &search) override final;
 
+  bool is_equal (const TypeBoundPredicate &other) const;
+
 private:
   DefId reference;
   Location locus;

^ 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: Extract helper lookup_associated_impl_block 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).