@@ -29,6 +29,107 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
2929 AutoTraitFinder { cx }
3030 }
3131
32+ fn generate_for_trait (
33+ & mut self ,
34+ ty : Ty < ' tcx > ,
35+ trait_def_id : DefId ,
36+ param_env : ty:: ParamEnv < ' tcx > ,
37+ param_env_def_id : DefId ,
38+ f : & auto_trait:: AutoTraitFinder < ' tcx > ,
39+ // If this is set, show only negative trait implementations, not positive ones.
40+ discard_positive_impl : bool ,
41+ ) -> Option < Item > {
42+ let tcx = self . cx . tcx ;
43+ let trait_ref = ty:: TraitRef { def_id : trait_def_id, substs : tcx. mk_substs_trait ( ty, & [ ] ) } ;
44+ if !self . cx . generated_synthetics . borrow_mut ( ) . insert ( ( ty, trait_def_id) ) {
45+ debug ! ( "get_auto_trait_impl_for({:?}): already generated, aborting" , trait_ref) ;
46+ return None ;
47+ }
48+
49+ let result = f. find_auto_trait_generics ( ty, param_env, trait_def_id, |infcx, info| {
50+ let region_data = info. region_data ;
51+
52+ let names_map = tcx
53+ . generics_of ( param_env_def_id)
54+ . params
55+ . iter ( )
56+ . filter_map ( |param| match param. kind {
57+ ty:: GenericParamDefKind :: Lifetime => Some ( param. name ) ,
58+ _ => None ,
59+ } )
60+ . map ( |name| ( name, Lifetime ( name) ) )
61+ . collect ( ) ;
62+ let lifetime_predicates = Self :: handle_lifetimes ( & region_data, & names_map) ;
63+ let new_generics = self . param_env_to_generics (
64+ infcx. tcx ,
65+ param_env_def_id,
66+ info. full_user_env ,
67+ lifetime_predicates,
68+ info. vid_to_region ,
69+ ) ;
70+
71+ debug ! (
72+ "find_auto_trait_generics(param_env_def_id={:?}, trait_def_id={:?}): \
73+ finished with {:?}",
74+ param_env_def_id, trait_def_id, new_generics
75+ ) ;
76+
77+ new_generics
78+ } ) ;
79+
80+ let negative_polarity;
81+ let new_generics = match result {
82+ AutoTraitResult :: PositiveImpl ( new_generics) => {
83+ negative_polarity = false ;
84+ if discard_positive_impl {
85+ return None ;
86+ }
87+ new_generics
88+ }
89+ AutoTraitResult :: NegativeImpl => {
90+ negative_polarity = true ;
91+
92+ // For negative impls, we use the generic params, but *not* the predicates,
93+ // from the original type. Otherwise, the displayed impl appears to be a
94+ // conditional negative impl, when it's really unconditional.
95+ //
96+ // For example, consider the struct Foo<T: Copy>(*mut T). Using
97+ // the original predicates in our impl would cause us to generate
98+ // `impl !Send for Foo<T: Copy>`, which makes it appear that Foo
99+ // implements Send where T is not copy.
100+ //
101+ // Instead, we generate `impl !Send for Foo<T>`, which better
102+ // expresses the fact that `Foo<T>` never implements `Send`,
103+ // regardless of the choice of `T`.
104+ let params = ( tcx. generics_of ( param_env_def_id) , ty:: GenericPredicates :: default ( ) )
105+ . clean ( self . cx )
106+ . params ;
107+
108+ Generics { params, where_predicates : Vec :: new ( ) }
109+ }
110+ AutoTraitResult :: ExplicitImpl => return None ,
111+ } ;
112+
113+ Some ( Item {
114+ source : Span :: dummy ( ) ,
115+ name : None ,
116+ attrs : Default :: default ( ) ,
117+ visibility : Inherited ,
118+ def_id : self . cx . next_def_id ( param_env_def_id. krate ) ,
119+ kind : box ImplItem ( Impl {
120+ unsafety : hir:: Unsafety :: Normal ,
121+ generics : new_generics,
122+ provided_trait_methods : Default :: default ( ) ,
123+ trait_ : Some ( trait_ref. clean ( self . cx ) . get_trait_type ( ) . unwrap ( ) ) ,
124+ for_ : ty. clean ( self . cx ) ,
125+ items : Vec :: new ( ) ,
126+ negative_polarity,
127+ synthetic : true ,
128+ blanket_impl : None ,
129+ } ) ,
130+ } )
131+ }
132+
32133 // FIXME(eddyb) figure out a better way to pass information about
33134 // parametrization of `ty` than `param_env_def_id`.
34135 crate fn get_auto_trait_impls ( & mut self , ty : Ty < ' tcx > , param_env_def_id : DefId ) -> Vec < Item > {
@@ -38,99 +139,22 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
38139
39140 debug ! ( "get_auto_trait_impls({:?})" , ty) ;
40141 let auto_traits: Vec < _ > = self . cx . auto_traits . iter ( ) . cloned ( ) . collect ( ) ;
41- auto_traits
142+ let mut auto_traits : Vec < Item > = auto_traits
42143 . into_iter ( )
43144 . filter_map ( |trait_def_id| {
44- let trait_ref =
45- ty:: TraitRef { def_id : trait_def_id, substs : tcx. mk_substs_trait ( ty, & [ ] ) } ;
46- if !self . cx . generated_synthetics . borrow_mut ( ) . insert ( ( ty, trait_def_id) ) {
47- debug ! ( "get_auto_trait_impl_for({:?}): already generated, aborting" , trait_ref) ;
48- return None ;
49- }
50-
51- let result =
52- f. find_auto_trait_generics ( ty, param_env, trait_def_id, |infcx, info| {
53- let region_data = info. region_data ;
54-
55- let names_map = tcx
56- . generics_of ( param_env_def_id)
57- . params
58- . iter ( )
59- . filter_map ( |param| match param. kind {
60- ty:: GenericParamDefKind :: Lifetime => Some ( param. name ) ,
61- _ => None ,
62- } )
63- . map ( |name| ( name, Lifetime ( name) ) )
64- . collect ( ) ;
65- let lifetime_predicates = Self :: handle_lifetimes ( & region_data, & names_map) ;
66- let new_generics = self . param_env_to_generics (
67- infcx. tcx ,
68- param_env_def_id,
69- info. full_user_env ,
70- lifetime_predicates,
71- info. vid_to_region ,
72- ) ;
73-
74- debug ! (
75- "find_auto_trait_generics(param_env_def_id={:?}, trait_def_id={:?}): \
76- finished with {:?}",
77- param_env_def_id, trait_def_id, new_generics
78- ) ;
79-
80- new_generics
81- } ) ;
82-
83- let negative_polarity;
84- let new_generics = match result {
85- AutoTraitResult :: PositiveImpl ( new_generics) => {
86- negative_polarity = false ;
87- new_generics
88- }
89- AutoTraitResult :: NegativeImpl => {
90- negative_polarity = true ;
91-
92- // For negative impls, we use the generic params, but *not* the predicates,
93- // from the original type. Otherwise, the displayed impl appears to be a
94- // conditional negative impl, when it's really unconditional.
95- //
96- // For example, consider the struct Foo<T: Copy>(*mut T). Using
97- // the original predicates in our impl would cause us to generate
98- // `impl !Send for Foo<T: Copy>`, which makes it appear that Foo
99- // implements Send where T is not copy.
100- //
101- // Instead, we generate `impl !Send for Foo<T>`, which better
102- // expresses the fact that `Foo<T>` never implements `Send`,
103- // regardless of the choice of `T`.
104- let params =
105- ( tcx. generics_of ( param_env_def_id) , ty:: GenericPredicates :: default ( ) )
106- . clean ( self . cx )
107- . params ;
108-
109- Generics { params, where_predicates : Vec :: new ( ) }
110- }
111- AutoTraitResult :: ExplicitImpl => return None ,
112- } ;
113-
114- Some ( Item {
115- source : Span :: dummy ( ) ,
116- name : None ,
117- attrs : Default :: default ( ) ,
118- visibility : Inherited ,
119- def_id : self . cx . next_def_id ( param_env_def_id. krate ) ,
120- kind : box ImplItem ( Impl {
121- unsafety : hir:: Unsafety :: Normal ,
122- generics : new_generics,
123- provided_trait_methods : Default :: default ( ) ,
124- trait_ : Some ( trait_ref. clean ( self . cx ) . get_trait_type ( ) . unwrap ( ) ) ,
125- for_ : ty. clean ( self . cx ) ,
126- items : Vec :: new ( ) ,
127- negative_polarity,
128- synthetic : true ,
129- blanket_impl : None ,
130- } ) ,
131- } )
145+ self . generate_for_trait ( ty, trait_def_id, param_env, param_env_def_id, & f, false )
132146 } )
133- . collect ( )
147+ . collect ( ) ;
148+ // We are only interested in case the type *doesn't* implement the Sized trait.
149+ if !ty. is_sized ( self . cx . tcx . at ( rustc_span:: DUMMY_SP ) , param_env) {
150+ // In case `#![no_core]` is used, `sized_trait` returns nothing.
151+ if let Some ( item) = self . cx . tcx . lang_items ( ) . sized_trait ( ) . and_then ( |sized_trait_did| {
152+ self . generate_for_trait ( ty, sized_trait_did, param_env, param_env_def_id, & f, true )
153+ } ) {
154+ auto_traits. push ( item) ;
155+ }
156+ }
157+ auto_traits
134158 }
135159
136160 fn get_lifetime ( region : Region < ' _ > , names_map : & FxHashMap < Symbol , Lifetime > ) -> Lifetime {
0 commit comments