@@ -7,7 +7,6 @@ use rustc_infer::infer::canonical::{self, Canonical};
7
7
use rustc_infer:: infer:: outlives:: components:: { push_outlives_components, Component } ;
8
8
use rustc_infer:: infer:: { InferCtxt , TyCtxtInferExt } ;
9
9
use rustc_infer:: traits:: query:: OutlivesBound ;
10
- use rustc_infer:: traits:: TraitEngineExt as _;
11
10
use rustc_middle:: ty:: query:: Providers ;
12
11
use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeVisitable } ;
13
12
use rustc_span:: source_map:: DUMMY_SP ;
@@ -65,70 +64,94 @@ fn compute_implied_outlives_bounds<'tcx>(
65
64
// than the ultimate set. (Note: normally there won't be
66
65
// unresolved inference variables here anyway, but there might be
67
66
// 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 {
105
81
ty:: PredicateKind :: Trait ( ..)
106
82
| ty:: PredicateKind :: Subtype ( ..)
107
83
| ty:: PredicateKind :: Coerce ( ..)
108
- | ty:: PredicateKind :: Projection ( ..)
109
84
| ty:: PredicateKind :: ClosureKind ( ..)
110
85
| ty:: PredicateKind :: ObjectSafe ( ..)
111
86
| ty:: PredicateKind :: ConstEvaluatable ( ..)
112
87
| 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
+ }
114
116
ty:: PredicateKind :: WellFormed ( arg) => {
115
117
wf_args. push ( arg) ;
116
- vec ! [ ]
118
+ true
117
119
}
118
120
119
121
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
+ }
121
128
}
122
129
123
130
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
+ }
128
141
}
129
- } ,
142
+ }
143
+ } ) ;
144
+
145
+ if !first {
146
+ break ;
130
147
}
131
- } ) ) ;
148
+
149
+ if first {
150
+ let _ = fulfill_cx. select_where_possible ( infcx) ;
151
+ }
152
+
153
+ first = false ;
154
+ }
132
155
}
133
156
134
157
// Ensure that those obligations that we had to solve
0 commit comments