public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: arthur.cohen@embecosm.com
To: gcc-patches@gcc.gnu.org
Cc: gcc-rust@gcc.gnu.org, Philip Herron <herron.philip@googlemail.com>
Subject: [committed 75/88] gccrs: Support for Sized builtin marker trait
Date: Wed,  5 Apr 2023 16:03:59 +0200	[thread overview]
Message-ID: <20230405140411.3016563-76-arthur.cohen@embecosm.com> (raw)
In-Reply-To: <20230405140411.3016563-1-arthur.cohen@embecosm.com>

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

When implementing general bounds checking as part of unify calls, we did
not check associated types on bounds which lead to alot of missed error
checking. This now recursively checks the bounds and the associated types
with a decent error message. This also required us to implement the Sized
marker trait to keep existing test-cases happy.

Fixes #1725

Signed-off-by: Philip Herron <herron.philip@googlemail.com>

gcc/rust/ChangeLog:

	* typecheck/rust-hir-trait-reference.cc (TraitReference::clear_associated_types): make const
	(TraitReference::clear_associated_type_projections): new interface
	* typecheck/rust-hir-trait-reference.h:
	* typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): refactor
	(TraitItemReference::associated_type_reset): reset projections
	* typecheck/rust-hir-type-bounds.h:
	* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): fix bounds
	* typecheck/rust-tyty-bounds.cc (TypeBoundsProbe::TypeBoundsProbe): refactor into cc file
	(TypeBoundsProbe::Probe): refactor
	(TypeBoundsProbe::is_bound_satisfied_for_type): likewise
	(TypeBoundsProbe::assemble_sized_builtin): add builtin for Sized
	(TypeCheckBase::get_predicate_from_bound): refactor
	(TypeBoundPredicate::lookup_associated_type): refactor
	* typecheck/rust-tyty-subst.cc (SubstitutionRef::lookup_associated_impl)
	(SubstitutionRef::prepare_higher_ranked_bounds): new interface to clear hanging bounds
	(SubstitutionRef::monomorphize): refactor
	* typecheck/rust-tyty-subst.h:
	* typecheck/rust-tyty.cc (BaseType::get_locus): helper
	(BaseType::satisfies_bound): ensure bounds are satisfied and assoicated types
	(ParamType::ParamType): new field in constructor
	(ParamType::clone): update clone
	(ParamType::set_implicit_self_trait): new interface
	(ParamType::is_implicit_self_trait): likewise
	* typecheck/rust-tyty.h: cleanup
	* util/rust-hir-map.cc (Mappings::Mappings): builtin marker
	(Mappings::~Mappings): delete marker
	(Mappings::lookup_builtin_marker): lookup
	* util/rust-hir-map.h: update header

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1725-1.rs: New test.
	* rust/compile/issue-1725-2.rs: New test.
---
 .../typecheck/rust-hir-trait-reference.cc     |  18 +-
 gcc/rust/typecheck/rust-hir-trait-reference.h |   6 +-
 gcc/rust/typecheck/rust-hir-trait-resolve.cc  |  27 +-
 gcc/rust/typecheck/rust-hir-type-bounds.h     |  34 +-
 .../typecheck/rust-hir-type-check-expr.cc     |   6 +
 gcc/rust/typecheck/rust-tyty-bounds.cc        | 111 ++++++-
 gcc/rust/typecheck/rust-tyty-subst.cc         | 291 ++++++++++--------
 gcc/rust/typecheck/rust-tyty-subst.h          |  12 +-
 gcc/rust/typecheck/rust-tyty.cc               |  82 ++++-
 gcc/rust/typecheck/rust-tyty.h                |   8 +-
 gcc/rust/util/rust-hir-map.cc                 |  17 +-
 gcc/rust/util/rust-hir-map.h                  |   3 +
 gcc/testsuite/rust/compile/issue-1725-1.rs    |  19 ++
 gcc/testsuite/rust/compile/issue-1725-2.rs    |  28 ++
 14 files changed, 476 insertions(+), 186 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/issue-1725-1.rs
 create mode 100644 gcc/testsuite/rust/compile/issue-1725-2.rs

diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.cc b/gcc/rust/typecheck/rust-hir-trait-reference.cc
index 8574988fb0b..a1229adc06c 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.cc
@@ -343,14 +343,26 @@ TraitReference::on_resolved ()
 }
 
 void
-TraitReference::clear_associated_types ()
+TraitReference::clear_associated_types () const
 {
-  for (auto &item : item_refs)
+  for (const auto &item : item_refs)
+    {
+      bool is_assoc_type = item.get_trait_item_type ()
+			   == TraitItemReference::TraitItemType::TYPE;
+      if (is_assoc_type)
+	item.associated_type_reset (false);
+    }
+}
+
+void
+TraitReference::clear_associated_type_projections () const
+{
+  for (const auto &item : item_refs)
     {
       bool is_assoc_type = item.get_trait_item_type ()
 			   == TraitItemReference::TraitItemType::TYPE;
       if (is_assoc_type)
-	item.associated_type_reset ();
+	item.associated_type_reset (true);
     }
 }
 
diff --git a/gcc/rust/typecheck/rust-hir-trait-reference.h b/gcc/rust/typecheck/rust-hir-trait-reference.h
index f3703efcced..d20b2952e5b 100644
--- a/gcc/rust/typecheck/rust-hir-trait-reference.h
+++ b/gcc/rust/typecheck/rust-hir-trait-reference.h
@@ -106,7 +106,7 @@ public:
 
   void associated_type_set (TyTy::BaseType *ty) const;
 
-  void associated_type_reset () const;
+  void associated_type_reset (bool only_projections) const;
 
   bool is_object_safe () const;
 
@@ -212,7 +212,9 @@ public:
 
   void on_resolved ();
 
-  void clear_associated_types ();
+  void clear_associated_types () const;
+
+  void clear_associated_type_projections () const;
 
   bool is_equal (const TraitReference &other) const;
 
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 6e23093eceb..2d7985703cf 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -161,6 +161,9 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
   TraitQueryGuard guard (trait_id);
   TyTy::BaseType *self = nullptr;
   std::vector<TyTy::SubstitutionParamMapping> substitutions;
+
+  // FIXME
+  // this should use the resolve_generic_params like everywhere else
   for (auto &generic_param : trait_reference->get_generic_params ())
     {
       switch (generic_param.get ()->get_kind ())
@@ -182,7 +185,11 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
 
 	    if (typaram.get_type_representation ().compare ("Self") == 0)
 	      {
-		self = param_type;
+		rust_assert (param_type->get_kind () == TyTy::TypeKind::PARAM);
+		TyTy::ParamType *p
+		  = static_cast<TyTy::ParamType *> (param_type);
+		p->set_implicit_self_trait ();
+		self = p;
 	      }
 	  }
 	  break;
@@ -365,7 +372,7 @@ TraitItemReference::associated_type_set (TyTy::BaseType *ty) const
 }
 
 void
-TraitItemReference::associated_type_reset () const
+TraitItemReference::associated_type_reset (bool only_projections) const
 {
   rust_assert (get_trait_item_type () == TraitItemType::TYPE);
 
@@ -374,7 +381,21 @@ TraitItemReference::associated_type_reset () const
   TyTy::PlaceholderType *placeholder
     = static_cast<TyTy::PlaceholderType *> (item_ty);
 
-  placeholder->clear_associated_type ();
+  if (!only_projections)
+    {
+      placeholder->clear_associated_type ();
+    }
+  else
+    {
+      if (!placeholder->can_resolve ())
+	return;
+
+      const TyTy::BaseType *r = placeholder->resolve ();
+      if (r->get_kind () == TyTy::TypeKind::PROJECTION)
+	{
+	  placeholder->clear_associated_type ();
+	}
+    }
 }
 
 TyTy::BaseType *
diff --git a/gcc/rust/typecheck/rust-hir-type-bounds.h b/gcc/rust/typecheck/rust-hir-type-bounds.h
index 4e8c58344de..628bba5da20 100644
--- a/gcc/rust/typecheck/rust-hir-type-bounds.h
+++ b/gcc/rust/typecheck/rust-hir-type-bounds.h
@@ -30,42 +30,18 @@ class TypeBoundsProbe : public TypeCheckBase
 {
 public:
   static std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
-  Probe (const TyTy::BaseType *receiver)
-  {
-    TypeBoundsProbe probe (receiver);
-    probe.scan ();
-    return probe.trait_references;
-  }
+  Probe (const TyTy::BaseType *receiver);
 
   static bool is_bound_satisfied_for_type (TyTy::BaseType *receiver,
-					   TraitReference *ref)
-  {
-    for (auto &bound : receiver->get_specified_bounds ())
-      {
-	const TraitReference *b = bound.get ();
-	if (b->is_equal (*ref))
-	  return true;
-      }
-
-    std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
-      = Probe (receiver);
-    for (auto &bound : bounds)
-      {
-	const TraitReference *b = bound.first;
-	if (b->is_equal (*ref))
-	  return true;
-      }
-
-    return false;
-  }
+					   TraitReference *ref);
 
 private:
   void scan ();
+  void assemble_sized_builtin ();
+  void assemble_builtin_candidate (Analysis::RustLangItem::ItemType item);
 
 private:
-  TypeBoundsProbe (const TyTy::BaseType *receiver)
-    : TypeCheckBase (), receiver (receiver)
-  {}
+  TypeBoundsProbe (const TyTy::BaseType *receiver);
 
   const TyTy::BaseType *receiver;
   std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> trait_references;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 46a14eb6e92..d4eea7ae954 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -1095,6 +1095,7 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
       return;
     }
 
+  fn->prepare_higher_ranked_bounds ();
   auto root = receiver_tyty->get_root ();
   if (root->get_kind () == TyTy::TypeKind::ADT)
     {
@@ -1659,6 +1660,11 @@ TypeCheckExpr::resolve_operator_overload (
   TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
   rust_assert (fn->is_method ());
 
+  fn->prepare_higher_ranked_bounds ();
+  rust_debug_loc (expr.get_locus (), "resolved operator overload to: {%u} {%s}",
+		  candidate.candidate.ty->get_ref (),
+		  candidate.candidate.ty->debug_str ().c_str ());
+
   auto root = lhs->get_root ();
   if (root->get_kind () == TyTy::TypeKind::ADT)
     {
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index b14e0c68e5a..76d2eeff8ef 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -23,6 +23,41 @@
 namespace Rust {
 namespace Resolver {
 
+TypeBoundsProbe::TypeBoundsProbe (const TyTy::BaseType *receiver)
+  : TypeCheckBase (), receiver (receiver)
+{}
+
+std::vector<std::pair<TraitReference *, HIR::ImplBlock *>>
+TypeBoundsProbe::Probe (const TyTy::BaseType *receiver)
+{
+  TypeBoundsProbe probe (receiver);
+  probe.scan ();
+  return probe.trait_references;
+}
+
+bool
+TypeBoundsProbe::is_bound_satisfied_for_type (TyTy::BaseType *receiver,
+					      TraitReference *ref)
+{
+  for (auto &bound : receiver->get_specified_bounds ())
+    {
+      const TraitReference *b = bound.get ();
+      if (b->is_equal (*ref))
+	return true;
+    }
+
+  std::vector<std::pair<TraitReference *, HIR::ImplBlock *>> bounds
+    = Probe (receiver);
+  for (auto &bound : bounds)
+    {
+      const TraitReference *b = bound.first;
+      if (b->is_equal (*ref))
+	return true;
+    }
+
+  return false;
+}
+
 void
 TypeBoundsProbe::scan ()
 {
@@ -57,6 +92,75 @@ TypeBoundsProbe::scan ()
       if (!trait_ref->is_error ())
 	trait_references.push_back ({trait_ref, path.second});
     }
+
+  // marker traits...
+  assemble_sized_builtin ();
+}
+
+void
+TypeBoundsProbe::assemble_sized_builtin ()
+{
+  const TyTy::BaseType *raw = receiver->destructure ();
+
+  // does this thing actually implement sized?
+  switch (raw->get_kind ())
+    {
+    case TyTy::ADT:
+    case TyTy::STR:
+    case TyTy::REF:
+    case TyTy::POINTER:
+    case TyTy::PARAM:
+    case TyTy::ARRAY:
+    case TyTy::SLICE:
+    case TyTy::FNDEF:
+    case TyTy::FNPTR:
+    case TyTy::TUPLE:
+    case TyTy::BOOL:
+    case TyTy::CHAR:
+    case TyTy::INT:
+    case TyTy::UINT:
+    case TyTy::FLOAT:
+    case TyTy::USIZE:
+    case TyTy::ISIZE:
+      assemble_builtin_candidate (Analysis::RustLangItem::SIZED);
+      break;
+
+      // not-sure about this.... FIXME
+    case TyTy::INFER:
+    case TyTy::NEVER:
+    case TyTy::PLACEHOLDER:
+    case TyTy::PROJECTION:
+    case TyTy::DYNAMIC:
+    case TyTy::CLOSURE:
+    case TyTy::ERROR:
+      break;
+    }
+}
+
+void
+TypeBoundsProbe::assemble_builtin_candidate (
+  Analysis::RustLangItem::ItemType lang_item)
+{
+  DefId id;
+  bool found_lang_item = mappings->lookup_lang_item (lang_item, &id);
+  if (!found_lang_item)
+    return;
+
+  HIR::Item *item = mappings->lookup_defid (id);
+  if (item == nullptr)
+    return;
+
+  rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
+  HIR::Trait *trait = static_cast<HIR::Trait *> (item);
+  const TyTy::BaseType *raw = receiver->destructure ();
+
+  // assemble the reference
+  TraitReference *trait_ref = TraitResolver::Resolve (*trait);
+  trait_references.push_back ({trait_ref, mappings->lookup_builtin_marker ()});
+
+  rust_debug ("Added builtin lang_item: %s for %s",
+	      Analysis::RustLangItem::ToString (lang_item).c_str (),
+	      raw->get_name ().c_str ());
 }
 
 TraitReference *
@@ -101,7 +205,8 @@ TypeCheckBase::get_predicate_from_bound (HIR::TypePath &type_path)
 	  = static_cast<HIR::TypePathSegmentFunction *> (final_seg.get ());
 	auto &fn = final_function_seg->get_function_path ();
 
-	// we need to make implicit generic args which must be an implicit Tuple
+	// we need to make implicit generic args which must be an implicit
+	// Tuple
 	auto crate_num = mappings->get_current_crate ();
 	HirId implicit_args_id = mappings->get_next_hir_id ();
 	Analysis::NodeMapping mapping (crate_num,
@@ -514,8 +619,8 @@ TypeBoundPredicate::lookup_associated_type (const std::string &search)
 {
   TypeBoundPredicateItem item = lookup_associated_item (search);
 
-  // only need to check that it is infact an associated type because other wise
-  // if it was not found it will just be an error node anyway
+  // only need to check that it is infact an associated type because other
+  // wise if it was not found it will just be an error node anyway
   if (!item.is_error ())
     {
       const auto raw = item.get_raw_item ();
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc b/gcc/rust/typecheck/rust-tyty-subst.cc
index e4fe30e00ea..d2f6cf607d1 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -119,11 +119,6 @@ SubstitutionParamMapping::fill_param_ty (
     {
       type.inherit_bounds (*param);
     }
-  else
-    {
-      if (!param->bounds_compatible (type, locus, true))
-	return false;
-    }
 
   if (type.get_kind () == TypeKind::PARAM)
     {
@@ -133,8 +128,15 @@ SubstitutionParamMapping::fill_param_ty (
   else
     {
       // check the substitution is compatible with bounds
-      if (!param->bounds_compatible (type, locus, true))
-	return false;
+      rust_debug_loc (locus,
+		      "fill_param_ty bounds_compatible: param %s type %s",
+		      param->get_name ().c_str (), type.get_name ().c_str ());
+
+      if (!param->is_implicit_self_trait ())
+	{
+	  if (!param->bounds_compatible (type, locus, true))
+	    return false;
+	}
 
       // recursively pass this down to all HRTB's
       for (auto &bound : param->get_specified_bounds ())
@@ -870,10 +872,149 @@ SubstitutionRef::solve_missing_mappings_from_this (SubstitutionRef &ref,
   return SubstitutionArgumentMappings (resolved_mappings, {}, 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 ()
+{
+  for (const auto &subst : get_substs ())
+    {
+      const TyTy::ParamType *pty = subst.get_param_ty ();
+      for (const auto &bound : pty->get_specified_bounds ())
+	{
+	  const auto ref = bound.get ();
+	  ref->clear_associated_type_projections ();
+	}
+    }
+}
+
 bool
 SubstitutionRef::monomorphize ()
 {
-  auto context = Resolver::TypeCheckContext::get ();
   for (const auto &subst : get_substs ())
     {
       const TyTy::ParamType *pty = subst.get_param_ty ();
@@ -887,136 +1028,16 @@ SubstitutionRef::monomorphize ()
 
       for (const auto &bound : pty->get_specified_bounds ())
 	{
-	  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)
+	  bool error_flag = false;
+	  auto associated
+	    = lookup_associated_impl (subst, bound, binding, &error_flag);
+	  if (associated != nullptr)
 	    {
-	      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);
-		    }
-		}
+	      associated->setup_associated_types (binding, bound);
 	    }
 
-	  if (!associated_impl_traits.empty ())
-	    {
-	      // 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);
-		}
-	    }
+	  if (error_flag)
+	    return false;
 	}
     }
 
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h b/gcc/rust/typecheck/rust-tyty-subst.h
index fd5826102b3..365fdb6c042 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -298,7 +298,13 @@ public:
   // TODO comment
   BaseType *infer_substitions (Location locus);
 
-  // TODO comment
+  // this clears any possible projections from higher ranked trait bounds which
+  // could be hanging around from a previous resolution
+  void prepare_higher_ranked_bounds ();
+
+  // FIXME
+  // this is bad name for this, i think it should be something like
+  // compute-higher-ranked-bounds
   bool monomorphize ();
 
   // TODO comment
@@ -308,6 +314,10 @@ 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.cc b/gcc/rust/typecheck/rust-tyty.cc
index fe5aa2b059c..d0d36ac0a11 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -31,6 +31,7 @@
 #include "rust-hir-type-bounds.h"
 #include "rust-hir-trait-resolve.h"
 #include "rust-tyty-cmp.h"
+#include "rust-type-util.h"
 
 #include "options.h"
 
@@ -266,6 +267,7 @@ BaseType::get_locus () const
   return ident.locus;
 }
 
+// FIXME this is missing locus
 bool
 BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const
 {
@@ -277,12 +279,67 @@ BaseType::satisfies_bound (const TypeBoundPredicate &predicate) const
 	return true;
     }
 
+  bool satisfied = false;
   auto probed = Resolver::TypeBoundsProbe::Probe (this);
   for (const auto &b : probed)
     {
       const Resolver::TraitReference *bound = b.first;
       if (bound->satisfies_bound (*query))
+	{
+	  satisfied = true;
+	  break;
+	}
+    }
+
+  if (!satisfied)
+    return false;
+
+  for (const auto &b : probed)
+    {
+      const Resolver::TraitReference *bound = b.first;
+      if (!bound->is_equal (*query))
+	continue;
+
+      // builtin ones have no impl-block this needs fixed and use a builtin node
+      // of somekind
+      if (b.second == nullptr)
 	return true;
+
+      // need to check that associated types can match as well
+      const HIR::ImplBlock &impl = *(b.second);
+      for (const auto &item : impl.get_impl_items ())
+	{
+	  TyTy::BaseType *impl_item_ty = nullptr;
+	  Analysis::NodeMapping i = item->get_impl_mappings ();
+	  bool query_ok = Resolver::query_type (i.get_hirid (), &impl_item_ty);
+	  if (!query_ok)
+	    return false;
+
+	  std::string item_name = item->get_impl_item_name ();
+	  TypeBoundPredicateItem lookup
+	    = predicate.lookup_associated_item (item_name);
+	  if (lookup.is_error ())
+	    return false;
+
+	  const auto *item_ref = lookup.get_raw_item ();
+	  TyTy::BaseType *bound_ty = item_ref->get_tyty ();
+
+	  // compare the types
+	  if (!bound_ty->can_eq (impl_item_ty, false))
+	    {
+	      RichLocation r (mappings->lookup_location (get_ref ()));
+	      r.add_range (predicate.get_locus ());
+	      r.add_range (mappings->lookup_location (i.get_hirid ()));
+
+	      rust_error_at (
+		r, "expected %<%s%> got %<%s%>",
+		bound_ty->destructure ()->get_name ().c_str (),
+		impl_item_ty->destructure ()->get_name ().c_str ());
+	      return false;
+	    }
+	}
+
+      return true;
     }
 
   return false;
@@ -2827,18 +2884,18 @@ ParamType::ParamType (std::string symbol, Location locus, HirId ref,
 	      {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
 	       locus},
 	      specified_bounds, refs),
-    symbol (symbol), param (param)
+    is_trait_self (false), symbol (symbol), param (param)
 {}
 
-ParamType::ParamType (std::string symbol, Location locus, HirId ref,
-		      HirId ty_ref, HIR::GenericParam &param,
+ParamType::ParamType (bool is_trait_self, std::string symbol, Location locus,
+		      HirId ref, HirId ty_ref, HIR::GenericParam &param,
 		      std::vector<TypeBoundPredicate> specified_bounds,
 		      std::set<HirId> refs)
   : BaseType (ref, ty_ref, TypeKind::PARAM,
 	      {Resolver::CanonicalPath::new_seg (UNKNOWN_NODEID, symbol),
 	       locus},
 	      specified_bounds, refs),
-    symbol (symbol), param (param)
+    is_trait_self (is_trait_self), symbol (symbol), param (param)
 {}
 
 HIR::GenericParam &
@@ -2906,8 +2963,9 @@ ParamType::can_eq (const BaseType *other, bool emit_errors) const
 BaseType *
 ParamType::clone () const
 {
-  return new ParamType (get_symbol (), ident.locus, get_ref (), get_ty_ref (),
-			param, get_specified_bounds (), get_combined_refs ());
+  return new ParamType (is_trait_self, get_symbol (), ident.locus, get_ref (),
+			get_ty_ref (), param, get_specified_bounds (),
+			get_combined_refs ());
 }
 
 BaseType *
@@ -2997,6 +3055,18 @@ ParamType::handle_substitions (SubstitutionArgumentMappings &subst_mappings)
   return p;
 }
 
+void
+ParamType::set_implicit_self_trait ()
+{
+  is_trait_self = true;
+}
+
+bool
+ParamType::is_implicit_self_trait () const
+{
+  return is_trait_self;
+}
+
 // StrType
 
 StrType::StrType (HirId ref, std::set<HirId> refs)
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index d2cf5b07fc1..64b9379a1c0 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -267,8 +267,8 @@ public:
 	     std::vector<TypeBoundPredicate> specified_bounds,
 	     std::set<HirId> refs = std::set<HirId> ());
 
-  ParamType (std::string symbol, Location locus, HirId ref, HirId ty_ref,
-	     HIR::GenericParam &param,
+  ParamType (bool is_trait_self, std::string symbol, Location locus, HirId ref,
+	     HirId ty_ref, HIR::GenericParam &param,
 	     std::vector<TypeBoundPredicate> specified_bounds,
 	     std::set<HirId> refs = std::set<HirId> ());
 
@@ -298,7 +298,11 @@ public:
 
   ParamType *handle_substitions (SubstitutionArgumentMappings &mappings);
 
+  void set_implicit_self_trait ();
+  bool is_implicit_self_trait () const;
+
 private:
+  bool is_trait_self;
   std::string symbol;
   HIR::GenericParam &param;
 };
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 1fc32038d19..a9687040144 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -96,9 +96,16 @@ static const HirId kDefaultCrateNumBegin = 0;
 Mappings::Mappings ()
   : crateNumItr (kDefaultCrateNumBegin), currentCrateNum (UNKNOWN_CREATENUM),
     hirIdIter (kDefaultHirIdBegin), nodeIdIter (kDefaultNodeIdBegin)
-{}
+{
+  Analysis::NodeMapping node (0, 0, 0, 0);
+  builtinMarker
+    = new HIR::ImplBlock (node, {}, {}, nullptr, nullptr, HIR::WhereClause ({}),
+			  Positive,
+			  HIR::Visibility (HIR::Visibility::VisType::PUBLIC),
+			  {}, {}, Location ());
+}
 
-Mappings::~Mappings () {}
+Mappings::~Mappings () { delete builtinMarker; }
 
 Mappings *
 Mappings::get ()
@@ -1035,5 +1042,11 @@ Mappings::lookup_ast_item (NodeId id, AST::Item **result)
   return true;
 }
 
+HIR::ImplBlock *
+Mappings::lookup_builtin_marker ()
+{
+  return builtinMarker;
+}
+
 } // namespace Analysis
 } // namespace Rust
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 13cae717031..9d6affa27e0 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -296,6 +296,8 @@ public:
   void insert_ast_item (AST::Item *item);
   bool lookup_ast_item (NodeId id, AST::Item **result);
 
+  HIR::ImplBlock *lookup_builtin_marker ();
+
 private:
   Mappings ();
 
@@ -304,6 +306,7 @@ private:
   HirId hirIdIter;
   NodeId nodeIdIter;
   std::map<CrateNum, LocalDefId> localIdIter;
+  HIR::ImplBlock *builtinMarker;
 
   std::map<NodeId, CrateNum> crate_node_to_crate_num;
   std::map<CrateNum, AST::Crate *> ast_crate_mappings;
diff --git a/gcc/testsuite/rust/compile/issue-1725-1.rs b/gcc/testsuite/rust/compile/issue-1725-1.rs
new file mode 100644
index 00000000000..1ace9fbbf30
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1725-1.rs
@@ -0,0 +1,19 @@
+mod core {
+    mod ops {
+        #[lang = "add"]
+        pub trait Add<Rhs = Self> {
+            type Output;
+
+            fn add(self, rhs: Rhs) -> Self::Output;
+        }
+    }
+}
+
+pub fn foo<T: core::ops::Add<Output = i32>>(a: T) -> i32 {
+    a + a
+}
+
+pub fn main() {
+    foo(123f32);
+    // { dg-error "bounds not satisfied for f32 .Add. is not satisfied" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/issue-1725-2.rs b/gcc/testsuite/rust/compile/issue-1725-2.rs
new file mode 100644
index 00000000000..8bfd0bbd924
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1725-2.rs
@@ -0,0 +1,28 @@
+mod core {
+    mod ops {
+        #[lang = "add"]
+        pub trait Add<Rhs = Self> {
+            type Output;
+
+            fn add(self, rhs: Rhs) -> Self::Output;
+        }
+    }
+}
+
+impl core::ops::Add for f32 {
+    type Output = f32;
+
+    fn add(self, rhs: Self) -> Self::Output {
+        self + rhs
+    }
+}
+
+pub fn foo<T: core::ops::Add<Output = i32>>(a: T) -> i32 {
+    a + a
+}
+
+pub fn main() {
+    foo(123f32);
+    // { dg-error "expected .i32. got .f32." "" { target *-*-* } .-1 }
+    // { dg-error "bounds not satisfied for f32 .Add. is not satisfied" "" { target *-*-* } .-2 }
+}
-- 
2.40.0


  parent reply	other threads:[~2023-04-05 14:06 UTC|newest]

Thread overview: 92+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-04-05 14:02 Rust front-end update 2023-04-05 arthur.cohen
2023-04-05 14:02 ` [committed 01/88] gccrs: fatal_error_flag: Fix typo in error message arthur.cohen
2023-04-05 14:02 ` [committed 02/88] gccrs: unsafe: check use of `target_feature` attribute arthur.cohen
2023-04-05 14:02 ` [committed 03/88] gccrs: Check for mutable references in const functions arthur.cohen
2023-04-05 14:02 ` [committed 04/88] gccrs: rust: add bound parsing in parse_generic_arg arthur.cohen
2023-04-05 14:02 ` [committed 05/88] gccrs: Implement declarative macro 2.0 parser arthur.cohen
2023-04-05 14:02 ` [committed 06/88] gccrs: Add name resolution to generic argument associated item bindings arthur.cohen
2023-04-05 14:02 ` [committed 07/88] gccrs: Support associated type bound arguments arthur.cohen
2023-04-05 14:02 ` [committed 08/88] gccrs: Reuse TypeCheckPattern on LetStmt's arthur.cohen
2023-04-05 14:02 ` [committed 09/88] gccrs: Add get_locus function for abstract class MetaItemInner arthur.cohen
2023-04-05 14:02 ` [committed 10/88] gccrs: diagnostics: Add underline for tokens in diagnostics arthur.cohen
2023-04-05 14:02 ` [committed 11/88] gccrs: Change how CompileVarDecl outputs Bvariable's arthur.cohen
2023-04-05 14:02 ` [committed 12/88] gccrs: testsuite: Handle Windows carriage returns properly arthur.cohen
2023-04-05 14:02 ` [committed 13/88] gccrs: Support GroupedPattern during name resolution arthur.cohen
2023-04-05 14:02 ` [committed 14/88] gccrs: Do not crash on empty macros expand. Fixes #1712 arthur.cohen
2023-04-05 14:02 ` [committed 15/88] gccrs: Add HIR lowering for GroupedPattern arthur.cohen
2023-04-05 14:03 ` [committed 16/88] gccrs: Add get_item method for HIR::GroupedPattern arthur.cohen
2023-04-05 14:03 ` [committed 17/88] gccrs: Add type resolution for grouped patterns arthur.cohen
2023-04-05 14:03 ` [committed 18/88] gccrs: Added missing GroupedPattern visitors for code generation arthur.cohen
2023-04-05 14:03 ` [committed 19/88] gccrs: Rename file rust-ast-full-test.cc to rust-ast.cc arthur.cohen
2023-04-05 14:03 ` [committed 20/88] gccrs: moved operator.h to util/rust-operators.h arthur.cohen
2023-04-05 14:03 ` [committed 21/88] gccrs: fixed compiler error message on wildcard pattern within expression arthur.cohen
2023-04-05 14:03 ` [committed 22/88] gccrs: fixed indentations in AST pretty expanded dump of trait arthur.cohen
2023-04-05 14:03 ` [committed 23/88] gccrs: macro: Allow builtin `MacroInvocation`s within the AST arthur.cohen
2023-04-05 14:03 ` [committed 24/88] gccrs: Create and use CompilePatternLet visitor for compiling let statments arthur.cohen
2023-04-05 14:03 ` [committed 25/88] gccrs: parser: Allow parsing multiple reference types arthur.cohen
2023-04-05 14:03 ` [committed 26/88] gccrs: Move rust-buffered-queue.h to util folder #1766 arthur.cohen
2023-04-05 14:03 ` [committed 27/88] gccrs: Improve GroupedPattern lowering arthur.cohen
2023-04-05 14:03 ` [committed 28/88] gccrs: Remove HIR::GroupedPattern arthur.cohen
2023-04-05 14:03 ` [committed 29/88] gccrs: Optimize HIR::ReferencePattern arthur.cohen
2023-04-05 14:03 ` [committed 30/88] gccrs: Implement lowering ReferencePattern from AST to HIR arthur.cohen
2023-04-05 14:03 ` [committed 31/88] gccrs: parser: Improve parsing of complex generic arguments arthur.cohen
2023-04-05 14:03 ` [committed 32/88] gccrs: parser: Fix parsing of closure param list arthur.cohen
2023-04-05 14:03 ` [committed 33/88] gccrs: Add support for feature check arthur.cohen
2023-04-05 14:03 ` [committed 34/88] gccrs: Removed comment copy-pasted from gcc/tree.def arthur.cohen
2023-04-05 14:03 ` [committed 35/88] gccrs: Add another test case for passing associated type-bounds arthur.cohen
2023-04-05 14:03 ` [committed 36/88] gccrs: Move TypePredicateItem impl out of the header arthur.cohen
2023-04-05 14:03 ` [committed 37/88] gccrs: Refactor TyVar and TypeBoundPredicates arthur.cohen
2023-04-05 14:03 ` [committed 38/88] gccrs: Refactor SubstitutionRef base class into its own CC file arthur.cohen
2023-04-05 14:03 ` [committed 39/88] gccrs: Refactor all substitution mapper code implementation " arthur.cohen
2023-04-05 14:03 ` [committed 40/88] gccrs: Refactor BaseType, InferType and ErrorType impl into cc file arthur.cohen
2023-04-05 14:03 ` [committed 41/88] gccrs: Refactor PathProbe " arthur.cohen
2023-04-05 14:03 ` [committed 42/88] gccrs: Refactor PathProbeType code into CC file arthur.cohen
2023-04-05 14:03 ` [committed 43/88] gccrs: Refactor all code out of the rust-tyty.h header arthur.cohen
2023-04-05 14:03 ` [committed 44/88] gccrs: Rename rust-tyctx.cc to rust-typecheck-context.cc arthur.cohen
2023-04-05 14:03 ` [committed 45/88] gccrs: Rename header rust-hir-trait-ref.h to rust-hir-trait-reference.h arthur.cohen
2023-04-05 14:03 ` [committed 46/88] gccrs: Refactor handle_substitutions to take a reference arthur.cohen
2023-04-05 14:03 ` [committed 47/88] gccrs: Clear the substitution callbacks when copying ArgumentMappings arthur.cohen
2023-04-05 14:03 ` [committed 48/88] gccrs: Add missing param subst callback arthur.cohen
2023-04-05 14:03 ` [committed 49/88] gccrs: Remove monomorphization hack to setup possible associated types arthur.cohen
2023-04-05 14:03 ` [committed 50/88] gccrs: Refactor the type unification code arthur.cohen
2023-04-05 14:03 ` [committed 51/88] gccrs: Fix nullptr dereference arthur.cohen
2023-04-05 14:03 ` [committed 52/88] gccrs: Add missing Sized, Copy and Clone lang item mappings arthur.cohen
2023-04-05 14:03 ` [committed 53/88] gccrs: Fix higher ranked trait bounds computation of self arthur.cohen
2023-04-05 14:03 ` [committed 54/88] gccrs: Remove bad error message on checking function arguments arthur.cohen
2023-04-05 14:03 ` [committed 55/88] gccrs: Add general TypeBounds checks arthur.cohen
2023-04-05 14:03 ` [committed 56/88] gccrs: Add support for TuplePattern in let statements arthur.cohen
2023-04-05 14:03 ` [committed 57/88] gccrs: rust-item: include rust-expr.h arthur.cohen
2023-04-05 14:03 ` [committed 58/88] gccrs: parser: Expose parse_macro_invocation as public API arthur.cohen
2023-04-05 14:03 ` [committed 59/88] gccrs: expansion: Add `get_token_slice` to `MacroInvocLexer` class arthur.cohen
2023-04-05 14:03 ` [committed 60/88] gccrs: macros: Perform macro expansion in a fixed-point fashion arthur.cohen
2023-04-05 14:03 ` [committed 61/88] gccrs: expander: Add documentation for `expand_eager_invocations` arthur.cohen
2023-04-05 14:03 ` [committed 62/88] gccrs: typecheck: Refactor rust-hir-trait-reference.h arthur.cohen
2023-04-05 14:03 ` [committed 63/88] gccrs: cli: Update safety warning message arthur.cohen
2023-04-05 14:03 ` [committed 64/88] gccrs: Update copyright years arthur.cohen
2023-04-05 14:03 ` [committed 65/88] gccrs: Add feature gate for "rust-intrinsic" arthur.cohen
2023-04-05 14:03 ` [committed 66/88] gccrs: Add variadic argument type checking arthur.cohen
2023-04-05 14:03 ` [committed 67/88] gccrs: Add test arthur.cohen
2023-04-05 14:03 ` [committed 68/88] gccrs: Simplify WildcardPattern let statement handling arthur.cohen
2023-04-05 14:03 ` [committed 69/88] gccrs: lex: Prevent directories in RAIIFile arthur.cohen
2023-04-05 14:03 ` [committed 70/88] gccrs: testsuite: Add empty string macro test arthur.cohen
2023-04-05 14:03 ` [committed 71/88] gccrs: Add support for parsing empty tuple patterns arthur.cohen
2023-04-05 14:03 ` [committed 72/88] gccrs: Implemented UTF-8 checking for include_str!() arthur.cohen
2023-04-05 14:03 ` [committed 73/88] gccrs: Extract query_type from TypeCheckBase to be a simple extern arthur.cohen
2023-04-05 14:03 ` [committed 74/88] gccrs: Add new virtual function HIR::ImplItem::get_impl_item_name arthur.cohen
2023-04-05 14:03 ` arthur.cohen [this message]
2023-04-05 14:04 ` [committed 76/88] gccrs: Fix regression in testcase arthur.cohen
2023-04-05 14:04 ` [committed 77/88] gccrs: Add trailing newline arthur.cohen
2023-04-05 14:04 ` [committed 78/88] gccrs: builtins: Return empty list of tokens instead of nullptr arthur.cohen
2023-04-05 14:04 ` [committed 79/88] gccrs: Fix formatting arthur.cohen
2023-04-05 14:04 ` [committed 80/88] gccrs: Add AST::AltPattern class arthur.cohen
2023-04-05 14:04 ` [committed 81/88] gccrs: Fix up DejaGnu directives in 'rust/compile/issue-1830_{bytes,str}.rs' test cases [#1838] arthur.cohen
2023-04-05 14:04 ` [committed 82/88] gccrs: rename rust-hir-full-tests.cc arthur.cohen
2023-04-05 14:04 ` [committed 83/88] gccrs: add test case to show our query-type system is working arthur.cohen
2023-04-05 14:04 ` [committed 84/88] gccrs: ast: Refactor TraitItem to keep Location info arthur.cohen
2023-04-05 14:04 ` [committed 85/88] gccrs: diagnostic: Refactor Error class arthur.cohen
2023-04-05 14:04 ` [committed 86/88] gccrs: Added AST Node AST::InlineAsm arthur.cohen
2023-04-05 14:04 ` [committed 87/88] gccrs: Address unsafe with/without block handling ambiguity arthur.cohen
2023-04-05 14:04 ` [committed 88/88] gccrs: Fix issue with parsing unsafe block expression statements arthur.cohen
2023-04-06  7:59 ` Rust front-end update 2023-04-05 Thomas Schwinge
2023-04-06  9:05   ` Arthur Cohen
2023-04-11  9:09 ` Richard Biener

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230405140411.3016563-76-arthur.cohen@embecosm.com \
    --to=arthur.cohen@embecosm.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=gcc-rust@gcc.gnu.org \
    --cc=herron.philip@googlemail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).