@@ -1290,44 +1290,37 @@ impl<'tcx> RegionInferenceContext<'tcx> {
12901290 // Grow `shorter_fr` until we find some non-local regions. (We
12911291 // always will.) We'll call them `shorter_fr+` -- they're ever
12921292 // so slightly larger than `shorter_fr`.
1293- let shorter_fr_plusses =
1293+ let shorter_fr_plus =
12941294 self . universal_region_relations . non_local_upper_bounds ( shorter_fr) ;
1295- debug ! (
1296- "try_propagate_universal_region_error: shorter_fr_plus={:?}" ,
1297- shorter_fr_plusses
1298- ) ;
12991295
1300- let fr_static = self . universal_regions ( ) . fr_static ;
1301- let single_region = shorter_fr_plusses. len ( ) == 1 ;
1302-
1303- for shorter_fr_plus in shorter_fr_plusses {
1304- // Don't propagate every `fr-: shorter_fr+`.
1305- // A smaller "optimal subset" exists, since full propagation is overly conservative
1306- // and can reject valid code. Consider this small example (`'b: 'a` == `a -> b`)
1307- // were we try to propagate region error `'d: 'a`:
1308- // a --> b --> d
1309- // \
1310- // \-> c
1311- // Here `shorter_fr_plusses` == `['b, 'c]`.
1312- // Propagating `'d: 'b` is correct and should happen; `'d: 'c` is redundant and can reject valid code.
1313- // We can come closer to this "optimal subset" by checking if the `shorter_fr+` should be outlived by `fr-`.
1314- // NOTE: [] is *not* a valid subset, so we check for that as well.
1315- if single_region
1316- || shorter_fr_plus == fr_static // `fr-: 'static` should be propagated
1317- || self . eval_outlives ( fr_minus, shorter_fr_plus)
1318- {
1319- debug ! (
1320- "try_propagate_universal_region_error: propagating {:?}: {:?}" ,
1321- fr_minus, shorter_fr_plus,
1322- ) ;
1323- // If that's the case, push the constraint `fr-: shorter_fr+`
1324- propagated_outlives_requirements. push ( ClosureOutlivesRequirement {
1325- subject : ClosureOutlivesSubject :: Region ( fr_minus) ,
1326- outlived_free_region : shorter_fr_plus,
1327- blame_span : blame_constraint. cause . span ,
1328- category : blame_constraint. category ,
1329- } ) ;
1330- }
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.
1298+ //
1299+ // Consider this example (`'b: 'a` == `a -> b`), where we try to propagate `'d: 'a`:
1300+ // a --> b --> d
1301+ // \
1302+ // \-> c
1303+ // 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.
1306+ //
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
1310+ . iter ( )
1311+ . filter ( |& & fr_plus| self . eval_outlives ( fr_minus, fr_plus) )
1312+ . copied ( )
1313+ . 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+`
1318+ propagated_outlives_requirements. push ( ClosureOutlivesRequirement {
1319+ subject : ClosureOutlivesSubject :: Region ( fr_minus) ,
1320+ outlived_free_region : fr,
1321+ blame_span : blame_constraint. cause . span ,
1322+ category : blame_constraint. category ,
1323+ } ) ;
13311324 }
13321325 return RegionRelationCheckResult :: Propagated ;
13331326 }
0 commit comments