From e4a4246a47b87630b1acc11b4140e044d606974e Mon Sep 17 00:00:00 2001 From: TheWastl <36932506+TheWastl@users.noreply.github.com> Date: Fri, 24 Jun 2022 22:42:47 +0200 Subject: [PATCH] const_prop_lint: Consider array length constant even if array is not --- compiler/rustc_mir_transform/src/const_prop_lint.rs | 13 ++++++++++++- .../issue-98444-const-index-out-of-bounds.rs | 8 ++++++++ .../issue-98444-const-index-out-of-bounds.stderr | 10 ++++++++++ src/test/ui/consts/issue-65348.rs | 1 + 4 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/const_prop/issue-98444-const-index-out-of-bounds.rs create mode 100644 src/test/ui/const_prop/issue-98444-const-index-out-of-bounds.stderr diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index c2ea55af48a1e..d4ad67338a2bd 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -501,12 +501,23 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { return None; } + Rvalue::Len(len_place) => { + // To get the length of an array, we don't need to know the value. + let ty = len_place.ty(self.local_decls, self.tcx).ty; + if let &ty::Array(_, len) = ty.kind() { + return self.use_ecx(source_info, |this| { + let const_len = this.ecx.const_to_op(len, None)?; + let ecx_place = this.ecx.eval_place(place)?; + this.ecx.copy_op(&const_len, &ecx_place, /*allow_transmute*/ false) + }); + } + } + // There's no other checking to do at this time. Rvalue::Aggregate(..) | Rvalue::Use(..) | Rvalue::CopyForDeref(..) | Rvalue::Repeat(..) - | Rvalue::Len(..) | Rvalue::Cast(..) | Rvalue::ShallowInitBox(..) | Rvalue::Discriminant(..) diff --git a/src/test/ui/const_prop/issue-98444-const-index-out-of-bounds.rs b/src/test/ui/const_prop/issue-98444-const-index-out-of-bounds.rs new file mode 100644 index 0000000000000..a6e0ce2103856 --- /dev/null +++ b/src/test/ui/const_prop/issue-98444-const-index-out-of-bounds.rs @@ -0,0 +1,8 @@ +// build-fail +// Need to use build-fail because check doesn't run constant propagation. + +fn main() { + let xs: [i32; 5] = [1, 2, 3, 4, 5]; + let _ = &xs; + let _ = xs[7]; //~ ERROR this operation will panic at runtime +} diff --git a/src/test/ui/const_prop/issue-98444-const-index-out-of-bounds.stderr b/src/test/ui/const_prop/issue-98444-const-index-out-of-bounds.stderr new file mode 100644 index 0000000000000..75580bbd6816e --- /dev/null +++ b/src/test/ui/const_prop/issue-98444-const-index-out-of-bounds.stderr @@ -0,0 +1,10 @@ +error: this operation will panic at runtime + --> $DIR/issue-98444-const-index-out-of-bounds.rs:7:13 + | +LL | let _ = xs[7]; + | ^^^^^ index out of bounds: the length is 5 but the index is 7 + | + = note: `#[deny(unconditional_panic)]` on by default + +error: aborting due to previous error + diff --git a/src/test/ui/consts/issue-65348.rs b/src/test/ui/consts/issue-65348.rs index 5eafa831d6317..e3a8c2c922bb1 100644 --- a/src/test/ui/consts/issue-65348.rs +++ b/src/test/ui/consts/issue-65348.rs @@ -1,4 +1,5 @@ // check-pass +#![allow(unconditional_panic)] struct Generic(T);