Skip to content

Commit 3e94dd7

Browse files
committed
document unstated condition of Subslice and validate more
1 parent 8f430d6 commit 3e94dd7

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
@@ -137,6 +137,7 @@ pub enum RuntimePhase {
137137
/// And the following variants are allowed:
138138
/// * [`StatementKind::Retag`]
139139
/// * [`StatementKind::SetDiscriminant`]
140+
/// * [`PlaceElem::ConstantIndex`] / [`PlaceElem::Subslice`] after [`PlaceElem::Subslice`]
140141
///
141142
/// Furthermore, `Copy` operands are allowed for non-`Copy` types.
142143
Initial = 0,
@@ -1246,6 +1247,9 @@ pub enum ProjectionElem<V, T> {
12461247
///
12471248
/// If `from_end` is true `slice[from..slice.len() - to]`.
12481249
/// Otherwise `array[from..to]`.
1250+
///
1251+
/// This projection cannot have `ConstantIndex` or additional `Subslice` projections after it
1252+
/// before runtime MIR.
12491253
Subslice {
12501254
from: u64,
12511255
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
{
@@ -921,6 +979,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
921979
}
922980
}
923981

982+
if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial)
983+
&& let Some(i) = place
984+
.projection
985+
.iter()
986+
.position(|elem| matches!(elem, ProjectionElem::Subslice { .. }))
987+
&& let Some(tail) = place.projection.get(i + 1..)
988+
&& tail.iter().any(|elem| {
989+
matches!(
990+
elem,
991+
ProjectionElem::ConstantIndex { .. } | ProjectionElem::Subslice { .. }
992+
)
993+
})
994+
{
995+
self.fail(
996+
location,
997+
format!("place {place:?} has `ConstantIndex` or `Subslice` after `Subslice`"),
998+
);
999+
}
1000+
9241001
self.super_place(place, cntxt, location);
9251002
}
9261003

0 commit comments

Comments
 (0)