From 273dc22b04411b9c156375d15ad2c8cead2e619e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 20 Nov 2023 23:35:20 +0000 Subject: [PATCH] Don't ICE when ambiguity is found when selecting Index implementation in typeck --- compiler/rustc_hir_typeck/src/expr.rs | 22 +++++++++++--- .../bad-index-modulo-higher-ranked-regions.rs | 29 +++++++++++++++++++ ...-index-modulo-higher-ranked-regions.stderr | 9 ++++++ 3 files changed, 56 insertions(+), 4 deletions(-) create mode 100644 tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs create mode 100644 tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d9b27fc13182c..8fcbe90e91a8c 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3064,7 +3064,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 = @@ -3074,7 +3076,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 @@ -3110,11 +3112,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 0000000000000..c8f6db7aef3e5 --- /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 { + f: F, + inner: T, +} + +impl Index for Map +where + T: Index, + 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 0000000000000..7c97843083916 --- /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`.