@@ -42,15 +42,15 @@ use rustc::traits::query::type_op::custom::CustomTypeOp;
42
42
use rustc:: traits:: query:: { Fallible , NoSolution } ;
43
43
use rustc:: traits:: { ObligationCause , PredicateObligations } ;
44
44
use rustc:: ty:: fold:: TypeFoldable ;
45
- use rustc:: ty:: subst:: Subst ;
45
+ use rustc:: ty:: subst:: { Subst , UnpackedKind } ;
46
46
use rustc:: ty:: { self , CanonicalTy , RegionVid , ToPolyTraitRef , Ty , TyCtxt , TyKind } ;
47
47
use std:: rc:: Rc ;
48
48
use std:: { fmt, iter} ;
49
49
use syntax_pos:: { Span , DUMMY_SP } ;
50
50
use transform:: { MirPass , MirSource } ;
51
51
52
52
use either:: Either ;
53
- use rustc_data_structures:: fx:: FxHashSet ;
53
+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
54
54
55
55
macro_rules! span_mirbug {
56
56
( $context: expr, $elem: expr, $( $message: tt) * ) => ( {
@@ -128,6 +128,7 @@ pub(crate) fn type_check<'gcx, 'tcx>(
128
128
let mut constraints = MirTypeckRegionConstraints {
129
129
liveness_constraints : LivenessValues :: new ( elements) ,
130
130
outlives_constraints : ConstraintSet :: default ( ) ,
131
+ closure_bounds_mapping : FxHashMap ( ) ,
131
132
type_tests : Vec :: default ( ) ,
132
133
} ;
133
134
let mut placeholder_indices = PlaceholderIndices :: default ( ) ;
@@ -752,6 +753,11 @@ crate struct MirTypeckRegionConstraints<'tcx> {
752
753
753
754
crate outlives_constraints : ConstraintSet ,
754
755
756
+ crate closure_bounds_mapping : FxHashMap <
757
+ Location ,
758
+ FxHashMap < ( RegionVid , RegionVid ) , ( ConstraintCategory , Span ) > ,
759
+ > ,
760
+
755
761
crate type_tests : Vec < TypeTest < ' tcx > > ,
756
762
}
757
763
@@ -860,7 +866,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
860
866
& mut self ,
861
867
locations : Locations ,
862
868
category : ConstraintCategory ,
863
- op : impl type_op:: TypeOp < ' gcx , ' tcx , Output = R > ,
869
+ op : impl type_op:: TypeOp < ' gcx , ' tcx , Output = R > ,
864
870
) -> Fallible < R > {
865
871
let ( r, opt_data) = op. fully_perform ( self . infcx ) ?;
866
872
@@ -1103,17 +1109,17 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
1103
1109
let place_ty = place. ty ( mir, tcx) . to_ty ( tcx) ;
1104
1110
let rv_ty = rv. ty ( mir, tcx) ;
1105
1111
if let Err ( terr) =
1106
- self . sub_types_or_anon ( rv_ty, place_ty, location. to_locations ( ) , category)
1107
- {
1108
- span_mirbug ! (
1112
+ self . sub_types_or_anon ( rv_ty, place_ty, location. to_locations ( ) , category)
1113
+ {
1114
+ span_mirbug ! (
1109
1115
self ,
1110
1116
stmt,
1111
1117
"bad assignment ({:?} = {:?}): {:?}" ,
1112
1118
place_ty,
1113
1119
rv_ty,
1114
1120
terr
1115
1121
) ;
1116
- }
1122
+ }
1117
1123
1118
1124
if let Some ( user_ty) = self . rvalue_user_ty ( rv) {
1119
1125
if let Err ( terr) = self . relate_type_and_user_type (
@@ -1233,17 +1239,17 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
1233
1239
1234
1240
let locations = term_location. to_locations ( ) ;
1235
1241
if let Err ( terr) =
1236
- self . sub_types ( rv_ty, place_ty, locations, ConstraintCategory :: Assignment )
1237
- {
1238
- span_mirbug ! (
1242
+ self . sub_types ( rv_ty, place_ty, locations, ConstraintCategory :: Assignment )
1243
+ {
1244
+ span_mirbug ! (
1239
1245
self ,
1240
1246
term,
1241
1247
"bad DropAndReplace ({:?} = {:?}): {:?}" ,
1242
1248
place_ty,
1243
1249
rv_ty,
1244
1250
terr
1245
1251
) ;
1246
- }
1252
+ }
1247
1253
}
1248
1254
TerminatorKind :: SwitchInt {
1249
1255
ref discr,
@@ -1387,17 +1393,17 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
1387
1393
let locations = term_location. to_locations ( ) ;
1388
1394
1389
1395
if let Err ( terr) =
1390
- self . sub_types_or_anon ( sig. output ( ) , dest_ty, locations, category)
1391
- {
1392
- span_mirbug ! (
1396
+ self . sub_types_or_anon ( sig. output ( ) , dest_ty, locations, category)
1397
+ {
1398
+ span_mirbug ! (
1393
1399
self ,
1394
1400
term,
1395
1401
"call dest mismatch ({:?} <- {:?}): {:?}" ,
1396
1402
dest_ty,
1397
1403
sig. output( ) ,
1398
1404
terr
1399
1405
) ;
1400
- }
1406
+ }
1401
1407
1402
1408
// When `#![feature(unsized_locals)]` is not enabled,
1403
1409
// this check is done at `check_local`.
@@ -2038,7 +2044,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
2038
2044
aggregate_kind, location
2039
2045
) ;
2040
2046
2041
- let instantiated_predicates = match aggregate_kind {
2047
+ let instantiated_predicates = match aggregate_kind {
2042
2048
AggregateKind :: Adt ( def, _, substs, _, _) => {
2043
2049
tcx. predicates_of ( def. did ) . instantiate ( tcx, substs)
2044
2050
}
@@ -2064,24 +2070,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
2064
2070
// these extra requirements are basically like where
2065
2071
// clauses on the struct.
2066
2072
AggregateKind :: Closure ( def_id, substs) => {
2067
- if let Some ( closure_region_requirements) =
2068
- tcx. mir_borrowck ( * def_id) . closure_requirements
2069
- {
2070
- let closure_constraints = closure_region_requirements. apply_requirements (
2071
- self . infcx . tcx ,
2072
- location,
2073
- * def_id,
2074
- * substs,
2075
- ) ;
2076
-
2077
- self . push_region_constraints (
2078
- location. to_locations ( ) ,
2079
- ConstraintCategory :: ClosureBounds ,
2080
- & closure_constraints,
2081
- ) ;
2082
- }
2083
-
2084
- tcx. predicates_of ( * def_id) . instantiate ( tcx, substs. substs )
2073
+ self . prove_closure_bounds ( tcx, * def_id, * substs, location)
2085
2074
}
2086
2075
2087
2076
AggregateKind :: Generator ( def_id, substs, _) => {
@@ -2097,6 +2086,72 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
2097
2086
) ;
2098
2087
}
2099
2088
2089
+ fn prove_closure_bounds (
2090
+ & mut self ,
2091
+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
2092
+ def_id : DefId ,
2093
+ substs : ty:: ClosureSubsts < ' tcx > ,
2094
+ location : Location ,
2095
+ ) -> ty:: InstantiatedPredicates < ' tcx > {
2096
+ if let Some ( closure_region_requirements) =
2097
+ tcx. mir_borrowck ( def_id) . closure_requirements
2098
+ {
2099
+ let closure_constraints = closure_region_requirements. apply_requirements (
2100
+ tcx,
2101
+ location,
2102
+ def_id,
2103
+ substs,
2104
+ ) ;
2105
+
2106
+ if let Some ( ref mut borrowck_context) = self . borrowck_context {
2107
+ let bounds_mapping = closure_constraints
2108
+ . iter ( )
2109
+ . enumerate ( )
2110
+ . filter_map ( |( idx, constraint) | {
2111
+ let ty:: OutlivesPredicate ( k1, r2) =
2112
+ constraint. no_late_bound_regions ( ) . unwrap_or_else ( || {
2113
+ bug ! (
2114
+ "query_constraint {:?} contained bound regions" ,
2115
+ constraint,
2116
+ ) ;
2117
+ } ) ;
2118
+
2119
+ match k1. unpack ( ) {
2120
+ UnpackedKind :: Lifetime ( r1) => {
2121
+ // constraint is r1: r2
2122
+ let r1_vid = borrowck_context. universal_regions . to_region_vid ( r1) ;
2123
+ let r2_vid = borrowck_context. universal_regions . to_region_vid ( r2) ;
2124
+ let outlives_requirements = & closure_region_requirements
2125
+ . outlives_requirements [ idx] ;
2126
+ Some ( (
2127
+ ( r1_vid, r2_vid) ,
2128
+ (
2129
+ outlives_requirements. category ,
2130
+ outlives_requirements. blame_span ,
2131
+ ) ,
2132
+ ) )
2133
+ }
2134
+ UnpackedKind :: Type ( _) => None ,
2135
+ }
2136
+ } )
2137
+ . collect ( ) ;
2138
+
2139
+ let existing = borrowck_context. constraints
2140
+ . closure_bounds_mapping
2141
+ . insert ( location, bounds_mapping) ;
2142
+ assert ! ( existing. is_none( ) , "Multiple closures at the same location." ) ;
2143
+ }
2144
+
2145
+ self . push_region_constraints (
2146
+ location. to_locations ( ) ,
2147
+ ConstraintCategory :: ClosureBounds ,
2148
+ & closure_constraints,
2149
+ ) ;
2150
+ }
2151
+
2152
+ tcx. predicates_of ( def_id) . instantiate ( tcx, substs. substs )
2153
+ }
2154
+
2100
2155
fn prove_trait_ref (
2101
2156
& mut self ,
2102
2157
trait_ref : ty:: TraitRef < ' tcx > ,
0 commit comments