@@ -7,7 +7,6 @@ use rustc_infer::infer::canonical::{self, Canonical};
77use rustc_infer:: infer:: outlives:: components:: { push_outlives_components, Component } ;
88use rustc_infer:: infer:: { InferCtxt , TyCtxtInferExt } ;
99use rustc_infer:: traits:: query:: OutlivesBound ;
10- use rustc_infer:: traits:: TraitEngineExt as _;
1110use rustc_middle:: ty:: query:: Providers ;
1211use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeVisitable } ;
1312use rustc_span:: source_map:: DUMMY_SP ;
@@ -65,70 +64,94 @@ fn compute_implied_outlives_bounds<'tcx>(
6564 // than the ultimate set. (Note: normally there won't be
6665 // unresolved inference variables here anyway, but there might be
6766 // during typeck under some circumstances.)
68- let obligations = wf:: obligations ( infcx, param_env, hir:: CRATE_HIR_ID , 0 , arg, DUMMY_SP )
69- . unwrap_or_default ( ) ;
70-
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.
92- fulfill_cx. register_predicate_obligations (
93- infcx,
94- obligations. iter ( ) . filter ( |o| o. predicate . has_infer_types_or_consts ( ) ) . cloned ( ) ,
95- ) ;
96-
97- // From the full set of obligations, just filter down to the
98- // region relationships.
99- implied_bounds. extend ( obligations. into_iter ( ) . flat_map ( |obligation| {
100- debug ! ( ?obligation) ;
101- assert ! ( !obligation. has_escaping_bound_vars( ) ) ;
102- match obligation. predicate . kind ( ) . no_bound_vars ( ) {
103- None => vec ! [ ] ,
104- Some ( pred) => match pred {
67+ let mut obligations =
68+ wf:: obligations ( infcx, param_env, hir:: CRATE_HIR_ID , 0 , arg, DUMMY_SP )
69+ . unwrap_or_default ( ) ;
70+
71+ let mut first = true ;
72+ loop {
73+ obligations. drain_filter ( |obligation| {
74+ debug ! ( ?obligation) ;
75+ assert ! ( !obligation. has_escaping_bound_vars( ) ) ;
76+ let pred = match obligation. predicate . kind ( ) . no_bound_vars ( ) {
77+ None => return false ,
78+ Some ( pred) => pred,
79+ } ;
80+ match pred {
10581 ty:: PredicateKind :: Trait ( ..)
10682 | ty:: PredicateKind :: Subtype ( ..)
10783 | ty:: PredicateKind :: Coerce ( ..)
108- | ty:: PredicateKind :: Projection ( ..)
10984 | ty:: PredicateKind :: ClosureKind ( ..)
11085 | ty:: PredicateKind :: ObjectSafe ( ..)
11186 | ty:: PredicateKind :: ConstEvaluatable ( ..)
11287 | ty:: PredicateKind :: ConstEquate ( ..)
113- | ty:: PredicateKind :: TypeWellFormedFromEnv ( ..) => vec ! [ ] ,
88+ | ty:: PredicateKind :: TypeWellFormedFromEnv ( ..) => true ,
89+ ty:: PredicateKind :: Projection ( ..) => {
90+ // N.B., all of these predicates *ought* to be easily proven
91+ // true. In fact, their correctness is (mostly) implied by
92+ // other parts of the program. However, in #42552, we had
93+ // an annoying scenario where:
94+ //
95+ // - Some `T::Foo` gets normalized, resulting in a
96+ // variable `_1` and a `T: Trait<Foo=_1>` constraint
97+ // (not sure why it couldn't immediately get
98+ // solved). This result of `_1` got cached.
99+ // - These obligations were dropped on the floor here,
100+ // rather than being registered.
101+ // - Then later we would get a request to normalize
102+ // `T::Foo` which would result in `_1` being used from
103+ // the cache, but hence without the `T: Trait<Foo=_1>`
104+ // constraint. As a result, `_1` never gets resolved,
105+ // and we get an ICE (in dropck).
106+ //
107+ // Therefore, we register any predicates involving
108+ // inference variables. We restrict ourselves to those
109+ // involving inference variables both for efficiency and
110+ // to avoids duplicate errors that otherwise show up.
111+ if obligation. has_infer_types_or_consts ( ) {
112+ fulfill_cx. register_predicate_obligation ( infcx, obligation. clone ( ) ) ;
113+ }
114+ true
115+ }
114116 ty:: PredicateKind :: WellFormed ( arg) => {
115117 wf_args. push ( arg) ;
116- vec ! [ ]
118+ true
117119 }
118120
119121 ty:: PredicateKind :: RegionOutlives ( ty:: OutlivesPredicate ( r_a, r_b) ) => {
120- vec ! [ OutlivesBound :: RegionSubRegion ( r_b, r_a) ]
122+ if first {
123+ false
124+ } else {
125+ implied_bounds. push ( OutlivesBound :: RegionSubRegion ( r_b, r_a) ) ;
126+ true
127+ }
121128 }
122129
123130 ty:: PredicateKind :: TypeOutlives ( ty:: OutlivesPredicate ( ty_a, r_b) ) => {
124- let ty_a = infcx. resolve_vars_if_possible ( ty_a) ;
125- let mut components = smallvec ! [ ] ;
126- push_outlives_components ( tcx, ty_a, & mut components) ;
127- implied_bounds_from_components ( r_b, components)
131+ if first {
132+ false
133+ } else {
134+ let ty_a = infcx. resolve_vars_if_possible ( ty_a) ;
135+ let mut components = smallvec ! [ ] ;
136+ push_outlives_components ( tcx, ty_a, & mut components) ;
137+ let bounds = implied_bounds_from_components ( r_b, components) ;
138+ implied_bounds. extend ( bounds) ;
139+ true
140+ }
128141 }
129- } ,
142+ }
143+ } ) ;
144+
145+ if !first {
146+ break ;
130147 }
131- } ) ) ;
148+
149+ if first {
150+ let _ = fulfill_cx. select_where_possible ( infcx) ;
151+ }
152+
153+ first = false ;
154+ }
132155 }
133156
134157 // Ensure that those obligations that we had to solve
0 commit comments