8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use rustc:: { self , hir} ;
11
+ use rustc:: hir;
12
12
use rustc:: traits:: { self , auto_trait as auto} ;
13
13
use rustc:: ty:: { ToPredicate , TypeFoldable } ;
14
+ use rustc:: ty:: subst:: Subst ;
15
+ use rustc:: infer:: InferOk ;
14
16
use std:: fmt:: Debug ;
17
+ use syntax_pos:: DUMMY_SP ;
15
18
16
19
use super :: * ;
17
20
@@ -82,22 +85,115 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
82
85
name : Option < String > ,
83
86
) -> Vec < Item >
84
87
where F : Fn ( DefId ) -> Def {
88
+ let tcx = self . cx . tcx ;
89
+ let generics = self . cx . tcx . generics_of ( def_id) ;
85
90
86
- if :: std:: env:: var ( "LOL" ) . is_ok ( ) {
87
- let ty = self . cx . tcx . type_of ( def_id) ;
88
- if let ty:: TyAdt ( _adt, _) = ty. sty {
89
- let subts = ty:: subst:: Substs :: identity_for_item ( self . cx . tcx . clone ( ) , def_id) ;
90
- self . cx . tcx . infer_ctxt ( ) . enter ( |infcx| {
91
- for impl_ in infcx. tcx . all_trait_implementations ( LOCAL_CRATE ) . iter ( ) {
92
- let trait_ref = rustc:: ty:: TraitRef :: new ( * impl_, subts) ;
93
- let pred = trait_ref. to_predicate ( ) ;
94
- let obligation = traits:: Obligation :: new ( traits:: ObligationCause :: dummy ( ) ,
95
- rustc:: ty:: ParamEnv :: empty ( ) ,
96
- pred) ;
97
- println ! ( "{} => {}" ,
98
- infcx. tcx. item_name( * impl_) . to_string( ) ,
99
- infcx. predicate_may_hold( & obligation) ) ;
100
- }
91
+ let ty = self . cx . tcx . type_of ( def_id) ;
92
+ let mut traits = FxHashMap ( ) ;
93
+ if let ty:: TyAdt ( _adt, _) = ty. sty {
94
+ use std:: rc:: Rc ;
95
+
96
+ let name = Rc :: new ( name. clone ( ) ) ;
97
+ let param_env = self . cx . tcx . param_env ( def_id) ;
98
+ for & trait_def_id in self . cx . tcx . all_traits ( LOCAL_CRATE ) . iter ( ) {
99
+ let name = name. clone ( ) ;
100
+ self . cx . tcx . for_each_relevant_impl ( trait_def_id, ty, |impl_def_id| {
101
+ let name = name. clone ( ) ;
102
+ self . cx . tcx . infer_ctxt ( ) . enter ( |infcx| {
103
+ let trait_ref = infcx. tcx . impl_trait_ref ( impl_def_id) . unwrap ( ) ;
104
+ let substs = infcx. fresh_substs_for_item ( DUMMY_SP , def_id) ;
105
+ let ty = ty. subst ( infcx. tcx , substs) ;
106
+ let param_env = param_env. subst ( infcx. tcx , substs) ;
107
+
108
+ let impl_substs = infcx. fresh_substs_for_item ( DUMMY_SP , impl_def_id) ;
109
+ let trait_ref = trait_ref. subst ( infcx. tcx , impl_substs) ;
110
+
111
+ // Require the type the impl is implemented on to match
112
+ // our type, and ignore the impl if there was a mismatch.
113
+ let cause = traits:: ObligationCause :: dummy ( ) ;
114
+ let eq_result = infcx. at ( & cause, param_env) . eq ( trait_ref. self_ty ( ) , ty) ;
115
+ if let Ok ( InferOk { value : ( ) , obligations } ) = eq_result {
116
+ // FIXME(eddyb) ignoring `obligations` might cause false positives.
117
+ drop ( obligations) ;
118
+
119
+ let may_apply = infcx. predicate_may_hold ( & traits:: Obligation :: new (
120
+ cause. clone ( ) ,
121
+ param_env,
122
+ trait_ref. to_predicate ( ) ,
123
+ ) ) ;
124
+ if may_apply {
125
+ // FIXME: add crate's id before the name to avoid removing a
126
+ // trait which doesn't exist.
127
+ if traits. get ( & trait_def_id) . is_none ( ) {
128
+ /*let generics = (infcx.tcx.generics_of(trait_def_id), &predicates).clean(cx);
129
+ get_path_for_type(self.cx.tcx, trait_def_id, hir::def::Def::Trait)*/
130
+ /*if let Some(i) = self.get_auto_trait_impl_for(
131
+ def_id,
132
+ name.clone(),
133
+ generics.clone(),
134
+ def_ctor,
135
+ trait_def_id,
136
+ ) {
137
+ traits.insert(trait_name, i);
138
+ }*/
139
+
140
+ let path = get_path_for_type ( infcx. tcx , def_id, def_ctor) ;
141
+ let mut segments = path. clone ( ) . segments . into_vec ( ) ;
142
+ let last = segments. pop ( ) . unwrap ( ) ;
143
+
144
+ use std:: ops:: Deref ;
145
+ let t_name: Option < String > = name. deref ( ) . clone ( ) ;
146
+ let real_name = t_name. map ( |name| Ident :: from_str ( & name) ) . unwrap_or ( last. ident ) ;
147
+
148
+ segments. push ( hir:: PathSegment :: new (
149
+ real_name,
150
+ self . generics_to_path_params ( generics. clone ( ) ) ,
151
+ false ,
152
+ ) ) ;
153
+ let new_path = hir:: Path {
154
+ span : path. span ,
155
+ def : path. def ,
156
+ segments : HirVec :: from_vec ( segments) ,
157
+ } ;
158
+ let ty = hir:: Ty {
159
+ id : ast:: DUMMY_NODE_ID ,
160
+ node : hir:: Ty_ :: TyPath ( hir:: QPath :: Resolved ( None , P ( new_path) ) ) ,
161
+ span : DUMMY_SP ,
162
+ hir_id : hir:: DUMMY_HIR_ID ,
163
+ } ;
164
+ traits. insert ( trait_def_id, Item {
165
+ source : Span :: empty ( ) ,
166
+ name : None ,
167
+ attrs : Default :: default ( ) ,
168
+ visibility : None ,
169
+ def_id : self . next_def_id ( def_id. krate ) ,
170
+ stability : None ,
171
+ deprecation : None ,
172
+ inner : ImplItem ( Impl {
173
+ unsafety : hir:: Unsafety :: Normal ,
174
+ generics : Generics {
175
+ params : generics. params . clean ( self . cx ) ,
176
+ where_predicates : Vec :: new ( ) ,
177
+ } ,
178
+ provided_trait_methods : FxHashSet ( ) ,
179
+ trait_ : Some ( hir:: TraitRef {
180
+ path,
181
+ ref_id : ast:: DUMMY_NODE_ID ,
182
+ } . clean ( self . cx ) ) ,
183
+
184
+ //Some(trait_ref.clean(self.cx)),
185
+ for_ : ty. clean ( self . cx ) ,
186
+ items : Vec :: new ( ) ,
187
+ polarity : None ,
188
+ synthetic : true ,
189
+ } )
190
+ } ) ;
191
+ }
192
+ //println!("=> {}", infcx.tcx.item_name(trait_def_id).to_string());
193
+ }
194
+ debug ! ( "{:?} => {}" , trait_ref, may_apply) ;
195
+ }
196
+ } ) ;
101
197
} ) ;
102
198
}
103
199
}
@@ -117,9 +213,6 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
117
213
return Vec :: new ( ) ;
118
214
}
119
215
120
- let tcx = self . cx . tcx ;
121
- let generics = self . cx . tcx . generics_of ( def_id) ;
122
-
123
216
debug ! (
124
217
"get_auto_trait_impls(def_id={:?}, def_ctor=..., generics={:?}" ,
125
218
def_id, generics
@@ -143,6 +236,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
143
236
def_ctor,
144
237
tcx. require_lang_item ( lang_items:: SyncTraitLangItem ) ,
145
238
) . into_iter ( ) )
239
+ . chain ( traits. into_iter ( ) . map ( |( _, v) | v) )
146
240
. collect ( ) ;
147
241
148
242
debug ! (
0 commit comments