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

The unify code was a bit dumb here where we always set emit_error to false for 
any
subtypes for example in comparing tuples we always emitted the whole tuple didnt
match the other tuple but really its much better to say expected bool got i32 
because
the element types didn't match.

gcc/rust/ChangeLog:

        * typecheck/rust-coercion.cc (TypeCoercionRules::coerce_unsized): dont 
emit error here
        * typecheck/rust-unify.cc (UnifyRules::resolve_subtype): new helper to 
handle emit error
        (UnifyRules::expect_adt): call resolve_subtype
        (UnifyRules::expect_reference): likewise
        (UnifyRules::expect_pointer): likewise
        (UnifyRules::expect_array): likewise
        (UnifyRules::expect_slice): likewise
        (UnifyRules::expect_fndef): likewise
        (UnifyRules::expect_fnptr): likewise
        (UnifyRules::expect_tuple): likewise
        (UnifyRules::expect_closure): likewise
        (UnifyRules::expect_opaque): likeiwse
        * typecheck/rust-unify.h: add new helper to header

gcc/testsuite/ChangeLog:

        * rust/compile/traits9.rs: update errors
        * rust/compile/unify-errors1.rs: New test.

Signed-off-by: Philip Herron <herron.phi...@googlemail.com>
---
 gcc/rust/typecheck/rust-coercion.cc         |   2 +-
 gcc/rust/typecheck/rust-unify.cc            | 128 +++++++++-----------
 gcc/rust/typecheck/rust-unify.h             |   3 +
 gcc/testsuite/rust/compile/traits9.rs       |   3 +-
 gcc/testsuite/rust/compile/unify-errors1.rs |  49 ++++++++
 5 files changed, 110 insertions(+), 75 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/unify-errors1.rs

diff --git a/gcc/rust/typecheck/rust-coercion.cc 
b/gcc/rust/typecheck/rust-coercion.cc
index 3a92a2f2f6e..50c74ed689d 100644
--- a/gcc/rust/typecheck/rust-coercion.cc
+++ b/gcc/rust/typecheck/rust-coercion.cc
@@ -401,7 +401,7 @@ TypeCoercionRules::coerce_unsized (TyTy::BaseType *source,
 
   if (expect_dyn && need_unsize)
     {
-      bool bounds_compatible = b->bounds_compatible (*a, locus, true);
+      bool bounds_compatible = b->bounds_compatible (*a, locus, false);
       if (!bounds_compatible)
        {
          unsafe_error = true;
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 95463ae9473..9144f2eafba 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -52,6 +52,22 @@ UnifyRules::Resolve (TyTy::TyWithLocation lhs, 
TyTy::TyWithLocation rhs,
   return result;
 }
 
+TyTy::BaseType *
+UnifyRules::resolve_subtype (TyTy::TyWithLocation lhs, TyTy::TyWithLocation 
rhs)
+{
+  TyTy::BaseType *result
+    = UnifyRules::Resolve (lhs, rhs, locus, commit_flag, emit_error, 
infer_flag,
+                          commits, infers);
+
+  // If the recursive call resulted in an error and would have emitted an error
+  // message, disable error emission for the current level to avoid duplicate
+  // errors
+  if (result->get_kind () == TyTy::TypeKind::ERROR && emit_error)
+    emit_error = false;
+
+  return result;
+}
+
 TyTy::BaseType *
 UnifyRules::get_base ()
 {
@@ -471,11 +487,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, 
TyTy::BaseType *rtype)
                TyTy::BaseType *other_field_ty = other_field->get_field_type ();
 
                TyTy::BaseType *unified_ty
-                 = UnifyRules::Resolve (TyTy::TyWithLocation (this_field_ty),
-                                        TyTy::TyWithLocation (other_field_ty),
-                                        locus, commit_flag,
-                                        false /* emit_error */, infer_flag,
-                                        commits, infers);
+                 = resolve_subtype (TyTy::TyWithLocation (this_field_ty),
+                                    TyTy::TyWithLocation (other_field_ty));
                if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
                  {
                    return new TyTy::ErrorType (0);
@@ -497,11 +510,8 @@ UnifyRules::expect_adt (TyTy::ADTType *ltype, 
TyTy::BaseType *rtype)
                auto pa = a.get_param_ty ();
                auto pb = b.get_param_ty ();
 
-               auto res
-                 = UnifyRules::Resolve (TyTy::TyWithLocation (pa),
-                                        TyTy::TyWithLocation (pb), locus,
-                                        commit_flag, false /* emit_error */,
-                                        infer_flag, commits, infers);
+               auto res = resolve_subtype (TyTy::TyWithLocation (pa),
+                                           TyTy::TyWithLocation (pb));
                if (res->get_kind () == TyTy::TypeKind::ERROR)
                  {
                    return new TyTy::ErrorType (0);
@@ -609,10 +619,8 @@ UnifyRules::expect_reference (TyTy::ReferenceType *ltype, 
TyTy::BaseType *rtype)
        auto other_base_type = type.get_base ();
 
        TyTy::BaseType *base_resolved
-         = UnifyRules::Resolve (TyTy::TyWithLocation (base_type),
-                                TyTy::TyWithLocation (other_base_type), locus,
-                                commit_flag, false /* emit_error */,
-                                infer_flag, commits, infers);
+         = resolve_subtype (TyTy::TyWithLocation (base_type),
+                            TyTy::TyWithLocation (other_base_type));
        if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
          {
            return new TyTy::ErrorType (0);
@@ -682,10 +690,8 @@ UnifyRules::expect_pointer (TyTy::PointerType *ltype, 
TyTy::BaseType *rtype)
        auto other_base_type = type.get_base ();
 
        TyTy::BaseType *base_resolved
-         = UnifyRules::Resolve (TyTy::TyWithLocation (base_type),
-                                TyTy::TyWithLocation (other_base_type), locus,
-                                commit_flag, false /* emit_error */,
-                                infer_flag, commits, infers);
+         = resolve_subtype (TyTy::TyWithLocation (base_type),
+                            TyTy::TyWithLocation (other_base_type));
        if (base_resolved->get_kind () == TyTy::TypeKind::ERROR)
          {
            return new TyTy::ErrorType (0);
@@ -815,10 +821,9 @@ UnifyRules::expect_array (TyTy::ArrayType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::ARRAY:
       {
        TyTy::ArrayType &type = *static_cast<TyTy::ArrayType *> (rtype);
-       TyTy::BaseType *element_unify = UnifyRules::Resolve (
-         TyTy::TyWithLocation (ltype->get_element_type ()),
-         TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag,
-         false /* emit_error*/, infer_flag, commits, infers);
+       TyTy::BaseType *element_unify
+         = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()),
+                            TyTy::TyWithLocation (type.get_element_type ()));
 
        if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
          {
@@ -877,10 +882,9 @@ UnifyRules::expect_slice (TyTy::SliceType *ltype, 
TyTy::BaseType *rtype)
     case TyTy::SLICE:
       {
        TyTy::SliceType &type = *static_cast<TyTy::SliceType *> (rtype);
-       TyTy::BaseType *element_unify = UnifyRules::Resolve (
-         TyTy::TyWithLocation (ltype->get_element_type ()),
-         TyTy::TyWithLocation (type.get_element_type ()), locus, commit_flag,
-         false /* emit_error*/, infer_flag, commits, infers);
+       TyTy::BaseType *element_unify
+         = resolve_subtype (TyTy::TyWithLocation (ltype->get_element_type ()),
+                            TyTy::TyWithLocation (type.get_element_type ()));
 
        if (element_unify->get_kind () != TyTy::TypeKind::ERROR)
          {
@@ -948,21 +952,17 @@ UnifyRules::expect_fndef (TyTy::FnType *ltype, 
TyTy::BaseType *rtype)
            auto a = ltype->param_at (i).get_type ();
            auto b = type.param_at (i).get_type ();
 
-           auto unified_param
-             = UnifyRules::Resolve (TyTy::TyWithLocation (a),
-                                    TyTy::TyWithLocation (b), locus,
-                                    commit_flag, false /* emit_errors */,
-                                    infer_flag, commits, infers);
+           auto unified_param = resolve_subtype (TyTy::TyWithLocation (a),
+                                                 TyTy::TyWithLocation (b));
            if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
              {
                return new TyTy::ErrorType (0);
              }
          }
 
-       auto unified_return = UnifyRules::Resolve (
-         TyTy::TyWithLocation (ltype->get_return_type ()),
-         TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag,
-         false /* emit_errors */, infer_flag, commits, infers);
+       auto unified_return
+         = resolve_subtype (TyTy::TyWithLocation (ltype->get_return_type ()),
+                            TyTy::TyWithLocation (type.get_return_type ()));
        if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
          {
            return new TyTy::ErrorType (0);
@@ -1041,21 +1041,17 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, 
TyTy::BaseType *rtype)
            auto a = ltype->get_param_type_at (i);
            auto b = type.get_param_type_at (i);
 
-           auto unified_param
-             = UnifyRules::Resolve (TyTy::TyWithLocation (a),
-                                    TyTy::TyWithLocation (b), locus,
-                                    commit_flag, false /* emit_errors */,
-                                    infer_flag, commits, infers);
+           auto unified_param = resolve_subtype (TyTy::TyWithLocation (a),
+                                                 TyTy::TyWithLocation (b));
            if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
              {
                return new TyTy::ErrorType (0);
              }
          }
 
-       auto unified_return = UnifyRules::Resolve (
-         TyTy::TyWithLocation (ltype->get_return_type ()),
-         TyTy::TyWithLocation (type.get_return_type ()), locus, commit_flag,
-         false /* emit_errors */, infer_flag, commits, infers);
+       auto unified_return
+         = resolve_subtype (TyTy::TyWithLocation (ltype->get_return_type ()),
+                            TyTy::TyWithLocation (type.get_return_type ()));
        if (unified_return->get_kind () == TyTy::TypeKind::ERROR)
          {
            return new TyTy::ErrorType (0);
@@ -1072,10 +1068,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, 
TyTy::BaseType *rtype)
        auto other_ret_type = type.get_return_type ();
 
        auto unified_result
-         = UnifyRules::Resolve (TyTy::TyWithLocation (this_ret_type),
-                                TyTy::TyWithLocation (other_ret_type), locus,
-                                commit_flag, false /*emit_errors*/, infer_flag,
-                                commits, infers);
+         = resolve_subtype (TyTy::TyWithLocation (this_ret_type),
+                            TyTy::TyWithLocation (other_ret_type));
        if (unified_result->get_kind () == TyTy::TypeKind::ERROR)
          {
            return new TyTy::ErrorType (0);
@@ -1092,10 +1086,8 @@ UnifyRules::expect_fnptr (TyTy::FnPtr *ltype, 
TyTy::BaseType *rtype)
            auto other_param = type.param_at (i).get_type ();
 
            auto unified_param
-             = UnifyRules::Resolve (TyTy::TyWithLocation (this_param),
-                                    TyTy::TyWithLocation (other_param), locus,
-                                    commit_flag, false /* emit_errors */,
-                                    infer_flag, commits, infers);
+             = resolve_subtype (TyTy::TyWithLocation (this_param),
+                                TyTy::TyWithLocation (other_param));
            if (unified_param->get_kind () == TyTy::TypeKind::ERROR)
              {
                return new TyTy::ErrorType (0);
@@ -1163,10 +1155,8 @@ UnifyRules::expect_tuple (TyTy::TupleType *ltype, 
TyTy::BaseType *rtype)
            TyTy::BaseType *fo = type.get_field (i);
 
            TyTy::BaseType *unified_ty
-             = UnifyRules::Resolve (TyTy::TyWithLocation (bo),
-                                    TyTy::TyWithLocation (fo), locus,
-                                    commit_flag, false /* emit_errors */,
-                                    infer_flag, commits, infers);
+             = resolve_subtype (TyTy::TyWithLocation (bo),
+                                TyTy::TyWithLocation (fo));
            if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
              return new TyTy::ErrorType (0);
 
@@ -1778,19 +1768,17 @@ UnifyRules::expect_closure (TyTy::ClosureType *ltype, 
TyTy::BaseType *rtype)
            return new TyTy::ErrorType (0);
          }
 
-       TyTy::BaseType *args_res = UnifyRules::Resolve (
-         TyTy::TyWithLocation (&ltype->get_parameters ()),
-         TyTy::TyWithLocation (&type.get_parameters ()), locus, commit_flag,
-         false /* emit_error */, infer_flag, commits, infers);
+       TyTy::BaseType *args_res
+         = resolve_subtype (TyTy::TyWithLocation (&ltype->get_parameters ()),
+                            TyTy::TyWithLocation (&type.get_parameters ()));
        if (args_res->get_kind () == TyTy::TypeKind::ERROR)
          {
            return new TyTy::ErrorType (0);
          }
 
-       TyTy::BaseType *res = UnifyRules::Resolve (
-         TyTy::TyWithLocation (&ltype->get_result_type ()),
-         TyTy::TyWithLocation (&type.get_result_type ()), locus, commit_flag,
-         false /* emit_error */, infer_flag, commits, infers);
+       TyTy::BaseType *res
+         = resolve_subtype (TyTy::TyWithLocation (&ltype->get_result_type ()),
+                            TyTy::TyWithLocation (&type.get_result_type ()));
        if (res == nullptr || res->get_kind () == TyTy::TypeKind::ERROR)
          {
            return new TyTy::ErrorType (0);
@@ -1842,10 +1830,8 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, 
TyTy::BaseType *rtype)
          auto lr = ltype->resolve ();
          auto rr = ro->resolve ();
 
-         auto res = UnifyRules::Resolve (TyTy::TyWithLocation (lr),
-                                         TyTy::TyWithLocation (rr), locus,
-                                         commit_flag, false /* emit_error */,
-                                         infer_flag, commits, infers);
+         auto res = resolve_subtype (TyTy::TyWithLocation (lr),
+                                     TyTy::TyWithLocation (rr));
          if (res->get_kind () == TyTy::TypeKind::ERROR)
            return new TyTy::ErrorType (0);
        }
@@ -1863,10 +1849,8 @@ UnifyRules::expect_opaque (TyTy::OpaqueType *ltype, 
TyTy::BaseType *rtype)
   else if (ltype->can_resolve ())
     {
       auto underly = ltype->resolve ();
-      auto res = UnifyRules::Resolve (TyTy::TyWithLocation (underly),
-                                     TyTy::TyWithLocation (rtype), locus,
-                                     commit_flag, false /* emit_error */,
-                                     infer_flag, commits, infers);
+      auto res = resolve_subtype (TyTy::TyWithLocation (underly),
+                                 TyTy::TyWithLocation (rtype));
       if (res->get_kind () == TyTy::TypeKind::ERROR)
        return new TyTy::ErrorType (0);
     }
diff --git a/gcc/rust/typecheck/rust-unify.h b/gcc/rust/typecheck/rust-unify.h
index 5ff3b7c48db..f64f0ed27b8 100644
--- a/gcc/rust/typecheck/rust-unify.h
+++ b/gcc/rust/typecheck/rust-unify.h
@@ -91,6 +91,9 @@ private:
              std::vector<CommitSite> &commits,
              std::vector<InferenceSite> &infers);
 
+  TyTy::BaseType *resolve_subtype (TyTy::TyWithLocation lhs,
+                                  TyTy::TyWithLocation rhs);
+
   void emit_type_mismatch () const;
   void emit_abi_mismatch (const TyTy::FnType &expected,
                          const TyTy::FnType &got) const;
diff --git a/gcc/testsuite/rust/compile/traits9.rs 
b/gcc/testsuite/rust/compile/traits9.rs
index bb3034d0f21..f4308e8ccc1 100644
--- a/gcc/testsuite/rust/compile/traits9.rs
+++ b/gcc/testsuite/rust/compile/traits9.rs
@@ -11,6 +11,5 @@ fn main() {
     a = Foo(123);
 
     let b: &dyn Bar = &a;
-    // { dg-error "bounds not satisfied for Foo .Bar. is not satisfied" "" { 
target *-*-* } .-1 }
-    // { dg-error "expected" "" { target *-*-* } .-2 }
+    // { dg-error "bounds not satisfied for Foo .Bar. is not satisfied 
.E0277." "" { target *-*-* } .-1 }
 }
diff --git a/gcc/testsuite/rust/compile/unify-errors1.rs 
b/gcc/testsuite/rust/compile/unify-errors1.rs
new file mode 100644
index 00000000000..0fe95efd0d7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/unify-errors1.rs
@@ -0,0 +1,49 @@
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+trait MyTrait {}
+
+struct Wrapper<T: MyTrait> {
+    value: T,
+}
+
+struct NotImpl;
+
+trait A {}
+trait B {}
+
+struct Wrapper2<T: A + B> {
+    value: T,
+}
+
+struct NotImpl2;
+
+impl A for NotImpl2 {}
+
+fn takes_tuple(x: (i32, bool)) {}
+
+fn requires_copy<T: Copy>(value: T) {}
+
+pub fn test() {
+    takes_tuple((1, 2));
+    // { dg-error "mismatched types, expected .bool. but got .<integer>. 
.E0308." "" { target *-*-* } .-1 }
+
+    takes_tuple((1, 2, 3));
+    // { dg-error "mismatched types, expected ..i32, bool.. but got 
..<integer>, <integer>, <integer>.. .E0308." "" { target *-*-* } .-1 }
+
+    takes_tuple("hello");
+    // { dg-error "mismatched types, expected ..i32, bool.. but got .& str. 
.E0308." "" { target *-*-* } .-1 }
+
+    let x = &mut 5;
+    requires_copy(x);
+    // { dg-error "bounds not satisfied for &mut <integer> .Copy. is not 
satisfied .E0277." "" { target *-*-* } .-1 }
+
+    let _x = Wrapper { value: NotImpl };
+    // { dg-error "bounds not satisfied for NotImpl .MyTrait. is not satisfied 
.E0277." "" { target *-*-* } .-1 }
+
+    let _x = Wrapper2 { value: NotImpl2 };
+    // { dg-error "bounds not satisfied for NotImpl2 .B. is not satisfied 
.E0277." "" { target *-*-* } .-1 }
+}
-- 
2.49.0

Reply via email to