mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-08 13:02:50 +00:00
do promote array indexing if we know it is in-bounds
This commit is contained in:
parent
69a997bef2
commit
f62cecd807
@ -415,10 +415,11 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||
// FIXME(eddyb) maybe cache this?
|
||||
fn validate_local(&self, local: Local) -> Result<(), Unpromotable> {
|
||||
if let TempState::Defined { location: loc, .. } = self.temps[local] {
|
||||
let num_stmts = self.body[loc.block].statements.len();
|
||||
let block = &self.body[loc.block];
|
||||
let num_stmts = block.statements.len();
|
||||
|
||||
if loc.statement_index < num_stmts {
|
||||
let statement = &self.body[loc.block].statements[loc.statement_index];
|
||||
let statement = &block.statements[loc.statement_index];
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (_, rhs)) => self.validate_rvalue(rhs),
|
||||
_ => {
|
||||
@ -430,7 +431,7 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let terminator = self.body[loc.block].terminator();
|
||||
let terminator = block.terminator();
|
||||
match &terminator.kind {
|
||||
TerminatorKind::Call { func, args, .. } => self.validate_call(func, args),
|
||||
TerminatorKind::Yield { .. } => Err(Unpromotable),
|
||||
@ -452,22 +453,15 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||
match elem {
|
||||
ProjectionElem::Deref => {
|
||||
let mut promotable = false;
|
||||
// The `is_empty` predicate is introduced to exclude the case
|
||||
// where the projection operations are [ .field, * ].
|
||||
// The reason is because promotion will be illegal if field
|
||||
// accesses precede the dereferencing.
|
||||
// We need to make sure this is a `Deref` of a local with no further projections.
|
||||
// Discussion can be found at
|
||||
// https://github.com/rust-lang/rust/pull/74945#discussion_r463063247
|
||||
// There may be opportunity for generalization, but this needs to be
|
||||
// accounted for.
|
||||
if place_base.projection.is_empty() {
|
||||
if let Some(local) = place_base.as_local() {
|
||||
// This is a special treatment for cases like *&STATIC where STATIC is a
|
||||
// global static variable.
|
||||
// This pattern is generated only when global static variables are directly
|
||||
// accessed and is qualified for promotion safely.
|
||||
if let TempState::Defined { location, .. } =
|
||||
self.temps[place_base.local]
|
||||
{
|
||||
if let TempState::Defined { location, .. } = self.temps[local] {
|
||||
let def_stmt = self.body[location.block]
|
||||
.statements
|
||||
.get(location.statement_index);
|
||||
@ -505,9 +499,49 @@ impl<'tcx> Validator<'_, 'tcx> {
|
||||
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {}
|
||||
|
||||
ProjectionElem::Index(local) => {
|
||||
// This could be OOB, so reject for implicit promotion.
|
||||
if !self.explicit {
|
||||
return Err(Unpromotable);
|
||||
let mut promotable = false;
|
||||
// Only accept if we can predict the index and are indexing an array.
|
||||
let val = if let TempState::Defined { location: loc, .. } =
|
||||
self.temps[local]
|
||||
{
|
||||
let block = &self.body[loc.block];
|
||||
if loc.statement_index < block.statements.len() {
|
||||
let statement = &block.statements[loc.statement_index];
|
||||
match &statement.kind {
|
||||
StatementKind::Assign(box (
|
||||
_,
|
||||
Rvalue::Use(Operand::Constant(c)),
|
||||
)) => c.literal.try_eval_usize(self.tcx, self.param_env),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if let Some(idx) = val {
|
||||
// Determine the type of the thing we are indexing.
|
||||
let ty = place_base.ty(self.body, self.tcx).ty;
|
||||
match ty.kind() {
|
||||
ty::Array(_, len) => {
|
||||
// It's an array; determine its length.
|
||||
if let Some(len) =
|
||||
len.try_eval_usize(self.tcx, self.param_env)
|
||||
{
|
||||
// If the index is in-bounds, go ahead.
|
||||
if idx < len {
|
||||
promotable = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if !promotable {
|
||||
return Err(Unpromotable);
|
||||
}
|
||||
}
|
||||
self.validate_local(local)?;
|
||||
}
|
||||
|
@ -24,41 +24,41 @@ fn main() -> () {
|
||||
}
|
||||
|
||||
alloc0 (static: FOO, size: 8, align: 4) {
|
||||
╾─alloc31─╼ 03 00 00 00 │ ╾──╼....
|
||||
╾─alloc27─╼ 03 00 00 00 │ ╾──╼....
|
||||
}
|
||||
|
||||
alloc31 (size: 48, align: 4) {
|
||||
0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 00 00 00 00 │ ....░░░░╾──╼....
|
||||
0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc14─╼ 02 00 00 00 │ ....░░░░╾──╼....
|
||||
0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc29─╼ 03 00 00 00 │ ....*...╾──╼....
|
||||
alloc27 (size: 48, align: 4) {
|
||||
0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc12─╼ 00 00 00 00 │ ....░░░░╾──╼....
|
||||
0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc17─╼ 02 00 00 00 │ ....░░░░╾──╼....
|
||||
0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc25─╼ 03 00 00 00 │ ....*...╾──╼....
|
||||
}
|
||||
|
||||
alloc8 (size: 0, align: 4) {}
|
||||
alloc12 (size: 0, align: 4) {}
|
||||
|
||||
alloc14 (size: 8, align: 4) {
|
||||
╾─alloc12─╼ ╾─alloc13─╼ │ ╾──╼╾──╼
|
||||
alloc17 (size: 8, align: 4) {
|
||||
╾─alloc15─╼ ╾─alloc16─╼ │ ╾──╼╾──╼
|
||||
}
|
||||
|
||||
alloc12 (size: 1, align: 1) {
|
||||
alloc15 (size: 1, align: 1) {
|
||||
05 │ .
|
||||
}
|
||||
|
||||
alloc13 (size: 1, align: 1) {
|
||||
alloc16 (size: 1, align: 1) {
|
||||
06 │ .
|
||||
}
|
||||
|
||||
alloc29 (size: 12, align: 4) {
|
||||
╾─a21+0x3─╼ ╾─alloc23─╼ ╾─a28+0x2─╼ │ ╾──╼╾──╼╾──╼
|
||||
alloc25 (size: 12, align: 4) {
|
||||
╾─a21+0x3─╼ ╾─alloc22─╼ ╾─a24+0x2─╼ │ ╾──╼╾──╼╾──╼
|
||||
}
|
||||
|
||||
alloc21 (size: 4, align: 1) {
|
||||
2a 45 15 6f │ *E.o
|
||||
}
|
||||
|
||||
alloc23 (size: 1, align: 1) {
|
||||
alloc22 (size: 1, align: 1) {
|
||||
2a │ *
|
||||
}
|
||||
|
||||
alloc28 (size: 4, align: 1) {
|
||||
alloc24 (size: 4, align: 1) {
|
||||
2a 45 15 6f │ *E.o
|
||||
}
|
||||
|
@ -24,44 +24,44 @@ fn main() -> () {
|
||||
}
|
||||
|
||||
alloc0 (static: FOO, size: 16, align: 8) {
|
||||
╾───────alloc31───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
╾───────alloc27───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
}
|
||||
|
||||
alloc31 (size: 72, align: 8) {
|
||||
0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc8────────╼ │ ....░░░░╾──────╼
|
||||
alloc27 (size: 72, align: 8) {
|
||||
0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc12───────╼ │ ....░░░░╾──────╼
|
||||
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
|
||||
0x20 │ ╾───────alloc14───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc29───────╼ │ ....*...╾──────╼
|
||||
0x20 │ ╾───────alloc17───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
|
||||
0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc25───────╼ │ ....*...╾──────╼
|
||||
0x40 │ 03 00 00 00 00 00 00 00 │ ........
|
||||
}
|
||||
|
||||
alloc8 (size: 0, align: 8) {}
|
||||
alloc12 (size: 0, align: 8) {}
|
||||
|
||||
alloc14 (size: 16, align: 8) {
|
||||
╾───────alloc12───────╼ ╾───────alloc13───────╼ │ ╾──────╼╾──────╼
|
||||
alloc17 (size: 16, align: 8) {
|
||||
╾───────alloc15───────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼
|
||||
}
|
||||
|
||||
alloc12 (size: 1, align: 1) {
|
||||
alloc15 (size: 1, align: 1) {
|
||||
05 │ .
|
||||
}
|
||||
|
||||
alloc13 (size: 1, align: 1) {
|
||||
alloc16 (size: 1, align: 1) {
|
||||
06 │ .
|
||||
}
|
||||
|
||||
alloc29 (size: 24, align: 8) {
|
||||
0x00 │ ╾─────alloc21+0x3─────╼ ╾───────alloc23───────╼ │ ╾──────╼╾──────╼
|
||||
0x10 │ ╾─────alloc28+0x2─────╼ │ ╾──────╼
|
||||
alloc25 (size: 24, align: 8) {
|
||||
0x00 │ ╾─────alloc21+0x3─────╼ ╾───────alloc22───────╼ │ ╾──────╼╾──────╼
|
||||
0x10 │ ╾─────alloc24+0x2─────╼ │ ╾──────╼
|
||||
}
|
||||
|
||||
alloc21 (size: 4, align: 1) {
|
||||
2a 45 15 6f │ *E.o
|
||||
}
|
||||
|
||||
alloc23 (size: 1, align: 1) {
|
||||
alloc22 (size: 1, align: 1) {
|
||||
2a │ *
|
||||
}
|
||||
|
||||
alloc28 (size: 4, align: 1) {
|
||||
alloc24 (size: 4, align: 1) {
|
||||
2a 45 15 6f │ *E.o
|
||||
}
|
||||
|
@ -24,30 +24,30 @@ fn main() -> () {
|
||||
}
|
||||
|
||||
alloc0 (static: FOO, size: 4, align: 4) {
|
||||
╾─alloc11─╼ │ ╾──╼
|
||||
╾─alloc10─╼ │ ╾──╼
|
||||
}
|
||||
|
||||
alloc11 (size: 168, align: 1) {
|
||||
alloc10 (size: 168, align: 1) {
|
||||
0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................
|
||||
0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc4──╼ │ ............╾──╼
|
||||
0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc5──╼ │ ............╾──╼
|
||||
0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc6──╼ 00 00 │ ..........╾──╼..
|
||||
0x90 │ ╾─a9+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............
|
||||
0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc7──╼ 00 00 │ ..........╾──╼..
|
||||
0x90 │ ╾─a8+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............
|
||||
0xa0 │ 00 00 00 00 00 00 00 00 │ ........
|
||||
}
|
||||
|
||||
alloc4 (size: 4, align: 4) {
|
||||
alloc5 (size: 4, align: 4) {
|
||||
2a 00 00 00 │ *...
|
||||
}
|
||||
|
||||
alloc6 (fn: main)
|
||||
alloc7 (fn: main)
|
||||
|
||||
alloc9 (size: 100, align: 1) {
|
||||
alloc8 (size: 100, align: 1) {
|
||||
0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
|
@ -24,12 +24,12 @@ fn main() -> () {
|
||||
}
|
||||
|
||||
alloc0 (static: FOO, size: 8, align: 8) {
|
||||
╾───────alloc11───────╼ │ ╾──────╼
|
||||
╾───────alloc10───────╼ │ ╾──────╼
|
||||
}
|
||||
|
||||
alloc11 (size: 180, align: 1) {
|
||||
alloc10 (size: 180, align: 1) {
|
||||
0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................
|
||||
0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc4── │ ............╾───
|
||||
0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc5── │ ............╾───
|
||||
0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............
|
||||
0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
@ -37,18 +37,18 @@ alloc11 (size: 180, align: 1) {
|
||||
0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─
|
||||
0x90 │ ─────alloc6─────╼ 00 00 ╾─────alloc9+0x63─────╼ │ ─────╼..╾──────╼
|
||||
0x90 │ ─────alloc7─────╼ 00 00 ╾─────alloc8+0x63─────╼ │ ─────╼..╾──────╼
|
||||
0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0xb0 │ 00 00 00 00 │ ....
|
||||
}
|
||||
|
||||
alloc4 (size: 4, align: 4) {
|
||||
alloc5 (size: 4, align: 4) {
|
||||
2a 00 00 00 │ *...
|
||||
}
|
||||
|
||||
alloc6 (fn: main)
|
||||
alloc7 (fn: main)
|
||||
|
||||
alloc9 (size: 100, align: 1) {
|
||||
alloc8 (size: 100, align: 1) {
|
||||
0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................
|
||||
|
@ -30,6 +30,9 @@ fn main() {
|
||||
baz_i32(&(1/1));
|
||||
baz_i32(&(1%1));
|
||||
|
||||
// in-bounds array access is okay
|
||||
baz_i32(&([1,2,3][0] + 1));
|
||||
|
||||
// Top-level projections do not get promoted, so no error here.
|
||||
if false {
|
||||
#[allow(unconditional_panic)]
|
||||
|
Loading…
Reference in New Issue
Block a user