Skip to content

Commit dd1e37f

Browse files
committed
document unstated condition of Subslice and validate more
1 parent 7c14395 commit dd1e37f

File tree

2 files changed

+81
-0
lines changed

2 files changed

+81
-0
lines changed

compiler/rustc_middle/src/mir/syntax.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ pub enum RuntimePhase {
135135
/// And the following variants are allowed:
136136
/// * [`StatementKind::Retag`]
137137
/// * [`StatementKind::SetDiscriminant`]
138+
/// * [`PlaceElem::ConstantIndex`] / [`PlaceElem::Subslice`] after [`PlaceElem::Subslice`]
138139
///
139140
/// Furthermore, `Copy` operands are allowed for non-`Copy` types.
140141
Initial = 0,
@@ -1244,6 +1245,9 @@ pub enum ProjectionElem<V, T> {
12441245
///
12451246
/// If `from_end` is true `slice[from..slice.len() - to]`.
12461247
/// Otherwise `array[from..to]`.
1248+
///
1249+
/// This projection cannot have `ConstantIndex` or additional `Subslice` projections after it
1250+
/// before runtime MIR.
12471251
Subslice {
12481252
from: u64,
12491253
to: u64,

compiler/rustc_mir_transform/src/validate.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,11 +802,69 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
802802
}
803803
}
804804
ProjectionElem::Index(index) => {
805+
let indexed_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty;
806+
match indexed_ty.kind() {
807+
ty::Array(_, _) | ty::Slice(_) => {}
808+
_ => self.fail(location, format!("{indexed_ty:?} cannot be indexed")),
809+
}
810+
805811
let index_ty = self.body.local_decls[index].ty;
806812
if index_ty != self.tcx.types.usize {
807813
self.fail(location, format!("bad index ({index_ty} != usize)"))
808814
}
809815
}
816+
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
817+
let indexed_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty;
818+
match indexed_ty.kind() {
819+
ty::Array(_, _) => {
820+
if from_end {
821+
self.fail(location, "arrays should not be indexed from end");
822+
}
823+
}
824+
ty::Slice(_) => {}
825+
_ => self.fail(location, format!("{indexed_ty:?} cannot be indexed")),
826+
}
827+
828+
if from_end {
829+
if offset > min_length {
830+
self.fail(
831+
location,
832+
format!(
833+
"constant index with offset -{offset} out of bounds of min length {min_length}"
834+
),
835+
);
836+
}
837+
} else {
838+
if offset >= min_length {
839+
self.fail(
840+
location,
841+
format!(
842+
"constant index with offset {offset} out of bounds of min length {min_length}"
843+
),
844+
);
845+
}
846+
}
847+
}
848+
ProjectionElem::Subslice { from, to, from_end } => {
849+
let indexed_ty = place_ref.ty(&self.body.local_decls, self.tcx).ty;
850+
match indexed_ty.kind() {
851+
ty::Array(_, _) => {
852+
if from_end {
853+
self.fail(location, "arrays should not be subsliced from end");
854+
}
855+
}
856+
ty::Slice(_) => {
857+
if !from_end {
858+
self.fail(location, "slices should be subsliced from end");
859+
}
860+
}
861+
_ => self.fail(location, format!("{indexed_ty:?} cannot be indexed")),
862+
}
863+
864+
if !from_end && from > to {
865+
self.fail(location, "backwards subslice {from}..{to}");
866+
}
867+
}
810868
ProjectionElem::OpaqueCast(ty)
811869
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) =>
812870
{
@@ -907,6 +965,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
907965
}
908966
}
909967

968+
if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial)
969+
&& let Some(i) = place
970+
.projection
971+
.iter()
972+
.position(|elem| matches!(elem, ProjectionElem::Subslice { .. }))
973+
&& let Some(tail) = place.projection.get(i + 1..)
974+
&& tail.iter().any(|elem| {
975+
matches!(
976+
elem,
977+
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. }
978+
)
979+
})
980+
{
981+
self.fail(
982+
location,
983+
format!("place {place:?} has `ConstantIndex` or `Subslice` after `Subslice`"),
984+
);
985+
}
986+
910987
self.super_place(place, cntxt, location);
911988
}
912989

0 commit comments

Comments
 (0)