@@ -49,7 +49,8 @@ fn compute_implied_outlives_bounds<'tcx>(
4949 let mut checked_wf_args = rustc_data_structures:: fx:: FxHashSet :: default ( ) ;
5050 let mut wf_args = vec ! [ ty. into( ) ] ;
5151
52- let mut implied_bounds = vec ! [ ] ;
52+ let mut outlives_bounds: Vec < ty:: OutlivesPredicate < ty:: GenericArg < ' tcx > , ty:: Region < ' tcx > > > =
53+ vec ! [ ] ;
5354
5455 let mut fulfill_cx = <dyn TraitEngine < ' tcx > >:: new ( tcx) ;
5556
@@ -65,41 +66,28 @@ fn compute_implied_outlives_bounds<'tcx>(
6566 // than the ultimate set. (Note: normally there won't be
6667 // unresolved inference variables here anyway, but there might be
6768 // during typeck under some circumstances.)
69+ //
70+ // FIXME(@lcnr): It's not really "always fine", having fewer implied
71+ // bounds can be backward incompatible, e.g. #101951 was caused by
72+ // us not dealing with inference vars in `TypeOutlives` predicates.
6873 let obligations = wf:: obligations ( infcx, param_env, hir:: CRATE_HIR_ID , 0 , arg, DUMMY_SP )
6974 . unwrap_or_default ( ) ;
7075
71- // N.B., all of these predicates *ought* to be easily proven
72- // true. In fact, their correctness is (mostly) implied by
73- // other parts of the program. However, in #42552, we had
74- // an annoying scenario where:
75- //
76- // - Some `T::Foo` gets normalized, resulting in a
77- // variable `_1` and a `T: Trait<Foo=_1>` constraint
78- // (not sure why it couldn't immediately get
79- // solved). This result of `_1` got cached.
80- // - These obligations were dropped on the floor here,
81- // rather than being registered.
82- // - Then later we would get a request to normalize
83- // `T::Foo` which would result in `_1` being used from
84- // the cache, but hence without the `T: Trait<Foo=_1>`
85- // constraint. As a result, `_1` never gets resolved,
86- // and we get an ICE (in dropck).
87- //
88- // Therefore, we register any predicates involving
89- // inference variables. We restrict ourselves to those
90- // involving inference variables both for efficiency and
91- // to avoids duplicate errors that otherwise show up.
76+ // While these predicates should all be implied by other parts of
77+ // the program, they are still relevant as they may constrain
78+ // inference variables, which is necessary to add the correct
79+ // implied bounds in some cases, mostly when dealing with projections.
9280 fulfill_cx. register_predicate_obligations (
9381 infcx,
9482 obligations. iter ( ) . filter ( |o| o. predicate . has_infer_types_or_consts ( ) ) . cloned ( ) ,
9583 ) ;
9684
9785 // From the full set of obligations, just filter down to the
9886 // region relationships.
99- implied_bounds . extend ( obligations. into_iter ( ) . flat_map ( |obligation| {
87+ outlives_bounds . extend ( obligations. into_iter ( ) . filter_map ( |obligation| {
10088 assert ! ( !obligation. has_escaping_bound_vars( ) ) ;
10189 match obligation. predicate . kind ( ) . no_bound_vars ( ) {
102- None => vec ! [ ] ,
90+ None => None ,
10391 Some ( pred) => match pred {
10492 ty:: PredicateKind :: Trait ( ..)
10593 | ty:: PredicateKind :: Subtype ( ..)
@@ -109,21 +97,18 @@ fn compute_implied_outlives_bounds<'tcx>(
10997 | ty:: PredicateKind :: ObjectSafe ( ..)
11098 | ty:: PredicateKind :: ConstEvaluatable ( ..)
11199 | ty:: PredicateKind :: ConstEquate ( ..)
112- | ty:: PredicateKind :: TypeWellFormedFromEnv ( ..) => vec ! [ ] ,
100+ | ty:: PredicateKind :: TypeWellFormedFromEnv ( ..) => None ,
113101 ty:: PredicateKind :: WellFormed ( arg) => {
114102 wf_args. push ( arg) ;
115- vec ! [ ]
103+ None
116104 }
117105
118106 ty:: PredicateKind :: RegionOutlives ( ty:: OutlivesPredicate ( r_a, r_b) ) => {
119- vec ! [ OutlivesBound :: RegionSubRegion ( r_b , r_a ) ]
107+ Some ( ty :: OutlivesPredicate ( r_a . into ( ) , r_b ) )
120108 }
121109
122110 ty:: PredicateKind :: TypeOutlives ( ty:: OutlivesPredicate ( ty_a, r_b) ) => {
123- let ty_a = infcx. resolve_vars_if_possible ( ty_a) ;
124- let mut components = smallvec ! [ ] ;
125- push_outlives_components ( tcx, ty_a, & mut components) ;
126- implied_bounds_from_components ( r_b, components)
111+ Some ( ty:: OutlivesPredicate ( ty_a. into ( ) , r_b) )
127112 }
128113 } ,
129114 }
@@ -133,9 +118,27 @@ fn compute_implied_outlives_bounds<'tcx>(
133118 // Ensure that those obligations that we had to solve
134119 // get solved *here*.
135120 match fulfill_cx. select_all_or_error ( infcx) . as_slice ( ) {
136- [ ] => Ok ( implied_bounds ) ,
137- _ => Err ( NoSolution ) ,
121+ [ ] => ( ) ,
122+ _ => return Err ( NoSolution ) ,
138123 }
124+
125+ // We lazily compute the outlives components as
126+ // `select_all_or_error` constrains inference variables.
127+ let implied_bounds = outlives_bounds
128+ . into_iter ( )
129+ . flat_map ( |ty:: OutlivesPredicate ( a, r_b) | match a. unpack ( ) {
130+ ty:: GenericArgKind :: Lifetime ( r_a) => vec ! [ OutlivesBound :: RegionSubRegion ( r_b, r_a) ] ,
131+ ty:: GenericArgKind :: Type ( ty_a) => {
132+ let ty_a = infcx. resolve_vars_if_possible ( ty_a) ;
133+ let mut components = smallvec ! [ ] ;
134+ push_outlives_components ( tcx, ty_a, & mut components) ;
135+ implied_bounds_from_components ( r_b, components)
136+ }
137+ ty:: GenericArgKind :: Const ( _) => unreachable ! ( ) ,
138+ } )
139+ . collect ( ) ;
140+
141+ Ok ( implied_bounds)
139142}
140143
141144/// When we have an implied bound that `T: 'a`, we can further break
0 commit comments