Skip to content

Commit 94241e7

Browse files
authored
Rollup merge of #103584 - ouz-a:issue-102303, r=oli-obk
Remove bounds check when array is indexed by enum As the title says, this reverts the behavior introduced with 1.64. Fixes #102303 r? `@oli-obk`
2 parents 4363467 + a1672ad commit 94241e7

File tree

9 files changed

+120
-19
lines changed

9 files changed

+120
-19
lines changed

compiler/rustc_mir_build/src/build/expr/as_rvalue.rs

+50-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use rustc_index::vec::Idx;
44
use rustc_middle::ty::util::IntTypeExt;
5+
use rustc_target::abi::{Abi, Primitive};
56

67
use crate::build::expr::as_place::PlaceBase;
78
use crate::build::expr::category::{Category, RvalueFunc};
@@ -198,15 +199,63 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
198199
let (source, ty) = if let ty::Adt(adt_def, ..) = source.ty.kind() && adt_def.is_enum() {
199200
let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx);
200201
let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not));
202+
let layout = this.tcx.layout_of(this.param_env.and(source.ty));
201203
let discr = this.temp(discr_ty, source.span);
202204
this.cfg.push_assign(
203205
block,
204206
source_info,
205207
discr,
206208
Rvalue::Discriminant(temp.into()),
207209
);
210+
let (op,ty) = (Operand::Move(discr), discr_ty);
211+
212+
if let Abi::Scalar(scalar) = layout.unwrap().abi{
213+
if let Primitive::Int(_, signed) = scalar.primitive() {
214+
let range = scalar.valid_range(&this.tcx);
215+
// FIXME: Handle wraparound cases too.
216+
if range.end >= range.start {
217+
let mut assumer = |range: u128, bin_op: BinOp| {
218+
// We will be overwriting this val if our scalar is signed value
219+
// because sign extension on unsigned types might cause unintended things
220+
let mut range_val =
221+
ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(discr_ty));
222+
let bool_ty = this.tcx.types.bool;
223+
if signed {
224+
let scalar_size_extend = scalar.size(&this.tcx).sign_extend(range);
225+
let discr_layout = this.tcx.layout_of(this.param_env.and(discr_ty));
226+
let truncated_val = discr_layout.unwrap().size.truncate(scalar_size_extend);
227+
range_val = ConstantKind::from_bits(
228+
this.tcx,
229+
truncated_val,
230+
ty::ParamEnv::empty().and(discr_ty),
231+
);
232+
}
233+
let lit_op = this.literal_operand(expr.span, range_val);
234+
let is_bin_op = this.temp(bool_ty, expr_span);
235+
this.cfg.push_assign(
236+
block,
237+
source_info,
238+
is_bin_op,
239+
Rvalue::BinaryOp(bin_op, Box::new(((lit_op), (Operand::Copy(discr))))),
240+
);
241+
this.cfg.push(
242+
block,
243+
Statement {
244+
source_info,
245+
kind: StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(
246+
Operand::Copy(is_bin_op),
247+
))),
248+
},
249+
)
250+
};
251+
assumer(range.end, BinOp::Ge);
252+
assumer(range.start, BinOp::Le);
253+
}
254+
}
255+
}
256+
257+
(op,ty)
208258

209-
(Operand::Move(discr), discr_ty)
210259
} else {
211260
let ty = source.ty;
212261
let source = unpack!(

compiler/rustc_mir_transform/src/check_unsafety.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -101,12 +101,10 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
101101
| StatementKind::Retag { .. }
102102
| StatementKind::AscribeUserType(..)
103103
| StatementKind::Coverage(..)
104+
| StatementKind::Intrinsic(..)
104105
| StatementKind::Nop => {
105106
// safe (at least as emitted during MIR construction)
106107
}
107-
108-
// Move to above list once mir construction uses it.
109-
StatementKind::Intrinsic(..) => unreachable!(),
110108
}
111109
self.super_statement(statement, location);
112110
}

src/test/codegen/enum-bounds-check-derived-idx.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,13 @@ pub enum Bar {
1212
// CHECK-LABEL: @lookup_inc
1313
#[no_mangle]
1414
pub fn lookup_inc(buf: &[u8; 5], f: Bar) -> u8 {
15-
// FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332
16-
// CHECK: panic_bounds_check
15+
// CHECK-NOT: panic_bounds_check
1716
buf[f as usize + 1]
1817
}
1918

2019
// CHECK-LABEL: @lookup_dec
2120
#[no_mangle]
2221
pub fn lookup_dec(buf: &[u8; 5], f: Bar) -> u8 {
23-
// FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332
24-
// CHECK: panic_bounds_check
22+
// CHECK-NOT: panic_bounds_check
2523
buf[f as usize - 1]
2624
}

src/test/codegen/enum-bounds-check-issue-13926.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ pub enum Exception {
1313
// CHECK-LABEL: @access
1414
#[no_mangle]
1515
pub fn access(array: &[usize; 12], exc: Exception) -> usize {
16-
// FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332
17-
// CHECK: panic_bounds_check
16+
// CHECK-NOT: panic_bounds_check
1817
array[(exc as u8 - 4) as usize]
1918
}

src/test/codegen/enum-bounds-check.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ pub enum Bar {
2121
// CHECK-LABEL: @lookup_unmodified
2222
#[no_mangle]
2323
pub fn lookup_unmodified(buf: &[u8; 5], f: Bar) -> u8 {
24-
// FIXME: panic check can be removed by adding the assumes back after https://github.com/rust-lang/rust/pull/98332
25-
// CHECK: panic_bounds_check
24+
// CHECK-NOT: panic_bounds_check
2625
buf[f as usize]
2726
}

src/test/mir-opt/building/enum_cast.bar.built.after.mir

+6
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@ fn bar(_1: Bar) -> usize {
55
let mut _0: usize; // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
66
let _2: Bar; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
77
let mut _3: isize; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
8+
let mut _4: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
9+
let mut _5: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
810

911
bb0: {
1012
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
1113
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
1214
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
15+
_4 = Ge(const 1_isize, _3); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
16+
assume(_4); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
17+
_5 = Le(const 0_isize, _3); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
18+
assume(_5); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
1319
_0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
1420
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
1521
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2

src/test/mir-opt/building/enum_cast.boo.built.after.mir

+6
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,17 @@ fn boo(_1: Boo) -> usize {
55
let mut _0: usize; // return place in scope 0 at $DIR/enum_cast.rs:+0:21: +0:26
66
let _2: Boo; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
77
let mut _3: u8; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
8+
let mut _4: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
9+
let mut _5: bool; // in scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
810

911
bb0: {
1012
StorageLive(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
1113
_2 = move _1; // scope 0 at $DIR/enum_cast.rs:+1:5: +1:8
1214
_3 = discriminant(_2); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
15+
_4 = Ge(const 1_u8, _3); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
16+
assume(_4); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
17+
_5 = Le(const 0_u8, _3); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
18+
assume(_5); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
1319
_0 = move _3 as usize (IntToInt); // scope 0 at $DIR/enum_cast.rs:+1:5: +1:17
1420
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+1:16: +1:17
1521
return; // scope 0 at $DIR/enum_cast.rs:+2:2: +2:2

src/test/mir-opt/building/enum_cast.droppy.built.after.mir

+13-7
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ fn droppy() -> () {
66
let _2: Droppy; // in scope 0 at $DIR/enum_cast.rs:+2:13: +2:14
77
let _4: Droppy; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
88
let mut _5: isize; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:18
9-
let _6: Droppy; // in scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
9+
let mut _6: bool; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
10+
let mut _7: bool; // in scope 0 at $DIR/enum_cast.rs:+5:17: +5:27
11+
let _8: Droppy; // in scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
1012
scope 1 {
1113
debug x => _2; // in scope 1 at $DIR/enum_cast.rs:+2:13: +2:14
1214
scope 2 {
@@ -17,7 +19,7 @@ fn droppy() -> () {
1719
}
1820
}
1921
scope 4 {
20-
debug z => _6; // in scope 4 at $DIR/enum_cast.rs:+7:9: +7:10
22+
debug z => _8; // in scope 4 at $DIR/enum_cast.rs:+7:9: +7:10
2123
}
2224

2325
bb0: {
@@ -29,6 +31,10 @@ fn droppy() -> () {
2931
StorageLive(_4); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
3032
_4 = move _2; // scope 3 at $DIR/enum_cast.rs:+5:17: +5:18
3133
_5 = discriminant(_4); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
34+
_6 = Ge(const 2_isize, _5); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
35+
assume(_6); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
36+
_7 = Le(const 0_isize, _5); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
37+
assume(_7); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
3238
_3 = move _5 as usize (IntToInt); // scope 3 at $DIR/enum_cast.rs:+5:17: +5:27
3339
drop(_4) -> [return: bb1, unwind: bb4]; // scope 3 at $DIR/enum_cast.rs:+5:26: +5:27
3440
}
@@ -44,15 +50,15 @@ fn droppy() -> () {
4450
bb2: {
4551
StorageDead(_2); // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6
4652
StorageDead(_1); // scope 0 at $DIR/enum_cast.rs:+6:5: +6:6
47-
StorageLive(_6); // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
48-
_6 = Droppy::B; // scope 0 at $DIR/enum_cast.rs:+7:13: +7:22
49-
FakeRead(ForLet(None), _6); // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
53+
StorageLive(_8); // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
54+
_8 = Droppy::B; // scope 0 at $DIR/enum_cast.rs:+7:13: +7:22
55+
FakeRead(ForLet(None), _8); // scope 0 at $DIR/enum_cast.rs:+7:9: +7:10
5056
_0 = const (); // scope 0 at $DIR/enum_cast.rs:+0:13: +8:2
51-
drop(_6) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2
57+
drop(_8) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2
5258
}
5359

5460
bb3: {
55-
StorageDead(_6); // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2
61+
StorageDead(_8); // scope 0 at $DIR/enum_cast.rs:+8:1: +8:2
5662
return; // scope 0 at $DIR/enum_cast.rs:+8:2: +8:2
5763
}
5864

src/test/ui/type-alias-enum-variants/self-in-enum-definition.stderr

+40
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,46 @@ LL | V3 = Self::V1 {} as u8 + 2,
1212
note: ...which requires const-evaluating + checking `Alpha::V3::{constant#0}`...
1313
--> $DIR/self-in-enum-definition.rs:5:10
1414
|
15+
LL | V3 = Self::V1 {} as u8 + 2,
16+
| ^^^^^^^^^^^^^^^^^^^^^
17+
note: ...which requires caching mir of `Alpha::V3::{constant#0}` for CTFE...
18+
--> $DIR/self-in-enum-definition.rs:5:10
19+
|
20+
LL | V3 = Self::V1 {} as u8 + 2,
21+
| ^^^^^^^^^^^^^^^^^^^^^
22+
note: ...which requires elaborating drops for `Alpha::V3::{constant#0}`...
23+
--> $DIR/self-in-enum-definition.rs:5:10
24+
|
25+
LL | V3 = Self::V1 {} as u8 + 2,
26+
| ^^^^^^^^^^^^^^^^^^^^^
27+
note: ...which requires borrow-checking `Alpha::V3::{constant#0}`...
28+
--> $DIR/self-in-enum-definition.rs:5:10
29+
|
30+
LL | V3 = Self::V1 {} as u8 + 2,
31+
| ^^^^^^^^^^^^^^^^^^^^^
32+
note: ...which requires processing MIR for `Alpha::V3::{constant#0}`...
33+
--> $DIR/self-in-enum-definition.rs:5:10
34+
|
35+
LL | V3 = Self::V1 {} as u8 + 2,
36+
| ^^^^^^^^^^^^^^^^^^^^^
37+
note: ...which requires const checking `Alpha::V3::{constant#0}`...
38+
--> $DIR/self-in-enum-definition.rs:5:10
39+
|
40+
LL | V3 = Self::V1 {} as u8 + 2,
41+
| ^^^^^^^^^^^^^^^^^^^^^
42+
note: ...which requires preparing `Alpha::V3::{constant#0}` for borrow checking...
43+
--> $DIR/self-in-enum-definition.rs:5:10
44+
|
45+
LL | V3 = Self::V1 {} as u8 + 2,
46+
| ^^^^^^^^^^^^^^^^^^^^^
47+
note: ...which requires unsafety-checking `Alpha::V3::{constant#0}`...
48+
--> $DIR/self-in-enum-definition.rs:5:10
49+
|
50+
LL | V3 = Self::V1 {} as u8 + 2,
51+
| ^^^^^^^^^^^^^^^^^^^^^
52+
note: ...which requires building MIR for `Alpha::V3::{constant#0}`...
53+
--> $DIR/self-in-enum-definition.rs:5:10
54+
|
1555
LL | V3 = Self::V1 {} as u8 + 2,
1656
| ^^^^^^^^^^^^^^^^^^^^^
1757
= note: ...which requires computing layout of `Alpha`...

0 commit comments

Comments
 (0)