11use smallvec:: smallvec;
22
3+ use crate :: traits:: { Obligation , ObligationCause , PredicateObligation } ;
34use rustc_data_structures:: fx:: FxHashSet ;
45use rustc_middle:: ty:: outlives:: Component ;
56use rustc_middle:: ty:: { self , ToPolyTraitRef , ToPredicate , TyCtxt , WithConstness } ;
7+ use rustc_span:: Span ;
68
79pub fn anonymize_predicate < ' tcx > (
810 tcx : TyCtxt < ' tcx > ,
@@ -87,7 +89,7 @@ impl<T: AsRef<ty::Predicate<'tcx>>> Extend<T> for PredicateSet<'tcx> {
8789/// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that
8890/// `T: Foo`, then we know that `T: 'static`.
8991pub struct Elaborator < ' tcx > {
90- stack : Vec < ty :: Predicate < ' tcx > > ,
92+ stack : Vec < PredicateObligation < ' tcx > > ,
9193 visited : PredicateSet < ' tcx > ,
9294}
9395
@@ -112,35 +114,60 @@ pub fn elaborate_predicates<'tcx>(
112114) -> Elaborator < ' tcx > {
113115 let mut visited = PredicateSet :: new ( tcx) ;
114116 predicates. retain ( |pred| visited. insert ( pred) ) ;
115- Elaborator { stack : predicates, visited }
117+ let obligations: Vec < _ > =
118+ predicates. into_iter ( ) . map ( |predicate| predicate_obligation ( predicate, None ) ) . collect ( ) ;
119+ elaborate_obligations ( tcx, obligations)
120+ }
121+
122+ pub fn elaborate_obligations < ' tcx > (
123+ tcx : TyCtxt < ' tcx > ,
124+ mut obligations : Vec < PredicateObligation < ' tcx > > ,
125+ ) -> Elaborator < ' tcx > {
126+ let mut visited = PredicateSet :: new ( tcx) ;
127+ obligations. retain ( |obligation| visited. insert ( & obligation. predicate ) ) ;
128+ Elaborator { stack : obligations, visited }
129+ }
130+
131+ fn predicate_obligation < ' tcx > (
132+ predicate : ty:: Predicate < ' tcx > ,
133+ span : Option < Span > ,
134+ ) -> PredicateObligation < ' tcx > {
135+ let mut cause = ObligationCause :: dummy ( ) ;
136+ if let Some ( span) = span {
137+ cause. span = span;
138+ }
139+ Obligation { cause, param_env : ty:: ParamEnv :: empty ( ) , recursion_depth : 0 , predicate }
116140}
117141
118142impl Elaborator < ' tcx > {
119143 pub fn filter_to_traits ( self ) -> FilterToTraits < Self > {
120144 FilterToTraits :: new ( self )
121145 }
122146
123- fn elaborate ( & mut self , predicate : & ty :: Predicate < ' tcx > ) {
147+ fn elaborate ( & mut self , obligation : & PredicateObligation < ' tcx > ) {
124148 let tcx = self . visited . tcx ;
125- match * predicate {
149+ match obligation . predicate {
126150 ty:: Predicate :: Trait ( ref data, _) => {
127151 // Get predicates declared on the trait.
128152 let predicates = tcx. super_predicates_of ( data. def_id ( ) ) ;
129153
130- let predicates = predicates
131- . predicates
132- . iter ( )
133- . map ( |( pred, _) | pred. subst_supertrait ( tcx, & data. to_poly_trait_ref ( ) ) ) ;
134- debug ! ( "super_predicates: data={:?} predicates={:?}" , data, predicates. clone( ) ) ;
154+ let obligations = predicates. predicates . iter ( ) . map ( |( pred, span) | {
155+ predicate_obligation (
156+ pred. subst_supertrait ( tcx, & data. to_poly_trait_ref ( ) ) ,
157+ Some ( * span) ,
158+ )
159+ } ) ;
160+ debug ! ( "super_predicates: data={:?} predicates={:?}" , data, & obligations) ;
135161
136162 // Only keep those bounds that we haven't already seen.
137163 // This is necessary to prevent infinite recursion in some
138164 // cases. One common case is when people define
139165 // `trait Sized: Sized { }` rather than `trait Sized { }`.
140166 let visited = & mut self . visited ;
141- let predicates = predicates. filter ( |pred| visited. insert ( pred) ) ;
167+ let obligations =
168+ obligations. filter ( |obligation| visited. insert ( & obligation. predicate ) ) ;
142169
143- self . stack . extend ( predicates ) ;
170+ self . stack . extend ( obligations ) ;
144171 }
145172 ty:: Predicate :: WellFormed ( ..) => {
146173 // Currently, we do not elaborate WF predicates,
@@ -221,25 +248,26 @@ impl Elaborator<'tcx> {
221248 None
222249 }
223250 } )
224- . filter ( |p| visited. insert ( p) ) ,
251+ . filter ( |p| visited. insert ( p) )
252+ . map ( |p| predicate_obligation ( p, None ) ) ,
225253 ) ;
226254 }
227255 }
228256 }
229257}
230258
231259impl Iterator for Elaborator < ' tcx > {
232- type Item = ty :: Predicate < ' tcx > ;
260+ type Item = PredicateObligation < ' tcx > ;
233261
234262 fn size_hint ( & self ) -> ( usize , Option < usize > ) {
235263 ( self . stack . len ( ) , None )
236264 }
237265
238- fn next ( & mut self ) -> Option < ty :: Predicate < ' tcx > > {
266+ fn next ( & mut self ) -> Option < Self :: Item > {
239267 // Extract next item from top-most stack frame, if any.
240- if let Some ( pred ) = self . stack . pop ( ) {
241- self . elaborate ( & pred ) ;
242- Some ( pred )
268+ if let Some ( obligation ) = self . stack . pop ( ) {
269+ self . elaborate ( & obligation ) ;
270+ Some ( obligation )
243271 } else {
244272 None
245273 }
@@ -282,12 +310,12 @@ impl<I> FilterToTraits<I> {
282310 }
283311}
284312
285- impl < ' tcx , I : Iterator < Item = ty :: Predicate < ' tcx > > > Iterator for FilterToTraits < I > {
313+ impl < ' tcx , I : Iterator < Item = PredicateObligation < ' tcx > > > Iterator for FilterToTraits < I > {
286314 type Item = ty:: PolyTraitRef < ' tcx > ;
287315
288316 fn next ( & mut self ) -> Option < ty:: PolyTraitRef < ' tcx > > {
289- while let Some ( pred ) = self . base_iterator . next ( ) {
290- if let ty:: Predicate :: Trait ( data, _) = pred {
317+ while let Some ( obligation ) = self . base_iterator . next ( ) {
318+ if let ty:: Predicate :: Trait ( data, _) = obligation . predicate {
291319 return Some ( data. to_poly_trait_ref ( ) ) ;
292320 }
293321 }
0 commit comments