about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs10
-rw-r--r--tests/ui/coercion/type-errors.rs19
-rw-r--r--tests/ui/coercion/type-errors.stderr14
4 files changed, 39 insertions, 12 deletions
diff --git a/compiler/rustc_hir_analysis/src/autoderef.rs b/compiler/rustc_hir_analysis/src/autoderef.rs
index 5bc904e5930..f2ceb470264 100644
--- a/compiler/rustc_hir_analysis/src/autoderef.rs
+++ b/compiler/rustc_hir_analysis/src/autoderef.rs
@@ -91,10 +91,6 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
             return None;
         };
 
-        if new_ty.references_error() {
-            return None;
-        }
-
         self.state.steps.push((self.state.cur_ty, kind));
         debug!(
             "autoderef stage #{:?} is {:?} from {:?}",
@@ -137,6 +133,10 @@ impl<'a, 'tcx> Autoderef<'a, 'tcx> {
         debug!("overloaded_deref_ty({:?})", ty);
         let tcx = self.infcx.tcx;
 
+        if ty.references_error() {
+            return None;
+        }
+
         // <ty as Deref>
         let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
         let cause = traits::ObligationCause::misc(self.span, self.body_id);
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 1bdfa452360..2c0a2f8e5b7 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -1635,6 +1635,12 @@ fn check_method_receiver<'tcx>(
     let receiver_ty = sig.inputs()[0];
     let receiver_ty = wfcx.normalize(span, None, receiver_ty);
 
+    // If the receiver already has errors reported, consider it valid to avoid
+    // unnecessary errors (#58712).
+    if receiver_ty.references_error() {
+        return Ok(());
+    }
+
     if tcx.features().arbitrary_self_types {
         if !receiver_is_valid(wfcx, span, receiver_ty, self_ty, true) {
             // Report error; `arbitrary_self_types` was enabled.
@@ -1749,9 +1755,7 @@ fn receiver_is_valid<'tcx>(
             }
         } else {
             debug!("receiver_is_valid: type `{:?}` does not deref to `{:?}`", receiver_ty, self_ty);
-            // If the receiver already has errors reported due to it, consider it valid to avoid
-            // unnecessary errors (#58712).
-            return receiver_ty.references_error();
+            return false;
         }
     }
 
diff --git a/tests/ui/coercion/type-errors.rs b/tests/ui/coercion/type-errors.rs
index a2f0e55f1b9..a86789907a0 100644
--- a/tests/ui/coercion/type-errors.rs
+++ b/tests/ui/coercion/type-errors.rs
@@ -1,15 +1,26 @@
-// Regression test for an ICE: https://github.com/rust-lang/rust/issues/120884
+// Test that we don't ICE for coercions with type errors.
 // We still need to properly go through coercions between types with errors instead of
 // shortcutting and returning success, because we need the adjustments for building the MIR.
 
 pub fn has_error() -> TypeError {}
 //~^ ERROR cannot find type `TypeError` in this scope
 
+// https://github.com/rust-lang/rust/issues/120884
+// Casting a function item to a data pointer in valid in HIR, but invalid in MIR.
+// We need an adjustment (ReifyFnPointer) to insert a cast from the function item
+// to a function pointer as a separate MIR statement.
 pub fn cast() -> *const u8 {
-    // Casting a function item to a data pointer in valid in HIR, but invalid in MIR.
-    // We need an adjustment (ReifyFnPointer) to insert a cast from the function item
-    // to a function pointer as a separate MIR statement.
     has_error as *const u8
 }
 
+// https://github.com/rust-lang/rust/issues/120945
+// This one ICEd, because we skipped the builtin deref from `&TypeError` to `TypeError`.
+pub fn autoderef_source(e: &TypeError) {
+    //~^ ERROR cannot find type `TypeError` in this scope
+    autoderef_target(e)
+}
+
+pub fn autoderef_target(_: &TypeError) {}
+//~^ ERROR cannot find type `TypeError` in this scope
+
 fn main() {}
diff --git a/tests/ui/coercion/type-errors.stderr b/tests/ui/coercion/type-errors.stderr
index 489cd9ddf13..14deb785f75 100644
--- a/tests/ui/coercion/type-errors.stderr
+++ b/tests/ui/coercion/type-errors.stderr
@@ -4,6 +4,18 @@ error[E0412]: cannot find type `TypeError` in this scope
 LL | pub fn has_error() -> TypeError {}
    |                       ^^^^^^^^^ not found in this scope
 
-error: aborting due to 1 previous error
+error[E0412]: cannot find type `TypeError` in this scope
+  --> $DIR/type-errors.rs:18:29
+   |
+LL | pub fn autoderef_source(e: &TypeError) {
+   |                             ^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `TypeError` in this scope
+  --> $DIR/type-errors.rs:23:29
+   |
+LL | pub fn autoderef_target(_: &TypeError) {}
+   |                             ^^^^^^^^^ not found in this scope
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0412`.