-
Notifications
You must be signed in to change notification settings - Fork 13.3k
const_eval: Consider array length constant even if array is not #99594
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
|
||
use rustc_middle::mir; | ||
use rustc_middle::mir::interpret::{InterpResult, Scalar}; | ||
use rustc_middle::ty; | ||
use rustc_middle::ty::layout::LayoutOf; | ||
|
||
use super::{InterpCx, Machine}; | ||
|
@@ -251,9 +252,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { | |
|
||
Len(place) => { | ||
let src = self.eval_place(place)?; | ||
let mplace = self.force_allocation(&src)?; | ||
let len = mplace.len(self)?; | ||
self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?; | ||
if let &ty::Array(_, len) = src.layout.ty.kind() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't look right. It is certainly not right without extensive comments explaining what is happening and why the old code is wrong. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's a fast path that does the right thing (codegen does this opt after all or mir opts do it for codegen). I wonder if this has any effect on miri at all (the force alloc will just happen later?). If there is no benefit to miri, we should just teach const prop about the Len Rvalue There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Miri shouldn't usually have fast paths though. We want to catch all the UB, not take any shortcuts. ;) However, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Ok, that makes sense.
I did some testing, and using
There's two ConstProps: And should I force-push this PR, or open a new one? Changing this one might make the existing discussion a bit confusing for future readers. (sorry for the delay) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The issue you want to fix is about the lint, so const_prop_lint is the most relevant one.
Ah, place_to_op will still want to read the local and that is where ConstProp bails. |
||
let len = self.const_to_op(len, Some(dest.layout))?; | ||
self.copy_op(&len, &dest, /*allow_transmute*/ false)?; | ||
} else { | ||
let mplace = self.force_allocation(&src)?; | ||
let len = mplace.len(self)?; | ||
self.write_scalar(Scalar::from_machine_usize(len, self), &dest)?; | ||
} | ||
} | ||
|
||
AddressOf(_, place) | Ref(_, _, place) => { | ||
|
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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
// check-pass | ||
#![allow(unconditional_panic)] | ||
|
||
struct Generic<T>(T); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You should be able to do
src.place_to_op(src)?
, which will give you aOpTy
, and then calllen
on that. That would avoidforce_allocation
.