public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] Support Autoderef coercions
@ 2022-08-06 12:10 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-08-06 12:10 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:5d17a8b6b2c086d4df516de06ddacdf88728f6ba

commit 5d17a8b6b2c086d4df516de06ddacdf88728f6ba
Author: Philip Herron <philip.herron@embecosm.com>
Date:   Wed Aug 3 13:14:54 2022 +0100

    Support Autoderef coercions
    
    This is an incremental approach to get our coercion sites more acurate to
    rustc. This allows us to support coercions which require a deref by sharing
    the code from the autoderef cycle. The eventual goal here will allow us to
    remove the rust-tyty-coercion rules which is messy and cannot handle logic
    such as DST's very well.
    
    Fixes #1198

Diff:
---
 gcc/rust/Make-lang.in                            |  1 +
 gcc/rust/backend/rust-compile-base.h             |  5 +-
 gcc/rust/backend/rust-compile-expr.cc            | 13 ++--
 gcc/rust/backend/rust-compile-expr.h             | 14 ++--
 gcc/rust/backend/rust-compile-stmt.h             |  3 +-
 gcc/rust/backend/rust-compile.cc                 | 28 ++++++--
 gcc/rust/typecheck/rust-autoderef.h              |  2 +-
 gcc/rust/typecheck/rust-coercion.cc              | 92 ++++++++++++++++++++++++
 gcc/rust/typecheck/rust-coercion.h               | 70 ++++++++++++++++++
 gcc/rust/typecheck/rust-hir-type-check-base.cc   | 21 +++++-
 gcc/rust/typecheck/rust-hir-type-check-base.h    |  2 +-
 gcc/rust/typecheck/rust-hir-type-check-expr.h    |  3 +-
 gcc/rust/typecheck/rust-hir-type-check-stmt.h    |  3 +-
 gcc/rust/typecheck/rust-hir-type-check-struct.cc |  9 ++-
 gcc/rust/typecheck/rust-tyty-call.cc             | 22 +++---
 gcc/testsuite/rust/compile/generics4.rs          |  7 +-
 gcc/testsuite/rust/compile/reference1.rs         |  3 +-
 gcc/testsuite/rust/compile/shadow1.rs            |  3 +-
 gcc/testsuite/rust/compile/type-bindings1.rs     |  1 -
 gcc/testsuite/rust/execute/torture/issue-1198.rs | 75 +++++++++++++++++++
 20 files changed, 330 insertions(+), 47 deletions(-)

diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index ee8473f83c2..886bafbe1e0 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -118,6 +118,7 @@ GRS_OBJS = \
     rust/rust-hir-type-check-pattern.o \
     rust/rust-hir-type-check-expr.o \
     rust/rust-hir-dot-operator.o \
+    rust/rust-coercion.o \
     rust/rust-hir-type-check-base.o \
     rust/rust-autoderef.o \
     rust/rust-substitution-mapper.o \
diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h
index aad0da38535..5a0ac8fe713 100644
--- a/gcc/rust/backend/rust-compile-base.h
+++ b/gcc/rust/backend/rust-compile-base.h
@@ -40,9 +40,12 @@ protected:
 protected:
   Context *get_context () { return ctx; }
 
-  tree coercion_site (tree rvalue, const TyTy::BaseType *actual,
+  tree coercion_site (HirId id, tree rvalue, const TyTy::BaseType *actual,
 		      const TyTy::BaseType *expected, Location lvalue_locus,
 		      Location rvalue_locus);
+  tree coercion_site1 (tree rvalue, const TyTy::BaseType *actual,
+		       const TyTy::BaseType *expected, Location lvalue_locus,
+		       Location rvalue_locus);
 
   tree coerce_to_dyn_object (tree compiled_ref, const TyTy::BaseType *actual,
 			     const TyTy::BaseType *expected,
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index 8576cf2fd19..38d10d2d41c 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -853,8 +853,9 @@ CompileExpr::visit (HIR::CallExpr &expr)
 	  Location lvalue_locus
 	    = ctx->get_mappings ()->lookup_location (expected->get_ty_ref ());
 	  Location rvalue_locus = argument->get_locus ();
-	  rvalue = coercion_site (rvalue, actual, expected, lvalue_locus,
-				  rvalue_locus);
+	  rvalue
+	    = coercion_site (argument->get_mappings ().get_hirid (), rvalue,
+			     actual, expected, lvalue_locus, rvalue_locus);
 
 	  // add it to the list
 	  arguments.push_back (rvalue);
@@ -951,8 +952,8 @@ CompileExpr::visit (HIR::CallExpr &expr)
       Location lvalue_locus
 	= ctx->get_mappings ()->lookup_location (expected->get_ty_ref ());
       Location rvalue_locus = argument->get_locus ();
-      rvalue
-	= coercion_site (rvalue, actual, expected, lvalue_locus, rvalue_locus);
+      rvalue = coercion_site (argument->get_mappings ().get_hirid (), rvalue,
+			      actual, expected, lvalue_locus, rvalue_locus);
 
       // add it to the list
       args.push_back (rvalue);
@@ -1069,8 +1070,8 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
       Location lvalue_locus
 	= ctx->get_mappings ()->lookup_location (expected->get_ty_ref ());
       Location rvalue_locus = argument->get_locus ();
-      rvalue
-	= coercion_site (rvalue, actual, expected, lvalue_locus, rvalue_locus);
+      rvalue = coercion_site (argument->get_mappings ().get_hirid (), rvalue,
+			      actual, expected, lvalue_locus, rvalue_locus);
 
       // add it to the list
       args.push_back (rvalue);
diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h
index bc1423991ac..9b8976de18a 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -177,9 +177,9 @@ public:
       expr.get_rhs ()->get_mappings ().get_hirid (), &actual);
     rust_assert (ok);
 
-    rvalue
-      = coercion_site (rvalue, actual, expected, expr.get_lhs ()->get_locus (),
-		       expr.get_rhs ()->get_locus ());
+    rvalue = coercion_site (expr.get_mappings ().get_hirid (), rvalue, actual,
+			    expected, expr.get_lhs ()->get_locus (),
+			    expr.get_rhs ()->get_locus ());
 
     tree assignment
       = ctx->get_backend ()->assignment_statement (lvalue, rvalue,
@@ -435,8 +435,9 @@ public:
 
 	if (ok)
 	  {
-	    rvalue = coercion_site (rvalue, actual, expected, lvalue_locus,
-				    rvalue_locus);
+	    rvalue
+	      = coercion_site (argument->get_mappings ().get_hirid (), rvalue,
+			       actual, expected, lvalue_locus, rvalue_locus);
 	  }
 
 	// add it to the list
@@ -469,7 +470,8 @@ public:
 	    // compile/torture/struct_base_init_1.rs
 	    if (ok)
 	      {
-		rvalue = coercion_site (rvalue, actual, expected, lvalue_locus,
+		rvalue = coercion_site (argument->get_mappings ().get_hirid (),
+					rvalue, actual, expected, lvalue_locus,
 					rvalue_locus);
 	      }
 
diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h
index aa17a4a4941..9bb4b7b07d2 100644
--- a/gcc/rust/backend/rust-compile-stmt.h
+++ b/gcc/rust/backend/rust-compile-stmt.h
@@ -87,7 +87,8 @@ public:
     Location lvalue_locus = stmt.get_pattern ()->get_locus ();
     Location rvalue_locus = stmt.get_init_expr ()->get_locus ();
     TyTy::BaseType *expected = ty;
-    init = coercion_site (init, actual, expected, lvalue_locus, rvalue_locus);
+    init = coercion_site (stmt.get_mappings ().get_hirid (), init, actual,
+			  expected, lvalue_locus, rvalue_locus);
 
     auto fnctx = ctx->peek_fn ();
     if (ty->is_unit ())
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 4f17fa6286e..8a614f200a6 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -198,9 +198,25 @@ CompileStructExprField::visit (HIR::StructExprFieldIdentifier &field)
 // Shared methods in compilation
 
 tree
-HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval,
+HIRCompileBase::coercion_site (HirId id, tree rvalue,
+			       const TyTy::BaseType *rval,
 			       const TyTy::BaseType *lval,
 			       Location lvalue_locus, Location rvalue_locus)
+{
+  std::vector<Resolver::Adjustment> *adjustments = nullptr;
+  bool ok = ctx->get_tyctx ()->lookup_autoderef_mappings (id, &adjustments);
+  if (ok)
+    {
+      rvalue = resolve_adjustements (*adjustments, rvalue, rvalue_locus);
+    }
+
+  return coercion_site1 (rvalue, rval, lval, lvalue_locus, rvalue_locus);
+}
+
+tree
+HIRCompileBase::coercion_site1 (tree rvalue, const TyTy::BaseType *rval,
+				const TyTy::BaseType *lval,
+				Location lvalue_locus, Location rvalue_locus)
 {
   if (rvalue == error_mark_node)
     return error_mark_node;
@@ -227,8 +243,8 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval,
 
       tree deref_rvalue = indirect_expression (rvalue, rvalue_locus);
       tree coerced
-	= coercion_site (deref_rvalue, act->get_base (), exp->get_base (),
-			 lvalue_locus, rvalue_locus);
+	= coercion_site1 (deref_rvalue, act->get_base (), exp->get_base (),
+			  lvalue_locus, rvalue_locus);
       if (exp->is_dyn_object () && SLICE_TYPE_P (TREE_TYPE (coerced)))
 	return coerced;
 
@@ -269,8 +285,10 @@ HIRCompileBase::coercion_site (tree rvalue, const TyTy::BaseType *rval,
       rust_assert (actual_base != nullptr);
 
       tree deref_rvalue = indirect_expression (rvalue, rvalue_locus);
-      tree coerced = coercion_site (deref_rvalue, actual_base, exp->get_base (),
-				    lvalue_locus, rvalue_locus);
+      tree coerced
+	= coercion_site1 (deref_rvalue, actual_base, exp->get_base (),
+			  lvalue_locus, rvalue_locus);
+
       if (exp->is_dyn_object () && SLICE_TYPE_P (TREE_TYPE (coerced)))
 	return coerced;
 
diff --git a/gcc/rust/typecheck/rust-autoderef.h b/gcc/rust/typecheck/rust-autoderef.h
index 159f4c06cbc..220b6f45091 100644
--- a/gcc/rust/typecheck/rust-autoderef.h
+++ b/gcc/rust/typecheck/rust-autoderef.h
@@ -157,7 +157,7 @@ protected:
   // type
   virtual void try_hook (const TyTy::BaseType &);
 
-  bool cycle (const TyTy::BaseType *receiver);
+  virtual bool cycle (const TyTy::BaseType *receiver);
 
   bool try_autoderefed (const TyTy::BaseType *r);
 
diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc
new file mode 100644
index 00000000000..e6e82c3f734
--- /dev/null
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -0,0 +1,92 @@
+// 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-coercion.h"
+
+namespace Rust {
+namespace Resolver {
+
+AutoderefTypeCoercion::CoercionResult
+AutoderefTypeCoercion::Coerce (const TyTy::BaseType *receiver,
+			       const TyTy::BaseType *expected, Location locus)
+{
+  AutoderefTypeCoercion resolver (expected, locus);
+  bool ok = resolver.cycle (receiver);
+  return ok ? resolver.try_result : CoercionResult::get_error ();
+}
+
+AutoderefTypeCoercion::AutoderefTypeCoercion (const TyTy::BaseType *expected,
+					      Location locus)
+  : AutoderefCycle (false), mappings (Analysis::Mappings::get ()),
+    context (TypeCheckContext::get ()), expected (expected), locus (locus),
+    try_result (CoercionResult::get_error ())
+{}
+
+bool
+AutoderefTypeCoercion::cycle (const TyTy::BaseType *receiver)
+{
+  // FIXME this is not finished and might be super simplified
+  // see:
+  // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs
+
+  if (receiver->get_kind () == TyTy::TypeKind::REF
+      && expected->get_kind () == TyTy::TypeKind::REF)
+    {
+      // if we expect to get a mutable pointer we can't get that from an
+      // immutable one so we have to be careful
+
+      const auto &receiver_ref
+	= static_cast<const TyTy::ReferenceType &> (*receiver);
+      const auto &expected_ref
+	= static_cast<const TyTy::ReferenceType &> (*expected);
+
+      // we can allow for mutability changes here by casting down from
+      // mutability eg:  mut vs const, we cant take a mutable reference from a
+      // const eg:  const vs mut we can take a const reference from a mutable
+      // one
+
+      bool mutability_ok
+	= !expected_ref.is_mutable ()
+	  || (expected_ref.is_mutable () == receiver_ref.is_mutable ());
+      if (!mutability_ok)
+	{
+	  RichLocation r (locus);
+	  r.add_range (mappings->lookup_location (receiver_ref.get_ref ()));
+	  r.add_range (mappings->lookup_location (expected_ref.get_ref ()));
+	  rust_error_at (r, "mismatched mutability");
+
+	  return false;
+	}
+    }
+
+  return AutoderefCycle::cycle (receiver);
+}
+
+bool
+AutoderefTypeCoercion::select (const TyTy::BaseType &autoderefed)
+{
+  if (autoderefed.can_eq (expected, false))
+    {
+      try_result = CoercionResult{adjustments, autoderefed.clone ()};
+      return true;
+    }
+  return false;
+}
+
+} // namespace Resolver
+} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-coercion.h b/gcc/rust/typecheck/rust-coercion.h
new file mode 100644
index 00000000000..c3d5d028e64
--- /dev/null
+++ b/gcc/rust/typecheck/rust-coercion.h
@@ -0,0 +1,70 @@
+// 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/>.
+
+#ifndef RUST_COERCION
+#define RUST_COERCION
+
+#include "rust-autoderef.h"
+#include "rust-hir-type-check.h"
+
+namespace Rust {
+namespace Resolver {
+
+class AutoderefTypeCoercion : protected AutoderefCycle
+{
+public:
+  struct CoercionResult
+  {
+    std::vector<Adjustment> adjustments;
+    TyTy::BaseType *tyty;
+
+    bool is_error ()
+    {
+      return tyty == nullptr || tyty->get_kind () == TyTy::TypeKind::ERROR;
+    }
+
+    static CoercionResult get_error () { return CoercionResult{{}, nullptr}; }
+  };
+
+  static CoercionResult Coerce (const TyTy::BaseType *receiver,
+				const TyTy::BaseType *expected, Location locus);
+
+protected:
+  AutoderefTypeCoercion (const TyTy::BaseType *expected, Location locus);
+
+  bool cycle (const TyTy::BaseType *receiver) override;
+
+  bool select (const TyTy::BaseType &autoderefed) override;
+
+private:
+  // context info
+  Analysis::Mappings *mappings;
+  TypeCheckContext *context;
+
+  // search
+  const TyTy::BaseType *expected;
+  Location locus;
+
+  // mutable fields
+  CoercionResult try_result;
+};
+
+} // namespace Resolver
+} // namespace Rust
+
+#endif // RUST_COERCION
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index 092b635bfa8..c50199847b7 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -17,6 +17,7 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-hir-type-check-base.h"
+#include "rust-coercion.h"
 
 namespace Rust {
 namespace Resolver {
@@ -328,10 +329,24 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, Location locus)
 }
 
 TyTy::BaseType *
-TypeCheckBase::coercion_site (TyTy::BaseType *lhs, TyTy::BaseType *rhs,
-			      Location)
+TypeCheckBase::coercion_site (HirId id, TyTy::BaseType *expected,
+			      TyTy::BaseType *expr, Location locus)
 {
-  return lhs->coerce (rhs);
+  auto context = TypeCheckContext::get ();
+  if (expected->get_kind () == TyTy::TypeKind::ERROR
+      || expr->get_kind () == TyTy::TypeKind::ERROR)
+    return expr;
+
+  // can we autoderef it?
+  auto result = AutoderefTypeCoercion::Coerce (expr, expected, locus);
+  if (!result.is_error ())
+    {
+      // save any adjustments
+      context->insert_autoderef_mappings (id, std::move (result.adjustments));
+      return expected->coerce (result.tyty);
+    }
+
+  return expected->coerce (expr);
 }
 
 } // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index 9d53610151d..4078697c927 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -39,7 +39,7 @@ public:
 
   virtual ~TypeCheckBase () {}
 
-  static TyTy::BaseType *coercion_site (TyTy::BaseType *lhs,
+  static TyTy::BaseType *coercion_site (HirId id, TyTy::BaseType *lhs,
 					TyTy::BaseType *rhs, Location locus);
 
 protected:
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 8a0c3054cd7..de542ca70e8 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -230,7 +230,8 @@ public:
     auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
     auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
 
-    coercion_site (lhs, rhs, expr.get_locus ());
+    coercion_site (expr.get_mappings ().get_hirid (), 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 11f4d642429..f8bf6e083dd 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h
@@ -99,7 +99,8 @@ public:
     if (specified_ty != nullptr && init_expr_ty != nullptr)
       {
 	// FIXME use this result and look at the regressions
-	coercion_site (specified_ty, init_expr_ty, stmt.get_locus ());
+	coercion_site (stmt.get_mappings ().get_hirid (), 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 736bc5e7857..5b522772a3e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
@@ -222,7 +222,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field)
 
   TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ());
   resolved_field_value_expr
-    = coercion_site (field_type->get_field_type (), value, field.get_locus ());
+    = coercion_site (field.get_mappings ().get_hirid (),
+		     field_type->get_field_type (), value, field.get_locus ());
   if (resolved_field_value_expr != nullptr)
     {
       fields_assigned.insert (field.field_name);
@@ -252,7 +253,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field)
 
   TyTy::BaseType *value = TypeCheckExpr::Resolve (field.get_value ());
   resolved_field_value_expr
-    = coercion_site (field_type->get_field_type (), value, field.get_locus ());
+    = coercion_site (field.get_mappings ().get_hirid (),
+		     field_type->get_field_type (), value, field.get_locus ());
   if (resolved_field_value_expr != nullptr)
     {
       fields_assigned.insert (field_name);
@@ -287,7 +289,8 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field)
   TyTy::BaseType *value = TypeCheckExpr::Resolve (&expr);
 
   resolved_field_value_expr
-    = coercion_site (field_type->get_field_type (), value, field.get_locus ());
+    = coercion_site (field.get_mappings ().get_hirid (),
+		     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
index 416527e3436..b810bd88512 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -58,7 +58,9 @@ TypeCheckCallExpr::visit (ADTType &type)
 	  return;
 	}
 
-      auto res = field_tyty->coerce (arg);
+      auto res = Resolver::TypeCheckBase::coercion_site (
+	argument->get_mappings ().get_hirid (), field_tyty, arg,
+	argument->get_locus ());
       if (res->get_kind () == TyTy::TypeKind::ERROR)
 	{
 	  return;
@@ -123,8 +125,9 @@ TypeCheckCallExpr::visit (FnType &type)
       if (i < type.num_params ())
 	{
 	  auto fnparam = type.param_at (i);
-	  auto resolved_argument_type
-	    = fnparam.second->coerce (argument_expr_tyty);
+	  auto resolved_argument_type = Resolver::TypeCheckBase::coercion_site (
+	    argument->get_mappings ().get_hirid (), fnparam.second,
+	    argument_expr_tyty, argument->get_locus ());
 	  if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
 	    {
 	      rust_error_at (argument->get_locus (),
@@ -176,9 +179,9 @@ TypeCheckCallExpr::visit (FnPtr &type)
 	  return;
 	}
 
-      auto resolved_argument_type
-	= Resolver::TypeCheckBase::coercion_site (fnparam, argument_expr_tyty,
-						  argument->get_locus ());
+      auto resolved_argument_type = Resolver::TypeCheckBase::coercion_site (
+	argument->get_mappings ().get_hirid (), fnparam, argument_expr_tyty,
+	argument->get_locus ());
       if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
 	{
 	  rust_error_at (argument->get_locus (),
@@ -234,10 +237,9 @@ TypeCheckMethodCallExpr::visit (FnType &type)
 	  return;
 	}
 
-      auto resolved_argument_type
-	= Resolver::TypeCheckBase::coercion_site (fnparam.second,
-						  argument_expr_tyty,
-						  argument->get_locus ());
+      auto resolved_argument_type = Resolver::TypeCheckBase::coercion_site (
+	argument->get_mappings ().get_hirid (), fnparam.second,
+	argument_expr_tyty, argument->get_locus ());
       if (resolved_argument_type->get_kind () == TyTy::TypeKind::ERROR)
 	{
 	  rust_error_at (argument->get_locus (),
diff --git a/gcc/testsuite/rust/compile/generics4.rs b/gcc/testsuite/rust/compile/generics4.rs
index 4eaaea7786c..8af13586a37 100644
--- a/gcc/testsuite/rust/compile/generics4.rs
+++ b/gcc/testsuite/rust/compile/generics4.rs
@@ -3,10 +3,9 @@ struct GenericStruct<T>(T, usize);
 fn main() {
     let a2;
     a2 = GenericStruct::<i8, i32>(1, 456); // { dg-error "generic item takes at most 1 type arguments but 2 were supplied" }
-    // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
-    // { dg-error {Failed to resolve expression of function call} "" { target *-*-* } .-2 }
-    // { duplicate _dg-error {failed to type resolve expression} "" { target *-*-* } .-3 }
-    // { dg-error {expected \[T\?\] got \[<tyty::error>\]} "" { target *-*-* } .-4 }
+                                           // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
+                                           // { dg-error {Failed to resolve expression of function call} "" { target *-*-* } .-2 }
+                                           // { duplicate _dg-error {failed to type resolve expression} "" { target *-*-* } .-3 }
 
     let b2: i32 = a2.0;
     // { dg-error {Expected Tuple or ADT got: T\?} "" { target *-*-* } .-1 }
diff --git a/gcc/testsuite/rust/compile/reference1.rs b/gcc/testsuite/rust/compile/reference1.rs
index 3d979269cf2..ff791533754 100644
--- a/gcc/testsuite/rust/compile/reference1.rs
+++ b/gcc/testsuite/rust/compile/reference1.rs
@@ -1,5 +1,6 @@
 fn main() {
     let a = &123;
     let b: &mut i32 = a;
-    // { dg-error "expected .&mut i32. got .& i32." "" { target *-*-* } .-1 }
+    // { dg-error "mismatched mutability" "" { target *-*-* } .-1 }
+    // { dg-error "expected .&mut i32. got .& i32." "" { target *-*-* } .-2 }
 }
diff --git a/gcc/testsuite/rust/compile/shadow1.rs b/gcc/testsuite/rust/compile/shadow1.rs
index 730b53dcfb9..77410e932da 100644
--- a/gcc/testsuite/rust/compile/shadow1.rs
+++ b/gcc/testsuite/rust/compile/shadow1.rs
@@ -3,6 +3,5 @@ fn main() {
     let mut x;
     x = true;
     x = x + 2; // { dg-error "cannot apply this operator to types bool and <integer>"  }
-    // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
-    // { dg-error {expected \[bool\] got \[<tyty::error>\]} "" { target *-*-* } .-2 }
+               // { dg-error {failed to type resolve expression} "" { target *-*-* } .-1 }
 }
diff --git a/gcc/testsuite/rust/compile/type-bindings1.rs b/gcc/testsuite/rust/compile/type-bindings1.rs
index 3f61b8b4e4e..ad85ed97ecb 100644
--- a/gcc/testsuite/rust/compile/type-bindings1.rs
+++ b/gcc/testsuite/rust/compile/type-bindings1.rs
@@ -7,5 +7,4 @@ fn main() {
     // { dg-error {failed to type resolve expression} "" { target *-*-* } .-2 }
     // { dg-error {Failed to resolve expression of function call} "" { target *-*-* } .-3 }
     // { duplicate _dg-error {failed to type resolve expression} "" { target *-*-* } .-4 }
-    // { dg-error {expected \[T\?\] got \[<tyty::error>\]} "" { target *-*-* } .-5 }
 }
diff --git a/gcc/testsuite/rust/execute/torture/issue-1198.rs b/gcc/testsuite/rust/execute/torture/issue-1198.rs
new file mode 100644
index 00000000000..fce44ad1994
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/issue-1198.rs
@@ -0,0 +1,75 @@
+/* { dg-output "foo_deref\nimm_deref\n123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+#[lang = "deref"]
+pub trait Deref {
+    type Target;
+
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "imm_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+impl<T> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        unsafe {
+            let a = "mut_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        *self
+    }
+}
+
+struct Foo<T>(T);
+impl<T> Deref for Foo<T> {
+    type Target = T;
+
+    fn deref(&self) -> &Self::Target {
+        unsafe {
+            let a = "foo_deref\n\0";
+            let b = a as *const str;
+            let c = b as *const i8;
+
+            printf(c);
+        }
+
+        &self.0
+    }
+}
+
+fn main() -> i32 {
+    let foo: Foo<i32> = Foo(123);
+    let bar: &i32 = &foo;
+
+    unsafe {
+        let a = "%i\n\0";
+        let b = a as *const str;
+        let c = b as *const i8;
+
+        printf(c, *bar);
+    }
+
+    0
+}


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

only message in thread, other threads:[~2022-08-06 12:10 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-06 12:10 [gcc/devel/rust/master] Support Autoderef coercions 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).