11use super :: callee:: DeferredCallResolution ;
22
3- use rustc_data_structures:: fx:: FxHashSet ;
3+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
44use rustc_hir as hir;
55use rustc_hir:: def_id:: LocalDefId ;
66use rustc_hir:: HirIdMap ;
@@ -10,7 +10,8 @@ use rustc_middle::ty::visit::TypeVisitable;
1010use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
1111use rustc_span:: def_id:: LocalDefIdMap ;
1212use rustc_span:: { self , Span } ;
13- use rustc_trait_selection:: traits:: { self , TraitEngine , TraitEngineExt as _} ;
13+ use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ;
14+ use rustc_trait_selection:: traits:: { self , PredicateObligation , TraitEngine , TraitEngineExt as _} ;
1415
1516use std:: cell:: RefCell ;
1617use std:: ops:: Deref ;
@@ -63,6 +64,8 @@ pub struct Inherited<'tcx> {
6364 /// we record that type variable here. This is later used to inform
6465 /// fallback. See the `fallback` module for details.
6566 pub ( super ) diverging_type_vars : RefCell < FxHashSet < Ty < ' tcx > > > ,
67+
68+ pub ( super ) infer_var_info : RefCell < FxHashMap < ty:: TyVid , ty:: InferVarInfo > > ,
6669}
6770
6871impl < ' tcx > Deref for Inherited < ' tcx > {
@@ -128,6 +131,7 @@ impl<'tcx> Inherited<'tcx> {
128131 deferred_generator_interiors : RefCell :: new ( Vec :: new ( ) ) ,
129132 diverging_type_vars : RefCell :: new ( Default :: default ( ) ) ,
130133 body_id,
134+ infer_var_info : RefCell :: new ( Default :: default ( ) ) ,
131135 }
132136 }
133137
@@ -136,6 +140,9 @@ impl<'tcx> Inherited<'tcx> {
136140 if obligation. has_escaping_bound_vars ( ) {
137141 span_bug ! ( obligation. cause. span, "escaping bound vars in predicate {:?}" , obligation) ;
138142 }
143+
144+ self . update_infer_var_info ( & obligation) ;
145+
139146 self . fulfillment_cx . borrow_mut ( ) . register_predicate_obligation ( self , obligation) ;
140147 }
141148
@@ -152,4 +159,43 @@ impl<'tcx> Inherited<'tcx> {
152159 self . register_predicates ( infer_ok. obligations ) ;
153160 infer_ok. value
154161 }
162+
163+ pub fn update_infer_var_info ( & self , obligation : & PredicateObligation < ' tcx > ) {
164+ let infer_var_info = & mut self . infer_var_info . borrow_mut ( ) ;
165+
166+ // (*) binder skipped
167+ if let ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( tpred) ) = obligation. predicate . kind ( ) . skip_binder ( )
168+ && let Some ( ty) = self . shallow_resolve ( tpred. self_ty ( ) ) . ty_vid ( ) . map ( |t| self . root_var ( t) )
169+ && self . tcx . lang_items ( ) . sized_trait ( ) . map_or ( false , |st| st != tpred. trait_ref . def_id )
170+ {
171+ let new_self_ty = self . tcx . types . unit ;
172+
173+ // Then construct a new obligation with Self = () added
174+ // to the ParamEnv, and see if it holds.
175+ let o = obligation. with ( self . tcx ,
176+ obligation
177+ . predicate
178+ . kind ( )
179+ . rebind (
180+ // (*) binder moved here
181+ ty:: PredicateKind :: Clause ( ty:: Clause :: Trait ( tpred. with_self_ty ( self . tcx , new_self_ty) ) )
182+ ) ,
183+ ) ;
184+ // Don't report overflow errors. Otherwise equivalent to may_hold.
185+ if let Ok ( result) = self . probe ( |_| self . evaluate_obligation ( & o) ) && result. may_apply ( ) {
186+ infer_var_info. entry ( ty) . or_default ( ) . self_in_trait = true ;
187+ }
188+ }
189+
190+ if let ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( predicate) ) =
191+ obligation. predicate . kind ( ) . skip_binder ( )
192+ {
193+ // If the projection predicate (Foo::Bar == X) has X as a non-TyVid,
194+ // we need to make it into one.
195+ if let Some ( vid) = predicate. term . ty ( ) . and_then ( |ty| ty. ty_vid ( ) ) {
196+ debug ! ( "infer_var_info: {:?}.output = true" , vid) ;
197+ infer_var_info. entry ( vid) . or_default ( ) . output = true ;
198+ }
199+ }
200+ }
155201}
0 commit comments