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