@@ -45,7 +45,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
45
45
use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
46
46
use rustc:: ty:: layout:: VariantIdx ;
47
47
use std:: rc:: Rc ;
48
- use std:: { fmt, iter} ;
48
+ use std:: { fmt, iter, mem } ;
49
49
use syntax_pos:: { Span , DUMMY_SP } ;
50
50
51
51
macro_rules! span_mirbug {
@@ -124,7 +124,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
124
124
let mut constraints = MirTypeckRegionConstraints {
125
125
placeholder_indices : PlaceholderIndices :: default ( ) ,
126
126
placeholder_index_to_region : IndexVec :: default ( ) ,
127
- liveness_constraints : LivenessValues :: new ( elements) ,
127
+ liveness_constraints : LivenessValues :: new ( elements. clone ( ) ) ,
128
128
outlives_constraints : ConstraintSet :: default ( ) ,
129
129
closure_bounds_mapping : Default :: default ( ) ,
130
130
type_tests : Vec :: default ( ) ,
@@ -253,7 +253,7 @@ enum FieldAccessError {
253
253
/// is a problem.
254
254
struct TypeVerifier < ' a , ' b : ' a , ' gcx : ' tcx , ' tcx : ' b > {
255
255
cx : & ' a mut TypeChecker < ' b , ' gcx , ' tcx > ,
256
- mir : & ' a Mir < ' tcx > ,
256
+ mir : & ' b Mir < ' tcx > ,
257
257
last_span : Span ,
258
258
mir_def_id : DefId ,
259
259
errors_reported : bool ,
@@ -385,7 +385,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
385
385
}
386
386
387
387
impl < ' 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 {
389
389
TypeVerifier {
390
390
mir,
391
391
mir_def_id : cx. mir_def_id ,
@@ -454,19 +454,31 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
454
454
Place :: Base ( PlaceBase :: Local ( index) ) => PlaceTy :: Ty {
455
455
ty : self . mir . local_decls [ index] . ty ,
456
456
} ,
457
- Place :: Base ( PlaceBase :: Promoted ( box ( _index , sty) ) ) => {
457
+ Place :: Base ( PlaceBase :: Promoted ( box ( index , sty) ) ) => {
458
458
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
+ }
470
482
PlaceTy :: Ty { ty : sty }
471
483
}
472
484
Place :: Base ( PlaceBase :: Static ( box Static { def_id, ty : sty } ) ) => {
@@ -533,6 +545,74 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
533
545
place_ty
534
546
}
535
547
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
+
536
616
fn sanitize_projection (
537
617
& mut self ,
538
618
base : PlaceTy < ' tcx > ,
@@ -2275,7 +2355,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
2275
2355
) -> ty:: InstantiatedPredicates < ' tcx > {
2276
2356
if let Some ( closure_region_requirements) = tcx. mir_borrowck ( def_id) . closure_requirements {
2277
2357
let closure_constraints =
2278
- closure_region_requirements. apply_requirements ( tcx, location , def_id, substs) ;
2358
+ closure_region_requirements. apply_requirements ( tcx, def_id, substs) ;
2279
2359
2280
2360
if let Some ( ref mut borrowck_context) = self . borrowck_context {
2281
2361
let bounds_mapping = closure_constraints
0 commit comments