about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-02-12 18:04:11 +0100
committerGitHub <noreply@github.com>2024-02-12 18:04:11 +0100
commit8e5f722ece25a9767bde50d4ad1b7161df1ee7f9 (patch)
tree2047975b00aa5025667ad90bed2664950db3734b /compiler
parent323f66a932cc0c16bfa98fc0556f793624e051b3 (diff)
parent95c5b060004928984b6b76a9ef67a3ca7147568c (diff)
downloadrust-8e5f722ece25a9767bde50d4ad1b7161df1ee7f9.tar.gz
rust-8e5f722ece25a9767bde50d4ad1b7161df1ee7f9.zip
Rollup merge of #120972 - lukas-code:autoderef-type-error, r=compiler-errors
fix ICE for deref coercions with type errors

Follow-up to https://github.com/rust-lang/rust/pull/120895, where I made types with errors go through the full coercion code, which is necessary if we want to build MIR for bodies with errors (https://github.com/rust-lang/rust/pull/120550).

The code for coercing `&T` to `&U` currently assumes that autoderef for `&T` will succeed for at least two steps (`&T` and `T`):

https://github.com/rust-lang/rust/blob/b17491c8f6d555386104dfd82004c01bfef09c95/compiler/rustc_hir_typeck/src/coercion.rs#L339-L464

But for types with errors, we previously only returned the no-op autoderef step (`&{type error}` -> `&{type error}`) and then stopped early. This PR changes autoderef for types with errors to still go through the built-in derefs (e.g. `&&{type error}` -> `&{type error}` -> `{type error}`) and only stop early when it would have to go looking for `Deref` trait impls.

fixes https://github.com/rust-lang/rust/issues/120945

r? ``@compiler-errors`` or compiler
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_hir_analysis/src/autoderef.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/check/wfcheck.rs10
2 files changed, 11 insertions, 7 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;
         }
     }