From 39bff4bf9c998ba77d12b36b26c604340638fa73 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Wed, 6 Apr 2022 21:27:46 -0700
Subject: [PATCH] don't report int/float ambiguity when we have previous errors

---
 .../src/traits/error_reporting/mod.rs         | 22 +++++++++++--
 .../ui/traits/no-fallback-multiple-impls.rs   | 16 ++++++++++
 .../traits/no-fallback-multiple-impls.stderr  |  9 ++++++
 src/test/ui/traits/test-2.rs                  |  4 +--
 src/test/ui/traits/test-2.stderr              | 32 ++-----------------
 5 files changed, 48 insertions(+), 35 deletions(-)
 create mode 100644 src/test/ui/traits/no-fallback-multiple-impls.rs
 create mode 100644 src/test/ui/traits/no-fallback-multiple-impls.stderr

diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 9998c5bb087e1..ac98dd5801e40 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -36,6 +36,7 @@ use rustc_span::symbol::{kw, sym};
 use rustc_span::{ExpnKind, Span, DUMMY_SP};
 use std::fmt;
 use std::iter;
+use std::ops::ControlFlow;
 
 use crate::traits::query::evaluate_obligation::InferCtxtExt as _;
 use crate::traits::query::normalize::AtExt as _;
@@ -2226,9 +2227,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
         post.dedup();
 
         if self.is_tainted_by_errors()
-            && crate_names.len() == 1
-            && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
-            && spans.len() == 0
+            && (crate_names.len() == 1
+                && spans.len() == 0
+                && ["`core`", "`alloc`", "`std`"].contains(&crate_names[0].as_str())
+                || predicate.visit_with(&mut HasNumericInferVisitor).is_break())
         {
             // Avoid complaining about other inference issues for expressions like
             // `42 >> 1`, where the types are still `{integer}`, but we want to
@@ -2666,3 +2668,17 @@ impl ArgKind {
         }
     }
 }
+
+struct HasNumericInferVisitor;
+
+impl<'tcx> ty::TypeVisitor<'tcx> for HasNumericInferVisitor {
+    type BreakTy = ();
+
+    fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
+        if matches!(ty.kind(), ty::Infer(ty::FloatVar(_) | ty::IntVar(_))) {
+            ControlFlow::Break(())
+        } else {
+            ControlFlow::CONTINUE
+        }
+    }
+}
diff --git a/src/test/ui/traits/no-fallback-multiple-impls.rs b/src/test/ui/traits/no-fallback-multiple-impls.rs
new file mode 100644
index 0000000000000..7ed3796f08b76
--- /dev/null
+++ b/src/test/ui/traits/no-fallback-multiple-impls.rs
@@ -0,0 +1,16 @@
+trait Fallback {
+    fn foo(&self) {}
+}
+
+impl Fallback for i32 {}
+
+impl Fallback for u64 {}
+
+impl Fallback for usize {}
+
+fn main() {
+    missing();
+    //~^ ERROR cannot find function `missing` in this scope
+    0.foo();
+    // But then we shouldn't report an inference ambiguity here...
+}
diff --git a/src/test/ui/traits/no-fallback-multiple-impls.stderr b/src/test/ui/traits/no-fallback-multiple-impls.stderr
new file mode 100644
index 0000000000000..61c9e5aaabdb4
--- /dev/null
+++ b/src/test/ui/traits/no-fallback-multiple-impls.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `missing` in this scope
+  --> $DIR/no-fallback-multiple-impls.rs:12:5
+   |
+LL |     missing();
+   |     ^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/src/test/ui/traits/test-2.rs b/src/test/ui/traits/test-2.rs
index d062de25ac8c1..342928e882a55 100644
--- a/src/test/ui/traits/test-2.rs
+++ b/src/test/ui/traits/test-2.rs
@@ -6,9 +6,9 @@ impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
 impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
 
 fn main() {
-    10.dup::<i32>(); //~ ERROR type annotations needed
+    10.dup::<i32>();
     //~^ ERROR this associated function takes 0 generic arguments but 1
-    10.blah::<i32, i32>(); //~ ERROR type annotations needed
+    10.blah::<i32, i32>();
     //~^ ERROR this associated function takes 1 generic argument but 2
     (Box::new(10) as Box<dyn bar>).dup();
     //~^ ERROR E0038
diff --git a/src/test/ui/traits/test-2.stderr b/src/test/ui/traits/test-2.stderr
index 5eec012458450..77ea4e4e974eb 100644
--- a/src/test/ui/traits/test-2.stderr
+++ b/src/test/ui/traits/test-2.stderr
@@ -79,35 +79,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn bar>>` for `Box<{integer}>`
    = note: required by cast to type `Box<dyn bar>`
 
-error[E0283]: type annotations needed
-  --> $DIR/test-2.rs:9:8
-   |
-LL |     10.dup::<i32>();
-   |        ^^^ cannot infer type for type `{integer}`
-   |
-note: multiple `impl`s satisfying `{integer}: bar` found
-  --> $DIR/test-2.rs:5:1
-   |
-LL | impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
-   | ^^^^^^^^^^^^^^^^
-LL | impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
-   | ^^^^^^^^^^^^^^^^
-
-error[E0283]: type annotations needed
-  --> $DIR/test-2.rs:11:8
-   |
-LL |     10.blah::<i32, i32>();
-   |        ^^^^ cannot infer type for type `{integer}`
-   |
-note: multiple `impl`s satisfying `{integer}: bar` found
-  --> $DIR/test-2.rs:5:1
-   |
-LL | impl bar for i32 { fn dup(&self) -> i32 { *self } fn blah<X>(&self) {} }
-   | ^^^^^^^^^^^^^^^^
-LL | impl bar for u32 { fn dup(&self) -> u32 { *self } fn blah<X>(&self) {} }
-   | ^^^^^^^^^^^^^^^^
-
-error: aborting due to 7 previous errors
+error: aborting due to 5 previous errors
 
-Some errors have detailed explanations: E0038, E0107, E0283.
+Some errors have detailed explanations: E0038, E0107.
 For more information about an error, try `rustc --explain E0038`.