@@ -39,13 +39,14 @@ use rustc::ty::fold::TypeFoldable;
3939use rustc:: ty:: subst:: { Subst , SubstsRef , UnpackedKind , UserSubsts } ;
4040use rustc:: ty:: {
4141 self , RegionVid , ToPolyTraitRef , Ty , TyCtxt , TyKind , UserType ,
42- CanonicalUserTypeAnnotation , UserTypeAnnotationIndex ,
42+ CanonicalUserTypeAnnotation , CanonicalUserTypeAnnotations ,
43+ UserTypeAnnotationIndex ,
4344} ;
4445use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
4546use rustc_data_structures:: indexed_vec:: { IndexVec , Idx } ;
4647use rustc:: ty:: layout:: VariantIdx ;
4748use std:: rc:: Rc ;
48- use std:: { fmt, iter} ;
49+ use std:: { fmt, iter, mem } ;
4950use syntax_pos:: { Span , DUMMY_SP } ;
5051
5152macro_rules! span_mirbug {
@@ -124,7 +125,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
124125 let mut constraints = MirTypeckRegionConstraints {
125126 placeholder_indices : PlaceholderIndices :: default ( ) ,
126127 placeholder_index_to_region : IndexVec :: default ( ) ,
127- liveness_constraints : LivenessValues :: new ( elements) ,
128+ liveness_constraints : LivenessValues :: new ( elements. clone ( ) ) ,
128129 outlives_constraints : ConstraintSet :: default ( ) ,
129130 closure_bounds_mapping : Default :: default ( ) ,
130131 type_tests : Vec :: default ( ) ,
@@ -253,7 +254,7 @@ enum FieldAccessError {
253254/// is a problem.
254255struct TypeVerifier < ' a , ' b : ' a , ' gcx : ' tcx , ' tcx : ' b > {
255256 cx : & ' a mut TypeChecker < ' b , ' gcx , ' tcx > ,
256- mir : & ' a Mir < ' tcx > ,
257+ mir : & ' b Mir < ' tcx > ,
257258 last_span : Span ,
258259 mir_def_id : DefId ,
259260 errors_reported : bool ,
@@ -283,7 +284,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
283284 location. to_locations ( ) ,
284285 ConstraintCategory :: Boring ,
285286 ) {
286- let annotation = & self . mir . user_type_annotations [ annotation_index] ;
287+ let annotation = & self . cx . user_type_annotations [ annotation_index] ;
287288 span_mirbug ! (
288289 self ,
289290 constant,
@@ -385,7 +386,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
385386}
386387
387388impl < ' a , ' b , ' gcx , ' tcx > TypeVerifier < ' a , ' b , ' gcx , ' tcx > {
388- fn new ( cx : & ' a mut TypeChecker < ' b , ' gcx , ' tcx > , mir : & ' a Mir < ' tcx > ) -> Self {
389+ fn new ( cx : & ' a mut TypeChecker < ' b , ' gcx , ' tcx > , mir : & ' b Mir < ' tcx > ) -> Self {
389390 TypeVerifier {
390391 mir,
391392 mir_def_id : cx. mir_def_id ,
@@ -454,19 +455,31 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
454455 Place :: Base ( PlaceBase :: Local ( index) ) => PlaceTy :: Ty {
455456 ty : self . mir . local_decls [ index] . ty ,
456457 } ,
457- Place :: Base ( PlaceBase :: Promoted ( box ( _index , sty) ) ) => {
458+ Place :: Base ( PlaceBase :: Promoted ( box ( index , sty) ) ) => {
458459 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()
460+
461+ if !self . errors_reported {
462+ let promoted_mir = & self . mir . promoted [ index] ;
463+ self . sanitize_promoted ( promoted_mir, location) ;
464+
465+ let promoted_ty = promoted_mir. return_ty ( ) ;
466+
467+ if let Err ( terr) = self . cx . eq_types (
468+ sty,
469+ promoted_ty,
470+ location. to_locations ( ) ,
471+ ConstraintCategory :: Boring ,
472+ ) {
473+ span_mirbug ! (
474+ self ,
475+ place,
476+ "bad promoted type ({:?}: {:?}): {:?}" ,
477+ promoted_ty,
478+ sty,
479+ terr
480+ ) ;
481+ } ;
482+ }
470483 PlaceTy :: Ty { ty : sty }
471484 }
472485 Place :: Base ( PlaceBase :: Static ( box Static { def_id, ty : sty } ) ) => {
@@ -533,6 +546,72 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
533546 place_ty
534547 }
535548
549+ fn sanitize_promoted ( & mut self , promoted_mir : & ' b Mir < ' tcx > , location : Location ) {
550+ // Determine the constraints from the promoted MIR by running the type
551+ // checker on the promoted MIR, then transfer the constraints back to
552+ // the main MIR, changing the locations to the provided location.
553+
554+ let parent_mir = mem:: replace ( & mut self . 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 = parent_mir;
577+ // Merge the outlives constraints back in, at the given location.
578+ if let Some ( ref mut base_bcx) = self . cx . borrowck_context {
579+ mem:: swap ( base_bcx. all_facts , all_facts) ;
580+ mem:: swap ( & mut base_bcx. constraints . outlives_constraints , & mut constraints) ;
581+ mem:: swap ( & mut base_bcx. constraints . closure_bounds_mapping , & mut closure_bounds) ;
582+
583+ let locations = location. to_locations ( ) ;
584+ for constraint in constraints. iter ( ) {
585+ let mut constraint = * constraint;
586+ constraint. locations = locations;
587+ if let ConstraintCategory :: Return
588+ | ConstraintCategory :: UseAsConst
589+ | ConstraintCategory :: UseAsStatic = constraint. category
590+ {
591+ // "Returning" from a promoted is an assigment to a
592+ // temporary from the user's point of view.
593+ constraint. category = ConstraintCategory :: Boring ;
594+ }
595+ base_bcx. constraints . outlives_constraints . push ( constraint)
596+ }
597+
598+ if !closure_bounds. is_empty ( ) {
599+ let combined_bounds_mapping = closure_bounds
600+ . into_iter ( )
601+ . flat_map ( |( _, value) | value)
602+ . collect ( ) ;
603+ let existing = base_bcx
604+ . constraints
605+ . closure_bounds_mapping
606+ . insert ( location, combined_bounds_mapping) ;
607+ assert ! (
608+ existing. is_none( ) ,
609+ "Multiple promoteds/closures at the same location."
610+ ) ;
611+ }
612+ }
613+ }
614+
536615 fn sanitize_projection (
537616 & mut self ,
538617 base : PlaceTy < ' tcx > ,
@@ -738,7 +817,9 @@ struct TypeChecker<'a, 'gcx: 'tcx, 'tcx: 'a> {
738817 infcx : & ' a InferCtxt < ' a , ' gcx , ' tcx > ,
739818 param_env : ty:: ParamEnv < ' gcx > ,
740819 last_span : Span ,
741- mir : & ' a Mir < ' tcx > ,
820+ /// User type annotations are shared between the main MIR and the MIR of
821+ /// all of the promoted items.
822+ user_type_annotations : & ' a CanonicalUserTypeAnnotations < ' tcx > ,
742823 mir_def_id : DefId ,
743824 region_bound_pairs : & ' a RegionBoundPairs < ' tcx > ,
744825 implicit_region_bound : Option < ty:: Region < ' tcx > > ,
@@ -893,8 +974,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
893974 let mut checker = Self {
894975 infcx,
895976 last_span : DUMMY_SP ,
896- mir,
897977 mir_def_id,
978+ user_type_annotations : & mir. user_type_annotations ,
898979 param_env,
899980 region_bound_pairs,
900981 implicit_region_bound,
@@ -910,9 +991,9 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
910991 fn check_user_type_annotations ( & mut self ) {
911992 debug ! (
912993 "check_user_type_annotations: user_type_annotations={:?}" ,
913- self . mir . user_type_annotations
994+ self . user_type_annotations
914995 ) ;
915- for user_annotation in & self . mir . user_type_annotations {
996+ for user_annotation in self . user_type_annotations {
916997 let CanonicalUserTypeAnnotation { span, ref user_ty, inferred_ty } = * user_annotation;
917998 let ( annotation, _) = self . infcx . instantiate_canonical_with_fresh_inference_vars (
918999 span, user_ty
@@ -1095,7 +1176,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
10951176 a, v, user_ty, locations,
10961177 ) ;
10971178
1098- let annotated_type = self . mir . user_type_annotations [ user_ty. base ] . inferred_ty ;
1179+ let annotated_type = self . user_type_annotations [ user_ty. base ] . inferred_ty ;
10991180 let mut curr_projected_ty = PlaceTy :: from_ty ( annotated_type) ;
11001181
11011182 let tcx = self . infcx . tcx ;
@@ -1281,7 +1362,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
12811362 location. to_locations ( ) ,
12821363 ConstraintCategory :: Boring ,
12831364 ) {
1284- let annotation = & mir . user_type_annotations [ annotation_index] ;
1365+ let annotation = & self . user_type_annotations [ annotation_index] ;
12851366 span_mirbug ! (
12861367 self ,
12871368 stmt,
@@ -1340,7 +1421,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
13401421 Locations :: All ( stmt. source_info . span ) ,
13411422 ConstraintCategory :: TypeAnnotation ,
13421423 ) {
1343- let annotation = & mir . user_type_annotations [ projection. base ] ;
1424+ let annotation = & self . user_type_annotations [ projection. base ] ;
13441425 span_mirbug ! (
13451426 self ,
13461427 stmt,
@@ -1998,7 +2079,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
19982079 }
19992080
20002081 Rvalue :: Ref ( region, _borrow_kind, borrowed_place) => {
2001- self . add_reborrow_constraint ( location, region, borrowed_place) ;
2082+ self . add_reborrow_constraint ( mir , location, region, borrowed_place) ;
20022083 }
20032084
20042085 // FIXME: These other cases have to be implemented in future PRs
@@ -2097,6 +2178,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
20972178 /// - `borrowed_place`: the place `P` being borrowed
20982179 fn add_reborrow_constraint (
20992180 & mut self ,
2181+ mir : & Mir < ' tcx > ,
21002182 location : Location ,
21012183 borrow_region : ty:: Region < ' tcx > ,
21022184 borrowed_place : & Place < ' tcx > ,
@@ -2146,7 +2228,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
21462228 match * elem {
21472229 ProjectionElem :: Deref => {
21482230 let tcx = self . infcx . tcx ;
2149- let base_ty = base. ty ( self . mir , tcx) . to_ty ( tcx) ;
2231+ let base_ty = base. ty ( mir, tcx) . to_ty ( tcx) ;
21502232
21512233 debug ! ( "add_reborrow_constraint - base_ty = {:?}" , base_ty) ;
21522234 match base_ty. sty {
@@ -2275,7 +2357,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
22752357 ) -> ty:: InstantiatedPredicates < ' tcx > {
22762358 if let Some ( closure_region_requirements) = tcx. mir_borrowck ( def_id) . closure_requirements {
22772359 let closure_constraints =
2278- closure_region_requirements. apply_requirements ( tcx, location , def_id, substs) ;
2360+ closure_region_requirements. apply_requirements ( tcx, def_id, substs) ;
22792361
22802362 if let Some ( ref mut borrowck_context) = self . borrowck_context {
22812363 let bounds_mapping = closure_constraints
0 commit comments