diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index f549807c39c..adcf8ff946d 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -3,7 +3,6 @@ // substitutions. use crate::check::FnCtxt; - use hir::def_id::LocalDefId; use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; @@ -16,6 +15,7 @@ use rustc_middle::mir::FakeReadCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast}; use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable}; +use rustc_middle::ty::TypeckResults; use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt}; use rustc_span::symbol::sym; use rustc_span::Span; @@ -192,6 +192,27 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } } + // (ouz-a 1005988): Normally `[T] : std::ops::Index` should be normalized + // into [T] but currently `Where` clause stops the normalization process for it, + // here we compare types of expr and base in a code without `Where` clause they would be equal + // if they are not we don't modify the expr, hence we bypass the ICE + fn is_builtin_index( + &mut self, + typeck_results: &TypeckResults<'tcx>, + e: &hir::Expr<'_>, + base_ty: Ty<'tcx>, + index_ty: Ty<'tcx>, + ) -> bool { + if let Some(elem_ty) = base_ty.builtin_index() { + let Some(exp_ty) = typeck_results.expr_ty_opt(e) else {return false;}; + let resolved_exp_ty = self.resolve(exp_ty, &e.span); + + elem_ty == resolved_exp_ty && index_ty == self.fcx.tcx.types.usize + } else { + false + } + } + // Similar to operators, indexing is always assumed to be overloaded // Here, correct cases where an indexing expression can be simplified // to use builtin indexing because the index type is known to be @@ -222,8 +243,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { ) }); let index_ty = self.fcx.resolve_vars_if_possible(index_ty); + let resolved_base_ty = self.resolve(*base_ty, &base.span); - if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize { + if self.is_builtin_index(&typeck_results, e, resolved_base_ty, index_ty) { // Remove the method call record typeck_results.type_dependent_defs_mut().remove(e.hir_id); typeck_results.node_substs_mut().remove(e.hir_id); diff --git a/src/test/mir-opt/issue-91633.rs b/src/test/mir-opt/issue-91633.rs new file mode 100644 index 00000000000..8f66019857f --- /dev/null +++ b/src/test/mir-opt/issue-91633.rs @@ -0,0 +1,31 @@ +// compile-flags: -Z mir-opt-level=0 +// EMIT_MIR issue_91633.hey.mir_map.0.mir +fn hey (it: &[T]) + where + [T] : std::ops::Index, + { + let _ = &it[0]; + } + +// EMIT_MIR issue_91633.bar.mir_map.0.mir +fn bar (it: Box<[T]>) + where + [T] : std::ops::Index, + { + let _ = it[0]; + } + +// EMIT_MIR issue_91633.fun.mir_map.0.mir +fn fun (it: &[T]) -> &T + { + let f = &it[0]; + f + } + +// EMIT_MIR issue_91633.foo.mir_map.0.mir +fn foo (it: Box<[T]>) -> T + { + let f = it[0].clone(); + f + } + fn main(){} diff --git a/src/test/mir-opt/issue_91633.bar.mir_map.0.mir b/src/test/mir-opt/issue_91633.bar.mir_map.0.mir new file mode 100644 index 00000000000..f5092d2ac92 --- /dev/null +++ b/src/test/mir-opt/issue_91633.bar.mir_map.0.mir @@ -0,0 +1,39 @@ +// MIR for `bar` 0 mir_map + +fn bar(_1: Box<[T]>) -> () { + debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14 + let mut _0: (); // return place in scope 0 at $DIR/issue-91633.rs:+1:2: +1:2 + let mut _2: &<[T] as std::ops::Index>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:19 + let mut _3: &[T]; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:16 + scope 1 { + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:19 + StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:16 + _3 = &(*_1); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:16 + _2 = <[T] as Index>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-91633.rs:+4:14: +4:19 + // mir::Constant + // + span: $DIR/issue-91633.rs:15:14: 15:19 + // + literal: Const { ty: for<'r> fn(&'r [T], usize) -> &'r <[T] as Index>::Output {<[T] as Index>::index}, val: Value() } + } + + bb1: { + StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+4:18: +4:19 + StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:19: +4:20 + _0 = const (); // scope 0 at $DIR/issue-91633.rs:+3:2: +5:3 + drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3 + } + + bb2: { + return; // scope 0 at $DIR/issue-91633.rs:+5:3: +5:3 + } + + bb3 (cleanup): { + drop(_1) -> bb4; // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3 + } + + bb4 (cleanup): { + resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +5:3 + } +} diff --git a/src/test/mir-opt/issue_91633.foo.mir_map.0.mir b/src/test/mir-opt/issue_91633.foo.mir_map.0.mir new file mode 100644 index 00000000000..2e8b0feedd3 --- /dev/null +++ b/src/test/mir-opt/issue_91633.foo.mir_map.0.mir @@ -0,0 +1,57 @@ +// MIR for `foo` 0 mir_map + +fn foo(_1: Box<[T]>) -> T { + debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:19: +0:21 + let mut _0: T; // return place in scope 0 at $DIR/issue-91633.rs:+0:36: +0:37 + let _2: T; // in scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 + let mut _3: &T; // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 + let _4: usize; // in scope 0 at $DIR/issue-91633.rs:+2:17: +2:18 + let mut _5: usize; // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 + let mut _6: bool; // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 + scope 1 { + debug f => _2; // in scope 1 at $DIR/issue-91633.rs:+2:10: +2:11 + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 + StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 + StorageLive(_4); // scope 0 at $DIR/issue-91633.rs:+2:17: +2:18 + _4 = const 0_usize; // scope 0 at $DIR/issue-91633.rs:+2:17: +2:18 + _5 = Len((*_1)); // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 + _6 = Lt(_4, _5); // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 + assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19 + } + + bb1: { + _3 = &(*_1)[_4]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 + _2 = ::clone(move _3) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27 + // mir::Constant + // + span: $DIR/issue-91633.rs:28:20: 28:25 + // + literal: Const { ty: for<'r> fn(&'r T) -> T {::clone}, val: Value() } + } + + bb2: { + StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+2:26: +2:27 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 + StorageDead(_4); // scope 0 at $DIR/issue-91633.rs:+2:27: +2:28 + _0 = move _2; // scope 1 at $DIR/issue-91633.rs:+3:6: +3:7 + drop(_2) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + } + + bb3: { + StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + drop(_1) -> [return: bb4, unwind: bb6]; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + } + + bb4: { + return; // scope 0 at $DIR/issue-91633.rs:+4:3: +4:3 + } + + bb5 (cleanup): { + drop(_1) -> bb6; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + } + + bb6 (cleanup): { + resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +4:3 + } +} diff --git a/src/test/mir-opt/issue_91633.fun.mir_map.0.mir b/src/test/mir-opt/issue_91633.fun.mir_map.0.mir new file mode 100644 index 00000000000..ded9a4cf7e3 --- /dev/null +++ b/src/test/mir-opt/issue_91633.fun.mir_map.0.mir @@ -0,0 +1,35 @@ +// MIR for `fun` 0 mir_map + +fn fun(_1: &[T]) -> &T { + debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14 + let mut _0: &T; // return place in scope 0 at $DIR/issue-91633.rs:+0:25: +0:27 + let _2: &T; // in scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 + let _3: usize; // in scope 0 at $DIR/issue-91633.rs:+2:18: +2:19 + let mut _4: usize; // in scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 + let mut _5: bool; // in scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 + scope 1 { + debug f => _2; // in scope 1 at $DIR/issue-91633.rs:+2:10: +2:11 + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 + StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+2:18: +2:19 + _3 = const 0_usize; // scope 0 at $DIR/issue-91633.rs:+2:18: +2:19 + _4 = Len((*_1)); // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 + _5 = Lt(_3, _4); // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 + assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb2]; // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20 + } + + bb1: { + _2 = &(*_1)[_3]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:20 + FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11 + _0 = &(*_2); // scope 1 at $DIR/issue-91633.rs:+3:6: +3:7 + StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3 + return; // scope 0 at $DIR/issue-91633.rs:+4:3: +4:3 + } + + bb2 (cleanup): { + resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +4:3 + } +} diff --git a/src/test/mir-opt/issue_91633.hey.mir_map.0.mir b/src/test/mir-opt/issue_91633.hey.mir_map.0.mir new file mode 100644 index 00000000000..74f4a5a9761 --- /dev/null +++ b/src/test/mir-opt/issue_91633.hey.mir_map.0.mir @@ -0,0 +1,35 @@ +// MIR for `hey` 0 mir_map + +fn hey(_1: &[T]) -> () { + debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14 + let mut _0: (); // return place in scope 0 at $DIR/issue-91633.rs:+1:2: +1:2 + let mut _2: &<[T] as std::ops::Index>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:20 + let _3: &<[T] as std::ops::Index>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:15: +4:20 + let mut _4: &[T]; // in scope 0 at $DIR/issue-91633.rs:+4:15: +4:17 + scope 1 { + } + + bb0: { + StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:20 + StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+4:15: +4:20 + StorageLive(_4); // scope 0 at $DIR/issue-91633.rs:+4:15: +4:17 + _4 = &(*_1); // scope 0 at $DIR/issue-91633.rs:+4:15: +4:17 + _3 = <[T] as Index>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/issue-91633.rs:+4:15: +4:20 + // mir::Constant + // + span: $DIR/issue-91633.rs:7:15: 7:20 + // + literal: Const { ty: for<'r> fn(&'r [T], usize) -> &'r <[T] as Index>::Output {<[T] as Index>::index}, val: Value() } + } + + bb1: { + StorageDead(_4); // scope 0 at $DIR/issue-91633.rs:+4:19: +4:20 + _2 = &(*_3); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:20 + StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:20: +4:21 + _0 = const (); // scope 0 at $DIR/issue-91633.rs:+3:2: +5:3 + StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3 + return; // scope 0 at $DIR/issue-91633.rs:+5:3: +5:3 + } + + bb2 (cleanup): { + resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +5:3 + } +} diff --git a/src/test/ui/typeck/issue-91633.rs b/src/test/ui/typeck/issue-91633.rs new file mode 100644 index 00000000000..331a798dd7a --- /dev/null +++ b/src/test/ui/typeck/issue-91633.rs @@ -0,0 +1,8 @@ +// check-pass +fn f (it: &[T]) +where + [T] : std::ops::Index, +{ + let _ = &it[0]; +} +fn main(){}