11use smallvec:: smallvec;
22
33use crate :: infer:: outlives:: components:: { push_outlives_components, Component } ;
4- use crate :: traits:: { self , Obligation , ObligationCause , PredicateObligation } ;
4+ use crate :: traits:: { self , Obligation , PredicateObligation } ;
55use rustc_data_structures:: fx:: { FxHashSet , FxIndexSet } ;
66use rustc_middle:: ty:: { self , ToPredicate , TyCtxt } ;
77use rustc_span:: symbol:: Ident ;
@@ -66,99 +66,143 @@ impl<'tcx> Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
6666/// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd`
6767/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
6868/// `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 > ,
7171 visited : PredicateSet < ' tcx > ,
7272}
7373
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 ;
7994}
8095
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+ }
87127}
88128
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 > (
90170 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) ) )
108174}
109175
110- pub fn elaborate_predicates_with_span < ' tcx > (
176+ pub fn elaborate_trait_refs < ' tcx > (
111177 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) ) )
129181}
130182
131- pub fn elaborate_obligations < ' tcx > (
183+ pub fn elaborate < ' tcx , O : Elaboratable < ' tcx > > (
132184 tcx : TyCtxt < ' tcx > ,
133- obligations : Vec < PredicateObligation < ' tcx > > ,
134- ) -> Elaborator < ' tcx > {
185+ obligations : impl IntoIterator < Item = O > ,
186+ ) -> Elaborator < ' tcx , O > {
135187 let mut elaborator = Elaborator { stack : Vec :: new ( ) , visited : PredicateSet :: new ( tcx) } ;
136188 elaborator. extend_deduped ( obligations) ;
137189 elaborator
138190}
139191
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 > ) {
150194 // Only keep those bounds that we haven't already seen.
151195 // This is necessary to prevent infinite recursion in some
152196 // cases. One common case is when people define
153197 // `trait Sized: Sized { }` rather than `trait Sized { }`.
154198 // 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 ( ) ) ) ) ;
156200 }
157201
158- fn elaborate ( & mut self , obligation : & PredicateObligation < ' tcx > ) {
202+ fn elaborate ( & mut self , elaboratable : & O ) {
159203 let tcx = self . visited . tcx ;
160204
161- let bound_predicate = obligation . predicate . kind ( ) ;
205+ let bound_predicate = elaboratable . predicate ( ) . kind ( ) ;
162206 match bound_predicate. skip_binder ( ) {
163207 ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( data) ) => {
164208 // Get predicates declared on the trait.
@@ -170,24 +214,11 @@ impl<'tcx> Elaborator<'tcx> {
170214 if data. constness == ty:: BoundConstness :: NotConst {
171215 pred = pred. without_const ( tcx) ;
172216 }
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 (
188218 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,
191222 )
192223 } ) ;
193224 debug ! ( ?data, ?obligations, "super_predicates" ) ;
@@ -290,13 +321,7 @@ impl<'tcx> Elaborator<'tcx> {
290321 . map ( |predicate_kind| {
291322 bound_predicate. rebind ( predicate_kind) . to_predicate ( tcx)
292323 } )
293- . map ( |predicate| {
294- predicate_obligation (
295- predicate,
296- obligation. param_env ,
297- obligation. cause . clone ( ) ,
298- )
299- } ) ,
324+ . map ( |predicate| elaboratable. child ( predicate) ) ,
300325 ) ;
301326 }
302327 ty:: PredicateKind :: TypeWellFormedFromEnv ( ..) => {
@@ -313,8 +338,8 @@ impl<'tcx> Elaborator<'tcx> {
313338 }
314339}
315340
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 ;
318343
319344 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
320345 ( self . stack . len ( ) , None )
0 commit comments