@@ -801,11 +801,69 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
801801 }
802802 }
803803 ProjectionElem :: Index ( index) => {
804+ let indexed_ty = place_ref. ty ( & self . body . local_decls , self . tcx ) . ty ;
805+ match indexed_ty. kind ( ) {
806+ ty:: Array ( _, _) | ty:: Slice ( _) => { }
807+ _ => self . fail ( location, format ! ( "{indexed_ty:?} cannot be indexed" ) ) ,
808+ }
809+
804810 let index_ty = self . body . local_decls [ index] . ty ;
805811 if index_ty != self . tcx . types . usize {
806812 self . fail ( location, format ! ( "bad index ({index_ty} != usize)" ) )
807813 }
808814 }
815+ ProjectionElem :: ConstantIndex { offset, min_length, from_end } => {
816+ let indexed_ty = place_ref. ty ( & self . body . local_decls , self . tcx ) . ty ;
817+ match indexed_ty. kind ( ) {
818+ ty:: Array ( _, _) => {
819+ if from_end {
820+ self . fail ( location, "arrays should not be indexed from end" ) ;
821+ }
822+ }
823+ ty:: Slice ( _) => { }
824+ _ => self . fail ( location, format ! ( "{indexed_ty:?} cannot be indexed" ) ) ,
825+ }
826+
827+ if from_end {
828+ if offset > min_length {
829+ self . fail (
830+ location,
831+ format ! (
832+ "constant index with offset -{offset} out of bounds of min length {min_length}"
833+ ) ,
834+ ) ;
835+ }
836+ } else {
837+ if offset >= min_length {
838+ self . fail (
839+ location,
840+ format ! (
841+ "constant index with offset {offset} out of bounds of min length {min_length}"
842+ ) ,
843+ ) ;
844+ }
845+ }
846+ }
847+ ProjectionElem :: Subslice { from, to, from_end } => {
848+ let indexed_ty = place_ref. ty ( & self . body . local_decls , self . tcx ) . ty ;
849+ match indexed_ty. kind ( ) {
850+ ty:: Array ( _, _) => {
851+ if from_end {
852+ self . fail ( location, "arrays should not be subsliced from end" ) ;
853+ }
854+ }
855+ ty:: Slice ( _) => {
856+ if !from_end {
857+ self . fail ( location, "slices should be subsliced from end" ) ;
858+ }
859+ }
860+ _ => self . fail ( location, format ! ( "{indexed_ty:?} cannot be indexed" ) ) ,
861+ }
862+
863+ if !from_end && from > to {
864+ self . fail ( location, "backwards subslice {from}..{to}" ) ;
865+ }
866+ }
809867 ProjectionElem :: OpaqueCast ( ty)
810868 if self . body . phase >= MirPhase :: Runtime ( RuntimePhase :: Initial ) =>
811869 {
@@ -906,6 +964,25 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
906964 }
907965 }
908966
967+ if self . body . phase < MirPhase :: Runtime ( RuntimePhase :: Initial )
968+ && let Some ( i) = place
969+ . projection
970+ . iter ( )
971+ . position ( |elem| matches ! ( elem, ProjectionElem :: Subslice { .. } ) )
972+ && let Some ( tail) = place. projection . get ( i + 1 ..)
973+ && tail. iter ( ) . any ( |elem| {
974+ matches ! (
975+ elem,
976+ ProjectionElem :: ConstantIndex { .. } | ProjectionElem :: Subslice { .. }
977+ )
978+ } )
979+ {
980+ self . fail (
981+ location,
982+ format ! ( "place {place:?} has `ConstantIndex` or `Subslice` after `Subslice`" ) ,
983+ ) ;
984+ }
985+
909986 self . super_place ( place, cntxt, location) ;
910987 }
911988
0 commit comments