Skip to content

Commit 7b45718

Browse files
committed
pass when where clause found
1 parent 75b7e52 commit 7b45718

File tree

7 files changed

+229
-2
lines changed

7 files changed

+229
-2
lines changed

compiler/rustc_typeck/src/check/writeback.rs

+24-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// substitutions.
44

55
use crate::check::FnCtxt;
6-
76
use hir::def_id::LocalDefId;
87
use rustc_data_structures::fx::FxHashMap;
98
use rustc_errors::ErrorGuaranteed;
@@ -16,6 +15,7 @@ use rustc_middle::mir::FakeReadCause;
1615
use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
1716
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
1817
use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
18+
use rustc_middle::ty::TypeckResults;
1919
use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt};
2020
use rustc_span::symbol::sym;
2121
use rustc_span::Span;
@@ -192,6 +192,27 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
192192
}
193193
}
194194

195+
// (ouz-a 1005988): Normally `[T] : std::ops::Index<usize>` should be normalized
196+
// into [T] but currently `Where` clause stops the normalization process for it,
197+
// here we compare types of expr and base in a code without `Where` clause they would be equal
198+
// if they are not we don't modify the expr, hence we bypass the ICE
199+
fn is_builtin_index(
200+
&mut self,
201+
typeck_results: &TypeckResults<'tcx>,
202+
e: &hir::Expr<'_>,
203+
base_ty: Ty<'tcx>,
204+
index_ty: Ty<'tcx>,
205+
) -> bool {
206+
if let Some(elem_ty) = base_ty.builtin_index() {
207+
let Some(exp_ty) = typeck_results.expr_ty_opt(e) else {return false;};
208+
let resolved_exp_ty = self.resolve(exp_ty, &e.span);
209+
210+
elem_ty == resolved_exp_ty && index_ty == self.fcx.tcx.types.usize
211+
} else {
212+
false
213+
}
214+
}
215+
195216
// Similar to operators, indexing is always assumed to be overloaded
196217
// Here, correct cases where an indexing expression can be simplified
197218
// to use builtin indexing because the index type is known to be
@@ -222,8 +243,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
222243
)
223244
});
224245
let index_ty = self.fcx.resolve_vars_if_possible(index_ty);
246+
let resolved_base_ty = self.resolve(*base_ty, &base.span);
225247

226-
if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize {
248+
if self.is_builtin_index(&typeck_results, e, resolved_base_ty, index_ty) {
227249
// Remove the method call record
228250
typeck_results.type_dependent_defs_mut().remove(e.hir_id);
229251
typeck_results.node_substs_mut().remove(e.hir_id);

src/test/mir-opt/issue-91633.rs

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// compile-flags: -Z mir-opt-level=0
2+
// EMIT_MIR issue_91633.hey.mir_map.0.mir
3+
fn hey<T> (it: &[T])
4+
where
5+
[T] : std::ops::Index<usize>,
6+
{
7+
let _ = &it[0];
8+
}
9+
10+
// EMIT_MIR issue_91633.bar.mir_map.0.mir
11+
fn bar<T> (it: Box<[T]>)
12+
where
13+
[T] : std::ops::Index<usize>,
14+
{
15+
let _ = it[0];
16+
}
17+
18+
// EMIT_MIR issue_91633.fun.mir_map.0.mir
19+
fn fun<T> (it: &[T]) -> &T
20+
{
21+
let f = &it[0];
22+
f
23+
}
24+
25+
// EMIT_MIR issue_91633.foo.mir_map.0.mir
26+
fn foo<T: Clone> (it: Box<[T]>) -> T
27+
{
28+
let f = it[0].clone();
29+
f
30+
}
31+
fn main(){}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
// MIR for `bar` 0 mir_map
2+
3+
fn bar(_1: Box<[T]>) -> () {
4+
debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14
5+
let mut _0: (); // return place in scope 0 at $DIR/issue-91633.rs:+1:2: +1:2
6+
let mut _2: &<[T] as std::ops::Index<usize>>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:19
7+
let mut _3: &[T]; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:16
8+
scope 1 {
9+
}
10+
11+
bb0: {
12+
StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:19
13+
StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:16
14+
_3 = &(*_1); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:16
15+
_2 = <[T] as Index<usize>>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-91633.rs:+4:14: +4:19
16+
// mir::Constant
17+
// + span: $DIR/issue-91633.rs:15:14: 15:19
18+
// + literal: Const { ty: for<'r> fn(&'r [T], usize) -> &'r <[T] as Index<usize>>::Output {<[T] as Index<usize>>::index}, val: Value(<ZST>) }
19+
}
20+
21+
bb1: {
22+
StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+4:18: +4:19
23+
StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:19: +4:20
24+
_0 = const (); // scope 0 at $DIR/issue-91633.rs:+3:2: +5:3
25+
drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3
26+
}
27+
28+
bb2: {
29+
return; // scope 0 at $DIR/issue-91633.rs:+5:3: +5:3
30+
}
31+
32+
bb3 (cleanup): {
33+
drop(_1) -> bb4; // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3
34+
}
35+
36+
bb4 (cleanup): {
37+
resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +5:3
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// MIR for `foo` 0 mir_map
2+
3+
fn foo(_1: Box<[T]>) -> T {
4+
debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:19: +0:21
5+
let mut _0: T; // return place in scope 0 at $DIR/issue-91633.rs:+0:36: +0:37
6+
let _2: T; // in scope 0 at $DIR/issue-91633.rs:+2:10: +2:11
7+
let mut _3: &T; // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:27
8+
let _4: usize; // in scope 0 at $DIR/issue-91633.rs:+2:17: +2:18
9+
let mut _5: usize; // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:19
10+
let mut _6: bool; // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:19
11+
scope 1 {
12+
debug f => _2; // in scope 1 at $DIR/issue-91633.rs:+2:10: +2:11
13+
}
14+
15+
bb0: {
16+
StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11
17+
StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27
18+
StorageLive(_4); // scope 0 at $DIR/issue-91633.rs:+2:17: +2:18
19+
_4 = const 0_usize; // scope 0 at $DIR/issue-91633.rs:+2:17: +2:18
20+
_5 = Len((*_1)); // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19
21+
_6 = Lt(_4, _5); // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19
22+
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
23+
}
24+
25+
bb1: {
26+
_3 = &(*_1)[_4]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27
27+
_2 = <T as Clone>::clone(move _3) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27
28+
// mir::Constant
29+
// + span: $DIR/issue-91633.rs:28:20: 28:25
30+
// + literal: Const { ty: for<'r> fn(&'r T) -> T {<T as Clone>::clone}, val: Value(<ZST>) }
31+
}
32+
33+
bb2: {
34+
StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+2:26: +2:27
35+
FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11
36+
StorageDead(_4); // scope 0 at $DIR/issue-91633.rs:+2:27: +2:28
37+
_0 = move _2; // scope 1 at $DIR/issue-91633.rs:+3:6: +3:7
38+
drop(_2) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3
39+
}
40+
41+
bb3: {
42+
StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3
43+
drop(_1) -> [return: bb4, unwind: bb6]; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3
44+
}
45+
46+
bb4: {
47+
return; // scope 0 at $DIR/issue-91633.rs:+4:3: +4:3
48+
}
49+
50+
bb5 (cleanup): {
51+
drop(_1) -> bb6; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3
52+
}
53+
54+
bb6 (cleanup): {
55+
resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +4:3
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// MIR for `fun` 0 mir_map
2+
3+
fn fun(_1: &[T]) -> &T {
4+
debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14
5+
let mut _0: &T; // return place in scope 0 at $DIR/issue-91633.rs:+0:25: +0:27
6+
let _2: &T; // in scope 0 at $DIR/issue-91633.rs:+2:10: +2:11
7+
let _3: usize; // in scope 0 at $DIR/issue-91633.rs:+2:18: +2:19
8+
let mut _4: usize; // in scope 0 at $DIR/issue-91633.rs:+2:15: +2:20
9+
let mut _5: bool; // in scope 0 at $DIR/issue-91633.rs:+2:15: +2:20
10+
scope 1 {
11+
debug f => _2; // in scope 1 at $DIR/issue-91633.rs:+2:10: +2:11
12+
}
13+
14+
bb0: {
15+
StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11
16+
StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+2:18: +2:19
17+
_3 = const 0_usize; // scope 0 at $DIR/issue-91633.rs:+2:18: +2:19
18+
_4 = Len((*_1)); // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20
19+
_5 = Lt(_3, _4); // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20
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
21+
}
22+
23+
bb1: {
24+
_2 = &(*_1)[_3]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:20
25+
FakeRead(ForLet(None), _2); // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11
26+
_0 = &(*_2); // scope 1 at $DIR/issue-91633.rs:+3:6: +3:7
27+
StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3
28+
StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3
29+
return; // scope 0 at $DIR/issue-91633.rs:+4:3: +4:3
30+
}
31+
32+
bb2 (cleanup): {
33+
resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +4:3
34+
}
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// MIR for `hey` 0 mir_map
2+
3+
fn hey(_1: &[T]) -> () {
4+
debug it => _1; // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14
5+
let mut _0: (); // return place in scope 0 at $DIR/issue-91633.rs:+1:2: +1:2
6+
let mut _2: &<[T] as std::ops::Index<usize>>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:20
7+
let _3: &<[T] as std::ops::Index<usize>>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:15: +4:20
8+
let mut _4: &[T]; // in scope 0 at $DIR/issue-91633.rs:+4:15: +4:17
9+
scope 1 {
10+
}
11+
12+
bb0: {
13+
StorageLive(_2); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:20
14+
StorageLive(_3); // scope 0 at $DIR/issue-91633.rs:+4:15: +4:20
15+
StorageLive(_4); // scope 0 at $DIR/issue-91633.rs:+4:15: +4:17
16+
_4 = &(*_1); // scope 0 at $DIR/issue-91633.rs:+4:15: +4:17
17+
_3 = <[T] as Index<usize>>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/issue-91633.rs:+4:15: +4:20
18+
// mir::Constant
19+
// + span: $DIR/issue-91633.rs:7:15: 7:20
20+
// + literal: Const { ty: for<'r> fn(&'r [T], usize) -> &'r <[T] as Index<usize>>::Output {<[T] as Index<usize>>::index}, val: Value(<ZST>) }
21+
}
22+
23+
bb1: {
24+
StorageDead(_4); // scope 0 at $DIR/issue-91633.rs:+4:19: +4:20
25+
_2 = &(*_3); // scope 0 at $DIR/issue-91633.rs:+4:14: +4:20
26+
StorageDead(_2); // scope 0 at $DIR/issue-91633.rs:+4:20: +4:21
27+
_0 = const (); // scope 0 at $DIR/issue-91633.rs:+3:2: +5:3
28+
StorageDead(_3); // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3
29+
return; // scope 0 at $DIR/issue-91633.rs:+5:3: +5:3
30+
}
31+
32+
bb2 (cleanup): {
33+
resume; // scope 0 at $DIR/issue-91633.rs:+0:1: +5:3
34+
}
35+
}

src/test/ui/typeck/issue-91633.rs

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// check-pass
2+
fn f<T> (it: &[T])
3+
where
4+
[T] : std::ops::Index<usize>,
5+
{
6+
let _ = &it[0];
7+
}
8+
fn main(){}

0 commit comments

Comments
 (0)