public inbox for gcc-rust@gcc.gnu.org
 help / color / mirror / Atom feed
* [COMMITTED] gccrs: Refactor unify to hit a unify_site
@ 2023-01-31 13:25 Arthur Cohen
  0 siblings, 0 replies; only message in thread
From: Arthur Cohen @ 2023-01-31 13:25 UTC (permalink / raw)
  To: gcc-patches; +Cc: gcc-rust, Philip Herron

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

This allows us to enforce better error handling on unify sites

gcc/rust/ChangeLog:

	* typecheck/rust-hir-type-check-base.cc (TypeCheckBase::unify_site): Add
	better unification function with debug calls.
	* typecheck/rust-autoderef.cc (AutoderefCycle::cycle): Add more debug
	calls and use new unify API.
	* typecheck/rust-coercion.cc (TypeCoercionRules::do_coercion): Likewise.
	(TypeCoercionRules::coerce_borrowed_pointer): Likewise.
	(TypeCoercionRules::select): Likewise.
	* typecheck/rust-hir-dot-operator.cc (MethodResolver::select): Likewise.
	* typecheck/rust-hir-trait-resolve.cc (TraitItemReference::resolve_item): Likewise.
	(TypeCheckBase::coercion_site): Likewise.
	(TypeCheckBase::cast_site): Likewise.
	* typecheck/rust-hir-type-check-base.h: Likewise.
	* typecheck/rust-hir-type-check-enumitem.cc (TypeCheckEnumItem::visit): Likewise.
	* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Likewise.
	* typecheck/rust-hir-type-check-implitem.cc (TypeCheckTopLevelImplItem::visit): Likewise.
	(TypeCheckImplItem::visit): Likewise.
	* typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit): Likewise.
	* typecheck/rust-hir-type-check-path.cc (TypeCheckExpr::resolve_segments): Likewise.
	* typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): Likewise.
	* typecheck/rust-hir-type-check-stmt.cc (TypeCheckStmt::visit): Likewise.
	* typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::resolve): Likewise.
	* typecheck/rust-hir-type-check-toplevel.cc (TypeCheckTopLevel::visit): Likewise.
	* typecheck/rust-hir-type-check-type.cc (TypeCheckType::visit): Likewise.
	* typecheck/rust-hir-type-check.cc (TypeResolution::Resolve): Likewise.
	* typecheck/rust-tyctx.cc (TypeCheckContext::peek_return_type): Likewise.
	* typecheck/rust-tyty-call.cc (TypeCheckMethodCallExpr::visit): Likewise.
	* typecheck/rust-tyty-cmp.h: Likewise.
	* typecheck/rust-tyty-rules.h: Likewise.
	* typecheck/rust-tyty.cc (BaseType::mappings_str): Likewise.
	(BaseType::debug): Print type name more clearly.
	(BaseType::debug_str): Add new function to print type pointer and name.
	(TupleType::get_name): Improve type name fetching function.
	(ReferenceType::get_name): Likewise.
	(PointerType::get_name): Likewise.
	* typecheck/rust-tyty.h: Refactor definitions outside of the header.

gcc/testsuite/ChangeLog:

	* rust/compile/issue-1152.rs: Fix dejagnu assertion.
	* rust/compile/tuple1.rs: Likewise.
	* rust/compile/type-alias1.rs: Likewise.
	* rust/execute/torture/operator_overload_9.rs: Likewise.
	* rust/execute/torture/slice1.rs: Rework test to use new parsing
	capability and stick to the original implementation.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/rust/typecheck/rust-autoderef.cc          |  15 +-
 gcc/rust/typecheck/rust-coercion.cc           |  62 +++-
 gcc/rust/typecheck/rust-hir-dot-operator.cc   |  15 +
 gcc/rust/typecheck/rust-hir-trait-resolve.cc  |  24 +-
 .../typecheck/rust-hir-type-check-base.cc     |  42 ++-
 gcc/rust/typecheck/rust-hir-type-check-base.h |   4 +
 .../typecheck/rust-hir-type-check-enumitem.cc |   6 +-
 .../typecheck/rust-hir-type-check-expr.cc     | 170 ++++++++---
 .../typecheck/rust-hir-type-check-implitem.cc |  17 +-
 .../typecheck/rust-hir-type-check-item.cc     |  11 +-
 .../typecheck/rust-hir-type-check-path.cc     |   5 +-
 .../typecheck/rust-hir-type-check-pattern.cc  |   4 +-
 .../typecheck/rust-hir-type-check-stmt.cc     |  15 +-
 .../typecheck/rust-hir-type-check-struct.cc   |  12 +-
 .../typecheck/rust-hir-type-check-toplevel.cc |  15 +-
 .../typecheck/rust-hir-type-check-type.cc     |   8 +-
 gcc/rust/typecheck/rust-hir-type-check.cc     |  12 +-
 gcc/rust/typecheck/rust-tyctx.cc              |   1 +
 gcc/rust/typecheck/rust-tyty-call.cc          |   5 +-
 gcc/rust/typecheck/rust-tyty-cmp.h            |   4 +-
 gcc/rust/typecheck/rust-tyty-rules.h          | 264 ++----------------
 gcc/rust/typecheck/rust-tyty.cc               |  61 +++-
 gcc/rust/typecheck/rust-tyty.h                |  36 +--
 gcc/testsuite/rust/compile/issue-1152.rs      |   2 -
 gcc/testsuite/rust/compile/tuple1.rs          |   2 +-
 gcc/testsuite/rust/compile/type-alias1.rs     |   2 +-
 .../execute/torture/operator_overload_9.rs    |   2 +-
 gcc/testsuite/rust/execute/torture/slice1.rs  |   7 +-
 28 files changed, 460 insertions(+), 363 deletions(-)

diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc
index 71d39cff3de..ca43f847e98 100644
--- a/gcc/rust/typecheck/rust-autoderef.cc
+++ b/gcc/rust/typecheck/rust-autoderef.cc
@@ -255,7 +255,12 @@ resolve_operator_overload_fn (
 	  lookup = fn->infer_substitions (Location ());
 	  rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
 	  fn = static_cast<TyTy::FnType *> (lookup);
-	  fn->get_self_type ()->unify (adjusted_self);
+
+	  Location unify_locus = mappings->lookup_location (ty->get_ref ());
+	  TypeCheckBase::unify_site (
+	    ty->get_ref (), TyTy::TyWithLocation (fn->get_self_type ()),
+	    TyTy::TyWithLocation (adjusted_self), unify_locus);
+
 	  lookup = fn;
 	}
     }
@@ -284,6 +289,7 @@ AutoderefCycle::cycle (const TyTy::BaseType *receiver)
   const TyTy::BaseType *r = receiver;
   while (true)
     {
+      rust_debug ("autoderef try 1: {%s}", r->debug_str ().c_str ());
       if (try_autoderefed (r))
 	return true;
 
@@ -292,12 +298,15 @@ AutoderefCycle::cycle (const TyTy::BaseType *receiver)
 	return false;
 
       // try unsize
+
       Adjustment unsize = Adjuster::try_unsize_type (r);
       if (!unsize.is_error ())
 	{
 	  adjustments.push_back (unsize);
 	  auto unsize_r = unsize.get_expected ();
 
+	  rust_debug ("autoderef try unsize: {%s}",
+		      unsize_r->debug_str ().c_str ());
 	  if (try_autoderefed (unsize_r))
 	    return true;
 
@@ -311,6 +320,8 @@ AutoderefCycle::cycle (const TyTy::BaseType *receiver)
 	  auto deref_r = deref.get_expected ();
 	  adjustments.push_back (deref);
 
+	  rust_debug ("autoderef try lang-item DEREF: {%s}",
+		      deref_r->debug_str ().c_str ());
 	  if (try_autoderefed (deref_r))
 	    return true;
 
@@ -324,6 +335,8 @@ AutoderefCycle::cycle (const TyTy::BaseType *receiver)
 	  auto deref_r = deref_mut.get_expected ();
 	  adjustments.push_back (deref_mut);
 
+	  rust_debug ("autoderef try lang-item DEREF_MUT: {%s}",
+		      deref_r->debug_str ().c_str ());
 	  if (try_autoderefed (deref_r))
 	    return true;
 
diff --git a/gcc/rust/typecheck/rust-coercion.cc b/gcc/rust/typecheck/rust-coercion.cc
index ceba6a843f9..fdf8eb95a33 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -16,6 +16,7 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
+#include "rust-hir-type-check-base.h"
 #include "rust-coercion.h"
 
 namespace Rust {
@@ -53,6 +54,49 @@ TypeCoercionRules::do_coercion (TyTy::BaseType *receiver)
   // see:
   // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs
 
+  // handle never
+  // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/coercion.rs#L155
+  if (receiver->get_kind () == TyTy::TypeKind::NEVER)
+    {
+      // Subtle: If we are coercing from `!` to `?T`, where `?T` is an unbound
+      // type variable, we want `?T` to fallback to `!` if not
+      // otherwise constrained. An example where this arises:
+      //
+      //     let _: Option<?T> = Some({ return; });
+      //
+      // here, we would coerce from `!` to `?T`.
+      if (expected->has_subsititions_defined () && !expected->is_concrete ())
+	{
+	  Location locus = mappings->lookup_location (receiver->get_ref ());
+	  TyTy::TyVar implicit_var
+	    = TyTy::TyVar::get_implicit_infer_var (locus);
+	  try_result = CoercionResult{{}, implicit_var.get_tyty ()};
+	  return true;
+	}
+      else
+	{
+	  bool expected_is_infer_var
+	    = expected->get_kind () == TyTy::TypeKind::INFER;
+	  bool expected_is_general_infer_var
+	    = expected_is_infer_var
+	      && (static_cast<TyTy::InferType *> (expected)->get_infer_kind ()
+		  == TyTy::InferType::InferTypeKind::GENERAL);
+
+	  // FIXME this 'expected_is_general_infer_var' case needs to eventually
+	  // should go away see: compile/never_type_err1.rs
+	  //
+	  // I think we need inference obligations to say that yes we have a
+	  // general inference variable but we add the oligation to the expected
+	  // type that it could default to '!'
+	  if (expected_is_general_infer_var)
+	    try_result = CoercionResult{{}, receiver};
+	  else
+	    try_result = CoercionResult{{}, expected->clone ()};
+
+	  return true;
+	}
+    }
+
   // unsize
   bool unsafe_error = false;
   CoercionResult unsize_coercion
@@ -163,13 +207,17 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver,
   switch (receiver->get_kind ())
     {
       case TyTy::TypeKind::REF: {
-	TyTy::ReferenceType *ref
+	TyTy::ReferenceType *from
 	  = static_cast<TyTy::ReferenceType *> (receiver);
-	from_mutbl = ref->mutability ();
+	from_mutbl = from->mutability ();
       }
       break;
 
       default: {
+	// FIXME
+	// we might be able to replace this with a can_eq because we default
+	// back to a final unity anyway
+	rust_debug ("coerce_borrowed_pointer -- unify");
 	TyTy::BaseType *result = receiver->unify (expected);
 	return CoercionResult{{}, result};
       }
@@ -183,7 +231,12 @@ TypeCoercionRules::coerce_borrowed_pointer (TyTy::BaseType *receiver,
       return TypeCoercionRules::CoercionResult::get_error ();
     }
 
+  rust_debug ("coerce_borrowed_pointer -- autoderef cycle");
   AutoderefCycle::cycle (receiver);
+  rust_debug ("coerce_borrowed_pointer -- result: [%s] with adjustments: [%zu]",
+	      try_result.is_error () ? "failed" : "matched",
+	      try_result.adjustments.size ());
+
   return try_result;
 }
 
@@ -310,7 +363,10 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
 bool
 TypeCoercionRules::select (const TyTy::BaseType &autoderefed)
 {
-  if (autoderefed.can_eq (expected, false))
+  rust_debug (
+    "autoderef type-coercion select autoderefed={%s} can_eq expected={%s}",
+    autoderefed.debug_str ().c_str (), expected->debug_str ().c_str ());
+  if (expected->can_eq (&autoderefed, false))
     {
       try_result = CoercionResult{adjustments, autoderefed.clone ()};
       return true;
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index 1cef7fe38a6..985e61b83f0 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -171,12 +171,21 @@ MethodResolver::select (const TyTy::BaseType &receiver)
     TyTy::FnType *fntype;
   };
 
+  rust_debug ("inherent_impl_fns found {%lu}, trait_fns found {%lu}, "
+	      "predicate_items found {%lu}",
+	      (unsigned long) inherent_impl_fns.size (),
+	      (unsigned long) trait_fns.size (),
+	      (unsigned long) predicate_items.size ());
+
   for (auto impl_item : inherent_impl_fns)
     {
       TyTy::FnType *fn = impl_item.ty;
       rust_assert (fn->is_method ());
 
       TyTy::BaseType *fn_self = fn->get_self_type ();
+      rust_debug ("dot-operator impl_item fn_self={%s} can_eq receiver={%s}",
+		  fn_self->debug_str ().c_str (),
+		  receiver.debug_str ().c_str ());
       if (fn_self->can_eq (&receiver, false))
 	{
 	  PathProbeCandidate::ImplItemCandidate c{impl_item.item,
@@ -195,6 +204,9 @@ MethodResolver::select (const TyTy::BaseType &receiver)
       rust_assert (fn->is_method ());
 
       TyTy::BaseType *fn_self = fn->get_self_type ();
+      rust_debug ("dot-operator trait_item fn_self={%s} can_eq receiver={%s}",
+		  fn_self->debug_str ().c_str (),
+		  receiver.debug_str ().c_str ());
       if (fn_self->can_eq (&receiver, false))
 	{
 	  PathProbeCandidate::TraitItemCandidate c{trait_item.reference,
@@ -214,6 +226,9 @@ MethodResolver::select (const TyTy::BaseType &receiver)
       rust_assert (fn->is_method ());
 
       TyTy::BaseType *fn_self = fn->get_self_type ();
+      rust_debug ("dot-operator predicate fn_self={%s} can_eq receiver={%s}",
+		  fn_self->debug_str ().c_str (),
+		  receiver.debug_str ().c_str ());
       if (fn_self->can_eq (&receiver, false))
 	{
 	  const TraitReference *trait_ref
diff --git a/gcc/rust/typecheck/rust-hir-trait-resolve.cc b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
index 93cef97afd3..c14a6c3a9be 100644
--- a/gcc/rust/typecheck/rust-hir-trait-resolve.cc
+++ b/gcc/rust/typecheck/rust-hir-trait-resolve.cc
@@ -324,10 +324,18 @@ TraitItemReference::resolve_item (HIR::TraitItemFunc &func)
 
   auto block_expr_ty = TypeCheckExpr::Resolve (func.get_block_expr ().get ());
 
-  context->pop_return_type ();
+  Location fn_return_locus
+    = func.get_decl ().has_return_type ()
+	? func.get_decl ().get_return_type ()->get_locus ()
+	: func.get_locus ();
+
+  TypeCheckBase::coercion_site (func.get_mappings ().get_hirid (),
+				TyTy::TyWithLocation (expected_ret_tyty,
+						      fn_return_locus),
+				TyTy::TyWithLocation (block_expr_ty),
+				func.get_locus ());
 
-  if (block_expr_ty->get_kind () != TyTy::NEVER)
-    expected_ret_tyty->unify (block_expr_ty);
+  context->pop_return_type ();
 }
 
 void
@@ -457,7 +465,10 @@ AssociatedImplTrait::setup_associated_types (
   // the type correctly as our receiver may be generic and we are inferring its
   // generic arguments and this Self might be the concrete version or vice
   // versa.
-  auto result = receiver->unify (impl_self_infer);
+  auto result = TypeCheckBase::unify_site (
+    get_impl_block ()->get_mappings ().get_hirid (),
+    TyTy::TyWithLocation (receiver), TyTy::TyWithLocation (impl_self_infer),
+    impl_predicate.get_locus ());
   rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
 
   // unify the bounds arguments
@@ -479,7 +490,10 @@ AssociatedImplTrait::setup_associated_types (
       TyTy::BaseType *a = impl_trait_predicate_args.at (i);
       TyTy::BaseType *b = hrtb_bound_arguments.at (i);
 
-      result = a->unify (b);
+      result
+	= TypeCheckBase::unify_site (a->get_ref (), TyTy::TyWithLocation (a),
+				     TyTy::TyWithLocation (b),
+				     impl_predicate.get_locus ());
       rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
     }
 
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.cc b/gcc/rust/typecheck/rust-hir-type-check-base.cc
index b809ac33108..d5121e7a7bc 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.cc
@@ -336,6 +336,30 @@ TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, Location locus)
   return repr;
 }
 
+TyTy::BaseType *
+TypeCheckBase::unify_site (HirId id, TyTy::TyWithLocation lhs,
+			   TyTy::TyWithLocation rhs, Location unify_locus)
+{
+  TyTy::BaseType *expected = lhs.get_ty ();
+  TyTy::BaseType *expr = rhs.get_ty ();
+
+  rust_debug ("unify_site id={%u} expected={%s} expr={%s}", id,
+	      expected->debug_str ().c_str (), expr->debug_str ().c_str ());
+
+  TyTy::BaseType *unified = expected->unify (expr);
+  if (unified->get_kind () == TyTy::TypeKind::ERROR)
+    {
+      RichLocation r (unify_locus);
+      r.add_range (lhs.get_locus ());
+      r.add_range (rhs.get_locus ());
+      rust_error_at (r, "expected %<%s%> got %<%s%>",
+		     expected->get_name ().c_str (),
+		     expr->get_name ().c_str ());
+    }
+
+  return unified;
+}
+
 TyTy::BaseType *
 TypeCheckBase::coercion_site (HirId id, TyTy::TyWithLocation lhs,
 			      TyTy::TyWithLocation rhs, Location locus)
@@ -363,7 +387,9 @@ TypeCheckBase::coercion_site (HirId id, TyTy::TyWithLocation lhs,
 
   rust_debug ("coerce_default_unify(a={%s}, b={%s})",
 	      receiver->debug_str ().c_str (), expected->debug_str ().c_str ());
-  TyTy::BaseType *coerced = expected->unify (receiver);
+  TyTy::BaseType *coerced
+    = unify_site (id, lhs, TyTy::TyWithLocation (receiver, rhs.get_locus ()),
+		  locus);
   context->insert_autoderef_mappings (id, std::move (result.adjustments));
   return coerced;
 }
@@ -393,7 +419,11 @@ TypeCheckBase::cast_site (HirId id, TyTy::TyWithLocation from,
   rust_debug ("cast_default_unify(a={%s}, b={%s})",
 	      casted_result->debug_str ().c_str (),
 	      to.get_ty ()->debug_str ().c_str ());
-  TyTy::BaseType *casted = to.get_ty ()->unify (casted_result);
+
+  TyTy::BaseType *casted
+    = unify_site (id, to,
+		  TyTy::TyWithLocation (casted_result, from.get_locus ()),
+		  cast_locus);
   context->insert_cast_autoderef_mappings (id, std::move (result.adjustments));
   return casted;
 }
@@ -411,6 +441,7 @@ TypeCheckBase::resolve_generic_params (
 	  // FIXME: Skipping Lifetime completely until better
 	  // handling.
 	  break;
+
 	  case HIR::GenericParam::GenericKind::CONST: {
 	    auto param
 	      = static_cast<HIR::ConstGenericParam *> (generic_param.get ());
@@ -422,7 +453,12 @@ TypeCheckBase::resolve_generic_params (
 		auto expr_type = TypeCheckExpr::Resolve (
 		  param->get_default_expression ().get ());
 
-		specified_type->unify (expr_type);
+		coercion_site (
+		  param->get_mappings ().get_hirid (),
+		  TyTy::TyWithLocation (specified_type),
+		  TyTy::TyWithLocation (
+		    expr_type, param->get_default_expression ()->get_locus ()),
+		  param->get_locus ());
 	      }
 
 	    context->insert_type (generic_param->get_mappings (),
diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h
index acdf55713d5..b8ff2cf6dc9 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-base.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-base.h
@@ -34,6 +34,10 @@ class TypeCheckBase
 public:
   virtual ~TypeCheckBase () {}
 
+  static TyTy::BaseType *unify_site (HirId id, TyTy::TyWithLocation lhs,
+				     TyTy::TyWithLocation rhs,
+				     Location unify_locus);
+
   static TyTy::BaseType *coercion_site (HirId id, TyTy::TyWithLocation lhs,
 					TyTy::TyWithLocation rhs,
 					Location coercion_locus);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc
index 0a99d444060..dd3cb12d17b 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-enumitem.cc
@@ -100,9 +100,9 @@ TypeCheckEnumItem::visit (HIR::EnumItemDiscriminant &item)
     = new TyTy::ISizeType (discriminant->get_mappings ().get_hirid ());
   context->insert_type (discriminant->get_mappings (), expected_ty);
 
-  auto unified = expected_ty->unify (capacity_type);
-  if (unified->get_kind () == TyTy::TypeKind::ERROR)
-    return;
+  unify_site (item.get_mappings ().get_hirid (),
+	      TyTy::TyWithLocation (expected_ty),
+	      TyTy::TyWithLocation (capacity_type), item.get_locus ());
 
   const CanonicalPath *canonical_path = nullptr;
   bool ok = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (),
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 8079c3c5cb5..a0eb1a596f7 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -158,17 +158,17 @@ void
 TypeCheckExpr::visit (HIR::ReturnExpr &expr)
 {
   auto fn_return_tyty = context->peek_return_type ();
-  rust_assert (fn_return_tyty != nullptr);
-
+  Location expr_locus = expr.has_return_expr () ? expr.get_expr ()->get_locus ()
+						: expr.get_locus ();
   TyTy::BaseType *expr_ty
     = expr.has_return_expr ()
 	? TypeCheckExpr::Resolve (expr.get_expr ())
 	: TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
 
-  infered = fn_return_tyty->unify (expr_ty);
-  fn_return_tyty->append_reference (expr_ty->get_ref ());
-  for (auto &ref : infered->get_combined_refs ())
-    fn_return_tyty->append_reference (ref);
+  infered = unify_site (expr.get_mappings ().get_hirid (),
+			TyTy::TyWithLocation (fn_return_tyty),
+			TyTy::TyWithLocation (expr_ty, expr_locus),
+			expr.get_locus ());
 
   infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
 }
@@ -240,9 +240,12 @@ TypeCheckExpr::visit (HIR::CompoundAssignmentExpr &expr)
 
   // we dont care about the result of the unify from a compound assignment
   // since this is a unit-type expr
-  auto result = lhs->unify (rhs);
-  if (result->get_kind () == TyTy::TypeKind::ERROR)
-    return;
+  coercion_site (expr.get_mappings ().get_hirid (),
+		 TyTy::TyWithLocation (lhs,
+				       expr.get_left_expr ()->get_locus ()),
+		 TyTy::TyWithLocation (rhs,
+				       expr.get_right_expr ()->get_locus ()),
+		 expr.get_locus ());
 
   auto lang_item_type
     = Analysis::RustLangItem::CompoundAssignmentOperatorToLangItem (
@@ -306,8 +309,13 @@ TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
       }
       break;
 
-    default:
-      infered = lhs->unify (rhs);
+      default: {
+	infered = unify_site (
+	  expr.get_mappings ().get_hirid (),
+	  TyTy::TyWithLocation (lhs, expr.get_lhs ()->get_locus ()),
+	  TyTy::TyWithLocation (rhs, expr.get_rhs ()->get_locus ()),
+	  expr.get_locus ());
+      }
       break;
     }
 }
@@ -318,9 +326,10 @@ TypeCheckExpr::visit (HIR::ComparisonExpr &expr)
   auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
   auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
 
-  auto result = lhs->unify (rhs);
-  if (result == nullptr || result->get_kind () == TyTy::TypeKind::ERROR)
-    return;
+  unify_site (expr.get_mappings ().get_hirid (),
+	      TyTy::TyWithLocation (lhs, expr.get_lhs ()->get_locus ()),
+	      TyTy::TyWithLocation (rhs, expr.get_rhs ()->get_locus ()),
+	      expr.get_locus ());
 
   bool ok = context->lookup_builtin ("bool", &infered);
   rust_assert (ok);
@@ -333,17 +342,28 @@ TypeCheckExpr::visit (HIR::LazyBooleanExpr &expr)
   auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
 
   // we expect the lhs and rhs must be bools at this point
-  TyTy::BoolType elhs (expr.get_mappings ().get_hirid ());
-  lhs = elhs.unify (lhs);
-  if (lhs->get_kind () == TyTy::TypeKind::ERROR)
-    return;
+  TyTy::BaseType *boolean_node = nullptr;
+  bool ok = context->lookup_builtin ("bool", &boolean_node);
+  rust_assert (ok);
 
-  TyTy::BoolType rlhs (expr.get_mappings ().get_hirid ());
-  rhs = elhs.unify (rhs);
-  if (lhs->get_kind () == TyTy::TypeKind::ERROR)
-    return;
+  // verify the lhs and rhs before unifying together
+  lhs = unify_site (expr.get_mappings ().get_hirid (),
+		    TyTy::TyWithLocation (boolean_node,
+					  expr.get_lhs ()->get_locus ()),
+		    TyTy::TyWithLocation (lhs, expr.get_lhs ()->get_locus ()),
+		    expr.get_locus ());
 
-  infered = lhs->unify (rhs);
+  rhs = unify_site (expr.get_mappings ().get_hirid (),
+		    TyTy::TyWithLocation (boolean_node,
+					  expr.get_rhs ()->get_locus ()),
+		    TyTy::TyWithLocation (rhs, expr.get_rhs ()->get_locus ()),
+		    expr.get_locus ());
+
+  infered
+    = unify_site (expr.get_mappings ().get_hirid (),
+		  TyTy::TyWithLocation (lhs, expr.get_lhs ()->get_locus ()),
+		  TyTy::TyWithLocation (rhs, expr.get_rhs ()->get_locus ()),
+		  expr.get_locus ());
 }
 
 void
@@ -428,7 +448,15 @@ TypeCheckExpr::visit (HIR::IfExprConseqElse &expr)
   else if (else_blk_resolved->get_kind () == TyTy::NEVER)
     infered = if_blk_resolved;
   else
-    infered = if_blk_resolved->unify (else_blk_resolved);
+    {
+      infered = unify_site (
+	expr.get_mappings ().get_hirid (),
+	TyTy::TyWithLocation (if_blk_resolved,
+			      expr.get_if_block ()->get_locus ()),
+	TyTy::TyWithLocation (else_blk_resolved,
+			      expr.get_else_block ()->get_locus ()),
+	expr.get_locus ());
+    }
 }
 
 void
@@ -443,7 +471,15 @@ TypeCheckExpr::visit (HIR::IfExprConseqIf &expr)
   else if (else_blk_resolved->get_kind () == TyTy::NEVER)
     infered = if_blk_resolved;
   else
-    infered = if_blk_resolved->unify (else_blk_resolved);
+    {
+      infered = unify_site (
+	expr.get_mappings ().get_hirid (),
+	TyTy::TyWithLocation (if_blk_resolved,
+			      expr.get_if_block ()->get_locus ()),
+	TyTy::TyWithLocation (else_blk_resolved,
+			      expr.get_conseq_if_expr ()->get_locus ()),
+	expr.get_locus ());
+    }
 }
 
 void
@@ -459,9 +495,10 @@ TypeCheckExpr::visit (HIR::IfLetExpr &expr)
       TyTy::BaseType *kase_arm_ty
 	= TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty);
 
-      TyTy::BaseType *checked_kase = scrutinee_tyty->unify (kase_arm_ty);
-      if (checked_kase->get_kind () == TyTy::TypeKind::ERROR)
-	return;
+      unify_site (expr.get_mappings ().get_hirid (),
+		  TyTy::TyWithLocation (scrutinee_tyty),
+		  TyTy::TyWithLocation (kase_arm_ty, pattern->get_locus ()),
+		  expr.get_locus ());
     }
 
   TypeCheckExpr::Resolve (expr.get_if_block ());
@@ -502,7 +539,10 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
 	{
 	  auto unit
 	    = TyTy::TupleType::get_unit_type (s->get_mappings ().get_hirid ());
-	  resolved = unit->unify (resolved);
+	  resolved
+	    = unify_site (s->get_mappings ().get_hirid (),
+			  TyTy::TyWithLocation (unit),
+			  TyTy::TyWithLocation (resolved), s->get_locus ());
 	}
     }
 
@@ -512,7 +552,10 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
     infered
       = TyTy::TupleType::get_unit_type (expr.get_mappings ().get_hirid ());
   else
-    infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
+    {
+      // FIXME this seems wrong
+      infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
+    }
 }
 
 void
@@ -552,7 +595,12 @@ TypeCheckExpr::visit (HIR::RangeFromToExpr &expr)
   TyTy::BaseType *from_ty
     = TypeCheckExpr::Resolve (expr.get_from_expr ().get ());
   TyTy::BaseType *to_ty = TypeCheckExpr::Resolve (expr.get_to_expr ().get ());
-  TyTy::BaseType *unified = from_ty->unify (to_ty);
+
+  TyTy::BaseType *unified = unify_site (
+    expr.get_mappings ().get_hirid (),
+    TyTy::TyWithLocation (from_ty, expr.get_from_expr ()->get_locus ()),
+    TyTy::TyWithLocation (to_ty, expr.get_to_expr ()->get_locus ()),
+    expr.get_locus ());
 
   // substitute it in
   std::vector<TyTy::SubstitutionArg> subst_mappings;
@@ -722,7 +770,11 @@ TypeCheckExpr::visit (HIR::RangeFromToInclExpr &expr)
   TyTy::BaseType *from_ty
     = TypeCheckExpr::Resolve (expr.get_from_expr ().get ());
   TyTy::BaseType *to_ty = TypeCheckExpr::Resolve (expr.get_to_expr ().get ());
-  TyTy::BaseType *unified = from_ty->unify (to_ty);
+  TyTy::BaseType *unified = unify_site (
+    expr.get_mappings ().get_hirid (),
+    TyTy::TyWithLocation (from_ty, expr.get_from_expr ()->get_locus ()),
+    TyTy::TyWithLocation (to_ty, expr.get_to_expr ()->get_locus ()),
+    expr.get_locus ());
 
   // substitute it in
   std::vector<TyTy::SubstitutionArg> subst_mappings;
@@ -763,9 +815,11 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
   if (maybe_simple_array_access
       && direct_array_expr_ty->get_kind () == TyTy::TypeKind::ARRAY)
     {
-      auto resolved_index_expr = size_ty->unify (index_expr_ty);
-      if (resolved_index_expr->get_kind () == TyTy::TypeKind::ERROR)
-	return;
+      unify_site (expr.get_index_expr ()->get_mappings ().get_hirid (),
+		  TyTy::TyWithLocation (size_ty),
+		  TyTy::TyWithLocation (index_expr_ty,
+					expr.get_index_expr ()->get_locus ()),
+		  expr.get_locus ());
 
       TyTy::ArrayType *array_type
 	= static_cast<TyTy::ArrayType *> (direct_array_expr_ty);
@@ -821,9 +875,11 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
 	context->insert_type (elems.get_num_copies_expr ()->get_mappings (),
 			      expected_ty);
 
-	auto unified = expected_ty->unify (capacity_type);
-	if (unified->get_kind () == TyTy::TypeKind::ERROR)
-	  return;
+	unify_site (
+	  expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty),
+	  TyTy::TyWithLocation (capacity_type,
+				elems.get_num_copies_expr ()->get_locus ()),
+	  expr.get_locus ());
 
 	capacity_expr = elems.get_num_copies_expr ();
       }
@@ -839,11 +895,16 @@ TypeCheckExpr::visit (HIR::ArrayExpr &expr)
 	    types.push_back (TypeCheckExpr::Resolve (elem.get ()));
 	  }
 
+	// this is a LUB
 	element_type
 	  = TyTy::TyVar::get_implicit_infer_var (expr.get_locus ()).get_tyty ();
 	for (auto &type : types)
 	  {
-	    element_type = element_type->unify (type);
+	    element_type
+	      = unify_site (expr.get_mappings ().get_hirid (),
+			    TyTy::TyWithLocation (element_type),
+			    TyTy::TyWithLocation (type, type->get_locus ()),
+			    expr.get_locus ());
 	  }
 
 	auto crate_num = mappings->get_current_crate ();
@@ -1165,7 +1226,12 @@ TypeCheckExpr::visit (HIR::BreakExpr &expr)
 	  return;
 	}
 
-      TyTy::BaseType *unified_ty = loop_context->unify (break_expr_tyty);
+      TyTy::BaseType *unified_ty
+	= unify_site (expr.get_mappings ().get_hirid (),
+		      TyTy::TyWithLocation (loop_context),
+		      TyTy::TyWithLocation (break_expr_tyty,
+					    expr.get_expr ()->get_locus ()),
+		      expr.get_locus ());
       context->swap_head_loop_context (unified_ty);
     }
 
@@ -1290,7 +1356,12 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr)
 	  TyTy::BaseType *kase_arm_ty
 	    = TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty);
 
-	  TyTy::BaseType *checked_kase = scrutinee_tyty->unify (kase_arm_ty);
+	  TyTy::BaseType *checked_kase = unify_site (
+	    expr.get_mappings ().get_hirid (),
+	    TyTy::TyWithLocation (scrutinee_tyty,
+				  expr.get_scrutinee_expr ()->get_locus ()),
+	    TyTy::TyWithLocation (kase_arm_ty, pattern->get_locus ()),
+	    expr.get_locus ());
 	  if (checked_kase->get_kind () == TyTy::TypeKind::ERROR)
 	    return;
 	}
@@ -1308,13 +1379,14 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr)
       return;
     }
 
+  // this is a LUB
   infered = kase_block_tys.at (0);
   for (size_t i = 1; i < kase_block_tys.size (); i++)
     {
       TyTy::BaseType *kase_ty = kase_block_tys.at (i);
-      infered = infered->unify (kase_ty);
-      if (infered->get_kind () == TyTy::TypeKind::ERROR)
-	return;
+      infered = unify_site (expr.get_mappings ().get_hirid (),
+			    TyTy::TyWithLocation (infered),
+			    TyTy::TyWithLocation (kase_ty), expr.get_locus ());
     }
 }
 
@@ -1470,7 +1542,11 @@ TypeCheckExpr::resolve_operator_overload (
   TyTy::FnType *type = static_cast<TyTy::FnType *> (lookup);
   rust_assert (type->num_params () > 0);
   auto fnparam = type->param_at (0);
-  fnparam.second->unify (adjusted_self); // typecheck the self
+
+  // typecheck the self
+  unify_site (expr.get_mappings ().get_hirid (),
+	      TyTy::TyWithLocation (fnparam.second),
+	      TyTy::TyWithLocation (adjusted_self), expr.get_locus ());
   if (rhs == nullptr)
     {
       rust_assert (type->num_params () == 1);
@@ -1479,7 +1555,9 @@ TypeCheckExpr::resolve_operator_overload (
     {
       rust_assert (type->num_params () == 2);
       auto fnparam = type->param_at (1);
-      fnparam.second->unify (rhs); // typecheck the rhs
+      unify_site (expr.get_mappings ().get_hirid (),
+		  TyTy::TyWithLocation (fnparam.second),
+		  TyTy::TyWithLocation (rhs), expr.get_locus ());
     }
 
   rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
index 1b99552e94b..f1f56d28ae2 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.cc
@@ -179,7 +179,12 @@ TypeCheckTopLevelImplItem::visit (HIR::ConstantItem &constant)
   TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
   TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
 
-  context->insert_type (constant.get_mappings (), type->unify (expr_type));
+  TyTy::BaseType *unified = unify_site (
+    constant.get_mappings ().get_hirid (),
+    TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()),
+    TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()),
+    constant.get_locus ());
+  context->insert_type (constant.get_mappings (), unified);
 }
 
 void
@@ -365,8 +370,16 @@ TypeCheckImplItem::visit (HIR::Function &function)
   auto block_expr_ty
     = TypeCheckExpr::Resolve (function.get_definition ().get ());
 
+  Location fn_return_locus = function.has_function_return_type ()
+			       ? function.get_return_type ()->get_locus ()
+			       : function.get_locus ();
+
+  coercion_site (function.get_definition ()->get_mappings ().get_hirid (),
+		 TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
+		 TyTy::TyWithLocation (block_expr_ty),
+		 function.get_definition ()->get_locus ());
+
   context->pop_return_type ();
-  expected_ret_tyty->unify (block_expr_ty);
 }
 
 void
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index 97a894b1b29..0aa26072efc 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc
@@ -214,10 +214,15 @@ TypeCheckItem::visit (HIR::Function &function)
   auto block_expr_ty
     = TypeCheckExpr::Resolve (function.get_definition ().get ());
 
-  context->pop_return_type ();
+  Location fn_return_locus = function.has_function_return_type ()
+			       ? function.get_return_type ()->get_locus ()
+			       : function.get_locus ();
+  coercion_site (function.get_definition ()->get_mappings ().get_hirid (),
+		 TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
+		 TyTy::TyWithLocation (block_expr_ty),
+		 function.get_definition ()->get_locus ());
 
-  if (block_expr_ty->get_kind () != TyTy::NEVER)
-    expected_ret_tyty->unify (block_expr_ty);
+  context->pop_return_type ();
 }
 
 void
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 765f8b21aa5..bf1de21ee4f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -390,7 +390,10 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
 	    impl_block_ty
 	      = SubstMapper::InferSubst (impl_block_ty, seg.get_locus ());
 
-	  prev_segment = prev_segment->unify (impl_block_ty);
+	  prev_segment = unify_site (seg.get_mappings ().get_hirid (),
+				     TyTy::TyWithLocation (prev_segment),
+				     TyTy::TyWithLocation (impl_block_ty),
+				     seg.get_locus ());
 	}
 
       if (tyseg->needs_generic_substitutions ())
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index 118cee811ce..82af7294d69 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -375,7 +375,9 @@ TypeCheckPattern::visit (HIR::RangePattern &pattern)
       break;
     }
 
-  infered = upper->unify (lower);
+  infered = unify_site (pattern.get_pattern_mappings ().get_hirid (),
+			TyTy::TyWithLocation (upper),
+			TyTy::TyWithLocation (lower), pattern.get_locus ());
 }
 
 void
diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
index 2b4925383e5..e82dd8e5300 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.cc
@@ -68,7 +68,11 @@ TypeCheckStmt::visit (HIR::ConstantItem &constant)
   TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
   TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
 
-  infered = type->unify (expr_type);
+  infered = unify_site (
+    constant.get_mappings ().get_hirid (),
+    TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()),
+    TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()),
+    constant.get_locus ());
   context->insert_type (constant.get_mappings (), infered);
 }
 
@@ -498,8 +502,13 @@ TypeCheckStmt::visit (HIR::Function &function)
 
   context->pop_return_type ();
 
-  if (block_expr_ty->get_kind () != TyTy::NEVER)
-    expected_ret_tyty->unify (block_expr_ty);
+  Location fn_return_locus = function.has_function_return_type ()
+			       ? function.get_return_type ()->get_locus ()
+			       : function.get_locus ();
+  coercion_site (function.get_definition ()->get_mappings ().get_hirid (),
+		 TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
+		 TyTy::TyWithLocation (block_expr_ty),
+		 function.get_definition ()->get_locus ());
 
   infered = fnType;
 }
diff --git a/gcc/rust/typecheck/rust-hir-type-check-struct.cc b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
index 38fd5e28c0d..259d4ca182e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-struct.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-struct.cc
@@ -57,14 +57,20 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
     {
       TyTy::BaseType *base_resolved
 	= TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ());
-      struct_def = static_cast<TyTy::ADTType *> (
-	struct_path_resolved->unify (base_resolved));
-      if (struct_def == nullptr)
+      TyTy::BaseType *base_unify = unify_site (
+	struct_expr.struct_base->base_struct->get_mappings ().get_hirid (),
+	TyTy::TyWithLocation (struct_path_resolved),
+	TyTy::TyWithLocation (base_resolved),
+	struct_expr.struct_base->base_struct->get_locus ());
+
+      if (base_unify->get_kind () != struct_path_ty->get_kind ())
 	{
 	  rust_fatal_error (struct_expr.struct_base->base_struct->get_locus (),
 			    "incompatible types for base struct reference");
 	  return;
 	}
+
+      struct_def = static_cast<TyTy::ADTType *> (base_unify);
     }
 
   // figure out the variant
diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc b/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc
index dd9abdd7d0d..b0ee292df10 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.cc
@@ -260,7 +260,13 @@ TypeCheckTopLevel::visit (HIR::StaticItem &var)
   TyTy::BaseType *type = TypeCheckType::Resolve (var.get_type ());
   TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (var.get_expr ());
 
-  context->insert_type (var.get_mappings (), type->unify (expr_type));
+  TyTy::BaseType *unified
+    = unify_site (var.get_mappings ().get_hirid (),
+		  TyTy::TyWithLocation (type, var.get_type ()->get_locus ()),
+		  TyTy::TyWithLocation (expr_type,
+					var.get_expr ()->get_locus ()),
+		  var.get_locus ());
+  context->insert_type (var.get_mappings (), unified);
 }
 
 void
@@ -269,7 +275,12 @@ TypeCheckTopLevel::visit (HIR::ConstantItem &constant)
   TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
   TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
 
-  context->insert_type (constant.get_mappings (), type->unify (expr_type));
+  TyTy::BaseType *unified = unify_site (
+    constant.get_mappings ().get_hirid (),
+    TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()),
+    TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()),
+    constant.get_locus ());
+  context->insert_type (constant.get_mappings (), unified);
 }
 
 void
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index 46e465ca2d4..06dc8e042d9 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -623,9 +623,11 @@ TypeCheckType::visit (HIR::ArrayType &type)
   rust_assert (ok);
   context->insert_type (type.get_size_expr ()->get_mappings (), expected_ty);
 
-  auto unified = expected_ty->unify (capacity_type);
-  if (unified->get_kind () == TyTy::TypeKind::ERROR)
-    return;
+  unify_site (type.get_size_expr ()->get_mappings ().get_hirid (),
+	      TyTy::TyWithLocation (expected_ty),
+	      TyTy::TyWithLocation (capacity_type,
+				    type.get_size_expr ()->get_locus ()),
+	      type.get_size_expr ()->get_locus ());
 
   TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ());
   translated = new TyTy::ArrayType (type.get_mappings ().get_hirid (),
diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc
index fb71cfb8e02..f2445cd3ba2 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check.cc
@@ -70,7 +70,12 @@ TypeResolution::Resolve (HIR::Crate &crate)
       }
     else
       {
-	auto result = ty->unify (default_type);
+	auto result
+	  = TypeCheckBase::unify_site (id, TyTy::TyWithLocation (ty),
+				       TyTy::TyWithLocation (default_type),
+				       Location ());
+	rust_assert (result);
+	rust_assert (result->get_kind () != TyTy::TypeKind::ERROR);
 	result->set_ref (id);
 	context->insert_type (
 	  Analysis::NodeMapping (mappings->get_current_crate (), 0, id,
@@ -144,7 +149,10 @@ TraitItemReference::get_type_from_constant (
       TyTy::BaseType *expr
 	= TypeCheckExpr::Resolve (constant.get_expr ().get ());
 
-      return type->unify (expr);
+      return TypeCheckBase::unify_site (constant.get_mappings ().get_hirid (),
+					TyTy::TyWithLocation (type),
+					TyTy::TyWithLocation (expr),
+					constant.get_locus ());
     }
   return type;
 }
diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc
index af86b064c6c..a0b5c5e849e 100644
--- a/gcc/rust/typecheck/rust-tyctx.cc
+++ b/gcc/rust/typecheck/rust-tyctx.cc
@@ -129,6 +129,7 @@ TypeCheckContext::lookup_type_by_node_id (NodeId ref, HirId *id)
 TyTy::BaseType *
 TypeCheckContext::peek_return_type ()
 {
+  rust_assert (!return_type_stack.empty ());
   return return_type_stack.back ().second;
 }
 
diff --git a/gcc/rust/typecheck/rust-tyty-call.cc b/gcc/rust/typecheck/rust-tyty-call.cc
index 70bc3d3c2a0..96c6b93e5c2 100644
--- a/gcc/rust/typecheck/rust-tyty-call.cc
+++ b/gcc/rust/typecheck/rust-tyty-call.cc
@@ -219,7 +219,10 @@ TypeCheckCallExpr::visit (FnPtr &type)
 void
 TypeCheckMethodCallExpr::visit (FnType &type)
 {
-  type.get_self_type ()->unify (adjusted_self);
+  Resolver::TypeCheckBase::unify_site (
+    call.get_mappings ().get_hirid (), TyWithLocation (type.get_self_type ()),
+    TyWithLocation (adjusted_self, call.get_receiver ()->get_locus ()),
+    call.get_locus ());
 
   // +1 for the receiver self
   size_t num_args_to_call = call.num_params () + 1;
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index 485546e2c05..2813bf42c1c 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -1243,8 +1243,8 @@ public:
     auto base_type = base->get_base ();
     auto other_base_type = type.get_base ();
 
-    bool mutability_match = base->is_mutable () == type.is_mutable ();
-    if (!mutability_match)
+    bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
+    if (!mutability_ok)
       {
 	BaseCmp::visit (type);
 	return;
diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h
index 8cf96409d14..7ffffc1dd59 100644
--- a/gcc/rust/typecheck/rust-tyty-rules.h
+++ b/gcc/rust/typecheck/rust-tyty-rules.h
@@ -123,269 +123,53 @@ public:
     return resolved;
   }
 
-  virtual void visit (TupleType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (TupleType &type) override {}
 
-  virtual void visit (ADTType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (ADTType &type) override {}
 
-  virtual void visit (InferType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (InferType &type) override {}
 
-  virtual void visit (FnType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (FnType &type) override {}
 
-  virtual void visit (FnPtr &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (FnPtr &type) override {}
 
-  virtual void visit (ArrayType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (ArrayType &type) override {}
 
-  virtual void visit (SliceType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (SliceType &type) override {}
 
-  virtual void visit (BoolType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (BoolType &type) override {}
 
-  virtual void visit (IntType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (IntType &type) override {}
 
-  virtual void visit (UintType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (UintType &type) override {}
 
-  virtual void visit (USizeType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (USizeType &type) override {}
 
-  virtual void visit (ISizeType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (ISizeType &type) override {}
 
-  virtual void visit (FloatType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (FloatType &type) override {}
 
-  virtual void visit (ErrorType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (ErrorType &type) override {}
 
-  virtual void visit (CharType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (CharType &type) override {}
 
-  virtual void visit (ReferenceType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (ReferenceType &type) override {}
 
-  virtual void visit (PointerType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (PointerType &type) override {}
 
-  virtual void visit (ParamType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (ParamType &type) override {}
 
-  virtual void visit (StrType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (StrType &type) override {}
 
-  virtual void visit (NeverType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (NeverType &type) override {}
 
-  virtual void visit (PlaceholderType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (PlaceholderType &type) override {}
 
-  virtual void visit (ProjectionType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (ProjectionType &type) override {}
 
-  virtual void visit (DynamicObjectType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (DynamicObjectType &type) override {}
 
-  virtual void visit (ClosureType &type) override
-  {
-    Location ref_locus = mappings->lookup_location (type.get_ref ());
-    Location base_locus = mappings->lookup_location (get_base ()->get_ref ());
-    RichLocation r (ref_locus);
-    r.add_range (base_locus);
-    rust_error_at (r, "expected [%s] got [%s]",
-		   get_base ()->as_string ().c_str (),
-		   type.as_string ().c_str ());
-  }
+  virtual void visit (ClosureType &type) override {}
 
 protected:
   BaseRules (BaseType *base)
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 42c021e3aa1..3e29bd2a92c 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -296,6 +296,33 @@ BaseType::destructure () const
   return x;
 }
 
+std::string
+BaseType::mappings_str () const
+{
+  std::string buffer = "Ref: " + std::to_string (get_ref ())
+		       + " TyRef: " + std::to_string (get_ty_ref ());
+  buffer += "[";
+  for (auto &ref : combined)
+    buffer += std::to_string (ref) + ",";
+  buffer += "]";
+  return "(" + buffer + ")";
+}
+
+std::string
+BaseType::debug_str () const
+{
+  // return TypeKindFormat::to_string (get_kind ()) + ":" + as_string () + ":"
+  //        + mappings_str () + ":" + bounds_as_string ();
+  return get_name ();
+}
+
+void
+BaseType::debug () const
+{
+  rust_debug ("[%p] %s", static_cast<const void *> (this),
+	      debug_str ().c_str ());
+}
+
 TyVar::TyVar (HirId ref) : ref (ref)
 {
   // ensure this reference is defined within the context
@@ -1159,11 +1186,29 @@ TupleType::accept_vis (TyConstVisitor &vis) const
 std::string
 TupleType::as_string () const
 {
+  size_t i = 0;
+  std::string fields_buffer;
+  for (const TyVar &field : get_fields ())
+    {
+      fields_buffer += field.get_tyty ()->as_string ();
+      bool has_next = (i + 1) < get_fields ().size ();
+      fields_buffer += has_next ? ", " : "";
+      i++;
+    }
+  return "(" + fields_buffer + ")";
+}
+
+std::string
+TupleType::get_name () const
+{
+  size_t i = 0;
   std::string fields_buffer;
   for (const TyVar &field : get_fields ())
     {
       fields_buffer += field.get_tyty ()->as_string ();
-      fields_buffer += ", ";
+      bool has_next = (i + 1) < get_fields ().size ();
+      fields_buffer += has_next ? ", " : "";
+      i++;
     }
   return "(" + fields_buffer + ")";
 }
@@ -2194,6 +2239,13 @@ ReferenceType::as_string () const
 	 + get_base ()->as_string ();
 }
 
+std::string
+ReferenceType::get_name () const
+{
+  return std::string ("&") + (is_mutable () ? "mut" : "") + " "
+	 + get_base ()->get_name ();
+}
+
 BaseType *
 ReferenceType::unify (BaseType *other)
 {
@@ -2277,6 +2329,13 @@ PointerType::as_string () const
 	 + get_base ()->as_string ();
 }
 
+std::string
+PointerType::get_name () const
+{
+  return std::string ("* ") + (is_mutable () ? "mut" : "const") + " "
+	 + get_base ()->get_name ();
+}
+
 BaseType *
 PointerType::unify (BaseType *other)
 {
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 9252d2affc9..14868f2bb81 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -230,28 +230,11 @@ public:
 
   bool contains_type_parameters () const { return !is_concrete (); }
 
-  std::string mappings_str () const
-  {
-    std::string buffer = "Ref: " + std::to_string (get_ref ())
-			 + " TyRef: " + std::to_string (get_ty_ref ());
-    buffer += "[";
-    for (auto &ref : combined)
-      buffer += std::to_string (ref) + ",";
-    buffer += "]";
-    return "(" + buffer + ")";
-  }
+  std::string mappings_str () const;
 
-  std::string debug_str () const
-  {
-    return TypeKindFormat::to_string (get_kind ()) + ":" + as_string () + ":"
-	   + mappings_str () + ":" + bounds_as_string ();
-  }
+  std::string debug_str () const;
 
-  void debug () const
-  {
-    rust_debug ("[%p] %s", static_cast<const void *> (this),
-		debug_str ().c_str ());
-  }
+  void debug () const;
 
   // FIXME this will eventually go away
   const BaseType *get_root () const;
@@ -560,7 +543,7 @@ public:
 
   const std::vector<TyVar> &get_fields () const { return fields; }
 
-  std::string get_name () const override final { return as_string (); }
+  std::string get_name () const override final;
 
   TupleType *handle_substitions (SubstitutionArgumentMappings mappings);
 
@@ -2164,10 +2147,7 @@ public:
 
   std::string as_string () const override;
 
-  std::string get_name () const override final
-  {
-    return "&" + get_base ()->get_name ();
-  }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
@@ -2249,11 +2229,7 @@ public:
   void accept_vis (TyConstVisitor &vis) const override;
 
   std::string as_string () const override;
-
-  std::string get_name () const override final
-  {
-    return "*" + get_base ()->get_name ();
-  }
+  std::string get_name () const override final;
 
   BaseType *unify (BaseType *other) override;
   bool can_eq (const BaseType *other, bool emit_errors) const override final;
diff --git a/gcc/testsuite/rust/compile/issue-1152.rs b/gcc/testsuite/rust/compile/issue-1152.rs
index 18eee9e6b4a..15697057ec6 100644
--- a/gcc/testsuite/rust/compile/issue-1152.rs
+++ b/gcc/testsuite/rust/compile/issue-1152.rs
@@ -1,8 +1,6 @@
 fn test() {
     let f = [0; -4_isize];
     // { dg-error "expected .usize. got .isize." "" { target *-*-* } .-1 }
-    // { dg-error "failed to type resolve expression" "" { target *-*-* } .-2 }
     let f = [0_usize; -1_isize];
     // { dg-error "expected .usize. got .isize." "" { target *-*-* } .-1 }
-    // { dg-error "failed to type resolve expression" "" { target *-*-* } .-2 }
 }
diff --git a/gcc/testsuite/rust/compile/tuple1.rs b/gcc/testsuite/rust/compile/tuple1.rs
index 84179b13727..0e381dc6ca4 100644
--- a/gcc/testsuite/rust/compile/tuple1.rs
+++ b/gcc/testsuite/rust/compile/tuple1.rs
@@ -1,5 +1,5 @@
 fn main() {
-    let a: (i32, bool) = (123, 123); // { dg-error "expected .bool. got .<integer>." }
+    let a: (i32, bool) = (123, 123); // { dg-error "expected" }
     let b;
     b = (456, 5f32);
 }
diff --git a/gcc/testsuite/rust/compile/type-alias1.rs b/gcc/testsuite/rust/compile/type-alias1.rs
index c7d7048246a..7d038cac469 100644
--- a/gcc/testsuite/rust/compile/type-alias1.rs
+++ b/gcc/testsuite/rust/compile/type-alias1.rs
@@ -2,5 +2,5 @@ type TypeAlias = (i32, u32);
 
 fn main() {
     let a: TypeAlias;
-    a = (123, 456f32); // { dg-error "expected .u32. got .f32." }
+    a = (123, 456f32); // { dg-error "expected" }
 }
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_9.rs b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
index fd972e28ab3..fbb96a60d36 100644
--- a/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
+++ b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
@@ -1,4 +1,4 @@
-/* { dg-output "mut_deref\n123\n" } */
+/* { dg-output "imm_deref\n123\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
diff --git a/gcc/testsuite/rust/execute/torture/slice1.rs b/gcc/testsuite/rust/execute/torture/slice1.rs
index a0488b3912c..206082af624 100644
--- a/gcc/testsuite/rust/execute/torture/slice1.rs
+++ b/gcc/testsuite/rust/execute/torture/slice1.rs
@@ -12,9 +12,10 @@ union Repr<T> {
 
 const fn slice_from_raw_parts<T>(data: *const T, len: usize) -> *const [T] {
     unsafe {
-        let a = FatPtr { data, len };
-        let b = Repr { raw: a };
-        b.rust
+        Repr {
+            raw: FatPtr { data, len },
+        }
+        .rust
     }
 }
 
-- 
2.39.1


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

only message in thread, other threads:[~2023-01-31 13:21 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-31 13:25 [COMMITTED] gccrs: Refactor unify to hit a unify_site Arthur Cohen

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).