1
1
use smallvec:: smallvec;
2
2
3
3
use crate :: infer:: outlives:: components:: { push_outlives_components, Component } ;
4
- use crate :: traits:: { self , Obligation , ObligationCause , PredicateObligation } ;
4
+ use crate :: traits:: { self , Obligation , PredicateObligation } ;
5
5
use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
6
6
use rustc_middle:: ty:: { self , ToPredicate , TyCtxt } ;
7
7
use rustc_span:: symbol:: Ident ;
@@ -66,99 +66,143 @@ impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
66
66
/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd`
67
67
/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
68
68
/// `T: Foo`, then we know that `T: 'static`.
69
- pub struct Elaborator < ' tcx > {
70
- stack : Vec < PredicateObligation < ' tcx > > ,
69
+ pub struct Elaborator < ' tcx , O > {
70
+ stack : Vec < O > ,
71
71
visited : PredicateSet < ' tcx > ,
72
72
}
73
73
74
- pub fn elaborate_trait_ref < ' tcx > (
75
- tcx : TyCtxt < ' tcx > ,
76
- trait_ref : ty:: PolyTraitRef < ' tcx > ,
77
- ) -> impl Iterator < Item = ty:: Predicate < ' tcx > > {
78
- elaborate_predicates ( tcx, std:: iter:: once ( trait_ref. without_const ( ) . to_predicate ( tcx) ) )
74
+ /// Describes how to elaborate an obligation into a sub-obligation.
75
+ ///
76
+ /// For [`Obligation`], a sub-obligation is combined with the current obligation's
77
+ /// param-env and cause code. For [`ty::Predicate`], none of this is needed, since
78
+ /// there is no param-env or cause code to copy over.
79
+ pub trait Elaboratable < ' tcx > {
80
+ fn predicate ( & self ) -> ty:: Predicate < ' tcx > ;
81
+
82
+ // Makes a new `Self` but with a different predicate.
83
+ fn child ( & self , predicate : ty:: Predicate < ' tcx > ) -> Self ;
84
+
85
+ // Makes a new `Self` but with a different predicate and a different cause
86
+ // code (if `Self` has one).
87
+ fn child_with_derived_cause (
88
+ & self ,
89
+ predicate : ty:: Predicate < ' tcx > ,
90
+ span : Span ,
91
+ parent_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
92
+ index : usize ,
93
+ ) -> Self ;
79
94
}
80
95
81
- pub fn elaborate_trait_refs < ' tcx > (
82
- tcx : TyCtxt < ' tcx > ,
83
- trait_refs : impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > ,
84
- ) -> impl Iterator < Item = ty:: Predicate < ' tcx > > {
85
- let predicates = trait_refs. map ( move |trait_ref| trait_ref. without_const ( ) . to_predicate ( tcx) ) ;
86
- elaborate_predicates ( tcx, predicates)
96
+ impl < ' tcx > Elaboratable < ' tcx > for PredicateObligation < ' tcx > {
97
+ fn predicate ( & self ) -> ty:: Predicate < ' tcx > {
98
+ self . predicate
99
+ }
100
+
101
+ fn child ( & self , predicate : ty:: Predicate < ' tcx > ) -> Self {
102
+ Obligation {
103
+ cause : self . cause . clone ( ) ,
104
+ param_env : self . param_env ,
105
+ recursion_depth : 0 ,
106
+ predicate,
107
+ }
108
+ }
109
+
110
+ fn child_with_derived_cause (
111
+ & self ,
112
+ predicate : ty:: Predicate < ' tcx > ,
113
+ span : Span ,
114
+ parent_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
115
+ index : usize ,
116
+ ) -> Self {
117
+ let cause = self . cause . clone ( ) . derived_cause ( parent_trait_pred, |derived| {
118
+ traits:: ImplDerivedObligation ( Box :: new ( traits:: ImplDerivedObligationCause {
119
+ derived,
120
+ impl_or_alias_def_id : parent_trait_pred. def_id ( ) ,
121
+ impl_def_predicate_index : Some ( index) ,
122
+ span,
123
+ } ) )
124
+ } ) ;
125
+ Obligation { cause, param_env : self . param_env , recursion_depth : 0 , predicate }
126
+ }
87
127
}
88
128
89
- pub fn elaborate_predicates < ' tcx > (
129
+ impl < ' tcx > Elaboratable < ' tcx > for ty:: Predicate < ' tcx > {
130
+ fn predicate ( & self ) -> ty:: Predicate < ' tcx > {
131
+ * self
132
+ }
133
+
134
+ fn child ( & self , predicate : ty:: Predicate < ' tcx > ) -> Self {
135
+ predicate
136
+ }
137
+
138
+ fn child_with_derived_cause (
139
+ & self ,
140
+ predicate : ty:: Predicate < ' tcx > ,
141
+ _span : Span ,
142
+ _parent_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
143
+ _index : usize ,
144
+ ) -> Self {
145
+ predicate
146
+ }
147
+ }
148
+
149
+ impl < ' tcx > Elaboratable < ' tcx > for ( ty:: Predicate < ' tcx > , Span ) {
150
+ fn predicate ( & self ) -> ty:: Predicate < ' tcx > {
151
+ self . 0
152
+ }
153
+
154
+ fn child ( & self , predicate : ty:: Predicate < ' tcx > ) -> Self {
155
+ ( predicate, self . 1 )
156
+ }
157
+
158
+ fn child_with_derived_cause (
159
+ & self ,
160
+ predicate : ty:: Predicate < ' tcx > ,
161
+ _span : Span ,
162
+ _parent_trait_pred : ty:: PolyTraitPredicate < ' tcx > ,
163
+ _index : usize ,
164
+ ) -> Self {
165
+ ( predicate, self . 1 )
166
+ }
167
+ }
168
+
169
+ pub fn elaborate_trait_ref < ' tcx > (
90
170
tcx : TyCtxt < ' tcx > ,
91
- predicates : impl Iterator < Item = ty:: Predicate < ' tcx > > ,
92
- ) -> impl Iterator < Item = ty:: Predicate < ' tcx > > {
93
- elaborate_obligations (
94
- tcx,
95
- predicates
96
- . map ( |predicate| {
97
- Obligation :: new (
98
- tcx,
99
- // We'll dump the cause/param-env later
100
- ObligationCause :: dummy ( ) ,
101
- ty:: ParamEnv :: empty ( ) ,
102
- predicate,
103
- )
104
- } )
105
- . collect ( ) ,
106
- )
107
- . map ( |obl| obl. predicate )
171
+ trait_ref : ty:: PolyTraitRef < ' tcx > ,
172
+ ) -> Elaborator < ' tcx , ty:: Predicate < ' tcx > > {
173
+ elaborate ( tcx, std:: iter:: once ( trait_ref. without_const ( ) . to_predicate ( tcx) ) )
108
174
}
109
175
110
- pub fn elaborate_predicates_with_span < ' tcx > (
176
+ pub fn elaborate_trait_refs < ' tcx > (
111
177
tcx : TyCtxt < ' tcx > ,
112
- predicates : impl Iterator < Item = ( ty:: Predicate < ' tcx > , Span ) > ,
113
- ) -> impl Iterator < Item = ( ty:: Predicate < ' tcx > , Span ) > {
114
- elaborate_obligations (
115
- tcx,
116
- predicates
117
- . map ( |( predicate, span) | {
118
- Obligation :: new (
119
- tcx,
120
- // We'll dump the cause/param-env later
121
- ObligationCause :: dummy_with_span ( span) ,
122
- ty:: ParamEnv :: empty ( ) ,
123
- predicate,
124
- )
125
- } )
126
- . collect ( ) ,
127
- )
128
- . map ( |obl| ( obl. predicate , obl. cause . span ) )
178
+ trait_refs : impl Iterator < Item = ty:: PolyTraitRef < ' tcx > > ,
179
+ ) -> Elaborator < ' tcx , ty:: Predicate < ' tcx > > {
180
+ elaborate ( tcx, trait_refs. map ( |trait_ref| trait_ref. to_predicate ( tcx) ) )
129
181
}
130
182
131
- pub fn elaborate_obligations < ' tcx > (
183
+ pub fn elaborate < ' tcx , O : Elaboratable < ' tcx > > (
132
184
tcx : TyCtxt < ' tcx > ,
133
- obligations : Vec < PredicateObligation < ' tcx > > ,
134
- ) -> Elaborator < ' tcx > {
185
+ obligations : impl IntoIterator < Item = O > ,
186
+ ) -> Elaborator < ' tcx , O > {
135
187
let mut elaborator = Elaborator { stack : Vec :: new ( ) , visited : PredicateSet :: new ( tcx) } ;
136
188
elaborator. extend_deduped ( obligations) ;
137
189
elaborator
138
190
}
139
191
140
- fn predicate_obligation < ' tcx > (
141
- predicate : ty:: Predicate < ' tcx > ,
142
- param_env : ty:: ParamEnv < ' tcx > ,
143
- cause : ObligationCause < ' tcx > ,
144
- ) -> PredicateObligation < ' tcx > {
145
- Obligation { cause, param_env, recursion_depth : 0 , predicate }
146
- }
147
-
148
- impl < ' tcx > Elaborator < ' tcx > {
149
- fn extend_deduped ( & mut self , obligations : impl IntoIterator < Item = PredicateObligation < ' tcx > > ) {
192
+ impl < ' tcx , O : Elaboratable < ' tcx > > Elaborator < ' tcx , O > {
193
+ fn extend_deduped ( & mut self , obligations : impl IntoIterator < Item = O > ) {
150
194
// Only keep those bounds that we haven't already seen.
151
195
// This is necessary to prevent infinite recursion in some
152
196
// cases. One common case is when people define
153
197
// `trait Sized: Sized { }` rather than `trait Sized { }`.
154
198
// let visited = &mut self.visited;
155
- self . stack . extend ( obligations. into_iter ( ) . filter ( |o| self . visited . insert ( o. predicate ) ) ) ;
199
+ self . stack . extend ( obligations. into_iter ( ) . filter ( |o| self . visited . insert ( o. predicate ( ) ) ) ) ;
156
200
}
157
201
158
- fn elaborate ( & mut self , obligation : & PredicateObligation < ' tcx > ) {
202
+ fn elaborate ( & mut self , elaboratable : & O ) {
159
203
let tcx = self . visited . tcx ;
160
204
161
- let bound_predicate = obligation . predicate . kind ( ) ;
205
+ let bound_predicate = elaboratable . predicate ( ) . kind ( ) ;
162
206
match bound_predicate. skip_binder ( ) {
163
207
ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( data) ) => {
164
208
// Get predicates declared on the trait.
@@ -170,24 +214,11 @@ impl<'tcx> Elaborator<'tcx> {
170
214
if data. constness == ty:: BoundConstness :: NotConst {
171
215
pred = pred. without_const ( tcx) ;
172
216
}
173
-
174
- let cause = obligation. cause . clone ( ) . derived_cause (
175
- bound_predicate. rebind ( data) ,
176
- |derived| {
177
- traits:: ImplDerivedObligation ( Box :: new (
178
- traits:: ImplDerivedObligationCause {
179
- derived,
180
- impl_or_alias_def_id : data. def_id ( ) ,
181
- impl_def_predicate_index : Some ( index) ,
182
- span,
183
- } ,
184
- ) )
185
- } ,
186
- ) ;
187
- predicate_obligation (
217
+ elaboratable. child_with_derived_cause (
188
218
pred. subst_supertrait ( tcx, & bound_predicate. rebind ( data. trait_ref ) ) ,
189
- obligation. param_env ,
190
- cause,
219
+ span,
220
+ bound_predicate. rebind ( data) ,
221
+ index,
191
222
)
192
223
} ) ;
193
224
debug ! ( ?data, ?obligations, "super_predicates" ) ;
@@ -290,13 +321,7 @@ impl<'tcx> Elaborator<'tcx> {
290
321
. map ( |predicate_kind| {
291
322
bound_predicate. rebind ( predicate_kind) . to_predicate ( tcx)
292
323
} )
293
- . map ( |predicate| {
294
- predicate_obligation (
295
- predicate,
296
- obligation. param_env ,
297
- obligation. cause . clone ( ) ,
298
- )
299
- } ) ,
324
+ . map ( |predicate| elaboratable. child ( predicate) ) ,
300
325
) ;
301
326
}
302
327
ty:: PredicateKind :: TypeWellFormedFromEnv ( ..) => {
@@ -313,8 +338,8 @@ impl<'tcx> Elaborator<'tcx> {
313
338
}
314
339
}
315
340
316
- impl < ' tcx > Iterator for Elaborator < ' tcx > {
317
- type Item = PredicateObligation < ' tcx > ;
341
+ impl < ' tcx , O : Elaboratable < ' tcx > > Iterator for Elaborator < ' tcx , O > {
342
+ type Item = O ;
318
343
319
344
fn size_hint ( & self ) -> ( usize , Option < usize > ) {
320
345
( self . stack . len ( ) , None )
0 commit comments