@@ -45,7 +45,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
4545use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
4646use rustc:: ty:: layout:: VariantIdx ;
4747use std:: rc:: Rc ;
48- use std:: { fmt, iter} ;
48+ use std:: { fmt, iter, mem } ;
4949use syntax_pos:: { Span , DUMMY_SP } ;
5050
5151macro_rules! span_mirbug {
@@ -124,7 +124,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
124124 let mut constraints = MirTypeckRegionConstraints {
125125 placeholder_indices : PlaceholderIndices :: default ( ) ,
126126 placeholder_index_to_region : IndexVec :: default ( ) ,
127- liveness_constraints : LivenessValues :: new ( elements) ,
127+ liveness_constraints : LivenessValues :: new ( elements. clone ( ) ) ,
128128 outlives_constraints : ConstraintSet :: default ( ) ,
129129 closure_bounds_mapping : Default :: default ( ) ,
130130 type_tests : Vec :: default ( ) ,
@@ -253,7 +253,7 @@ enum FieldAccessError {
253253/// is a problem.
254254struct TypeVerifier < ' a , ' b : ' a , ' gcx : ' tcx , ' tcx : ' b > {
255255 cx : & ' a mut TypeChecker < ' b , ' gcx , ' tcx > ,
256- mir : & ' a Mir < ' tcx > ,
256+ mir : & ' b Mir < ' tcx > ,
257257 last_span : Span ,
258258 mir_def_id : DefId ,
259259 errors_reported : bool ,
@@ -385,7 +385,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
385385}
386386
387387impl < ' a , ' b , ' gcx , ' tcx > TypeVerifier < ' a , ' b , ' gcx , ' tcx > {
388- fn new ( cx : & ' a mut TypeChecker < ' b , ' gcx , ' tcx > , mir : & ' a Mir < ' tcx > ) -> Self {
388+ fn new ( cx : & ' a mut TypeChecker < ' b , ' gcx , ' tcx > , mir : & ' b Mir < ' tcx > ) -> Self {
389389 TypeVerifier {
390390 mir,
391391 mir_def_id : cx. mir_def_id ,
@@ -454,19 +454,31 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
454454 Place :: Base ( PlaceBase :: Local ( index) ) => PlaceTy :: Ty {
455455 ty : self . mir . local_decls [ index] . ty ,
456456 } ,
457- Place :: Base ( PlaceBase :: Promoted ( box ( _index , sty) ) ) => {
457+ Place :: Base ( PlaceBase :: Promoted ( box ( index , sty) ) ) => {
458458 let sty = self . sanitize_type ( place, sty) ;
459- // FIXME -- promoted MIR return types reference
460- // various "free regions" (e.g., scopes and things)
461- // that they ought not to do. We have to figure out
462- // how best to handle that -- probably we want treat
463- // promoted MIR much like closures, renumbering all
464- // their free regions and propagating constraints
465- // upwards. We have the same acyclic guarantees, so
466- // that should be possible. But for now, ignore them.
467- //
468- // let promoted_mir = &self.mir.promoted[index];
469- // promoted_mir.return_ty()
459+
460+ if !self . errors_reported {
461+ let promoted_mir = & self . mir . promoted [ index] ;
462+ self . sanitize_promoted ( promoted_mir, location) ;
463+
464+ let promoted_ty = promoted_mir. return_ty ( ) ;
465+
466+ if let Err ( terr) = self . cx . eq_types (
467+ sty,
468+ promoted_ty,
469+ location. to_locations ( ) ,
470+ ConstraintCategory :: Boring ,
471+ ) {
472+ span_mirbug ! (
473+ self ,
474+ place,
475+ "bad promoted type ({:?}: {:?}): {:?}" ,
476+ promoted_ty,
477+ sty,
478+ terr
479+ ) ;
480+ } ;
481+ }
470482 PlaceTy :: Ty { ty : sty }
471483 }
472484 Place :: Base ( PlaceBase :: Static ( box Static { def_id, ty : sty } ) ) => {
@@ -533,6 +545,74 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
533545 place_ty
534546 }
535547
548+ fn sanitize_promoted ( & mut self , promoted_mir : & ' b Mir < ' tcx > , location : Location ) {
549+ // Determine the constraints from the promoted MIR by running the type
550+ // checker on the promoted MIR, then transfer the constraints back to
551+ // the main MIR, changing the locations to the provided location.
552+
553+ let main_mir = mem:: replace ( & mut self . mir , promoted_mir) ;
554+ self . cx . mir = promoted_mir;
555+
556+ let all_facts = & mut None ;
557+ let mut constraints = Default :: default ( ) ;
558+ let mut closure_bounds = Default :: default ( ) ;
559+ if let Some ( ref mut bcx) = self . cx . borrowck_context {
560+ // Don't try to add borrow_region facts for the promoted MIR
561+ mem:: swap ( bcx. all_facts , all_facts) ;
562+
563+ // Use a new sets of constraints and closure bounds so that we can
564+ // modify their locations.
565+ mem:: swap ( & mut bcx. constraints . outlives_constraints , & mut constraints) ;
566+ mem:: swap ( & mut bcx. constraints . closure_bounds_mapping , & mut closure_bounds) ;
567+ } ;
568+
569+ self . visit_mir ( promoted_mir) ;
570+
571+ if !self . errors_reported {
572+ // if verifier failed, don't do further checks to avoid ICEs
573+ self . cx . typeck_mir ( promoted_mir) ;
574+ }
575+
576+ self . mir = main_mir;
577+ self . cx . mir = main_mir;
578+ // Merge the outlives constraints back in, at the given location.
579+ if let Some ( ref mut base_bcx) = self . cx . borrowck_context {
580+ mem:: swap ( base_bcx. all_facts , all_facts) ;
581+ mem:: swap ( & mut base_bcx. constraints . outlives_constraints , & mut constraints) ;
582+ mem:: swap ( & mut base_bcx. constraints . closure_bounds_mapping , & mut closure_bounds) ;
583+
584+ let locations = location. to_locations ( ) ;
585+ for constraint in constraints. iter ( ) {
586+ let mut constraint = * constraint;
587+ constraint. locations = locations;
588+ if let ConstraintCategory :: Return
589+ | ConstraintCategory :: UseAsConst
590+ | ConstraintCategory :: UseAsStatic = constraint. category
591+ {
592+ // "Returning" from a promoted is an assigment to a
593+ // temporary from the user's point of view.
594+ constraint. category = ConstraintCategory :: Boring ;
595+ }
596+ base_bcx. constraints . outlives_constraints . push ( constraint)
597+ }
598+
599+ if !closure_bounds. is_empty ( ) {
600+ let combined_bounds_mapping = closure_bounds
601+ . into_iter ( )
602+ . flat_map ( |( _, value) | value)
603+ . collect ( ) ;
604+ let existing = base_bcx
605+ . constraints
606+ . closure_bounds_mapping
607+ . insert ( location, combined_bounds_mapping) ;
608+ assert ! (
609+ existing. is_none( ) ,
610+ "Multiple promoteds/closures at the same location."
611+ ) ;
612+ }
613+ }
614+ }
615+
536616 fn sanitize_projection (
537617 & mut self ,
538618 base : PlaceTy < ' tcx > ,
@@ -2275,7 +2355,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
22752355 ) -> ty:: InstantiatedPredicates < ' tcx > {
22762356 if let Some ( closure_region_requirements) = tcx. mir_borrowck ( def_id) . closure_requirements {
22772357 let closure_constraints =
2278- closure_region_requirements. apply_requirements ( tcx, location , def_id, substs) ;
2358+ closure_region_requirements. apply_requirements ( tcx, def_id, substs) ;
22792359
22802360 if let Some ( ref mut borrowck_context) = self . borrowck_context {
22812361 let bounds_mapping = closure_constraints
0 commit comments