diff --git a/gcc/rust/typecheck/rust-autoderef.cc b/gcc/rust/typecheck/rust-autoderef.cc
index ca43f847e98..fe05aeec388 100644
--- a/gcc/rust/typecheck/rust-autoderef.cc
+++ b/gcc/rust/typecheck/rust-autoderef.cc
@@ -139,15 +139,23 @@ resolve_operator_overload_fn (
     return false;
 
   auto segment = HIR::PathIdentSegment (associated_item_name);
-  auto candidate
+  auto candidates
     = MethodResolver::Probe (ty, HIR::PathIdentSegment (associated_item_name),
 			     true);
 
-  bool have_implementation_for_lang_item = !candidate.is_error ();
+  bool have_implementation_for_lang_item = !candidates.empty ();
   if (!have_implementation_for_lang_item)
     return false;
 
+  // multiple candidates?
+  if (candidates.size () > 1)
+    {
+      // error out? probably not for this case
+      return false;
+    }
+
   // Get the adjusted self
+  auto candidate = *candidates.begin ();
   Adjuster adj (ty);
   TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
 
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index ed2df11da45..84fa8d4f08b 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -25,18 +25,17 @@ namespace Resolver {
 
 MethodResolver::MethodResolver (bool autoderef_flag,
 				const HIR::PathIdentSegment &segment_name)
-  : AutoderefCycle (autoderef_flag), segment_name (segment_name),
-    try_result (MethodCandidate::get_error ())
+  : AutoderefCycle (autoderef_flag), segment_name (segment_name), result ()
 {}
 
-MethodCandidate
+std::set<MethodCandidate>
 MethodResolver::Probe (const TyTy::BaseType *receiver,
 		       const HIR::PathIdentSegment &segment_name,
 		       bool autoderef_flag)
 {
   MethodResolver resolver (autoderef_flag, segment_name);
-  bool ok = resolver.cycle (receiver);
-  return ok ? resolver.try_result : MethodCandidate::get_error ();
+  resolver.cycle (receiver);
+  return resolver.result;
 }
 
 void
@@ -177,8 +176,18 @@ MethodResolver::select (const TyTy::BaseType &receiver)
 	      (unsigned long) trait_fns.size (),
 	      (unsigned long) predicate_items.size ());
 
-  for (auto impl_item : inherent_impl_fns)
+  // see the follow for the proper fix to get rid of this we need to assemble
+  // candidates based on a match expression gathering the relevant impl blocks
+  // https://github.com/rust-lang/rust/blob/7eac88abb2e57e752f3302f02be5f3ce3d7adfb4/compiler/rustc_typeck/src/check/method/probe.rs#L580-L694
+  TyTy::set_cmp_autoderef_mode ();
+
+  bool found_possible_candidate = false;
+  for (auto &impl_item : inherent_impl_fns)
     {
+      bool is_trait_impl_block = impl_item.impl_block->has_trait_ref ();
+      if (is_trait_impl_block)
+	continue;
+
       TyTy::FnType *fn = impl_item.ty;
       rust_assert (fn->is_method ());
 
@@ -190,13 +199,50 @@ MethodResolver::select (const TyTy::BaseType &receiver)
 	{
 	  PathProbeCandidate::ImplItemCandidate c{impl_item.item,
 						  impl_item.impl_block};
-	  try_result = MethodCandidate{
+	  auto try_result = MethodCandidate{
 	    PathProbeCandidate (PathProbeCandidate::CandidateType::IMPL_FUNC,
 				fn, impl_item.item->get_locus (), c),
 	    adjustments};
-	  return true;
+	  result.insert (std::move (try_result));
+	  found_possible_candidate = true;
 	}
     }
+  if (found_possible_candidate)
+    {
+      TyTy::reset_cmp_autoderef_mode ();
+      return true;
+    }
+
+  for (auto &impl_item : inherent_impl_fns)
+    {
+      bool is_trait_impl_block = impl_item.impl_block->has_trait_ref ();
+      if (!is_trait_impl_block)
+	continue;
+
+      TyTy::FnType *fn = impl_item.ty;
+      rust_assert (fn->is_method ());
+
+      TyTy::BaseType *fn_self = fn->get_self_type ();
+      rust_debug (
+	"dot-operator trait_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,
+						  impl_item.impl_block};
+	  auto try_result = MethodCandidate{
+	    PathProbeCandidate (PathProbeCandidate::CandidateType::IMPL_FUNC,
+				fn, impl_item.item->get_locus (), c),
+	    adjustments};
+	  result.insert (std::move (try_result));
+	  found_possible_candidate = true;
+	}
+    }
+  if (found_possible_candidate)
+    {
+      TyTy::reset_cmp_autoderef_mode ();
+      return true;
+    }
 
   for (auto trait_item : trait_fns)
     {
@@ -212,13 +258,19 @@ MethodResolver::select (const TyTy::BaseType &receiver)
 	  PathProbeCandidate::TraitItemCandidate c{trait_item.reference,
 						   trait_item.item_ref,
 						   nullptr};
-	  try_result = MethodCandidate{
+	  auto try_result = MethodCandidate{
 	    PathProbeCandidate (PathProbeCandidate::CandidateType::TRAIT_FUNC,
 				fn, trait_item.item->get_locus (), c),
 	    adjustments};
-	  return true;
+	  result.insert (std::move (try_result));
+	  found_possible_candidate = true;
 	}
     }
+  if (found_possible_candidate)
+    {
+      TyTy::reset_cmp_autoderef_mode ();
+      return true;
+    }
 
   for (const auto &predicate : predicate_items)
     {
@@ -238,15 +290,17 @@ MethodResolver::select (const TyTy::BaseType &receiver)
 
 	  PathProbeCandidate::TraitItemCandidate c{trait_ref, trait_item,
 						   nullptr};
-	  try_result = MethodCandidate{
+	  auto try_result = MethodCandidate{
 	    PathProbeCandidate (PathProbeCandidate::CandidateType::TRAIT_FUNC,
 				fn->clone (), trait_item->get_locus (), c),
 	    adjustments};
-	  return true;
+	  result.insert (std::move (try_result));
+	  found_possible_candidate = true;
 	}
     }
 
-  return false;
+  TyTy::reset_cmp_autoderef_mode ();
+  return found_possible_candidate;
 }
 
 std::vector<MethodResolver::predicate_candidate>
diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.h b/gcc/rust/typecheck/rust-hir-dot-operator.h
index 8341173a061..e14baf3f87d 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.h
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.h
@@ -35,6 +35,13 @@ struct MethodCandidate
   }
 
   bool is_error () const { return candidate.is_error (); }
+
+  DefId get_defid () const { return candidate.get_defid (); }
+
+  bool operator< (const MethodCandidate &c) const
+  {
+    return get_defid () < c.get_defid ();
+  }
 };
 
 class MethodResolver : private TypeCheckBase, protected AutoderefCycle
@@ -46,9 +53,10 @@ public:
     TyTy::FnType *fntype;
   };
 
-  static MethodCandidate Probe (const TyTy::BaseType *receiver,
-				const HIR::PathIdentSegment &segment_name,
-				bool autoderef_flag = false);
+  static std::set<MethodCandidate>
+  Probe (const TyTy::BaseType *receiver,
+	 const HIR::PathIdentSegment &segment_name,
+	 bool autoderef_flag = false);
 
   static std::vector<predicate_candidate> get_predicate_items (
     const HIR::PathIdentSegment &segment_name, const TyTy::BaseType &receiver,
@@ -68,7 +76,7 @@ private:
   std::vector<MethodResolver::predicate_candidate> predicate_items;
 
   // mutable fields
-  MethodCandidate try_result;
+  std::set<MethodCandidate> result;
 };
 
 } // namespace Resolver
diff --git a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
index 3733f555cfb..6e2fe1b2286 100644
--- a/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
+++ b/gcc/rust/typecheck/rust-hir-inherent-impl-overlap.h
@@ -93,8 +93,9 @@ public:
 
     HirId impl_type_id = impl->get_type ()->get_mappings ().get_hirid ();
     TyTy::BaseType *impl_type = nullptr;
-    bool ok = context->lookup_type (impl_type_id, &impl_type);
-    rust_assert (ok);
+    bool ok = query_type (impl_type_id, &impl_type);
+    if (!ok)
+      return;
 
     std::string impl_item_name;
     ok = ImplItemToName::resolve (impl_item, impl_item_name);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 2f22c82f063..4e377d52a0f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -1015,10 +1015,10 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
 
   context->insert_receiver (expr.get_mappings ().get_hirid (), receiver_tyty);
 
-  auto candidate
+  auto candidates
     = MethodResolver::Probe (receiver_tyty,
 			     expr.get_method_name ().get_segment ());
-  if (candidate.is_error ())
+  if (candidates.empty ())
     {
       rust_error_at (
 	expr.get_method_name ().get_locus (),
@@ -1027,6 +1027,19 @@ TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
       return;
     }
 
+  if (candidates.size () > 1)
+    {
+      RichLocation r (expr.get_method_name ().get_locus ());
+      for (auto &c : candidates)
+	r.add_range (c.candidate.locus);
+
+      rust_error_at (
+	r, "multiple candidates found for method %<%s%>",
+	expr.get_method_name ().get_segment ().as_string ().c_str ());
+      return;
+    }
+
+  auto candidate = *candidates.begin ();
   rust_debug_loc (expr.get_method_name ().get_locus (),
 		  "resolved method to: {%u} {%s}",
 		  candidate.candidate.ty->get_ref (),
@@ -1422,14 +1435,28 @@ TypeCheckExpr::resolve_operator_overload (
     return false;
 
   auto segment = HIR::PathIdentSegment (associated_item_name);
-  auto candidate
+  auto candidates
     = MethodResolver::Probe (lhs, HIR::PathIdentSegment (associated_item_name));
 
-  bool have_implementation_for_lang_item = !candidate.is_error ();
+  bool have_implementation_for_lang_item = candidates.size () > 0;
   if (!have_implementation_for_lang_item)
     return false;
 
+  if (candidates.size () > 1)
+    {
+      // mutliple candidates
+      RichLocation r (expr.get_locus ());
+      for (auto &c : candidates)
+	r.add_range (c.candidate.locus);
+
+      rust_error_at (
+	r, "multiple candidates found for possible operator overload");
+
+      return false;
+    }
+
   // Get the adjusted self
+  auto candidate = *candidates.begin ();
   Adjuster adj (lhs);
   TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
 
diff --git a/gcc/rust/typecheck/rust-tyty-cmp.h b/gcc/rust/typecheck/rust-tyty-cmp.h
index d47cbb4369a..5dfd2d7184a 100644
--- a/gcc/rust/typecheck/rust-tyty-cmp.h
+++ b/gcc/rust/typecheck/rust-tyty-cmp.h
@@ -28,6 +28,10 @@
 namespace Rust {
 namespace TyTy {
 
+// we need to fix this properly by implementing the match for assembling
+// candidates
+extern bool autoderef_cmp_flag;
+
 class BaseCmp : public TyConstVisitor
 {
 public:
@@ -1244,6 +1248,9 @@ public:
     auto other_base_type = type.get_base ();
 
     bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
+    if (autoderef_cmp_flag)
+      mutability_ok = base->mutability () == type.mutability ();
+
     if (!mutability_ok)
       {
 	BaseCmp::visit (type);
@@ -1289,9 +1296,10 @@ public:
     auto base_type = base->get_base ();
     auto other_base_type = type.get_base ();
 
-    // rust is permissive about mutablity here you can always go from mutable to
-    // immutable but not the otherway round
     bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
+    if (autoderef_cmp_flag)
+      mutability_ok = base->mutability () == type.mutability ();
+
     if (!mutability_ok)
       {
 	BaseCmp::visit (type);
@@ -1370,7 +1378,7 @@ public:
 
   void visit (const ArrayType &) override { ok = true; }
 
-  void visit (const SliceType &) override { ok = true; }
+  void visit (const SliceType &) override { ok = !autoderef_cmp_flag; }
 
   void visit (const BoolType &) override { ok = true; }
 
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index e2f79971337..462c5bf91fd 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -32,6 +32,19 @@
 namespace Rust {
 namespace TyTy {
 
+bool autoderef_cmp_flag = false;
+
+void
+set_cmp_autoderef_mode ()
+{
+  autoderef_cmp_flag = true;
+}
+void
+reset_cmp_autoderef_mode ()
+{
+  autoderef_cmp_flag = false;
+}
+
 std::string
 TypeKindFormat::to_string (TypeKind kind)
 {
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index a033fcad6c9..b17f01f67ea 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -135,6 +135,11 @@ protected:
   std::vector<TypeBoundPredicate> specified_bounds;
 };
 
+extern void
+set_cmp_autoderef_mode ();
+extern void
+reset_cmp_autoderef_mode ();
+
 class TyVisitor;
 class TyConstVisitor;
 class BaseType : public TypeBoundsMappings
diff --git a/gcc/testsuite/rust/compile/generics7.rs b/gcc/testsuite/rust/compile/generics7.rs
index 2a41632e693..2789c30ee38 100644
--- a/gcc/testsuite/rust/compile/generics7.rs
+++ b/gcc/testsuite/rust/compile/generics7.rs
@@ -3,13 +3,13 @@ struct Foo<A> {
 }
 
 impl Foo<isize> {
-    fn bar(self) -> isize { // { dg-error "duplicate definitions with name bar" }
+    fn bar(self) -> isize {
         self.a
     }
 }
 
 impl Foo<char> {
-    fn bar(self) -> char { // { dg-error "duplicate definitions with name bar" }
+    fn bar(self) -> char {
         self.a
     }
 }
@@ -23,4 +23,6 @@ impl<T> Foo<T> {
 fn main() {
     let a = Foo { a: 123 };
     a.bar();
+    // { dg-error "multiple candidates found for method .bar." "" { target *-*-* } .-1 }
+    // { dg-error "failed to type resolve expression" "" { target *-*-* } .-2 }
 }
diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_9.rs b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs
index fbb96a60d36..fd972e28ab3 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 "imm_deref\n123\n" } */
+/* { dg-output "mut_deref\n123\n" } */
 extern "C" {
     fn printf(s: *const i8, ...);
 }
