@@ -29,7 +29,7 @@ use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionV
29
29
use rustc:: infer:: type_variable:: TypeVariableOrigin ;
30
30
use rustc:: mir:: interpret:: { InterpError :: BoundsCheck , ConstValue } ;
31
31
use rustc:: mir:: tcx:: PlaceTy ;
32
- use rustc:: mir:: visit:: { PlaceContext , Visitor , MutatingUseContext , NonMutatingUseContext } ;
32
+ use rustc:: mir:: visit:: { PlaceContext , Visitor , NonMutatingUseContext } ;
33
33
use rustc:: mir:: * ;
34
34
use rustc:: traits:: query:: type_op;
35
35
use rustc:: traits:: query:: type_op:: custom:: CustomTypeOp ;
@@ -447,92 +447,95 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
447
447
context : PlaceContext ,
448
448
) -> PlaceTy < ' tcx > {
449
449
debug ! ( "sanitize_place: {:?}" , place) ;
450
- let place_ty = match place {
451
- Place :: Base ( PlaceBase :: Local ( index) ) =>
452
- PlaceTy :: from_ty ( self . mir . local_decls [ * index] . ty ) ,
453
- Place :: Base ( PlaceBase :: Static ( box Static { kind, ty : sty } ) ) => {
454
- let sty = self . sanitize_type ( place, sty) ;
455
- let check_err =
456
- |verifier : & mut TypeVerifier < ' a , ' b , ' gcx , ' tcx > ,
457
- place : & Place < ' tcx > ,
458
- ty,
459
- sty| {
460
- if let Err ( terr) = verifier. cx . eq_types (
461
- sty,
462
- ty,
463
- location. to_locations ( ) ,
464
- ConstraintCategory :: Boring ,
465
- ) {
466
- span_mirbug ! (
467
- verifier,
468
- place,
469
- "bad promoted type ({:?}: {:?}): {:?}" ,
470
- ty,
471
- sty,
472
- terr
473
- ) ;
450
+
451
+ place. iterate ( |place_base, place_projection| {
452
+ let mut place_ty = match place_base {
453
+ PlaceBase :: Local ( index) =>
454
+ PlaceTy :: from_ty ( self . mir . local_decls [ * index] . ty ) ,
455
+ PlaceBase :: Static ( box Static { kind, ty : sty } ) => {
456
+ let sty = self . sanitize_type ( place, sty) ;
457
+ let check_err =
458
+ |verifier : & mut TypeVerifier < ' a , ' b , ' gcx , ' tcx > ,
459
+ place : & Place < ' tcx > ,
460
+ ty,
461
+ sty| {
462
+ if let Err ( terr) = verifier. cx . eq_types (
463
+ sty,
464
+ ty,
465
+ location. to_locations ( ) ,
466
+ ConstraintCategory :: Boring ,
467
+ ) {
468
+ span_mirbug ! (
469
+ verifier,
470
+ place,
471
+ "bad promoted type ({:?}: {:?}): {:?}" ,
472
+ ty,
473
+ sty,
474
+ terr
475
+ ) ;
476
+ } ;
474
477
} ;
475
- } ;
476
- match kind {
477
- StaticKind :: Promoted ( promoted ) => {
478
- if ! self . errors_reported {
479
- let promoted_mir = & self . mir . promoted [ * promoted ] ;
480
- self . sanitize_promoted ( promoted_mir , location ) ;
481
-
482
- let promoted_ty = promoted_mir . return_ty ( ) ;
483
- check_err ( self , place , promoted_ty , sty ) ;
478
+ match kind {
479
+ StaticKind :: Promoted ( promoted ) => {
480
+ if ! self . errors_reported {
481
+ let promoted_mir = & self . mir . promoted [ * promoted ] ;
482
+ self . sanitize_promoted ( promoted_mir , location ) ;
483
+
484
+ let promoted_ty = promoted_mir . return_ty ( ) ;
485
+ check_err ( self , place , promoted_ty , sty ) ;
486
+ }
484
487
}
485
- }
486
- StaticKind :: Static ( def_id) => {
487
- let ty = self . tcx ( ) . type_of ( * def_id) ;
488
- let ty = self . cx . normalize ( ty, location) ;
488
+ StaticKind :: Static ( def_id) => {
489
+ let ty = self . tcx ( ) . type_of ( * def_id) ;
490
+ let ty = self . cx . normalize ( ty, location) ;
489
491
490
- check_err ( self , place, ty, sty) ;
492
+ check_err ( self , place, ty, sty) ;
493
+ }
491
494
}
495
+ PlaceTy :: from_ty ( sty)
496
+ }
497
+ } ;
498
+
499
+ // FIXME use place_projection.is_empty() when is available
500
+ if let Place :: Base ( _) = place {
501
+ if let PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) = context {
502
+ let tcx = self . tcx ( ) ;
503
+ let trait_ref = ty:: TraitRef {
504
+ def_id : tcx. lang_items ( ) . copy_trait ( ) . unwrap ( ) ,
505
+ substs : tcx. mk_substs_trait ( place_ty. ty , & [ ] ) ,
506
+ } ;
507
+
508
+ // In order to have a Copy operand, the type T of the
509
+ // value must be Copy. Note that we prove that T: Copy,
510
+ // rather than using the `is_copy_modulo_regions`
511
+ // test. This is important because
512
+ // `is_copy_modulo_regions` ignores the resulting region
513
+ // obligations and assumes they pass. This can result in
514
+ // bounds from Copy impls being unsoundly ignored (e.g.,
515
+ // #29149). Note that we decide to use Copy before knowing
516
+ // whether the bounds fully apply: in effect, the rule is
517
+ // that if a value of some type could implement Copy, then
518
+ // it must.
519
+ self . cx . prove_trait_ref (
520
+ trait_ref,
521
+ location. to_locations ( ) ,
522
+ ConstraintCategory :: CopyBound ,
523
+ ) ;
492
524
}
493
- PlaceTy :: from_ty ( sty)
494
525
}
495
- Place :: Projection ( ref proj) => {
496
- let base_context = if context. is_mutating_use ( ) {
497
- PlaceContext :: MutatingUse ( MutatingUseContext :: Projection )
498
- } else {
499
- PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Projection )
500
- } ;
501
- let base_ty = self . sanitize_place ( & proj. base , location, base_context) ;
502
- if base_ty. variant_index . is_none ( ) {
503
- if base_ty. ty . references_error ( ) {
526
+
527
+ for proj in place_projection {
528
+ if place_ty. variant_index . is_none ( ) {
529
+ if place_ty. ty . references_error ( ) {
504
530
assert ! ( self . errors_reported) ;
505
531
return PlaceTy :: from_ty ( self . tcx ( ) . types . err ) ;
506
532
}
507
533
}
508
- self . sanitize_projection ( base_ty , & proj. elem , place, location)
534
+ place_ty = self . sanitize_projection ( place_ty , & proj. elem , place, location)
509
535
}
510
- } ;
511
- if let PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Copy ) = context {
512
- let tcx = self . tcx ( ) ;
513
- let trait_ref = ty:: TraitRef {
514
- def_id : tcx. lang_items ( ) . copy_trait ( ) . unwrap ( ) ,
515
- substs : tcx. mk_substs_trait ( place_ty. ty , & [ ] ) ,
516
- } ;
517
536
518
- // In order to have a Copy operand, the type T of the
519
- // value must be Copy. Note that we prove that T: Copy,
520
- // rather than using the `is_copy_modulo_regions`
521
- // test. This is important because
522
- // `is_copy_modulo_regions` ignores the resulting region
523
- // obligations and assumes they pass. This can result in
524
- // bounds from Copy impls being unsoundly ignored (e.g.,
525
- // #29149). Note that we decide to use Copy before knowing
526
- // whether the bounds fully apply: in effect, the rule is
527
- // that if a value of some type could implement Copy, then
528
- // it must.
529
- self . cx . prove_trait_ref (
530
- trait_ref,
531
- location. to_locations ( ) ,
532
- ConstraintCategory :: CopyBound ,
533
- ) ;
534
- }
535
- place_ty
537
+ place_ty
538
+ } )
536
539
}
537
540
538
541
fn sanitize_promoted ( & mut self , promoted_mir : & ' b Mir < ' tcx > , location : Location ) {
0 commit comments