Skip to content

Make PlaceElem::Index take a Place. #106594

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
wants to merge 1 commit into from
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
5 changes: 4 additions & 1 deletion compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ pub(crate) use region_errors::{ErrorConstraintInfo, RegionErrorKind, RegionError
pub(crate) use region_name::{RegionName, RegionNameSource};
pub(crate) use rustc_const_eval::util::CallKind;

#[derive(Copy, Clone)]
pub(super) struct DescribePlaceOpt {
pub including_downcast: bool,

Expand Down Expand Up @@ -265,7 +266,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
}
ProjectionElem::Index(index) => {
buf.push('[');
if self.append_local_to_string(*index, &mut buf).is_err() {
if let Some(index) = self.describe_place_with_options(index.as_ref(), opt) {
buf.push_str(&index);
} else {
buf.push('_');
}
buf.push(']');
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_cranelift/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -851,8 +851,8 @@ pub(crate) fn codegen_place<'tcx>(
PlaceElem::Field(field, _ty) => {
cplace = cplace.place_field(fx, field);
}
PlaceElem::Index(local) => {
let index = fx.get_local_place(local).to_cvalue(fx).load_scalar(fx);
PlaceElem::Index(index) => {
let index = codegen_place(fx, index).to_cvalue(fx).load_scalar(fx);
cplace = cplace.place_index(fx, index);
}
PlaceElem::ConstantIndex { offset, min_length: _, from_end } => {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_codegen_ssa/src/mir/analyze.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,9 @@ impl<'mir, 'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> LocalAnalyzer<'mir, 'a, 'tcx,
// HACK(eddyb) this emulates the old `visit_projection_elem`, this
// entire `visit_place`-like `process_place` method should be rewritten,
// now that we have moved to the "slice of projections" representation.
if let mir::ProjectionElem::Index(local) = elem {
self.visit_local(
local,
if let mir::ProjectionElem::Index(ref index) = elem {
self.visit_place(
index,
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
location,
);
Expand Down
8 changes: 4 additions & 4 deletions compiler/rustc_const_eval/src/interpret/projection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,9 +360,9 @@ where
Field(field, _) => self.place_field(base, field.index())?,
Downcast(_, variant) => self.place_downcast(base, variant)?,
Deref => self.deref_operand(&self.place_to_op(base)?)?.into(),
Index(local) => {
Index(place) => {
let layout = self.layout_of(self.tcx.types.usize)?;
let n = self.local_to_op(self.frame(), local, Some(layout))?;
let n = self.eval_place_to_op(place, Some(layout))?;
let n = self.read_machine_usize(&n)?;
self.place_index(base, n)?
}
Expand All @@ -389,9 +389,9 @@ where
Field(field, _) => self.operand_field(base, field.index())?,
Downcast(_, variant) => self.operand_downcast(base, variant)?,
Deref => self.deref_operand(base)?.into(),
Index(local) => {
Index(place) => {
let layout = self.layout_of(self.tcx.types.usize)?;
let n = self.local_to_op(self.frame(), local, Some(layout))?;
let n = self.eval_place_to_op(place, Some(layout))?;
let n = self.read_machine_usize(&n)?;
self.operand_index(base, n)?
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,9 @@ where
let mut place = place;
while let Some((place_base, elem)) = place.last_projection() {
match elem {
ProjectionElem::Index(index) if in_local(index) => return true,
ProjectionElem::Index(index) if in_place::<Q, _>(cx, in_local, index.as_ref()) => {
return true;
}

ProjectionElem::Deref
| ProjectionElem::Field(_, _)
Expand Down
35 changes: 18 additions & 17 deletions compiler/rustc_const_eval/src/transform/promote_consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,27 +361,28 @@ impl<'tcx> Validator<'_, 'tcx> {

ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. } => {}

ProjectionElem::Index(local) => {
ProjectionElem::Index(place) => {
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
let val = if let Some(local) = place.as_local()
&& 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;
Expand All @@ -403,7 +404,7 @@ impl<'tcx> Validator<'_, 'tcx> {
return Err(Unpromotable);
}

self.validate_local(local)?;
self.validate_place(place.as_ref())?;
}

ProjectionElem::Field(..) => {
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/transform/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
location: Location,
) {
match elem {
ProjectionElem::Index(index) => {
let index_ty = self.body.local_decls[index].ty;
ProjectionElem::Index(ref index) => {
let index_ty = Place::ty(index, &self.body.local_decls, self.tcx).ty;
if index_ty != self.tcx.types.usize {
self.fail(location, format!("bad index ({:?} != usize)", index_ty))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/mir/syntax.rs
Original file line number Diff line number Diff line change
Expand Up @@ -956,7 +956,7 @@ pub enum ProjectionElem<V, T> {

/// Alias for projections as they appear in places, where the base is a place
/// and the index is a local.
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
pub type PlaceElem<'tcx> = ProjectionElem<Place<'tcx>, Ty<'tcx>>;

///////////////////////////////////////////////////////////////////////////
// Operands
Expand Down
16 changes: 8 additions & 8 deletions compiler/rustc_middle/src/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1078,15 +1078,15 @@ macro_rules! visit_place_fns {
location: Location,
) -> Option<PlaceElem<'tcx>> {
match elem {
PlaceElem::Index(local) => {
let mut new_local = local;
self.visit_local(
&mut new_local,
PlaceElem::Index(place) => {
let mut new_place = place;
self.visit_place(
&mut new_place,
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
location,
);

if new_local == local { None } else { Some(PlaceElem::Index(new_local)) }
if new_place == place { None } else { Some(PlaceElem::Index(new_place)) }
}
PlaceElem::Field(field, ty) => {
let mut new_ty = ty;
Expand Down Expand Up @@ -1170,9 +1170,9 @@ macro_rules! visit_place_fns {
ProjectionElem::OpaqueCast(ty) | ProjectionElem::Field(_, ty) => {
self.visit_ty(ty, TyContext::Location(location));
}
ProjectionElem::Index(local) => {
self.visit_local(
local,
ProjectionElem::Index(ref place) => {
self.visit_place(
place,
PlaceContext::NonMutatingUse(NonMutatingUseContext::Copy),
location,
);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2048,7 +2048,7 @@ impl<'tcx> TyCtxt<'tcx> {
}

pub fn mk_place_index(self, place: Place<'tcx>, index: Local) -> Place<'tcx> {
self.mk_place_elem(place, PlaceElem::Index(index))
self.mk_place_elem(place, PlaceElem::Index(index.into()))
}

/// This method copies `Place`'s projection, add an element and reintern it. Should not be used
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
_ => (*arg, PlaceElem::Deref),
)
},
ExprKind::Index { lhs, index } => (*lhs, PlaceElem::Index(self.parse_local(*index)?)),
ExprKind::Index { lhs, index } => (*lhs, PlaceElem::Index(self.parse_place(*index)?)),
ExprKind::Field { lhs, name: field, .. } => (*lhs, PlaceElem::Field(*field, expr.ty)),
_ => {
let place = self.parse_local(expr_id).map(Place::from)?;
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_build/src/build/expr/as_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ impl<'tcx> PlaceBuilder<'tcx> {
}

fn index(self, index: Local) -> Self {
self.project(PlaceElem::Index(index))
self.project(PlaceElem::Index(index.into()))
}

pub(crate) fn project(mut self, elem: PlaceElem<'tcx>) -> Self {
Expand Down
8 changes: 7 additions & 1 deletion compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
//! `a[x]` would still overlap them both. But that is not this
//! representation does today.)

use rustc_middle::mir::{Local, Operand, PlaceElem, ProjectionElem};
use rustc_middle::mir::{Local, Operand, Place, PlaceElem, ProjectionElem};
use rustc_middle::ty::Ty;

#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
Expand All @@ -36,6 +36,12 @@ impl Lift for Local {
AbstractOperand
}
}
impl<'tcx> Lift for Place<'tcx> {
type Abstract = AbstractOperand;
fn lift(&self) -> Self::Abstract {
AbstractOperand
}
}
impl<'tcx> Lift for Ty<'tcx> {
type Abstract = AbstractType;
fn lift(&self) -> Self::Abstract {
Expand Down
16 changes: 2 additions & 14 deletions compiler/rustc_mir_transform/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,13 +128,7 @@ impl<'tcx> MutVisitor<'tcx> for DerefArgVisitor<'tcx> {
self.tcx,
);
} else {
self.visit_local(&mut place.local, context, location);

for elem in place.projection.iter() {
if let PlaceElem::Index(local) = elem {
assert_ne!(local, SELF_ARG);
}
}
self.super_place(place, context, location);
}
}
}
Expand Down Expand Up @@ -167,13 +161,7 @@ impl<'tcx> MutVisitor<'tcx> for PinArgVisitor<'tcx> {
self.tcx,
);
} else {
self.visit_local(&mut place.local, context, location);

for elem in place.projection.iter() {
if let PlaceElem::Index(local) = elem {
assert_ne!(local, SELF_ARG);
}
}
self.super_place(place, context, location);
}
}
}
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_mir_transform/src/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1054,12 +1054,6 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
}

fn visit_place(&mut self, place: &mut Place<'tcx>, context: PlaceContext, location: Location) {
for elem in place.projection {
// FIXME: Make sure that return place is not used in an indexing projection, since it
// won't be rebased as it is supposed to be.
assert_ne!(ProjectionElem::Index(RETURN_PLACE), elem);
}

// If this is the `RETURN_PLACE`, we need to rebase any projections onto it.
let dest_proj_len = self.destination.projection.len();
if place.local == RETURN_PLACE && dest_proj_len > 0 {
Expand Down
23 changes: 23 additions & 0 deletions src/test/mir-opt/inline/issue_106141.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
pub fn outer() -> usize {
inner()
}

fn index() -> usize {
loop {}
}

#[inline]
fn inner() -> usize {
let buffer = &[true];
let index = index();
// DestProp may unify `index` with `_0`. Check that inlining does not ICE.
if buffer[index] {
index
} else {
0
}
}

fn main() {
let _ = outer();
}