@@ -75,15 +75,6 @@ macro_rules! span_mirbug {
7575 } )
7676}
7777
78- macro_rules! span_mirbug_and_err {
79- ( $context: expr, $elem: expr, $( $message: tt) * ) => ( {
80- {
81- span_mirbug!( $context, $elem, $( $message) * ) ;
82- $context. error( )
83- }
84- } )
85- }
86-
8778mod canonical;
8879mod constraint_conversion;
8980pub ( crate ) mod free_region_relations;
@@ -263,6 +254,74 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
263254 self . sanitize_place ( place, location, context) ;
264255 }
265256
257+ fn visit_projection_elem (
258+ & mut self ,
259+ place : PlaceRef < ' tcx > ,
260+ elem : PlaceElem < ' tcx > ,
261+ context : PlaceContext ,
262+ location : Location ,
263+ ) {
264+ let tcx = self . tcx ( ) ;
265+ let base_ty = place. ty ( self . body ( ) , tcx) ;
266+ match elem {
267+ // All these projections don't add any constraints, so there's nothing to
268+ // do here. We check their invariants in the MIR validator after all.
269+ ProjectionElem :: Deref
270+ | ProjectionElem :: Index ( _)
271+ | ProjectionElem :: ConstantIndex { .. }
272+ | ProjectionElem :: Subslice { .. }
273+ | ProjectionElem :: Downcast ( ..) => { }
274+ ProjectionElem :: Field ( field, fty) => {
275+ let fty = self . typeck . normalize ( fty, location) ;
276+ match self . expected_field_ty ( base_ty, field, location) {
277+ Ok ( ty) => {
278+ let ty = self . typeck . normalize ( ty, location) ;
279+ debug ! ( ?fty, ?ty) ;
280+
281+ if let Err ( terr) = self . typeck . relate_types (
282+ ty,
283+ context. ambient_variance ( ) ,
284+ fty,
285+ location. to_locations ( ) ,
286+ ConstraintCategory :: Boring ,
287+ ) {
288+ span_mirbug ! (
289+ self ,
290+ place,
291+ "bad field access ({:?}: {:?}): {:?}" ,
292+ ty,
293+ fty,
294+ terr
295+ ) ;
296+ }
297+ }
298+ Err ( FieldAccessError :: OutOfRange { field_count } ) => span_mirbug ! (
299+ self ,
300+ place,
301+ "accessed field #{} but variant only has {}" ,
302+ field. index( ) ,
303+ field_count
304+ ) ,
305+ }
306+ }
307+ ProjectionElem :: OpaqueCast ( ty) => {
308+ let ty = self . typeck . normalize ( ty, location) ;
309+ self . typeck
310+ . relate_types (
311+ ty,
312+ context. ambient_variance ( ) ,
313+ base_ty. ty ,
314+ location. to_locations ( ) ,
315+ ConstraintCategory :: TypeAnnotation ,
316+ )
317+ . unwrap ( ) ;
318+ }
319+ ProjectionElem :: Subtype ( _) => {
320+ bug ! ( "ProjectionElem::Subtype shouldn't exist in borrowck" )
321+ }
322+ }
323+ }
324+
266325 fn visit_const_operand ( & mut self , constant : & ConstOperand < ' tcx > , location : Location ) {
267326 debug ! ( ?constant, ?location, "visit_const_operand" ) ;
268327
@@ -444,25 +503,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
444503 /// Checks that the types internal to the `place` match up with
445504 /// what would be expected.
446505 #[ instrument( level = "debug" , skip( self , location) , ret) ]
447- fn sanitize_place (
448- & mut self ,
449- place : & Place < ' tcx > ,
450- location : Location ,
451- context : PlaceContext ,
452- ) -> PlaceTy < ' tcx > {
453- let mut place_ty = PlaceTy :: from_ty ( self . body ( ) . local_decls [ place. local ] . ty ) ;
454-
455- for elem in place. projection . iter ( ) {
456- if place_ty. variant_index . is_none ( ) {
457- if let Err ( guar) = place_ty. ty . error_reported ( ) {
458- return PlaceTy :: from_ty ( Ty :: new_error ( self . tcx ( ) , guar) ) ;
459- }
460- }
461- place_ty = self . sanitize_projection ( place_ty, elem, place, location, context) ;
462- }
463-
506+ fn sanitize_place ( & mut self , place : & Place < ' tcx > , location : Location , context : PlaceContext ) {
507+ self . super_place ( place, context, location) ;
508+ let tcx = self . tcx ( ) ;
509+ let place_ty = place. ty ( self . body ( ) , tcx) ;
464510 if let PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) = context {
465- let tcx = self . tcx ( ) ;
466511 let trait_ref = ty:: TraitRef :: new (
467512 tcx,
468513 tcx. require_lang_item ( LangItem :: Copy , Some ( self . last_span ) ) ,
@@ -486,8 +531,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
486531 ConstraintCategory :: CopyBound ,
487532 ) ;
488533 }
489-
490- place_ty
491534 }
492535
493536 fn sanitize_promoted ( & mut self , promoted_body : & ' b Body < ' tcx > , location : Location ) {
@@ -547,144 +590,8 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
547590 }
548591 }
549592
550- #[ instrument( skip( self , location) , ret, level = "debug" ) ]
551- fn sanitize_projection (
552- & mut self ,
553- base : PlaceTy < ' tcx > ,
554- pi : PlaceElem < ' tcx > ,
555- place : & Place < ' tcx > ,
556- location : Location ,
557- context : PlaceContext ,
558- ) -> PlaceTy < ' tcx > {
559- let tcx = self . tcx ( ) ;
560- let base_ty = base. ty ;
561- match pi {
562- ProjectionElem :: Deref => {
563- let deref_ty = base_ty. builtin_deref ( true ) ;
564- PlaceTy :: from_ty ( deref_ty. unwrap_or_else ( || {
565- span_mirbug_and_err ! ( self , place, "deref of non-pointer {:?}" , base_ty)
566- } ) )
567- }
568- ProjectionElem :: Index ( i) => {
569- let index_ty = Place :: from ( i) . ty ( self . body ( ) , tcx) . ty ;
570- if index_ty != tcx. types . usize {
571- PlaceTy :: from_ty ( span_mirbug_and_err ! ( self , i, "index by non-usize {:?}" , i) )
572- } else {
573- PlaceTy :: from_ty ( base_ty. builtin_index ( ) . unwrap_or_else ( || {
574- span_mirbug_and_err ! ( self , place, "index of non-array {:?}" , base_ty)
575- } ) )
576- }
577- }
578- ProjectionElem :: ConstantIndex { .. } => {
579- // consider verifying in-bounds
580- PlaceTy :: from_ty ( base_ty. builtin_index ( ) . unwrap_or_else ( || {
581- span_mirbug_and_err ! ( self , place, "index of non-array {:?}" , base_ty)
582- } ) )
583- }
584- ProjectionElem :: Subslice { from, to, from_end } => {
585- PlaceTy :: from_ty ( match base_ty. kind ( ) {
586- ty:: Array ( inner, _) => {
587- assert ! ( !from_end, "array subslices should not use from_end" ) ;
588- Ty :: new_array ( tcx, * inner, to - from)
589- }
590- ty:: Slice ( ..) => {
591- assert ! ( from_end, "slice subslices should use from_end" ) ;
592- base_ty
593- }
594- _ => span_mirbug_and_err ! ( self , place, "slice of non-array {:?}" , base_ty) ,
595- } )
596- }
597- ProjectionElem :: Downcast ( maybe_name, index) => match base_ty. kind ( ) {
598- ty:: Adt ( adt_def, _args) if adt_def. is_enum ( ) => {
599- if index. as_usize ( ) >= adt_def. variants ( ) . len ( ) {
600- PlaceTy :: from_ty ( span_mirbug_and_err ! (
601- self ,
602- place,
603- "cast to variant #{:?} but enum only has {:?}" ,
604- index,
605- adt_def. variants( ) . len( )
606- ) )
607- } else {
608- PlaceTy { ty : base_ty, variant_index : Some ( index) }
609- }
610- }
611- // We do not need to handle coroutines here, because this runs
612- // before the coroutine transform stage.
613- _ => {
614- let ty = if let Some ( name) = maybe_name {
615- span_mirbug_and_err ! (
616- self ,
617- place,
618- "can't downcast {:?} as {:?}" ,
619- base_ty,
620- name
621- )
622- } else {
623- span_mirbug_and_err ! ( self , place, "can't downcast {:?}" , base_ty)
624- } ;
625- PlaceTy :: from_ty ( ty)
626- }
627- } ,
628- ProjectionElem :: Field ( field, fty) => {
629- let fty = self . typeck . normalize ( fty, location) ;
630- match self . field_ty ( place, base, field, location) {
631- Ok ( ty) => {
632- let ty = self . typeck . normalize ( ty, location) ;
633- debug ! ( ?fty, ?ty) ;
634-
635- if let Err ( terr) = self . typeck . relate_types (
636- ty,
637- context. ambient_variance ( ) ,
638- fty,
639- location. to_locations ( ) ,
640- ConstraintCategory :: Boring ,
641- ) {
642- span_mirbug ! (
643- self ,
644- place,
645- "bad field access ({:?}: {:?}): {:?}" ,
646- ty,
647- fty,
648- terr
649- ) ;
650- }
651- }
652- Err ( FieldAccessError :: OutOfRange { field_count } ) => span_mirbug ! (
653- self ,
654- place,
655- "accessed field #{} but variant only has {}" ,
656- field. index( ) ,
657- field_count
658- ) ,
659- }
660- PlaceTy :: from_ty ( fty)
661- }
662- ProjectionElem :: Subtype ( _) => {
663- bug ! ( "ProjectionElem::Subtype shouldn't exist in borrowck" )
664- }
665- ProjectionElem :: OpaqueCast ( ty) => {
666- let ty = self . typeck . normalize ( ty, location) ;
667- self . typeck
668- . relate_types (
669- ty,
670- context. ambient_variance ( ) ,
671- base. ty ,
672- location. to_locations ( ) ,
673- ConstraintCategory :: TypeAnnotation ,
674- )
675- . unwrap ( ) ;
676- PlaceTy :: from_ty ( ty)
677- }
678- }
679- }
680-
681- fn error ( & mut self ) -> Ty < ' tcx > {
682- Ty :: new_misc_error ( self . tcx ( ) )
683- }
684-
685- fn field_ty (
593+ fn expected_field_ty (
686594 & mut self ,
687- parent : & dyn fmt:: Debug ,
688595 base_ty : PlaceTy < ' tcx > ,
689596 field : FieldIdx ,
690597 location : Location ,
@@ -747,12 +654,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
747654 } ;
748655 }
749656 _ => {
750- return Ok ( span_mirbug_and_err ! (
751- self ,
752- parent,
753- "can't project out of {:?}" ,
754- base_ty
755- ) ) ;
657+ span_bug ! ( self . last_span, "can't project out of {:?}" , base_ty) ;
756658 }
757659 } ,
758660 } ;
0 commit comments