public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] gccrs: Fix higher ranked trait bounds computation of self
@ 2023-02-07 17:56 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2023-02-07 17:56 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:aff069dfb1fb1dcd785d5af68373d83289d62c72

commit aff069dfb1fb1dcd785d5af68373d83289d62c72
Author: Philip Herron <herron.philip@googlemail.com>
Date:   Tue Jan 31 18:52:33 2023 +0000

    gccrs: Fix higher ranked trait bounds computation of self
    
    This updates the higher ranked trait bounds computation to handle ambigious
    cases. When we have a slice for example:
    
      let slice = &a[1..3];
    
    This works by reusing the Index operator overload from libcore, so when the
    index range of 1..3 is computed, the type system needs to compute what the
    types of index are; this works by integer inference variables
    Range<<integer>> that need to be unified with the impl Index for
    Range<Usize> which computes the real type of usize for the index. This is
    fine but what happens when we have the Copy and Clone traits bounds which
    have implementations for all the primitive types i8, i16, i32, i64...
    which is valid for any integer inference variable so the code prior to this
    patch would have grabbed the first impl it would have found and used it
    which is incorrect. When we have integer or float inference variables we
    need to look for their respective defaults or emit an ambigious type bound
    error.
    
    Signed-off-by: Philip Herron <herron.philip@googlemail.com>
    
    gcc/rust/ChangeLog:
    
            * typecheck/rust-hir-trait-reference.h: add const infterface
            * typecheck/rust-tyty-subst.cc (SubstitutionParamMapping::get_generic_param): make const
            (SubstitutionRef::monomorphize): fix issue
            * typecheck/rust-tyty-subst.h: constify interface

Diff:
---
 gcc/rust/typecheck/rust-hir-trait-reference.h |   1 +
 gcc/rust/typecheck/rust-tyty-subst.cc         | 107 ++++++++++++++++++++++++--
 gcc/rust/typecheck/rust-tyty-subst.h          |   2 +-
 3 files changed, 102 insertions(+), 8 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h
index 0d4da3b59cf..aec1dd56bcc 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -496,6 +496,7 @@ public:
   HIR::ImplBlock *get_impl_block () { return impl; }
 
   TyTy::BaseType *get_self () { return self; }
+  const TyTy::BaseType *get_self () const { return self; }
 
   TyTy::BaseType *
   setup_associated_types (const TyTy::BaseType *self,
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index 996bbf2d885..3dfe95873bc 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -65,7 +65,7 @@ SubstitutionParamMapping::get_param_ty () const
 }
 
 const HIR::TypeParam &
-SubstitutionParamMapping::get_generic_param ()
+SubstitutionParamMapping::get_generic_param () const
 {
   return generic;
 }
@@ -892,8 +892,7 @@ SubstitutionRef::monomorphize ()
 	  // setup any associated type mappings for the specified bonds and this
 	  // type
 	  auto candidates = Resolver::TypeBoundsProbe::Probe (binding);
-
-	  Resolver::AssociatedImplTrait *associated_impl_trait = nullptr;
+	  std::vector<Resolver::AssociatedImplTrait *> associated_impl_traits;
 	  for (auto &probed_bound : candidates)
 	    {
 	      const Resolver::TraitReference *bound_trait_ref
@@ -914,15 +913,109 @@ SubstitutionRef::monomorphize ()
 		    = associated->get_self ()->can_eq (binding, false);
 		  if (found_trait && found_self)
 		    {
-		      associated_impl_trait = associated;
-		      break;
+		      associated_impl_traits.push_back (associated);
 		    }
 		}
 	    }
 
-	  if (associated_impl_trait != nullptr)
+	  if (!associated_impl_traits.empty ())
 	    {
-	      associated_impl_trait->setup_associated_types (binding, bound);
+	      // 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 (associated_impl_traits.size () == 1)
+		{
+		  Resolver::AssociatedImplTrait *associate_impl_trait
+		    = associated_impl_traits.at (0);
+		  associate_impl_trait->setup_associated_types (binding, bound);
+		}
+	      else
+		{
+		  // 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 (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 ());
+
+		      return false;
+		    }
+
+		  associate_impl_trait->setup_associated_types (binding, bound);
+		}
 	    }
 	}
     }
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h
index 039eb36589e..982861e9bc6 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -48,7 +48,7 @@ public:
 
   const ParamType *get_param_ty () const;
 
-  const HIR::TypeParam &get_generic_param ();
+  const HIR::TypeParam &get_generic_param () const;
 
   // this is used for the backend to override the HirId ref of the param to
   // what the concrete type is for the rest of the context

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

only message in thread, other threads:[~2023-02-07 17:56 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-07 17:56 [gcc/devel/rust/master] gccrs: Fix higher ranked trait bounds computation of self 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).