about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-11-21 23:46:20 +0100
committerGitHub <noreply@github.com>2023-11-21 23:46:20 +0100
commit802f71b29477799583ea1da6b59617c0c0fa5016 (patch)
tree455a936c25ceefc70d2c650fd3b97ec7f7ed5793
parenta11be28e13047956e1550d9d5cc89ec0fdde0699 (diff)
parent273dc22b04411b9c156375d15ad2c8cead2e619e (diff)
Rollup merge of #118112 - compiler-errors:index-ambiguity-ice, r=aliemjay
Don't ICE when ambiguity is found when selecting `Index` implementation in typeck

Fixes #118111

The problem here is when we're manually "selecting" an impl for `base_ty: Index<?0>`, we don't consider placeholder region errors (leak check) or ambiguous predicates. Those can lead to us not actually emitting any fulfillment errors on line 3131.
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs22
-rw-r--r--tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs29
-rw-r--r--tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr9
3 files changed, 56 insertions, 4 deletions
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 4b7de36e7c7..84e0b56dab1 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -3067,7 +3067,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             return None;
         };
 
-        self.commit_if_ok(|_| {
+        self.commit_if_ok(|snapshot| {
+            let outer_universe = self.universe();
+
             let ocx = ObligationCtxt::new(self);
             let impl_args = self.fresh_args_for_item(base_expr.span, impl_def_id);
             let impl_trait_ref =
@@ -3077,7 +3079,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Match the impl self type against the base ty. If this fails,
             // we just skip this impl, since it's not particularly useful.
             let impl_trait_ref = ocx.normalize(&cause, self.param_env, impl_trait_ref);
-            ocx.eq(&cause, self.param_env, impl_trait_ref.self_ty(), base_ty)?;
+            ocx.eq(&cause, self.param_env, base_ty, impl_trait_ref.self_ty())?;
 
             // Register the impl's predicates. One of these predicates
             // must be unsatisfied, or else we wouldn't have gotten here
@@ -3113,11 +3115,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Ty::new_projection(self.tcx, index_trait_output_def_id, impl_trait_ref.args),
             );
 
-            let errors = ocx.select_where_possible();
+            let true_errors = ocx.select_where_possible();
+
+            // Do a leak check -- we can't really report report a useful error here,
+            // but it at least avoids an ICE when the error has to do with higher-ranked
+            // lifetimes.
+            self.leak_check(outer_universe, Some(snapshot))?;
+
+            // Bail if we have ambiguity errors, which we can't report in a useful way.
+            let ambiguity_errors = ocx.select_all_or_error();
+            if true_errors.is_empty() && !ambiguity_errors.is_empty() {
+                return Err(NoSolution);
+            }
+
             // There should be at least one error reported. If not, we
             // will still delay a span bug in `report_fulfillment_errors`.
             Ok::<_, NoSolution>((
-                self.err_ctxt().report_fulfillment_errors(errors),
+                self.err_ctxt().report_fulfillment_errors(true_errors),
                 impl_trait_ref.args.type_at(1),
                 element_ty,
             ))
diff --git a/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs
new file mode 100644
index 00000000000..c8f6db7aef3
--- /dev/null
+++ b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs
@@ -0,0 +1,29 @@
+// Test against ICE in #118111
+
+use std::ops::Index;
+
+struct Map<T, F> {
+    f: F,
+    inner: T,
+}
+
+impl<T, F, Idx> Index<Idx> for Map<T, F>
+where
+    T: Index<Idx>,
+    F: FnOnce(&T, Idx) -> Idx,
+{
+    type Output = T::Output;
+
+    fn index(&self, index: Idx) -> &Self::Output {
+        todo!()
+    }
+}
+
+fn main() {
+    Map { inner: [0_usize], f: |_, i: usize| 1_usize }[0];
+    //~^ ERROR cannot index into a value of type
+    // Problem here is that
+    //   `f: |_, i: usize| ...`
+    // should be
+    //   `f: |_: &_, i: usize| ...`
+}
diff --git a/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr
new file mode 100644
index 00000000000..7c978430839
--- /dev/null
+++ b/tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr
@@ -0,0 +1,9 @@
+error[E0608]: cannot index into a value of type `Map<[usize; 1], {closure@$DIR/bad-index-modulo-higher-ranked-regions.rs:23:32: 23:45}>`
+  --> $DIR/bad-index-modulo-higher-ranked-regions.rs:23:55
+   |
+LL |     Map { inner: [0_usize], f: |_, i: usize| 1_usize }[0];
+   |                                                       ^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0608`.