Skip to content

Commit 2cfcc0c

Browse files
committed
Fix regionck failure when converting Index to IndexMut
1 parent 6b09c37 commit 2cfcc0c

File tree

1 file changed

+24
-13
lines changed

1 file changed

+24
-13
lines changed

src/librustc_typeck/check/place_op.rs

+24-13
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_middle::ty::{self, Ty};
99
use rustc_span::symbol::{sym, Ident};
1010
use rustc_span::Span;
1111
use rustc_trait_selection::autoderef::Autoderef;
12+
use std::slice;
1213

1314
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1415
/// Type-check `*oprnd_expr` with `oprnd_expr` type-checked already.
@@ -245,19 +246,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
245246
}
246247

247248
match expr.kind {
248-
hir::ExprKind::Index(ref base_expr, ref index_expr) => {
249-
// We need to get the final type in case dereferences were needed for the trait
250-
// to apply (#72002).
251-
let index_expr_ty = self.typeck_results.borrow().expr_ty_adjusted(index_expr);
252-
self.convert_place_op_to_mutable(
253-
PlaceOp::Index,
254-
expr,
255-
base_expr,
256-
&[index_expr_ty],
257-
);
249+
hir::ExprKind::Index(ref base_expr, ..) => {
250+
self.convert_place_op_to_mutable(PlaceOp::Index, expr, base_expr);
258251
}
259252
hir::ExprKind::Unary(hir::UnOp::UnDeref, ref base_expr) => {
260-
self.convert_place_op_to_mutable(PlaceOp::Deref, expr, base_expr, &[]);
253+
self.convert_place_op_to_mutable(PlaceOp::Deref, expr, base_expr);
261254
}
262255
_ => {}
263256
}
@@ -269,9 +262,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
269262
op: PlaceOp,
270263
expr: &hir::Expr<'_>,
271264
base_expr: &hir::Expr<'_>,
272-
arg_tys: &[Ty<'tcx>],
273265
) {
274-
debug!("convert_place_op_to_mutable({:?}, {:?}, {:?}, {:?})", op, expr, base_expr, arg_tys);
266+
debug!("convert_place_op_to_mutable({:?}, {:?}, {:?})", op, expr, base_expr);
275267
if !self.typeck_results.borrow().is_method_call(expr) {
276268
debug!("convert_place_op_to_mutable - builtin, nothing to do");
277269
return;
@@ -286,6 +278,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
286278
.expect("place op takes something that is not a ref")
287279
.ty;
288280

281+
let arg_ty = match op {
282+
PlaceOp::Deref => None,
283+
PlaceOp::Index => {
284+
// We would need to recover the `T` used when we resolve `<_ as Index<T>>::index`
285+
// in try_index_step. This is the subst at index 1.
286+
//
287+
// Note: we should *not* use `expr_ty` of index_expr here because autoderef
288+
// during coercions can cause type of index_expr to differ from `T` (#72002).
289+
// We also could not use `expr_ty_adjusted` of index_expr because reborrowing
290+
// during coercions can also cause type of index_expr to differ from `T`,
291+
// which can potentially cause regionck failure (#74933).
292+
Some(self.typeck_results.borrow().node_substs(expr.hir_id).type_at(1))
293+
}
294+
};
295+
let arg_tys = match arg_ty {
296+
None => &[],
297+
Some(ref ty) => slice::from_ref(ty),
298+
};
299+
289300
let method = self.try_mutable_overloaded_place_op(expr.span, base_ty, arg_tys, op);
290301
let method = match method {
291302
Some(ok) => self.register_infer_ok_obligations(ok),

0 commit comments

Comments
 (0)