public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] Ensure autoderef for generic recivers in method calls
@ 2022-06-08 11:42 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-06-08 11:42 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:243e5d800dc03f36025e72d275b79a2098dbb953

commit 243e5d800dc03f36025e72d275b79a2098dbb953
Author: Philip Herron <philip.herron@embecosm.com>
Date:   Wed Oct 20 19:39:01 2021 +0100

    Ensure autoderef for generic recivers in method calls
    
    This changes our TyTy::BaseType::can_eq interface to allow
    ParamTypes to be compatable with everything except reference
    and pointer types to ensure we apply autoderef adjustments
    correctly.
    
    Fixes #753

Diff:
---
 gcc/rust/typecheck/rust-hir-dot-operator.h         |   6 +-
 .../typecheck/rust-hir-inherent-impl-overlap.h     |   2 +-
 gcc/rust/typecheck/rust-hir-path-probe.h           |   2 +-
 gcc/rust/typecheck/rust-hir-type-check-expr.h      |   2 +-
 gcc/rust/typecheck/rust-hir-type-check-implitem.h  |   6 +-
 gcc/rust/typecheck/rust-hir-type-check-path.cc     |   7 +-
 gcc/rust/typecheck/rust-hir-type-check.h           |   2 +-
 gcc/rust/typecheck/rust-tyty-bounds.cc             |   2 +-
 gcc/rust/typecheck/rust-tyty-cmp.h                 | 227 ++++++++++++++-------
 gcc/rust/typecheck/rust-tyty.cc                    | 115 ++++++-----
 gcc/rust/typecheck/rust-tyty.h                     |  72 ++++---
 gcc/testsuite/rust/execute/torture/trait8.rs       |  41 ++++
 12 files changed, 323 insertions(+), 161 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h
index 9c0cc431c2a..98ae5ab65d9 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -115,7 +115,7 @@ private:
 	    if (fn->is_method ())
 	      {
 		TyTy::BaseType *fn_self = fn->get_self_type ();
-		if (receiver->can_eq (fn_self, false))
+		if (receiver->can_eq (fn_self, false, true))
 		  {
 		    return &c;
 		  }
@@ -143,7 +143,7 @@ private:
 	    if (fn->is_method ())
 	      {
 		TyTy::BaseType *fn_self = fn->get_self_type ();
-		if (receiver->can_eq (fn_self, false))
+		if (receiver->can_eq (fn_self, false, true))
 		  {
 		    return &c;
 		  }
@@ -165,7 +165,7 @@ private:
 	    if (fn->is_method ())
 	      {
 		TyTy::BaseType *fn_self = fn->get_self_type ();
-		if (receiver->can_eq (fn_self, false))
+		if (receiver->can_eq (fn_self, false, true))
 		  {
 		    return &c;
 		  }
diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
index 9a2c7fe3c07..eac86b01cdc 100644
--- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
+++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
@@ -122,7 +122,7 @@ public:
 	    if (query == candidate)
 	      continue;
 
-	    if (query->can_eq (candidate, false))
+	    if (query->can_eq (candidate, false, false))
 	      possible_collision (it->second, iy->second);
 	  }
       }
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index d2b5f5b5c78..8ceec00ffce 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -227,7 +227,7 @@ protected:
     bool ok = context->lookup_type (impl_ty_id, &impl_block_ty);
     rust_assert (ok);
 
-    if (!receiver->can_eq (impl_block_ty, false))
+    if (!receiver->can_eq (impl_block_ty, false, false))
       return;
 
     // lets visit the impl_item
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 83fafa66ee5..8c415ebd446 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -320,7 +320,7 @@ public:
 	    // always be at the end of the list
 
 	    auto s = fn->get_self_type ()->get_root ();
-	    rust_assert (s->can_eq (adt, false));
+	    rust_assert (s->can_eq (adt, false, false));
 	    rust_assert (s->get_kind () == TyTy::TypeKind::ADT);
 	    const TyTy::ADTType *self_adt
 	      = static_cast<const TyTy::ADTType *> (s);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
index 1260c2e7c88..f3a08707dfd 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h
@@ -377,7 +377,7 @@ public:
       return;
 
     // check the types are compatible
-    if (!resolved_trait_item.get_tyty ()->can_eq (lookup, true))
+    if (!resolved_trait_item.get_tyty ()->can_eq (lookup, true, false))
       {
 	RichLocation r (constant.get_locus ());
 	r.add_range (resolved_trait_item.get_locus ());
@@ -413,7 +413,7 @@ public:
       return;
 
     // check the types are compatible
-    if (!resolved_trait_item.get_tyty ()->can_eq (lookup, true))
+    if (!resolved_trait_item.get_tyty ()->can_eq (lookup, true, false))
       {
 	RichLocation r (type.get_locus ());
 	r.add_range (resolved_trait_item.get_locus ());
@@ -487,7 +487,7 @@ public:
       = trait_item_fntype->handle_substitions (implicit_self_substs);
 
     // check the types are compatible
-    if (!trait_item_fntype->can_eq (fntype, true))
+    if (!trait_item_fntype->can_eq (fntype, true, false))
       {
 	RichLocation r (function.get_locus ());
 	r.add_range (resolved_trait_item.get_locus ());
diff --git a/gcc/rust/typecheck/rust-hir-type-check-path.cc b/gcc/rust/typecheck/rust-hir-type-check-path.cc
index 0aea8ca669a..c74ac85ae7e 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-path.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-path.cc
@@ -376,9 +376,12 @@ TypeCheckExpr::resolve_segments (NodeId root_resolved_node_id,
 	      AssociatedImplTrait *lookup_associated = nullptr;
 	      bool found_impl_trait = context->lookup_associated_trait_impl (
 		impl->get_mappings ().get_hirid (), &lookup_associated);
-	      rust_assert (found_impl_trait);
 
-	      lookup_associated->setup_associated_types ();
+	      // setup associated mappings if possible we might be resolving a
+	      // path within a default implementation of a trait function
+	      // see: testsuite/rust/compile/torture/traits16.rs
+	      if (found_impl_trait)
+		lookup_associated->setup_associated_types ();
 
 	      // we need a new ty_ref_id for this trait item
 	      tyseg = tyseg->clone ();
diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h
index d3dc4c997c0..5760c4e9c5d 100644
--- a/gcc/rust/typecheck/rust-hir-type-check.h
+++ b/gcc/rust/typecheck/rust-hir-type-check.h
@@ -187,7 +187,7 @@ public:
 
     for (auto &item : it->second)
       {
-	if (item.first->can_eq (self, false))
+	if (item.first->can_eq (self, false, false))
 	  {
 	    *mapping = item.second;
 	    return true;
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc b/gcc/rust/typecheck/rust-tyty-bounds.cc
index 5f69deb52d3..89093949e41 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -40,7 +40,7 @@ TypeBoundsProbe::scan ()
       if (!ok)
 	return true;
 
-      if (!receiver->can_eq (impl_type, false))
+      if (!receiver->can_eq (impl_type, false, false))
 	return true;
 
       possible_trait_paths.push_back ({impl->get_trait_ref ().get (), impl});
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index 519501fa02c..9ebd5647cc1 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -371,8 +371,18 @@ public:
 
   virtual void visit (const ParamType &type) override
   {
-    // it is ok for types to can eq to a ParamType
-    ok = true;
+    ok = false;
+    if (emit_error_flag)
+      {
+	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 (const DynamicObjectType &type) override
@@ -408,10 +418,10 @@ public:
   }
 
 protected:
-  BaseCmp (const BaseType *base, bool emit_errors)
+  BaseCmp (const BaseType *base, bool emit_errors, bool autoderef_mode)
     : mappings (Analysis::Mappings::get ()),
       context (Resolver::TypeCheckContext::get ()), ok (false),
-      emit_error_flag (emit_errors)
+      emit_error_flag (emit_errors), autoderef_mode_flag (autoderef_mode)
   {}
 
   Analysis::Mappings *mappings;
@@ -419,6 +429,7 @@ protected:
 
   bool ok;
   bool emit_error_flag;
+  bool autoderef_mode_flag;
 
 private:
   /* Returns a pointer to the ty that created this rule. */
@@ -430,8 +441,8 @@ class InferCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  InferCmp (const InferType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  InferCmp (const InferType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const BoolType &type) override
@@ -641,18 +652,7 @@ public:
     BaseCmp::visit (type);
   }
 
-  void visit (const ParamType &type) override
-  {
-    bool is_valid
-      = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
-    if (is_valid)
-      {
-	ok = true;
-	return;
-      }
-
-    BaseCmp::visit (type);
-  }
+  void visit (const ParamType &) override { ok = true; }
 
   void visit (const DynamicObjectType &type) override
   {
@@ -690,8 +690,8 @@ class FnCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  FnCmp (const FnType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  FnCmp (const FnType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const InferType &type) override
@@ -712,7 +712,7 @@ public:
 	auto a = base->param_at (i).second;
 	auto b = type.param_at (i).second;
 
-	if (!a->can_eq (b, emit_error_flag))
+	if (!a->can_eq (b, emit_error_flag, autoderef_mode_flag))
 	  {
 	    emit_error_flag = false;
 	    BaseCmp::visit (type);
@@ -721,7 +721,8 @@ public:
       }
 
     if (!base->get_return_type ()->can_eq (type.get_return_type (),
-					   emit_error_flag))
+					   emit_error_flag,
+					   autoderef_mode_flag))
       {
 	emit_error_flag = false;
 	BaseCmp::visit (type);
@@ -741,8 +742,8 @@ class FnptrCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  FnptrCmp (const FnPtr *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  FnptrCmp (const FnPtr *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const InferType &type) override
@@ -766,7 +767,8 @@ public:
 
     auto this_ret_type = base->get_return_type ();
     auto other_ret_type = type.get_return_type ();
-    if (!this_ret_type->can_eq (other_ret_type, emit_error_flag))
+    if (!this_ret_type->can_eq (other_ret_type, emit_error_flag,
+				autoderef_mode_flag))
       {
 	BaseCmp::visit (type);
 	return;
@@ -776,7 +778,8 @@ public:
       {
 	auto this_param = base->param_at (i);
 	auto other_param = type.param_at (i);
-	if (!this_param->can_eq (other_param, emit_error_flag))
+	if (!this_param->can_eq (other_param, emit_error_flag,
+				 autoderef_mode_flag))
 	  {
 	    BaseCmp::visit (type);
 	    return;
@@ -796,7 +799,8 @@ public:
 
     auto this_ret_type = base->get_return_type ();
     auto other_ret_type = type.get_return_type ();
-    if (!this_ret_type->can_eq (other_ret_type, emit_error_flag))
+    if (!this_ret_type->can_eq (other_ret_type, emit_error_flag,
+				autoderef_mode_flag))
       {
 	BaseCmp::visit (type);
 	return;
@@ -806,7 +810,8 @@ public:
       {
 	auto this_param = base->param_at (i);
 	auto other_param = type.param_at (i).second;
-	if (!this_param->can_eq (other_param, emit_error_flag))
+	if (!this_param->can_eq (other_param, emit_error_flag,
+				 autoderef_mode_flag))
 	  {
 	    BaseCmp::visit (type);
 	    return;
@@ -826,8 +831,8 @@ class ClosureCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  ClosureCmp (const ClosureType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  ClosureCmp (const ClosureType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
 private:
@@ -840,8 +845,8 @@ class ArrayCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  ArrayCmp (const ArrayType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  ArrayCmp (const ArrayType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const ArrayType &type) override
@@ -856,7 +861,8 @@ public:
     // check base type
     const BaseType *base_element = base->get_element_type ();
     const BaseType *other_element = type.get_element_type ();
-    if (!base_element->can_eq (other_element, emit_error_flag))
+    if (!base_element->can_eq (other_element, emit_error_flag,
+			       autoderef_mode_flag))
       {
 	BaseCmp::visit (type);
 	return;
@@ -865,6 +871,8 @@ public:
     ok = true;
   }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
   const ArrayType *base;
@@ -875,8 +883,8 @@ class BoolCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  BoolCmp (const BoolType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  BoolCmp (const BoolType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const BoolType &type) override { ok = true; }
@@ -886,6 +894,8 @@ public:
     ok = type.get_infer_kind () == InferType::InferTypeKind::GENERAL;
   }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
   const BoolType *base;
@@ -896,8 +906,8 @@ class IntCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  IntCmp (const IntType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  IntCmp (const IntType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const InferType &type) override
@@ -910,6 +920,8 @@ public:
     ok = type.get_int_kind () == base->get_int_kind ();
   }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
   const IntType *base;
@@ -920,8 +932,8 @@ class UintCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  UintCmp (const UintType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  UintCmp (const UintType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const InferType &type) override
@@ -934,6 +946,8 @@ public:
     ok = type.get_uint_kind () == base->get_uint_kind ();
   }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
   const UintType *base;
@@ -944,8 +958,8 @@ class FloatCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  FloatCmp (const FloatType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  FloatCmp (const FloatType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const InferType &type) override
@@ -958,6 +972,8 @@ public:
     ok = type.get_float_kind () == base->get_float_kind ();
   }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
   const FloatType *base;
@@ -968,8 +984,8 @@ class ADTCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  ADTCmp (const ADTType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  ADTCmp (const ADTType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const ADTType &type) override
@@ -994,7 +1010,8 @@ public:
 	TyTy::BaseType *this_field_ty = base_field->get_field_type ();
 	TyTy::BaseType *other_field_ty = other_field->get_field_type ();
 
-	if (!this_field_ty->can_eq (other_field_ty, emit_error_flag))
+	if (!this_field_ty->can_eq (other_field_ty, emit_error_flag,
+				    autoderef_mode_flag))
 	  {
 	    BaseCmp::visit (type);
 	    return;
@@ -1004,6 +1021,8 @@ public:
     ok = true;
   }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
   const ADTType *base;
@@ -1014,8 +1033,8 @@ class TupleCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  TupleCmp (const TupleType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  TupleCmp (const TupleType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const TupleType &type) override
@@ -1031,7 +1050,7 @@ public:
 	BaseType *bo = base->get_field (i);
 	BaseType *fo = type.get_field (i);
 
-	if (!bo->can_eq (fo, emit_error_flag))
+	if (!bo->can_eq (fo, emit_error_flag, autoderef_mode_flag))
 	  {
 	    BaseCmp::visit (type);
 	    return;
@@ -1041,6 +1060,8 @@ public:
     ok = true;
   }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
   const TupleType *base;
@@ -1051,8 +1072,8 @@ class USizeCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  USizeCmp (const USizeType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  USizeCmp (const USizeType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const InferType &type) override
@@ -1062,6 +1083,8 @@ public:
 
   void visit (const USizeType &type) override { ok = true; }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
   const USizeType *base;
@@ -1072,8 +1095,8 @@ class ISizeCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  ISizeCmp (const ISizeType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  ISizeCmp (const ISizeType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const InferType &type) override
@@ -1083,6 +1106,8 @@ public:
 
   void visit (const ISizeType &type) override { ok = true; }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
   const ISizeType *base;
@@ -1093,8 +1118,8 @@ class CharCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  CharCmp (const CharType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  CharCmp (const CharType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const InferType &type) override
@@ -1104,6 +1129,8 @@ public:
 
   void visit (const CharType &type) override { ok = true; }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
   const CharType *base;
@@ -1114,8 +1141,9 @@ class ReferenceCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  ReferenceCmp (const ReferenceType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  ReferenceCmp (const ReferenceType *base, bool emit_errors,
+		bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const ReferenceType &type) override
@@ -1123,7 +1151,8 @@ public:
     auto base_type = base->get_base ();
     auto other_base_type = type.get_base ();
 
-    ok = base_type->can_eq (other_base_type, emit_error_flag)
+    ok = base_type->can_eq (other_base_type, emit_error_flag,
+			    autoderef_mode_flag)
 	 && (base->is_mutable () == type.is_mutable ());
   }
 
@@ -1137,8 +1166,8 @@ class PointerCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  PointerCmp (const PointerType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  PointerCmp (const PointerType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const ReferenceType &type) override
@@ -1146,7 +1175,8 @@ public:
     auto base_type = base->get_base ();
     auto other_base_type = type.get_base ();
 
-    ok = base_type->can_eq (other_base_type, emit_error_flag)
+    ok = base_type->can_eq (other_base_type, emit_error_flag,
+			    autoderef_mode_flag)
 	 && (base->is_mutable () == type.is_mutable ());
   }
 
@@ -1160,8 +1190,8 @@ class ParamCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  ParamCmp (const ParamType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  ParamCmp (const ParamType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   // param types are a placeholder we shouldn't have cases where we unify
@@ -1183,13 +1213,7 @@ public:
     bool ok = context->lookup_type (base->get_ty_ref (), &lookup);
     rust_assert (ok);
 
-    if (lookup->get_kind () == TypeKind::PARAM)
-      {
-	InferType infer (UNKNOWN_HIRID, InferType::InferTypeKind::GENERAL);
-	return infer.can_eq (other, emit_error_flag);
-      }
-
-    return lookup->can_eq (other, emit_error_flag);
+    return lookup->can_eq (other, emit_error_flag, autoderef_mode_flag);
   }
 
   // imagine the case where we have:
@@ -1198,7 +1222,46 @@ public:
   // impl <X>Foo<X> { ... }
   // both of these types are compatible so we mostly care about the number of
   // generic arguments
-  void visit (const ParamType &type) override { ok = true; }
+  void visit (const ParamType &) override { ok = true; }
+
+  void visit (const TupleType &) override { ok = true; }
+
+  void visit (const ADTType &) override { ok = true; }
+
+  void visit (const InferType &) override { ok = true; }
+
+  void visit (const FnType &) override { ok = true; }
+
+  void visit (const FnPtr &) override { ok = true; }
+
+  void visit (const ArrayType &) override { ok = true; }
+
+  void visit (const BoolType &) override { ok = true; }
+
+  void visit (const IntType &) override { ok = true; }
+
+  void visit (const UintType &) override { ok = true; }
+
+  void visit (const USizeType &) override { ok = true; }
+
+  void visit (const ISizeType &) override { ok = true; }
+
+  void visit (const FloatType &) override { ok = true; }
+
+  void visit (const CharType &) override { ok = true; }
+
+  void visit (const ReferenceType &) override { ok = !autoderef_mode_flag; }
+
+  void visit (const PointerType &) override { ok = !autoderef_mode_flag; }
+
+  void visit (const StrType &) override { ok = true; }
+
+  void visit (const NeverType &) override { ok = true; }
+
+  void visit (const PlaceholderType &type) override
+  {
+    ok = base->get_symbol ().compare (type.get_symbol ()) == 0;
+  }
 
 private:
   const BaseType *get_base () const override { return base; }
@@ -1211,12 +1274,14 @@ class StrCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  StrCmp (const StrType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  StrCmp (const StrType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const StrType &type) override { ok = true; }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
   const StrType *base;
@@ -1227,12 +1292,14 @@ class NeverCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  NeverCmp (const NeverType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  NeverCmp (const NeverType *base, bool emit_errors, bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const NeverType &type) override { ok = true; }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
   const NeverType *base;
@@ -1243,8 +1310,9 @@ class PlaceholderCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  PlaceholderCmp (const PlaceholderType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  PlaceholderCmp (const PlaceholderType *base, bool emit_errors,
+		  bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   bool can_eq (const BaseType *other) override
@@ -1253,7 +1321,7 @@ public:
       return BaseCmp::can_eq (other);
 
     BaseType *lookup = base->resolve ();
-    return lookup->can_eq (other, emit_error_flag);
+    return lookup->can_eq (other, emit_error_flag, autoderef_mode_flag);
   }
 
   void visit (const TupleType &) override { ok = true; }
@@ -1308,8 +1376,9 @@ class DynamicCmp : public BaseCmp
   using Rust::TyTy::BaseCmp::visit;
 
 public:
-  DynamicCmp (const DynamicObjectType *base, bool emit_errors)
-    : BaseCmp (base, emit_errors), base (base)
+  DynamicCmp (const DynamicObjectType *base, bool emit_errors,
+	      bool autoderef_mode)
+    : BaseCmp (base, emit_errors, autoderef_mode), base (base)
   {}
 
   void visit (const DynamicObjectType &type) override
@@ -1324,6 +1393,8 @@ public:
     ok = base->bounds_compatible (type, ref_locus, false);
   }
 
+  void visit (const ParamType &type) override { ok = true; }
+
 private:
   const BaseType *get_base () const override { return base; }
 
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 1e7c87e0beb..37f93b40cf4 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -201,9 +201,10 @@ InferType::unify (BaseType *other)
 }
 
 bool
-InferType::can_eq (const BaseType *other, bool emit_errors) const
+InferType::can_eq (const BaseType *other, bool emit_errors,
+		   bool autoderef_mode) const
 {
-  InferCmp r (this, emit_errors);
+  InferCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -278,7 +279,8 @@ ErrorType::unify (BaseType *other)
 }
 
 bool
-ErrorType::can_eq (const BaseType *other, bool emit_errors) const
+ErrorType::can_eq (const BaseType *other, bool emit_errors,
+		   bool autoderef_mode) const
 {
   return get_kind () == other->get_kind ();
 }
@@ -641,9 +643,10 @@ ADTType::cast (BaseType *other)
 }
 
 bool
-ADTType::can_eq (const BaseType *other, bool emit_errors) const
+ADTType::can_eq (const BaseType *other, bool emit_errors,
+		 bool autoderef_mode) const
 {
-  ADTCmp r (this, emit_errors);
+  ADTCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -822,9 +825,10 @@ TupleType::cast (BaseType *other)
 }
 
 bool
-TupleType::can_eq (const BaseType *other, bool emit_errors) const
+TupleType::can_eq (const BaseType *other, bool emit_errors,
+		   bool autoderef_mode) const
 {
-  TupleCmp r (this, emit_errors);
+  TupleCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -926,9 +930,10 @@ FnType::cast (BaseType *other)
 }
 
 bool
-FnType::can_eq (const BaseType *other, bool emit_errors) const
+FnType::can_eq (const BaseType *other, bool emit_errors,
+		bool autoderef_mode) const
 {
-  FnCmp r (this, emit_errors);
+  FnCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1143,9 +1148,10 @@ FnPtr::cast (BaseType *other)
 }
 
 bool
-FnPtr::can_eq (const BaseType *other, bool emit_errors) const
+FnPtr::can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const
 {
-  FnptrCmp r (this, emit_errors);
+  FnptrCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1209,9 +1215,10 @@ ClosureType::unify (BaseType *other)
 }
 
 bool
-ClosureType::can_eq (const BaseType *other, bool emit_errors) const
+ClosureType::can_eq (const BaseType *other, bool emit_errors,
+		     bool autoderef_mode) const
 {
-  ClosureCmp r (this, emit_errors);
+  ClosureCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1297,9 +1304,10 @@ ArrayType::cast (BaseType *other)
 }
 
 bool
-ArrayType::can_eq (const BaseType *other, bool emit_errors) const
+ArrayType::can_eq (const BaseType *other, bool emit_errors,
+		   bool autoderef_mode) const
 {
-  ArrayCmp r (this, emit_errors);
+  ArrayCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1372,9 +1380,10 @@ BoolType::cast (BaseType *other)
 }
 
 bool
-BoolType::can_eq (const BaseType *other, bool emit_errors) const
+BoolType::can_eq (const BaseType *other, bool emit_errors,
+		  bool autoderef_mode) const
 {
-  BoolCmp r (this, emit_errors);
+  BoolCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1438,9 +1447,10 @@ IntType::cast (BaseType *other)
 }
 
 bool
-IntType::can_eq (const BaseType *other, bool emit_errors) const
+IntType::can_eq (const BaseType *other, bool emit_errors,
+		 bool autoderef_mode) const
 {
-  IntCmp r (this, emit_errors);
+  IntCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1515,9 +1525,10 @@ UintType::cast (BaseType *other)
 }
 
 bool
-UintType::can_eq (const BaseType *other, bool emit_errors) const
+UintType::can_eq (const BaseType *other, bool emit_errors,
+		  bool autoderef_mode) const
 {
-  UintCmp r (this, emit_errors);
+  UintCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1586,9 +1597,10 @@ FloatType::cast (BaseType *other)
 }
 
 bool
-FloatType::can_eq (const BaseType *other, bool emit_errors) const
+FloatType::can_eq (const BaseType *other, bool emit_errors,
+		   bool autoderef_mode) const
 {
-  FloatCmp r (this, emit_errors);
+  FloatCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1649,9 +1661,10 @@ USizeType::cast (BaseType *other)
 }
 
 bool
-USizeType::can_eq (const BaseType *other, bool emit_errors) const
+USizeType::can_eq (const BaseType *other, bool emit_errors,
+		   bool autoderef_mode) const
 {
-  USizeCmp r (this, emit_errors);
+  USizeCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1701,9 +1714,10 @@ ISizeType::cast (BaseType *other)
 }
 
 bool
-ISizeType::can_eq (const BaseType *other, bool emit_errors) const
+ISizeType::can_eq (const BaseType *other, bool emit_errors,
+		   bool autoderef_mode) const
 {
-  ISizeCmp r (this, emit_errors);
+  ISizeCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1753,9 +1767,10 @@ CharType::cast (BaseType *other)
 }
 
 bool
-CharType::can_eq (const BaseType *other, bool emit_errors) const
+CharType::can_eq (const BaseType *other, bool emit_errors,
+		  bool autoderef_mode) const
 {
-  CharCmp r (this, emit_errors);
+  CharCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1806,9 +1821,10 @@ ReferenceType::cast (BaseType *other)
 }
 
 bool
-ReferenceType::can_eq (const BaseType *other, bool emit_errors) const
+ReferenceType::can_eq (const BaseType *other, bool emit_errors,
+		       bool autoderef_mode) const
 {
-  ReferenceCmp r (this, emit_errors);
+  ReferenceCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1892,9 +1908,10 @@ PointerType::cast (BaseType *other)
 }
 
 bool
-PointerType::can_eq (const BaseType *other, bool emit_errors) const
+PointerType::can_eq (const BaseType *other, bool emit_errors,
+		     bool autoderef_mode) const
 {
-  PointerCmp r (this, emit_errors);
+  PointerCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -1987,9 +2004,10 @@ ParamType::cast (BaseType *other)
 }
 
 bool
-ParamType::can_eq (const BaseType *other, bool emit_errors) const
+ParamType::can_eq (const BaseType *other, bool emit_errors,
+		   bool autoderef_mode) const
 {
-  ParamCmp r (this, emit_errors);
+  ParamCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -2044,7 +2062,7 @@ ParamType::is_equal (const BaseType &other) const
     return false;
 
   if (can_resolve ())
-    return resolve ()->can_eq (other2.resolve (), false);
+    return resolve ()->can_eq (other2.resolve (), false, false);
 
   return get_symbol ().compare (other2.get_symbol ()) == 0;
 }
@@ -2108,9 +2126,10 @@ StrType::cast (BaseType *other)
 }
 
 bool
-StrType::can_eq (const BaseType *other, bool emit_errors) const
+StrType::can_eq (const BaseType *other, bool emit_errors,
+		 bool autoderef_mode) const
 {
-  StrCmp r (this, emit_errors);
+  StrCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -2160,9 +2179,10 @@ NeverType::cast (BaseType *other)
 }
 
 bool
-NeverType::can_eq (const BaseType *other, bool emit_errors) const
+NeverType::can_eq (const BaseType *other, bool emit_errors,
+		   bool autoderef_mode) const
 {
-  NeverCmp r (this, emit_errors);
+  NeverCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -2215,9 +2235,10 @@ PlaceholderType::cast (BaseType *other)
 }
 
 bool
-PlaceholderType::can_eq (const BaseType *other, bool emit_errors) const
+PlaceholderType::can_eq (const BaseType *other, bool emit_errors,
+			 bool autoderef_mode) const
 {
-  PlaceholderCmp r (this, emit_errors);
+  PlaceholderCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
@@ -2315,9 +2336,10 @@ ProjectionType::cast (BaseType *other)
 }
 
 bool
-ProjectionType::can_eq (const BaseType *other, bool emit_errors) const
+ProjectionType::can_eq (const BaseType *other, bool emit_errors,
+			bool autoderef_mode) const
 {
-  return base->can_eq (other, emit_errors);
+  return base->can_eq (other, emit_errors, autoderef_mode);
 }
 
 BaseType *
@@ -2421,9 +2443,10 @@ DynamicObjectType::unify (BaseType *other)
 }
 
 bool
-DynamicObjectType::can_eq (const BaseType *other, bool emit_errors) const
+DynamicObjectType::can_eq (const BaseType *other, bool emit_errors,
+			   bool autoderef_mode) const
 {
-  DynamicCmp r (this, emit_errors);
+  DynamicCmp r (this, emit_errors, autoderef_mode);
   return r.can_eq (other);
 }
 
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index f6a279737d1..27daa7cf57d 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -259,7 +259,8 @@ public:
   //
   // It can also be used to optional emit errors for trait item compatibility
   // checks
-  virtual bool can_eq (const BaseType *other, bool emit_errors) const = 0;
+  virtual bool can_eq (const BaseType *other, bool emit_errors,
+		       bool autoderef_mode) const = 0;
 
   // this is the base coercion interface for types
   virtual BaseType *coerce (BaseType *other) = 0;
@@ -404,7 +405,8 @@ public:
 
   BaseType *unify (BaseType *other) override;
 
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
 
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
@@ -442,7 +444,8 @@ public:
   std::string as_string () const override;
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -476,7 +479,8 @@ public:
   std::string as_string () const override;
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -564,7 +568,8 @@ public:
   std::string as_string () const override;
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -998,7 +1003,8 @@ public:
   std::string as_string () const override;
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1126,7 +1132,8 @@ public:
   std::string get_identifier () const { return identifier; }
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1234,7 +1241,8 @@ public:
   std::string as_string () const override;
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1294,7 +1302,8 @@ public:
   std::string get_name () const override final { return as_string (); }
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1346,7 +1355,8 @@ public:
   std::string get_name () const override final { return as_string (); }
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1388,7 +1398,8 @@ public:
   std::string get_name () const override final { return as_string (); }
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1424,7 +1435,8 @@ public:
   std::string get_name () const override final { return as_string (); }
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1467,7 +1479,8 @@ public:
   std::string get_name () const override final { return as_string (); }
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1508,7 +1521,8 @@ public:
   std::string get_name () const override final { return as_string (); }
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1541,7 +1555,8 @@ public:
   std::string get_name () const override final { return as_string (); }
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1567,7 +1582,8 @@ public:
   std::string get_name () const override final { return as_string (); }
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1593,7 +1609,8 @@ public:
   std::string get_name () const override final { return as_string (); }
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1623,7 +1640,8 @@ public:
   std::string get_name () const override final { return as_string (); }
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1670,7 +1688,8 @@ public:
   std::string get_name () const override final { return as_string (); }
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1715,7 +1734,8 @@ public:
   std::string as_string () const override;
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1751,7 +1771,8 @@ public:
   std::string as_string () const override;
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1784,7 +1805,8 @@ public:
   std::string as_string () const override;
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1852,7 +1874,8 @@ public:
   std::string as_string () const override;
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
 
@@ -1912,7 +1935,8 @@ public:
   std::string as_string () const override;
 
   BaseType *unify (BaseType *other) override;
-  bool can_eq (const BaseType *other, bool emit_errors) const override final;
+  bool can_eq (const BaseType *other, bool emit_errors,
+	       bool autoderef_mode) const override final;
   BaseType *coerce (BaseType *other) override;
   BaseType *cast (BaseType *other) override;
   bool is_equal (const BaseType &other) const override;
diff --git a/gcc/testsuite/rust/execute/torture/trait8.rs b/gcc/testsuite/rust/execute/torture/trait8.rs
new file mode 100644
index 00000000000..da8a560388e
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait8.rs
@@ -0,0 +1,41 @@
+/* { dg-output "123\n" } */
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+pub trait Foo {
+    type A;
+
+    fn bar(&self) -> Self::A;
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
+
+struct S(i32);
+impl Foo for S {
+    type A = i32;
+
+    fn bar(&self) -> Self::A {
+        // { dg-warning "unused name" "" { target *-*-* } .-1 }
+        self.0
+    }
+}
+
+fn test_bar<T: Foo>(x: T) -> T::A {
+    x.bar()
+}
+
+fn main() -> i32 {
+    let a;
+    a = S(123);
+
+    let bar: i32 = test_bar(a);
+    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-06-08 11:42 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-06-08 11:42 [gcc/devel/rust/master] Ensure autoderef for generic recivers in method calls 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).