@@ -75,15 +75,6 @@ macro_rules! span_mirbug {
75
75
} )
76
76
}
77
77
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
-
87
78
mod canonical;
88
79
mod constraint_conversion;
89
80
pub ( crate ) mod free_region_relations;
@@ -263,6 +254,74 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
263
254
self . sanitize_place ( place, location, context) ;
264
255
}
265
256
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
+
266
325
fn visit_const_operand ( & mut self , constant : & ConstOperand < ' tcx > , location : Location ) {
267
326
debug ! ( ?constant, ?location, "visit_const_operand" ) ;
268
327
@@ -444,25 +503,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
444
503
/// Checks that the types internal to the `place` match up with
445
504
/// what would be expected.
446
505
#[ 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) ;
464
510
if let PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) = context {
465
- let tcx = self . tcx ( ) ;
466
511
let trait_ref = ty:: TraitRef :: new (
467
512
tcx,
468
513
tcx. require_lang_item ( LangItem :: Copy , Some ( self . last_span ) ) ,
@@ -486,8 +531,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
486
531
ConstraintCategory :: CopyBound ,
487
532
) ;
488
533
}
489
-
490
- place_ty
491
534
}
492
535
493
536
fn sanitize_promoted ( & mut self , promoted_body : & ' b Body < ' tcx > , location : Location ) {
@@ -547,144 +590,8 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
547
590
}
548
591
}
549
592
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 (
686
594
& mut self ,
687
- parent : & dyn fmt:: Debug ,
688
595
base_ty : PlaceTy < ' tcx > ,
689
596
field : FieldIdx ,
690
597
location : Location ,
@@ -747,12 +654,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
747
654
} ;
748
655
}
749
656
_ => {
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) ;
756
658
}
757
659
} ,
758
660
} ;
0 commit comments