@@ -15,7 +15,7 @@ use rustc::mir::{
15
15
ConstraintCategory , Local , Location , Mir ,
16
16
} ;
17
17
use rustc:: ty:: { self , RegionVid , Ty , TyCtxt , TypeFoldable } ;
18
- use rustc:: util:: common;
18
+ use rustc:: util:: common:: { self , ErrorReported } ;
19
19
use rustc_data_structures:: bit_set:: BitSet ;
20
20
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
21
21
use rustc_data_structures:: graph:: scc:: Sccs ;
@@ -1157,63 +1157,107 @@ impl<'tcx> RegionInferenceContext<'tcx> {
1157
1157
. is_none( )
1158
1158
) ;
1159
1159
1160
+ // Only check all of the relations for the main representative of each
1161
+ // SCC, otherwise just check that we outlive said representative. This
1162
+ // reduces the number of redundant relations propagated out of
1163
+ // closures.
1164
+ // Note that the representative will be a universal region if there is
1165
+ // one in this SCC, so we will always check the representative here.
1166
+ let representative = self . scc_representatives [ longer_fr_scc] ;
1167
+ if representative != longer_fr {
1168
+ self . check_universal_region_relation (
1169
+ longer_fr,
1170
+ representative,
1171
+ infcx,
1172
+ mir,
1173
+ mir_def_id,
1174
+ propagated_outlives_requirements,
1175
+ errors_buffer,
1176
+ ) ;
1177
+ return ;
1178
+ }
1179
+
1160
1180
// Find every region `o` such that `fr: o`
1161
1181
// (because `fr` includes `end(o)`).
1162
1182
for shorter_fr in self . scc_values . universal_regions_outlived_by ( longer_fr_scc) {
1163
- // If it is known that `fr: o`, carry on.
1164
- if self . universal_region_relations
1165
- . outlives ( longer_fr, shorter_fr)
1166
- {
1167
- continue ;
1183
+ if let Some ( ErrorReported ) = self . check_universal_region_relation (
1184
+ longer_fr,
1185
+ shorter_fr,
1186
+ infcx,
1187
+ mir,
1188
+ mir_def_id,
1189
+ propagated_outlives_requirements,
1190
+ errors_buffer,
1191
+ ) {
1192
+ // continuing to iterate just reports more errors than necessary
1193
+ return ;
1168
1194
}
1195
+ }
1196
+ }
1169
1197
1170
- debug ! (
1171
- "check_universal_region: fr={:?} does not outlive shorter_fr={:?}" ,
1172
- longer_fr, shorter_fr,
1173
- ) ;
1198
+ fn check_universal_region_relation (
1199
+ & self ,
1200
+ longer_fr : RegionVid ,
1201
+ shorter_fr : RegionVid ,
1202
+ infcx : & InferCtxt < ' _ , ' gcx , ' tcx > ,
1203
+ mir : & Mir < ' tcx > ,
1204
+ mir_def_id : DefId ,
1205
+ propagated_outlives_requirements : & mut Option < & mut Vec < ClosureOutlivesRequirement < ' gcx > > > ,
1206
+ errors_buffer : & mut Vec < Diagnostic > ,
1207
+ ) -> Option < ErrorReported > {
1208
+ // If it is known that `fr: o`, carry on.
1209
+ if self . universal_region_relations
1210
+ . outlives ( longer_fr, shorter_fr)
1211
+ {
1212
+ return None ;
1213
+ }
1174
1214
1175
- let blame_span_category = self . find_outlives_blame_span ( mir, longer_fr, shorter_fr) ;
1176
-
1177
- if let Some ( propagated_outlives_requirements) = propagated_outlives_requirements {
1178
- // Shrink `fr` until we find a non-local region (if we do).
1179
- // We'll call that `fr-` -- it's ever so slightly smaller than `fr`.
1180
- if let Some ( fr_minus) = self . universal_region_relations
1181
- . non_local_lower_bound ( longer_fr)
1182
- {
1183
- debug ! ( "check_universal_region: fr_minus={:?}" , fr_minus) ;
1184
-
1185
- // Grow `shorter_fr` until we find a non-local
1186
- // region. (We always will.) We'll call that
1187
- // `shorter_fr+` -- it's ever so slightly larger than
1188
- // `fr`.
1189
- let shorter_fr_plus = self . universal_region_relations
1190
- . non_local_upper_bound ( shorter_fr) ;
1191
- debug ! (
1192
- "check_universal_region: shorter_fr_plus={:?}" ,
1193
- shorter_fr_plus
1194
- ) ;
1215
+ debug ! (
1216
+ "check_universal_region_relation: fr={:?} does not outlive shorter_fr={:?}" ,
1217
+ longer_fr, shorter_fr,
1218
+ ) ;
1195
1219
1196
- // Push the constraint `fr-: shorter_fr+`
1197
- propagated_outlives_requirements. push ( ClosureOutlivesRequirement {
1198
- subject : ClosureOutlivesSubject :: Region ( fr_minus) ,
1199
- outlived_free_region : shorter_fr_plus,
1200
- blame_span : blame_span_category. 1 ,
1201
- category : blame_span_category. 0 ,
1202
- } ) ;
1203
- continue ;
1204
- }
1205
- }
1206
1220
1207
- // If we are not in a context where we can propagate
1208
- // errors, or we could not shrink `fr` to something
1209
- // smaller, then just report an error.
1210
- //
1211
- // Note: in this case, we use the unapproximated regions
1212
- // to report the error. This gives better error messages
1213
- // in some cases.
1214
- self . report_error ( mir, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer) ;
1215
- return ; // continuing to iterate just reports more errors than necessary
1221
+ if let Some ( propagated_outlives_requirements) = propagated_outlives_requirements {
1222
+ // Shrink `fr` until we find a non-local region (if we do).
1223
+ // We'll call that `fr-` -- it's ever so slightly smaller than `fr`.
1224
+ if let Some ( fr_minus) = self . universal_region_relations
1225
+ . non_local_lower_bound ( longer_fr)
1226
+ {
1227
+ debug ! ( "check_universal_region: fr_minus={:?}" , fr_minus) ;
1228
+
1229
+ let blame_span_category = self . find_outlives_blame_span ( mir, longer_fr, shorter_fr) ;
1230
+
1231
+ // Grow `shorter_fr` until we find a non-local
1232
+ // region. (We always will.) We'll call that
1233
+ // `shorter_fr+` -- it's ever so slightly larger than
1234
+ // `fr`.
1235
+ let shorter_fr_plus = self . universal_region_relations
1236
+ . non_local_upper_bound ( shorter_fr) ;
1237
+ debug ! (
1238
+ "check_universal_region: shorter_fr_plus={:?}" ,
1239
+ shorter_fr_plus
1240
+ ) ;
1241
+
1242
+ // Push the constraint `fr-: shorter_fr+`
1243
+ propagated_outlives_requirements. push ( ClosureOutlivesRequirement {
1244
+ subject : ClosureOutlivesSubject :: Region ( fr_minus) ,
1245
+ outlived_free_region : shorter_fr_plus,
1246
+ blame_span : blame_span_category. 1 ,
1247
+ category : blame_span_category. 0 ,
1248
+ } ) ;
1249
+ return None ;
1250
+ }
1216
1251
}
1252
+
1253
+ // If we are not in a context where we can't propagate errors, or we
1254
+ // could not shrink `fr` to something smaller, then just report an
1255
+ // error.
1256
+ //
1257
+ // Note: in this case, we use the unapproximated regions to report the
1258
+ // error. This gives better error messages in some cases.
1259
+ self . report_error ( mir, infcx, mir_def_id, longer_fr, shorter_fr, errors_buffer) ;
1260
+ Some ( ErrorReported )
1217
1261
}
1218
1262
1219
1263
fn check_bound_universal_region < ' gcx > (
0 commit comments