8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
- use rustc:: traits:: auto_trait as auto;
12
- use rustc:: ty:: TypeFoldable ;
13
11
use rustc:: hir;
12
+ use rustc:: traits:: { self , auto_trait as auto} ;
13
+ use rustc:: ty:: { self , 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 ;
18
+
19
+ use core:: DocAccessLevels ;
15
20
16
21
use super :: * ;
17
22
@@ -75,6 +80,141 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
75
80
self . get_auto_trait_impls ( did, & def_ctor, Some ( name) )
76
81
}
77
82
83
+ fn get_real_ty < F > ( & self ,
84
+ def_id : DefId ,
85
+ def_ctor : & F ,
86
+ real_name : & Option < Ident > ,
87
+ generics : & ty:: Generics ,
88
+ ) -> hir:: Ty
89
+ where F : Fn ( DefId ) -> Def {
90
+ let path = get_path_for_type ( self . cx . tcx , def_id, def_ctor) ;
91
+ let mut segments = path. segments . into_vec ( ) ;
92
+ let last = segments. pop ( ) . unwrap ( ) ;
93
+
94
+ segments. push ( hir:: PathSegment :: new (
95
+ real_name. unwrap_or ( last. ident ) ,
96
+ self . generics_to_path_params ( generics. clone ( ) ) ,
97
+ false ,
98
+ ) ) ;
99
+
100
+ let new_path = hir:: Path {
101
+ span : path. span ,
102
+ def : path. def ,
103
+ segments : HirVec :: from_vec ( segments) ,
104
+ } ;
105
+
106
+ hir:: Ty {
107
+ id : ast:: DUMMY_NODE_ID ,
108
+ node : hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , P ( new_path) ) ) ,
109
+ span : DUMMY_SP ,
110
+ hir_id : hir:: DUMMY_HIR_ID ,
111
+ }
112
+ }
113
+
114
+ pub fn get_blanket_impls < F > (
115
+ & self ,
116
+ def_id : DefId ,
117
+ def_ctor : & F ,
118
+ name : Option < String > ,
119
+ generics : & ty:: Generics ,
120
+ ) -> Vec < Item >
121
+ where F : Fn ( DefId ) -> Def {
122
+ let ty = self . cx . tcx . type_of ( def_id) ;
123
+ let mut traits = Vec :: new ( ) ;
124
+ if self . cx . access_levels . borrow ( ) . is_doc_reachable ( def_id) {
125
+ let real_name = name. clone ( ) . map ( |name| Ident :: from_str ( & name) ) ;
126
+ let param_env = self . cx . tcx . param_env ( def_id) ;
127
+ for & trait_def_id in self . cx . all_traits . iter ( ) {
128
+ if !self . cx . access_levels . borrow ( ) . is_doc_reachable ( trait_def_id) ||
129
+ self . cx . generated_synthetics
130
+ . borrow_mut ( )
131
+ . get ( & ( def_id, trait_def_id) )
132
+ . is_some ( ) {
133
+ continue
134
+ }
135
+ self . cx . tcx . for_each_relevant_impl ( trait_def_id, ty, |impl_def_id| {
136
+ self . cx . tcx . infer_ctxt ( ) . enter ( |infcx| {
137
+ let t_generics = infcx. tcx . generics_of ( impl_def_id) ;
138
+ let trait_ref = infcx. tcx . impl_trait_ref ( impl_def_id) . unwrap ( ) ;
139
+
140
+ match infcx. tcx . type_of ( impl_def_id) . sty {
141
+ :: rustc:: ty:: TypeVariants :: TyParam ( _) => { } ,
142
+ _ => return ,
143
+ }
144
+
145
+ let substs = infcx. fresh_substs_for_item ( DUMMY_SP , def_id) ;
146
+ let ty = ty. subst ( infcx. tcx , substs) ;
147
+ let param_env = param_env. subst ( infcx. tcx , substs) ;
148
+
149
+ let impl_substs = infcx. fresh_substs_for_item ( DUMMY_SP , impl_def_id) ;
150
+ let trait_ref = trait_ref. subst ( infcx. tcx , impl_substs) ;
151
+
152
+ // Require the type the impl is implemented on to match
153
+ // our type, and ignore the impl if there was a mismatch.
154
+ let cause = traits:: ObligationCause :: dummy ( ) ;
155
+ let eq_result = infcx. at ( & cause, param_env)
156
+ . eq ( trait_ref. self_ty ( ) , ty) ;
157
+ if let Ok ( InferOk { value : ( ) , obligations } ) = eq_result {
158
+ // FIXME(eddyb) ignoring `obligations` might cause false positives.
159
+ drop ( obligations) ;
160
+
161
+ let may_apply = infcx. predicate_may_hold ( & traits:: Obligation :: new (
162
+ cause. clone ( ) ,
163
+ param_env,
164
+ trait_ref. to_predicate ( ) ,
165
+ ) ) ;
166
+ if !may_apply {
167
+ return
168
+ }
169
+ self . cx . generated_synthetics . borrow_mut ( )
170
+ . insert ( ( def_id, trait_def_id) ) ;
171
+ let trait_ = hir:: TraitRef {
172
+ path : get_path_for_type ( infcx. tcx ,
173
+ trait_def_id,
174
+ hir:: def:: Def :: Trait ) ,
175
+ ref_id : ast:: DUMMY_NODE_ID ,
176
+ } ;
177
+ let provided_trait_methods =
178
+ infcx. tcx . provided_trait_methods ( trait_def_id)
179
+ . into_iter ( )
180
+ . map ( |meth| meth. ident . to_string ( ) )
181
+ . collect ( ) ;
182
+
183
+ let ty = self . get_real_ty ( def_id, def_ctor, & real_name, generics) ;
184
+ let predicates = infcx. tcx . predicates_of ( impl_def_id) ;
185
+
186
+ traits. push ( Item {
187
+ source : infcx. tcx . def_span ( impl_def_id) . clean ( self . cx ) ,
188
+ name : None ,
189
+ attrs : Default :: default ( ) ,
190
+ visibility : None ,
191
+ def_id : self . next_def_id ( impl_def_id. krate ) ,
192
+ stability : None ,
193
+ deprecation : None ,
194
+ inner : ImplItem ( Impl {
195
+ unsafety : hir:: Unsafety :: Normal ,
196
+ generics : ( t_generics, & predicates) . clean ( self . cx ) ,
197
+ provided_trait_methods,
198
+ trait_ : Some ( trait_. clean ( self . cx ) ) ,
199
+ for_ : ty. clean ( self . cx ) ,
200
+ items : infcx. tcx . associated_items ( impl_def_id)
201
+ . collect :: < Vec < _ > > ( )
202
+ . clean ( self . cx ) ,
203
+ polarity : None ,
204
+ synthetic : false ,
205
+ blanket_impl : Some ( infcx. tcx . type_of ( impl_def_id)
206
+ . clean ( self . cx ) ) ,
207
+ } ) ,
208
+ } ) ;
209
+ debug ! ( "{:?} => {}" , trait_ref, may_apply) ;
210
+ }
211
+ } ) ;
212
+ } ) ;
213
+ }
214
+ }
215
+ traits
216
+ }
217
+
78
218
pub fn get_auto_trait_impls < F > (
79
219
& self ,
80
220
def_id : DefId ,
@@ -122,6 +262,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
122
262
def_ctor,
123
263
tcx. require_lang_item ( lang_items:: SyncTraitLangItem ) ,
124
264
) . into_iter ( ) )
265
+ . chain ( self . get_blanket_impls ( def_id, def_ctor, name, & generics) . into_iter ( ) )
125
266
. collect ( ) ;
126
267
127
268
debug ! (
@@ -196,31 +337,8 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
196
337
}
197
338
_ => unreachable ! ( ) ,
198
339
} ;
199
-
200
- let path = get_path_for_type ( self . cx . tcx , def_id, def_ctor) ;
201
- let mut segments = path. segments . into_vec ( ) ;
202
- let last = segments. pop ( ) . unwrap ( ) ;
203
-
204
340
let real_name = name. map ( |name| Ident :: from_str ( & name) ) ;
205
-
206
- segments. push ( hir:: PathSegment :: new (
207
- real_name. unwrap_or ( last. ident ) ,
208
- self . generics_to_path_params ( generics. clone ( ) ) ,
209
- false ,
210
- ) ) ;
211
-
212
- let new_path = hir:: Path {
213
- span : path. span ,
214
- def : path. def ,
215
- segments : HirVec :: from_vec ( segments) ,
216
- } ;
217
-
218
- let ty = hir:: Ty {
219
- id : ast:: DUMMY_NODE_ID ,
220
- node : hir:: TyKind :: Path ( hir:: QPath :: Resolved ( None , P ( new_path) ) ) ,
221
- span : DUMMY_SP ,
222
- hir_id : hir:: DUMMY_HIR_ID ,
223
- } ;
341
+ let ty = self . get_real_ty ( def_id, def_ctor, & real_name, & generics) ;
224
342
225
343
return Some ( Item {
226
344
source : Span :: empty ( ) ,
@@ -239,6 +357,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
239
357
items : Vec :: new ( ) ,
240
358
polarity,
241
359
synthetic : true ,
360
+ blanket_impl : None ,
242
361
} ) ,
243
362
} ) ;
244
363
}
0 commit comments