@@ -9,8 +9,6 @@ use rustc_infer::traits::query::OutlivesBound;
9
9
use rustc_middle:: infer:: canonical:: CanonicalQueryResponse ;
10
10
use rustc_middle:: traits:: ObligationCause ;
11
11
use rustc_middle:: ty:: { self , ParamEnvAnd , Ty , TyCtxt , TypeVisitableExt } ;
12
- use rustc_span:: def_id:: CRATE_DEF_ID ;
13
- use rustc_span:: DUMMY_SP ;
14
12
use smallvec:: { smallvec, SmallVec } ;
15
13
16
14
#[ derive( Copy , Clone , Debug , HashStable , TypeFoldable , TypeVisitable ) ]
@@ -58,69 +56,52 @@ impl<'tcx> super::QueryTypeOp<'tcx> for ImpliedOutlivesBounds<'tcx> {
58
56
}
59
57
}
60
58
59
+ /// For the sake of completeness, we should be careful when dealing with inference artifacts:
60
+ /// - `ty` must be fully resolved.
61
+ /// - `normalize_op` must return a fully resolved type.
61
62
pub fn compute_implied_outlives_bounds_inner < ' tcx > (
62
63
ocx : & ObligationCtxt < ' _ , ' tcx > ,
63
64
param_env : ty:: ParamEnv < ' tcx > ,
64
65
ty : Ty < ' tcx > ,
65
66
) -> Result < Vec < OutlivesBound < ' tcx > > , NoSolution > {
66
- let tcx = ocx. infcx . tcx ;
67
+ let normalize_op = |ty : Ty < ' tcx > | {
68
+ let ty = if ocx. infcx . next_trait_solver ( ) {
69
+ solve:: deeply_normalize ( ocx. infcx . at ( & ObligationCause :: dummy ( ) , param_env) , ty)
70
+ // FIXME(-Ztrait-solver=next)
71
+ . unwrap_or_else ( |_errs| ty)
72
+ } else {
73
+ ocx. normalize ( & ObligationCause :: dummy ( ) , param_env, ty)
74
+ } ;
75
+ if !ocx. select_all_or_error ( ) . is_empty ( ) {
76
+ return Err ( NoSolution ) ;
77
+ }
78
+ let ty = ocx. infcx . resolve_vars_if_possible ( ty) ;
79
+ assert ! ( !ty. has_non_region_infer( ) ) ;
80
+ Ok ( ty)
81
+ } ;
67
82
68
83
// Sometimes when we ask what it takes for T: WF, we get back that
69
84
// U: WF is required; in that case, we push U onto this stack and
70
85
// process it next. Because the resulting predicates aren't always
71
86
// guaranteed to be a subset of the original type, so we need to store the
72
87
// WF args we've computed in a set.
73
88
let mut checked_wf_args = rustc_data_structures:: fx:: FxHashSet :: default ( ) ;
74
- let mut wf_args = vec ! [ ty. into( ) ] ;
89
+ let mut wf_args = vec ! [ ty. into( ) , normalize_op ( ty ) ? . into ( ) ] ;
75
90
76
- let mut outlives_bounds: Vec < ty:: OutlivesPredicate < ty:: GenericArg < ' tcx > , ty:: Region < ' tcx > > > =
77
- vec ! [ ] ;
91
+ let mut outlives_bounds: Vec < OutlivesBound < ' tcx > > = vec ! [ ] ;
78
92
79
93
while let Some ( arg) = wf_args. pop ( ) {
80
94
if !checked_wf_args. insert ( arg) {
81
95
continue ;
82
96
}
83
97
84
- // Compute the obligations for `arg` to be well-formed. If `arg` is
85
- // an unresolved inference variable, just substituted an empty set
86
- // -- because the return type here is going to be things we *add*
87
- // to the environment, it's always ok for this set to be smaller
88
- // than the ultimate set. (Note: normally there won't be
89
- // unresolved inference variables here anyway, but there might be
90
- // during typeck under some circumstances.)
91
- //
92
- // FIXME(@lcnr): It's not really "always fine", having fewer implied
93
- // bounds can be backward incompatible, e.g. #101951 was caused by
94
- // us not dealing with inference vars in `TypeOutlives` predicates.
95
- let obligations = wf:: obligations ( ocx. infcx , param_env, CRATE_DEF_ID , 0 , arg, DUMMY_SP )
96
- . unwrap_or_default ( ) ;
97
-
98
- for obligation in obligations {
99
- debug ! ( ?obligation) ;
98
+ // From the full set of obligations, just filter down to the region relationships.
99
+ for obligation in
100
+ wf:: unnormalized_obligations ( ocx. infcx , param_env, arg) . into_iter ( ) . flatten ( )
101
+ {
100
102
assert ! ( !obligation. has_escaping_bound_vars( ) ) ;
101
-
102
- // While these predicates should all be implied by other parts of
103
- // the program, they are still relevant as they may constrain
104
- // inference variables, which is necessary to add the correct
105
- // implied bounds in some cases, mostly when dealing with projections.
106
- //
107
- // Another important point here: we only register `Projection`
108
- // predicates, since otherwise we might register outlives
109
- // predicates containing inference variables, and we don't
110
- // learn anything new from those.
111
- if obligation. predicate . has_non_region_infer ( ) {
112
- match obligation. predicate . kind ( ) . skip_binder ( ) {
113
- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Projection ( ..) )
114
- | ty:: PredicateKind :: AliasRelate ( ..) => {
115
- ocx. register_obligation ( obligation. clone ( ) ) ;
116
- }
117
- _ => { }
118
- }
119
- }
120
-
121
- let pred = match obligation. predicate . kind ( ) . no_bound_vars ( ) {
122
- None => continue ,
123
- Some ( pred) => pred,
103
+ let Some ( pred) = obligation. predicate . kind ( ) . no_bound_vars ( ) else {
104
+ continue ;
124
105
} ;
125
106
match pred {
126
107
ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( ..) )
@@ -143,53 +124,24 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
143
124
}
144
125
145
126
// We need to register region relationships
146
- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: RegionOutlives ( ty:: OutlivesPredicate (
147
- r_a,
148
- r_b,
149
- ) ) ) => outlives_bounds. push ( ty:: OutlivesPredicate ( r_a. into ( ) , r_b) ) ,
127
+ ty:: PredicateKind :: Clause ( ty:: ClauseKind :: RegionOutlives (
128
+ ty:: OutlivesPredicate ( r_a, r_b) ,
129
+ ) ) => outlives_bounds. push ( OutlivesBound :: RegionSubRegion ( r_b, r_a) ) ,
150
130
151
131
ty:: PredicateKind :: Clause ( ty:: ClauseKind :: TypeOutlives ( ty:: OutlivesPredicate (
152
132
ty_a,
153
133
r_b,
154
- ) ) ) => outlives_bounds. push ( ty:: OutlivesPredicate ( ty_a. into ( ) , r_b) ) ,
155
- }
156
- }
157
- }
158
-
159
- // This call to `select_all_or_error` is necessary to constrain inference variables, which we
160
- // use further down when computing the implied bounds.
161
- match ocx. select_all_or_error ( ) . as_slice ( ) {
162
- [ ] => ( ) ,
163
- _ => return Err ( NoSolution ) ,
164
- }
165
-
166
- // We lazily compute the outlives components as
167
- // `select_all_or_error` constrains inference variables.
168
- let mut implied_bounds = Vec :: new ( ) ;
169
- for ty:: OutlivesPredicate ( a, r_b) in outlives_bounds {
170
- match a. unpack ( ) {
171
- ty:: GenericArgKind :: Lifetime ( r_a) => {
172
- implied_bounds. push ( OutlivesBound :: RegionSubRegion ( r_b, r_a) )
173
- }
174
- ty:: GenericArgKind :: Type ( ty_a) => {
175
- let mut ty_a = ocx. infcx . resolve_vars_if_possible ( ty_a) ;
176
- // Need to manually normalize in the new solver as `wf::obligations` does not.
177
- if ocx. infcx . next_trait_solver ( ) {
178
- ty_a = solve:: deeply_normalize (
179
- ocx. infcx . at ( & ObligationCause :: dummy ( ) , param_env) ,
180
- ty_a,
181
- )
182
- . map_err ( |_errs| NoSolution ) ?;
134
+ ) ) ) => {
135
+ let ty_a = normalize_op ( ty_a) ?;
136
+ let mut components = smallvec ! [ ] ;
137
+ push_outlives_components ( ocx. infcx . tcx , ty_a, & mut components) ;
138
+ outlives_bounds. extend ( implied_bounds_from_components ( r_b, components) )
183
139
}
184
- let mut components = smallvec ! [ ] ;
185
- push_outlives_components ( tcx, ty_a, & mut components) ;
186
- implied_bounds. extend ( implied_bounds_from_components ( r_b, components) )
187
140
}
188
- ty:: GenericArgKind :: Const ( _) => unreachable ! ( ) ,
189
141
}
190
142
}
191
143
192
- Ok ( implied_bounds )
144
+ Ok ( outlives_bounds )
193
145
}
194
146
195
147
/// When we have an implied bound that `T: 'a`, we can further break
0 commit comments