Skip to content

Commit

Permalink
Rollup merge of rust-lang#118112 - compiler-errors:index-ambiguity-ic…
Browse files Browse the repository at this point in the history
…e, r=aliemjay

Don't ICE when ambiguity is found when selecting `Index` implementation in typeck

Fixes rust-lang#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.
  • Loading branch information
matthiaskrgr authored Nov 21, 2023
2 parents 29c4bb1 + 273dc22 commit 2c85424
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 4 deletions.
22 changes: 18 additions & 4 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand All @@ -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
Expand Down Expand Up @@ -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,
))
Expand Down
29 changes: 29 additions & 0 deletions tests/ui/typeck/bad-index-modulo-higher-ranked-regions.rs
Original file line number Diff line number Diff line change
@@ -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| ...`
}
9 changes: 9 additions & 0 deletions tests/ui/typeck/bad-index-modulo-higher-ranked-regions.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 2c85424

Please sign in to comment.