@@ -1275,49 +1275,81 @@ impl<'tcx> RegionInferenceContext<'tcx> {
12751275 shorter_fr : RegionVid ,
12761276 propagated_outlives_requirements : & mut Option < & mut Vec < ClosureOutlivesRequirement < ' tcx > > > ,
12771277 ) -> RegionRelationCheckResult {
1278- if let Some ( propagated_outlives_requirements) = propagated_outlives_requirements
1279- // Shrink `longer_fr` until we find a non-local region (if we do) .
1280- // We'll call it `fr -` -- it's ever so slightly smaller than
1278+ if let Some ( propagated_outlives_requirements) = propagated_outlives_requirements {
1279+ // Shrink `longer_fr` until we find some non-local regions .
1280+ // We'll call them `longer_fr -` -- they are ever so slightly smaller than
12811281 // `longer_fr`.
1282- && let Some ( fr_minus) = self . universal_region_relations . non_local_lower_bound ( longer_fr)
1283- {
1284- debug ! ( "try_propagate_universal_region_error: fr_minus={:?}" , fr_minus) ;
1282+ let longer_fr_minus = self . universal_region_relations . non_local_lower_bounds ( longer_fr) ;
1283+
1284+ debug ! ( "try_propagate_universal_region_error: fr_minus={:?}" , longer_fr_minus) ;
1285+
1286+ // If we don't find a any non-local regions, we should error out as there is nothing
1287+ // to propagate.
1288+ if longer_fr_minus. is_empty ( ) {
1289+ return RegionRelationCheckResult :: Error ;
1290+ }
12851291
12861292 let blame_constraint = self
12871293 . best_blame_constraint ( longer_fr, NllRegionVariableOrigin :: FreeRegion , shorter_fr)
12881294 . 0 ;
12891295
1290- // Grow `shorter_fr` until we find some non-local regions. (We
1291- // always will.) We'll call them `shorter_fr+` -- they're ever
1292- // so slightly larger than `shorter_fr`.
1296+ // Grow `shorter_fr` until we find some non-local regions.
1297+ // We will always find at least one: `'static`. We'll call
1298+ // them `shorter_fr+` -- they're ever so slightly larger
1299+ // than `shorter_fr`.
12931300 let shorter_fr_plus =
12941301 self . universal_region_relations . non_local_upper_bounds ( shorter_fr) ;
1302+ debug ! ( "try_propagate_universal_region_error: shorter_fr_plus={:?}" , shorter_fr_plus) ;
1303+
1304+ // We then create constraints `longer_fr-: shorter_fr+` that may or may not
1305+ // be propagated (see below).
1306+ let mut constraints = vec ! [ ] ;
1307+ for fr_minus in longer_fr_minus {
1308+ for shorter_fr_plus in & shorter_fr_plus {
1309+ constraints. push ( ( fr_minus, * shorter_fr_plus) ) ;
1310+ }
1311+ }
12951312
1296- // If any of the `shorter_fr+` regions are already outlived by `fr-`, we propagate only those.
1297- // Otherwise, we might incorrectly reject valid code.
1313+ // We only need to propagate at least one of the constraints for
1314+ // soundness. However, we want to avoid arbitrary choices here
1315+ // and currently don't support returning OR constraints.
1316+ //
1317+ // If any of the `shorter_fr+` regions are already outlived by `longer_fr-`,
1318+ // we propagate only those.
12981319 //
12991320 // Consider this example (`'b: 'a` == `a -> b`), where we try to propagate `'d: 'a`:
13001321 // a --> b --> d
13011322 // \
13021323 // \-> c
13031324 // Here, `shorter_fr+` of `'a` == `['b, 'c]`.
1304- // Propagating `'d: 'b` is correct and should occur; `'d: 'c` is redundant because of `'d: 'b`
1305- // and could reject valid code.
1325+ // Propagating `'d: 'b` is correct and should occur; `'d: 'c` is redundant because of
1326+ // `'d: 'b` and could reject valid code.
13061327 //
1307- // So we filter `shorter_fr+` to regions already outlived by `fr -`, but if the filter yields an empty set,
1308- // we fall back to the original one.
1309- let subset: Vec < _ > = shorter_fr_plus
1328+ // So we filter the constraints to regions already outlived by `longer_fr -`, but if
1329+ // the filter yields an empty set, we fall back to the original one.
1330+ let subset: Vec < _ > = constraints
13101331 . iter ( )
1311- . filter ( |& & fr_plus| self . eval_outlives ( fr_minus, fr_plus) )
1332+ . filter ( |& & ( fr_minus, shorter_fr_plus) | {
1333+ self . eval_outlives ( fr_minus, shorter_fr_plus)
1334+ } )
13121335 . copied ( )
13131336 . collect ( ) ;
1314- let shorter_fr_plus = if subset. is_empty ( ) { shorter_fr_plus } else { subset } ;
1315- debug ! ( "try_propagate_universal_region_error: shorter_fr_plus={:?}" , shorter_fr_plus) ;
1316- for fr in shorter_fr_plus {
1317- // Push the constraint `fr-: shorter_fr+`
1337+ let propagated_constraints = if subset. is_empty ( ) { constraints } else { subset } ;
1338+ debug ! (
1339+ "try_propagate_universal_region_error: constraints={:?}" ,
1340+ propagated_constraints
1341+ ) ;
1342+
1343+ assert ! (
1344+ !propagated_constraints. is_empty( ) ,
1345+ "Expected at least one constraint to propagate here"
1346+ ) ;
1347+
1348+ for ( fr_minus, fr_plus) in propagated_constraints {
1349+ // Push the constraint `long_fr-: shorter_fr+`
13181350 propagated_outlives_requirements. push ( ClosureOutlivesRequirement {
13191351 subject : ClosureOutlivesSubject :: Region ( fr_minus) ,
1320- outlived_free_region : fr ,
1352+ outlived_free_region : fr_plus ,
13211353 blame_span : blame_constraint. cause . span ,
13221354 category : blame_constraint. category ,
13231355 } ) ;
0 commit comments