@@ -15,7 +15,7 @@ use rustc::mir::{
1515 ConstraintCategory , Local , Location , Mir ,
1616} ;
1717use rustc:: ty:: { self , RegionVid , Ty , TyCtxt , TypeFoldable } ;
18- use rustc:: util:: common;
18+ use rustc:: util:: common:: { self , ErrorReported } ;
1919use rustc_data_structures:: bit_set:: BitSet ;
2020use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
2121use rustc_data_structures:: graph:: scc:: Sccs ;
@@ -1157,63 +1157,107 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11571157 . is_none( )
11581158 ) ;
11591159
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+
11601180 // Find every region `o` such that `fr: o`
11611181 // (because `fr` includes `end(o)`).
11621182 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 ;
11681194 }
1195+ }
1196+ }
11691197
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+ }
11741214
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+ ) ;
11951219
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- }
12061220
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+ }
12161251 }
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 )
12171261 }
12181262
12191263 fn check_bound_universal_region < ' gcx > (
0 commit comments