@@ -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