Skip to content

const_prop_lint: Consider array length constant even if array is not #100160

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion compiler/rustc_mir_transform/src/const_prop_lint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -501,12 +501,23 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
return None;
}

Rvalue::Len(len_place) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should make the same change in the const_prop pass as well:

but that doesn't have to be in this PR 🙂

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

afaicr this is not necessary, because there are optimizations taking care of this before const prop runs

// 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(..)
Expand Down
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -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

1 change: 1 addition & 0 deletions src/test/ui/consts/issue-65348.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// check-pass
#![allow(unconditional_panic)]

struct Generic<T>(T);

Expand Down
34 changes: 33 additions & 1 deletion src/tools/clippy/tests/ui/indexing_slicing_index.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,23 @@
error: this operation will panic at runtime
--> $DIR/indexing_slicing_index.rs:23:5
|
LL | x[4]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
| ^^^^ index out of bounds: the length is 4 but the index is 4
|
= note: `#[deny(unconditional_panic)]` on by default

error: this operation will panic at runtime
--> $DIR/indexing_slicing_index.rs:24:5
|
LL | x[1 << 3]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
| ^^^^^^^^^ index out of bounds: the length is 4 but the index is 8

error: this operation will panic at runtime
--> $DIR/indexing_slicing_index.rs:29:5
|
LL | x[const { idx4() }]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
| ^^^^^^^^^^^^^^^^^^^ index out of bounds: the length is 4 but the index is 4

error[E0080]: evaluation of `main::{constant#3}` failed
--> $DIR/indexing_slicing_index.rs:31:14
|
Expand All @@ -10,6 +30,18 @@ error[E0080]: erroneous constant used
LL | const { &ARR[idx4()] }; // Ok, let rustc handle const contexts.
| ^^^^^^^^^^^^^^^^^^^^^^ referenced constant has errors

error: this operation will panic at runtime
--> $DIR/indexing_slicing_index.rs:35:5
|
LL | y[4]; // Ok, rustc will handle references too.
| ^^^^ index out of bounds: the length is 4 but the index is 4

error: this operation will panic at runtime
--> $DIR/indexing_slicing_index.rs:44:5
|
LL | x[N]; // Ok, let rustc's `unconditional_panic` lint handle `usize` indexing on arrays.
| ^^^^ index out of bounds: the length is 4 but the index is 15

error: indexing may panic
--> $DIR/indexing_slicing_index.rs:22:5
|
Expand Down Expand Up @@ -59,6 +91,6 @@ LL | v[M];
|
= help: consider using `.get(n)` or `.get_mut(n)` instead

error: aborting due to 8 previous errors
error: aborting due to 13 previous errors

For more information about this error, try `rustc --explain E0080`.
16 changes: 15 additions & 1 deletion src/tools/clippy/tests/ui/self_assignment.stderr
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
error: this operation will panic at runtime
--> $DIR/self_assignment.rs:16:15
|
LL | s.b[10] = s.b[5 + 5];
| ^^^^^^^^^^ index out of bounds: the length is 10 but the index is 10
|
= note: `#[deny(unconditional_panic)]` on by default

error: this operation will panic at runtime
--> $DIR/self_assignment.rs:16:5
|
LL | s.b[10] = s.b[5 + 5];
| ^^^^^^^ index out of bounds: the length is 10 but the index is 10

error: self-assignment of `a` to `a`
--> $DIR/self_assignment.rs:12:5
|
Expand Down Expand Up @@ -66,5 +80,5 @@ error: self-assignment of `(t.0)` to `t.0`
LL | t.0 = (t.0);
| ^^^^^^^^^^^

error: aborting due to 11 previous errors
error: aborting due to 13 previous errors