88// option. This file may not be copied, modified, or distributed
99// except according to those terms.
1010
11- use rustc:: traits:: auto_trait as auto;
12- use rustc:: ty:: TypeFoldable ;
1311use 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 ;
1416use std:: fmt:: Debug ;
17+ use syntax_pos:: DUMMY_SP ;
18+
19+ use core:: DocAccessLevels ;
1520
1621use super :: * ;
1722
@@ -75,6 +80,141 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
7580 self . get_auto_trait_impls ( did, & def_ctor, Some ( name) )
7681 }
7782
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+
78218 pub fn get_auto_trait_impls < F > (
79219 & self ,
80220 def_id : DefId ,
@@ -122,6 +262,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
122262 def_ctor,
123263 tcx. require_lang_item ( lang_items:: SyncTraitLangItem ) ,
124264 ) . into_iter ( ) )
265+ . chain ( self . get_blanket_impls ( def_id, def_ctor, name, & generics) . into_iter ( ) )
125266 . collect ( ) ;
126267
127268 debug ! (
@@ -196,31 +337,8 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
196337 }
197338 _ => unreachable ! ( ) ,
198339 } ;
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-
204340 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) ;
224342
225343 return Some ( Item {
226344 source : Span :: empty ( ) ,
@@ -239,6 +357,7 @@ impl<'a, 'tcx, 'rcx> AutoTraitFinder<'a, 'tcx, 'rcx> {
239357 items : Vec :: new ( ) ,
240358 polarity,
241359 synthetic : true ,
360+ blanket_impl : None ,
242361 } ) ,
243362 } ) ;
244363 }
0 commit comments