@@ -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,51 @@ 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
+ . map_err ( |_errs| NoSolution ) ?
71
+ } else {
72
+ ocx. normalize ( & ObligationCause :: dummy ( ) , param_env, ty)
73
+ } ;
74
+ if !ocx. select_all_or_error ( ) . is_empty ( ) {
75
+ return Err ( NoSolution ) ;
76
+ }
77
+ let ty = ocx. infcx . resolve_vars_if_possible ( ty) ;
78
+ assert ! ( !ty. has_non_region_infer( ) ) ;
79
+ Ok ( ty)
80
+ } ;
67
81
68
82
// Sometimes when we ask what it takes for T: WF, we get back that
69
83
// U: WF is required; in that case, we push U onto this stack and
70
84
// process it next. Because the resulting predicates aren't always
71
85
// guaranteed to be a subset of the original type, so we need to store the
72
86
// WF args we've computed in a set.
73
87
let mut checked_wf_args = rustc_data_structures:: fx:: FxHashSet :: default ( ) ;
74
- let mut wf_args = vec ! [ ty. into( ) ] ;
88
+ let mut wf_args = vec ! [ ty. into( ) , normalize_op ( ty ) ? . into ( ) ] ;
75
89
76
- let mut outlives_bounds: Vec < ty:: OutlivesPredicate < ty:: GenericArg < ' tcx > , ty:: Region < ' tcx > > > =
77
- vec ! [ ] ;
90
+ let mut outlives_bounds: Vec < OutlivesBound < ' tcx > > = vec ! [ ] ;
78
91
79
92
while let Some ( arg) = wf_args. pop ( ) {
80
93
if !checked_wf_args. insert ( arg) {
81
94
continue ;
82
95
}
83
96
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) ;
97
+ // From the full set of obligations, just filter down to the region relationships.
98
+ for obligation in
99
+ wf:: unnormalized_obligations ( ocx. infcx , param_env, arg) . into_iter ( ) . flatten ( )
100
+ {
100
101
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,
102
+ let Some ( pred) = obligation. predicate . kind ( ) . no_bound_vars ( ) else {
103
+ continue ;
124
104
} ;
125
105
match pred {
126
106
ty:: PredicateKind :: Clause ( ty:: ClauseKind :: Trait ( ..) )
@@ -144,53 +124,24 @@ pub fn compute_implied_outlives_bounds_inner<'tcx>(
144
124
}
145
125
146
126
// We need to register region relationships
147
- ty:: PredicateKind :: Clause ( ty:: ClauseKind :: RegionOutlives ( ty:: OutlivesPredicate (
148
- r_a,
149
- r_b,
150
- ) ) ) => 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) ) ,
151
130
152
131
ty:: PredicateKind :: Clause ( ty:: ClauseKind :: TypeOutlives ( ty:: OutlivesPredicate (
153
132
ty_a,
154
133
r_b,
155
- ) ) ) => outlives_bounds. push ( ty:: OutlivesPredicate ( ty_a. into ( ) , r_b) ) ,
156
- }
157
- }
158
- }
159
-
160
- // This call to `select_all_or_error` is necessary to constrain inference variables, which we
161
- // use further down when computing the implied bounds.
162
- match ocx. select_all_or_error ( ) . as_slice ( ) {
163
- [ ] => ( ) ,
164
- _ => return Err ( NoSolution ) ,
165
- }
166
-
167
- // We lazily compute the outlives components as
168
- // `select_all_or_error` constrains inference variables.
169
- let mut implied_bounds = Vec :: new ( ) ;
170
- for ty:: OutlivesPredicate ( a, r_b) in outlives_bounds {
171
- match a. unpack ( ) {
172
- ty:: GenericArgKind :: Lifetime ( r_a) => {
173
- implied_bounds. push ( OutlivesBound :: RegionSubRegion ( r_b, r_a) )
174
- }
175
- ty:: GenericArgKind :: Type ( ty_a) => {
176
- let mut ty_a = ocx. infcx . resolve_vars_if_possible ( ty_a) ;
177
- // Need to manually normalize in the new solver as `wf::obligations` does not.
178
- if ocx. infcx . next_trait_solver ( ) {
179
- ty_a = solve:: deeply_normalize (
180
- ocx. infcx . at ( & ObligationCause :: dummy ( ) , param_env) ,
181
- ty_a,
182
- )
183
- . 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) )
184
139
}
185
- let mut components = smallvec ! [ ] ;
186
- push_outlives_components ( tcx, ty_a, & mut components) ;
187
- implied_bounds. extend ( implied_bounds_from_components ( r_b, components) )
188
140
}
189
- ty:: GenericArgKind :: Const ( _) => unreachable ! ( ) ,
190
141
}
191
142
}
192
143
193
- Ok ( implied_bounds )
144
+ Ok ( outlives_bounds )
194
145
}
195
146
196
147
/// When we have an implied bound that `T: 'a`, we can further break
0 commit comments