[gcc/devel/rust/master] Refactor all coercion type calls into a single coercion_site function

Thomas Schwinge tschwinge@gcc.gnu.org
Sat Aug 6 12:09:35 GMT 2022


https://gcc.gnu.org/g:2dc902baa1388841096e16e660082a8e79fce17e

commit 2dc902baa1388841096e16e660082a8e79fce17e
Author: Philip Herron <philip.herron@embecosm.com>
Date:   Fri Jul 29 16:21:33 2022 +0100

    Refactor all coercion type calls into a single coercion_site function
    
    In order to fully support coercion sites we need a single place in order to
    implement the logic. This refactors all the coercion calls to have a single
    TypeCheckBase::coercion_site(lhs, rhs, location). Eventually we will do
    something similar for unifications and casts so we can improve our
    diagnostics.

Diff:
---
 gcc/rust/Make-lang.in                            |   1 +
 gcc/rust/typecheck/rust-hir-type-check-base.cc   |   7 +
 gcc/rust/typecheck/rust-hir-type-check-base.h    |   3 +
 gcc/rust/typecheck/rust-hir-type-check-expr.h    |   2 +-
 gcc/rust/typecheck/rust-hir-type-check-stmt.h    |   2 +-
 gcc/rust/typecheck/rust-hir-type-check-struct.cc |  13 +-
 gcc/rust/typecheck/rust-tyty-call.cc             | 267 +++++++++++++++++++++++
 gcc/rust/typecheck/rust-tyty.cc                  | 238 --------------------
 8 files changed, 288 insertions(+), 245 deletions(-)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 78c3d0f6e78..ee8473f83c2 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -106,6 +106,7 @@ GRS_OBJS = \
     rust/rust-pub-restricted-visitor.o \
     rust/rust-privacy-reporter.o \
     rust/rust-tyty.o \
+    rust/rust-tyty-call.o \
     rust/rust-tyctx.o \
     rust/rust-tyty-bounds.o \
     rust/rust-hir-type-check-util.o \
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 2a47c58664b..092b635bfa8 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -327,5 +327,12 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, Location locus)
   return repr;
 }
 
+TyTy::BaseType *
+TypeCheckBase::coercion_site (TyTy::BaseType *lhs, TyTy::BaseType *rhs,
+			      Location)
+{
+  return lhs->coerce (rhs);
+}
+
 } // namespace Resolver
 } // namespace Rust
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index f7a1bd4fa84..9d53610151d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -39,6 +39,9 @@ public:
 
   virtual ~TypeCheckBase () {}
 
+  static TyTy::BaseType *coercion_site (TyTy::BaseType *lhs,
+					TyTy::BaseType *rhs, Location locus);
+
 protected:
   TypeCheckBase ()
     : mappings (Analysis::Mappings::get ()), resolver (Resolver::get ()),
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index df07cb3e920..88545c6e5cb 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -380,7 +380,7 @@ public:
     auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
     auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
 
-    lhs->coerce (rhs);
+    coercion_site (lhs, rhs, expr.get_locus ());
   }
 
   void visit (HIR::CompoundAssignmentExpr &expr) override
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
index b2b68c05494..11f4d642429 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
@@ -99,7 +99,7 @@ public:
     if (specified_ty != nullptr && init_expr_ty != nullptr)
       {
 	// FIXME use this result and look at the regressions
-	specified_ty->coerce (init_expr_ty);
+	coercion_site (specified_ty, init_expr_ty, stmt.get_locus ());
 	context->insert_type (stmt_pattern.get_pattern_mappings (),
 			      specified_ty);
       }
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
index 6634ad4ad7d..736bc5e7857 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
@@ -42,8 +42,8 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr)
     {
       TyTy::BaseType *base_resolved
 	= TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ());
-      struct_def
-	= (TyTy::ADTType *) struct_path_resolved->coerce (base_resolved);
+      struct_def = static_cast<TyTy::ADTType *> (
+	struct_path_resolved->coerce (base_resolved));
       if (struct_def == nullptr)
 	{
 	  rust_fatal_error (struct_expr.struct_base->base_struct->get_locus (),
@@ -221,7 +221,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
     }
 
   TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ());
-  resolved_field_value_expr = field_type->get_field_type ()->coerce (value);
+  resolved_field_value_expr
+    = coercion_site (field_type->get_field_type (), value, field.get_locus ());
   if (resolved_field_value_expr != nullptr)
     {
       fields_assigned.insert (field.field_name);
@@ -250,7 +251,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
     }
 
   TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ());
-  resolved_field_value_expr = field_type->get_field_type ()->coerce (value);
+  resolved_field_value_expr
+    = coercion_site (field_type->get_field_type (), value, field.get_locus ());
   if (resolved_field_value_expr != nullptr)
     {
       fields_assigned.insert (field_name);
@@ -284,7 +286,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
 			    field.get_locus ());
   TyTy::BaseType *value = TypeCheckExpr::Resolve (&expr);
 
-  resolved_field_value_expr = field_type->get_field_type ()->coerce (value);
+  resolved_field_value_expr
+    = coercion_site (field_type->get_field_type (), value, field.get_locus ());
   if (resolved_field_value_expr != nullptr)
 
     {
diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc
new file mode 100644
index 00000000000..416527e3436
--- /dev/null
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -0,0 +1,267 @@
+// Copyright (C) 2020-2022 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-tyty-call.h"
+#include "rust-hir-type-check-expr.h"
+
+namespace Rust {
+namespace TyTy {
+
+void
+TypeCheckCallExpr::visit (ADTType &type)
+{
+  rust_assert (!variant.is_error ());
+  if (variant.get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
+    {
+      rust_error_at (
+	call.get_locus (),
+	"expected function, tuple struct or tuple variant, found struct %<%s%>",
+	type.get_name ().c_str ());
+      return;
+    }
+
+  if (call.num_params () != variant.num_fields ())
+    {
+      rust_error_at (call.get_locus (),
+		     "unexpected number of arguments %lu expected %lu",
+		     (unsigned long) call.num_params (),
+		     (unsigned long) variant.num_fields ());
+      return;
+    }
+
+  size_t i = 0;
+  for (auto &argument : call.get_arguments ())
+    {
+      StructFieldType *field = variant.get_field_at_index (i);
+      BaseType *field_tyty = field->get_field_type ();
+
+      BaseType *arg = Resolver::TypeCheckExpr::Resolve (argument.get ());
+      if (arg->get_kind () == TyTy::TypeKind::ERROR)
+	{
+	  rust_error_at (argument->get_locus (),
+			 "failed to resolve argument type");
+	  return;
+	}
+
+      auto res = field_tyty->coerce (arg);
+      if (res->get_kind () == TyTy::TypeKind::ERROR)
+	{
+	  return;
+	}
+
+      delete res;
+      i++;
+    }
+
+  if (i != call.num_params ())
+    {
+      rust_error_at (call.get_locus (),
+		     "unexpected number of arguments %lu expected %lu",
+		     (unsigned long) i, (unsigned long) call.num_params ());
+      return;
+    }
+
+  resolved = type.clone ();
+}
+
+void
+TypeCheckCallExpr::visit (FnType &type)
+{
+  type.monomorphize ();
+  if (call.num_params () != type.num_params ())
+    {
+      if (type.is_varadic ())
+	{
+	  if (call.num_params () < type.num_params ())
+	    {
+	      rust_error_at (call.get_locus (),
+			     "unexpected number of arguments %lu expected %lu",
+			     (unsigned long) call.num_params (),
+			     (unsigned long) type.num_params ());
+	      return;
+	    }
+	}
+      else
+	{
+	  rust_error_at (call.get_locus (),
+			 "unexpected number of arguments %lu expected %lu",
+			 (unsigned long) call.num_params (),
+			 (unsigned long) type.num_params ());
+	  return;
+	}
+    }
+
+  size_t i = 0;
+  for (auto &argument : call.get_arguments ())
+    {
+      auto argument_expr_tyty
+	= Resolver::TypeCheckExpr::Resolve (argument.get ());
+      if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
+	{
+	  rust_error_at (
+	    argument->get_locus (),
+	    "failed to resolve type for argument expr in CallExpr");
+	  return;
+	}
+
+      // it might be a varadic function
+      if (i < type.num_params ())
+	{
+	  auto fnparam = type.param_at (i);
+	  auto resolved_argument_type
+	    = fnparam.second->coerce (argument_expr_tyty);
+	  if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
+	    {
+	      rust_error_at (argument->get_locus (),
+			     "Type Resolution failure on parameter");
+	      return;
+	    }
+	}
+
+      context->insert_type (argument->get_mappings (), argument_expr_tyty);
+
+      i++;
+    }
+
+  if (i < call.num_params ())
+    {
+      rust_error_at (call.get_locus (),
+		     "unexpected number of arguments %lu expected %lu",
+		     (unsigned long) i, (unsigned long) call.num_params ());
+      return;
+    }
+
+  type.monomorphize ();
+  resolved = type.get_return_type ()->clone ();
+}
+
+void
+TypeCheckCallExpr::visit (FnPtr &type)
+{
+  if (call.num_params () != type.num_params ())
+    {
+      rust_error_at (call.get_locus (),
+		     "unexpected number of arguments %lu expected %lu",
+		     (unsigned long) call.num_params (),
+		     (unsigned long) type.num_params ());
+      return;
+    }
+
+  size_t i = 0;
+  for (auto &argument : call.get_arguments ())
+    {
+      auto fnparam = type.param_at (i);
+      auto argument_expr_tyty
+	= Resolver::TypeCheckExpr::Resolve (argument.get ());
+      if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
+	{
+	  rust_error_at (
+	    argument->get_locus (),
+	    "failed to resolve type for argument expr in CallExpr");
+	  return;
+	}
+
+      auto resolved_argument_type
+	= Resolver::TypeCheckBase::coercion_site (fnparam, argument_expr_tyty,
+						  argument->get_locus ());
+      if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
+	{
+	  rust_error_at (argument->get_locus (),
+			 "Type Resolution failure on parameter");
+	  return;
+	}
+
+      context->insert_type (argument->get_mappings (), argument_expr_tyty);
+
+      i++;
+    }
+
+  if (i != call.num_params ())
+    {
+      rust_error_at (call.get_locus (),
+		     "unexpected number of arguments %lu expected %lu",
+		     (unsigned long) i, (unsigned long) call.num_params ());
+      return;
+    }
+
+  resolved = type.get_return_type ()->monomorphized_clone ();
+}
+
+// method call checker
+
+void
+TypeCheckMethodCallExpr::visit (FnType &type)
+{
+  type.get_self_type ()->unify (adjusted_self);
+
+  // +1 for the receiver self
+  size_t num_args_to_call = call.num_params () + 1;
+  if (num_args_to_call != type.num_params ())
+    {
+      rust_error_at (call.get_locus (),
+		     "unexpected number of arguments %lu expected %lu",
+		     (unsigned long) call.num_params (),
+		     (unsigned long) type.num_params ());
+      return;
+    }
+
+  size_t i = 1;
+  for (auto &argument : call.get_arguments ())
+    {
+      auto fnparam = type.param_at (i);
+      auto argument_expr_tyty
+	= Resolver::TypeCheckExpr::Resolve (argument.get ());
+      if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
+	{
+	  rust_error_at (
+	    argument->get_locus (),
+	    "failed to resolve type for argument expr in CallExpr");
+	  return;
+	}
+
+      auto resolved_argument_type
+	= Resolver::TypeCheckBase::coercion_site (fnparam.second,
+						  argument_expr_tyty,
+						  argument->get_locus ());
+      if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
+	{
+	  rust_error_at (argument->get_locus (),
+			 "Type Resolution failure on parameter");
+	  return;
+	}
+
+      context->insert_type (argument->get_mappings (), argument_expr_tyty);
+
+      i++;
+    }
+
+  if (i != num_args_to_call)
+    {
+      rust_error_at (call.get_locus (),
+		     "unexpected number of arguments %lu expected %lu",
+		     (unsigned long) i, (unsigned long) call.num_params ());
+      return;
+    }
+
+  type.monomorphize ();
+
+  resolved = type.get_return_type ()->monomorphized_clone ();
+}
+
+} // namespace TyTy
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 05cd8ce971a..daedfc3012c 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -3205,243 +3205,5 @@ DynamicObjectType::get_object_items () const
   return items;
 }
 
-// rust-tyty-call.h
-
-void
-TypeCheckCallExpr::visit (ADTType &type)
-{
-  rust_assert (!variant.is_error ());
-  if (variant.get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
-    {
-      rust_error_at (
-	call.get_locus (),
-	"expected function, tuple struct or tuple variant, found struct %<%s%>",
-	type.get_name ().c_str ());
-      return;
-    }
-
-  if (call.num_params () != variant.num_fields ())
-    {
-      rust_error_at (call.get_locus (),
-		     "unexpected number of arguments %lu expected %lu",
-		     (unsigned long) call.num_params (),
-		     (unsigned long) variant.num_fields ());
-      return;
-    }
-
-  size_t i = 0;
-  for (auto &argument : call.get_arguments ())
-    {
-      StructFieldType *field = variant.get_field_at_index (i);
-      BaseType *field_tyty = field->get_field_type ();
-
-      BaseType *arg = Resolver::TypeCheckExpr::Resolve (argument.get ());
-      if (arg->get_kind () == TyTy::TypeKind::ERROR)
-	{
-	  rust_error_at (argument->get_locus (),
-			 "failed to resolve argument type");
-	  return;
-	}
-
-      auto res = field_tyty->coerce (arg);
-      if (res->get_kind () == TyTy::TypeKind::ERROR)
-	{
-	  return;
-	}
-
-      delete res;
-      i++;
-    }
-
-  if (i != call.num_params ())
-    {
-      rust_error_at (call.get_locus (),
-		     "unexpected number of arguments %lu expected %lu",
-		     (unsigned long) i, (unsigned long) call.num_params ());
-      return;
-    }
-
-  resolved = type.clone ();
-}
-
-void
-TypeCheckCallExpr::visit (FnType &type)
-{
-  type.monomorphize ();
-  if (call.num_params () != type.num_params ())
-    {
-      if (type.is_varadic ())
-	{
-	  if (call.num_params () < type.num_params ())
-	    {
-	      rust_error_at (call.get_locus (),
-			     "unexpected number of arguments %lu expected %lu",
-			     (unsigned long) call.num_params (),
-			     (unsigned long) type.num_params ());
-	      return;
-	    }
-	}
-      else
-	{
-	  rust_error_at (call.get_locus (),
-			 "unexpected number of arguments %lu expected %lu",
-			 (unsigned long) call.num_params (),
-			 (unsigned long) type.num_params ());
-	  return;
-	}
-    }
-
-  size_t i = 0;
-  for (auto &argument : call.get_arguments ())
-    {
-      auto argument_expr_tyty
-	= Resolver::TypeCheckExpr::Resolve (argument.get ());
-      if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
-	{
-	  rust_error_at (
-	    argument->get_locus (),
-	    "failed to resolve type for argument expr in CallExpr");
-	  return;
-	}
-
-      // it might be a varadic function
-      if (i < type.num_params ())
-	{
-	  auto fnparam = type.param_at (i);
-	  auto resolved_argument_type
-	    = fnparam.second->coerce (argument_expr_tyty);
-	  if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
-	    {
-	      rust_error_at (argument->get_locus (),
-			     "Type Resolution failure on parameter");
-	      return;
-	    }
-	}
-
-      context->insert_type (argument->get_mappings (), argument_expr_tyty);
-
-      i++;
-    }
-
-  if (i < call.num_params ())
-    {
-      rust_error_at (call.get_locus (),
-		     "unexpected number of arguments %lu expected %lu",
-		     (unsigned long) i, (unsigned long) call.num_params ());
-      return;
-    }
-
-  type.monomorphize ();
-  resolved = type.get_return_type ()->clone ();
-}
-
-void
-TypeCheckCallExpr::visit (FnPtr &type)
-{
-  if (call.num_params () != type.num_params ())
-    {
-      rust_error_at (call.get_locus (),
-		     "unexpected number of arguments %lu expected %lu",
-		     (unsigned long) call.num_params (),
-		     (unsigned long) type.num_params ());
-      return;
-    }
-
-  size_t i = 0;
-  for (auto &argument : call.get_arguments ())
-    {
-      auto fnparam = type.param_at (i);
-      auto argument_expr_tyty
-	= Resolver::TypeCheckExpr::Resolve (argument.get ());
-      if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
-	{
-	  rust_error_at (
-	    argument->get_locus (),
-	    "failed to resolve type for argument expr in CallExpr");
-	  return;
-	}
-
-      auto resolved_argument_type = fnparam->coerce (argument_expr_tyty);
-      if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
-	{
-	  rust_error_at (argument->get_locus (),
-			 "Type Resolution failure on parameter");
-	  return;
-	}
-
-      context->insert_type (argument->get_mappings (), argument_expr_tyty);
-
-      i++;
-    }
-
-  if (i != call.num_params ())
-    {
-      rust_error_at (call.get_locus (),
-		     "unexpected number of arguments %lu expected %lu",
-		     (unsigned long) i, (unsigned long) call.num_params ());
-      return;
-    }
-
-  resolved = type.get_return_type ()->monomorphized_clone ();
-}
-
-// method call checker
-
-void
-TypeCheckMethodCallExpr::visit (FnType &type)
-{
-  type.get_self_type ()->unify (adjusted_self);
-
-  // +1 for the receiver self
-  size_t num_args_to_call = call.num_params () + 1;
-  if (num_args_to_call != type.num_params ())
-    {
-      rust_error_at (call.get_locus (),
-		     "unexpected number of arguments %lu expected %lu",
-		     (unsigned long) call.num_params (),
-		     (unsigned long) type.num_params ());
-      return;
-    }
-
-  size_t i = 1;
-  for (auto &argument : call.get_arguments ())
-    {
-      auto fnparam = type.param_at (i);
-      auto argument_expr_tyty
-	= Resolver::TypeCheckExpr::Resolve (argument.get ());
-      if (argument_expr_tyty->get_kind () == TyTy::TypeKind::ERROR)
-	{
-	  rust_error_at (
-	    argument->get_locus (),
-	    "failed to resolve type for argument expr in CallExpr");
-	  return;
-	}
-
-      auto resolved_argument_type = fnparam.second->coerce (argument_expr_tyty);
-      if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
-	{
-	  rust_error_at (argument->get_locus (),
-			 "Type Resolution failure on parameter");
-	  return;
-	}
-
-      context->insert_type (argument->get_mappings (), argument_expr_tyty);
-
-      i++;
-    }
-
-  if (i != num_args_to_call)
-    {
-      rust_error_at (call.get_locus (),
-		     "unexpected number of arguments %lu expected %lu",
-		     (unsigned long) i, (unsigned long) call.num_params ());
-      return;
-    }
-
-  type.monomorphize ();
-
-  resolved = type.get_return_type ()->monomorphized_clone ();
-}
-
 } // namespace TyTy
 } // namespace Rust


More information about the Gcc-cvs mailing list