1
1
use super :: callee:: DeferredCallResolution ;
2
2
3
- use rustc_data_structures:: fx:: FxHashSet ;
3
+ use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
4
4
use rustc_hir as hir;
5
5
use rustc_hir:: def_id:: LocalDefId ;
6
6
use rustc_hir:: HirIdMap ;
@@ -10,7 +10,8 @@ use rustc_middle::ty::visit::TypeVisitable;
10
10
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
11
11
use rustc_span:: def_id:: LocalDefIdMap ;
12
12
use 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 _} ;
14
15
15
16
use std:: cell:: RefCell ;
16
17
use std:: ops:: Deref ;
@@ -63,6 +64,8 @@ pub struct Inherited<'tcx> {
63
64
/// we record that type variable here. This is later used to inform
64
65
/// fallback. See the `fallback` module for details.
65
66
pub ( super ) diverging_type_vars : RefCell < FxHashSet < Ty < ' tcx > > > ,
67
+
68
+ pub ( super ) infer_var_info : RefCell < FxHashMap < ty:: TyVid , ty:: InferVarInfo > > ,
66
69
}
67
70
68
71
impl < ' tcx > Deref for Inherited < ' tcx > {
@@ -128,6 +131,7 @@ impl<'tcx> Inherited<'tcx> {
128
131
deferred_generator_interiors : RefCell :: new ( Vec :: new ( ) ) ,
129
132
diverging_type_vars : RefCell :: new ( Default :: default ( ) ) ,
130
133
body_id,
134
+ infer_var_info : RefCell :: new ( Default :: default ( ) ) ,
131
135
}
132
136
}
133
137
@@ -136,6 +140,9 @@ impl<'tcx> Inherited<'tcx> {
136
140
if obligation. has_escaping_bound_vars ( ) {
137
141
span_bug ! ( obligation. cause. span, "escaping bound vars in predicate {:?}" , obligation) ;
138
142
}
143
+
144
+ self . update_infer_var_info ( & obligation) ;
145
+
139
146
self . fulfillment_cx . borrow_mut ( ) . register_predicate_obligation ( self , obligation) ;
140
147
}
141
148
@@ -152,4 +159,43 @@ impl<'tcx> Inherited<'tcx> {
152
159
self . register_predicates ( infer_ok. obligations ) ;
153
160
infer_ok. value
154
161
}
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
+ }
155
201
}
0 commit comments