@@ -29,7 +29,7 @@ use rustc::infer::{InferCtxt, InferOk, LateBoundRegionConversionTime, NLLRegionV
2929use rustc:: infer:: type_variable:: TypeVariableOrigin ;
3030use rustc:: mir:: interpret:: { InterpError :: BoundsCheck , ConstValue } ;
3131use rustc:: mir:: tcx:: PlaceTy ;
32- use rustc:: mir:: visit:: { PlaceContext , Visitor , MutatingUseContext , NonMutatingUseContext } ;
32+ use rustc:: mir:: visit:: { PlaceContext , Visitor , NonMutatingUseContext } ;
3333use rustc:: mir:: * ;
3434use rustc:: traits:: query:: type_op;
3535use rustc:: traits:: query:: type_op:: custom:: CustomTypeOp ;
@@ -447,92 +447,95 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
447447 context : PlaceContext ,
448448 ) -> PlaceTy < ' tcx > {
449449 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+ } ;
474477 } ;
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+ }
484487 }
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) ;
489491
490- check_err ( self , place, ty, sty) ;
492+ check_err ( self , place, ty, sty) ;
493+ }
491494 }
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+ ) ;
492524 }
493- PlaceTy :: from_ty ( sty)
494525 }
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 ( ) {
504530 assert ! ( self . errors_reported) ;
505531 return PlaceTy :: from_ty ( self . tcx ( ) . types . err ) ;
506532 }
507533 }
508- self . sanitize_projection ( base_ty , & proj. elem , place, location)
534+ place_ty = self . sanitize_projection ( place_ty , & proj. elem , place, location)
509535 }
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- } ;
517536
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+ } )
536539 }
537540
538541 fn sanitize_promoted ( & mut self , promoted_mir : & ' b Mir < ' tcx > , location : Location ) {
0 commit comments