@@ -194,11 +194,12 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor;
194194use rustc:: hir:: map as hir_map;
195195use rustc:: hir:: def_id:: DefId ;
196196use rustc:: middle:: const_val:: ConstVal ;
197- use rustc:: middle:: lang_items:: { ExchangeMallocFnLangItem } ;
197+ use rustc:: middle:: lang_items:: { ExchangeMallocFnLangItem , StartFnLangItem } ;
198198use rustc:: traits;
199- use rustc:: ty:: subst:: Substs ;
199+ use rustc:: ty:: subst:: { Substs , Kind } ;
200200use rustc:: ty:: { self , TypeFoldable , Ty , TyCtxt } ;
201201use rustc:: ty:: adjustment:: CustomCoerceUnsized ;
202+ use rustc:: session:: config;
202203use rustc:: mir:: { self , Location } ;
203204use rustc:: mir:: visit:: Visitor as MirVisitor ;
204205use rustc:: mir:: mono:: MonoItem ;
@@ -212,6 +213,8 @@ use rustc_data_structures::bitvec::BitVector;
212213
213214use syntax:: attr;
214215
216+ use std:: iter;
217+
215218#[ derive( PartialEq , Eq , Hash , Clone , Copy , Debug ) ]
216219pub enum MonoItemCollectionMode {
217220 Eager ,
@@ -329,6 +332,8 @@ fn collect_roots<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
329332 tcx. hir . local_def_id ( node_id)
330333 } ) ;
331334
335+ debug ! ( "collect_roots: entry_fn = {:?}" , entry_fn) ;
336+
332337 let mut visitor = RootCollector {
333338 tcx,
334339 mode,
@@ -951,16 +956,8 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
951956 // actually used somewhere. Just declaring them is insufficient.
952957 }
953958 hir:: ItemFn ( ..) => {
954- let tcx = self . tcx ;
955- let def_id = tcx. hir . local_def_id ( item. id ) ;
956-
957- if self . is_root ( def_id) {
958- debug ! ( "RootCollector: ItemFn({})" ,
959- def_id_to_string( tcx, def_id) ) ;
960-
961- let instance = Instance :: mono ( tcx, def_id) ;
962- self . output . push ( MonoItem :: Fn ( instance) ) ;
963- }
959+ let def_id = self . tcx . hir . local_def_id ( item. id ) ;
960+ self . push_if_root ( def_id) ;
964961 }
965962 }
966963 }
@@ -973,16 +970,8 @@ impl<'b, 'a, 'v> ItemLikeVisitor<'v> for RootCollector<'b, 'a, 'v> {
973970 fn visit_impl_item ( & mut self , ii : & ' v hir:: ImplItem ) {
974971 match ii. node {
975972 hir:: ImplItemKind :: Method ( hir:: MethodSig { .. } , _) => {
976- let tcx = self . tcx ;
977- let def_id = tcx. hir . local_def_id ( ii. id ) ;
978-
979- if self . is_root ( def_id) {
980- debug ! ( "RootCollector: MethodImplItem({})" ,
981- def_id_to_string( tcx, def_id) ) ;
982-
983- let instance = Instance :: mono ( tcx, def_id) ;
984- self . output . push ( MonoItem :: Fn ( instance) ) ;
985- }
973+ let def_id = self . tcx . hir . local_def_id ( ii. id ) ;
974+ self . push_if_root ( def_id) ;
986975 }
987976 _ => { /* Nothing to do here */ }
988977 }
@@ -1003,6 +992,56 @@ impl<'b, 'a, 'v> RootCollector<'b, 'a, 'v> {
1003992 }
1004993 }
1005994 }
995+
996+ /// If `def_id` represents a root, then push it onto the list of
997+ /// outputs. (Note that all roots must be monomorphic.)
998+ fn push_if_root ( & mut self , def_id : DefId ) {
999+ if self . is_root ( def_id) {
1000+ debug ! ( "RootCollector::push_if_root: found root def_id={:?}" , def_id) ;
1001+
1002+ let instance = Instance :: mono ( self . tcx , def_id) ;
1003+ self . output . push ( create_fn_mono_item ( instance) ) ;
1004+
1005+ self . push_extra_entry_roots ( def_id) ;
1006+ }
1007+ }
1008+
1009+ /// As a special case, when/if we encounter the
1010+ /// `main()` function, we also have to generate a
1011+ /// monomorphized copy of the start lang item based on
1012+ /// the return type of `main`. This is not needed when
1013+ /// the user writes their own `start` manually.
1014+ fn push_extra_entry_roots ( & mut self , def_id : DefId ) {
1015+ if self . entry_fn != Some ( def_id) {
1016+ return ;
1017+ }
1018+
1019+ if self . tcx . sess . entry_type . get ( ) != Some ( config:: EntryMain ) {
1020+ return ;
1021+ }
1022+
1023+ let start_def_id = match self . tcx . lang_items ( ) . require ( StartFnLangItem ) {
1024+ Ok ( s) => s,
1025+ Err ( err) => self . tcx . sess . fatal ( & err) ,
1026+ } ;
1027+ let main_ret_ty = self . tcx . fn_sig ( def_id) . output ( ) ;
1028+
1029+ // Given that `main()` has no arguments,
1030+ // then its return type cannot have
1031+ // late-bound regions, since late-bound
1032+ // regions must appear in the argument
1033+ // listing.
1034+ let main_ret_ty = main_ret_ty. no_late_bound_regions ( ) . unwrap ( ) ;
1035+
1036+ let start_instance = Instance :: resolve (
1037+ self . tcx ,
1038+ ty:: ParamEnv :: empty ( traits:: Reveal :: All ) ,
1039+ start_def_id,
1040+ self . tcx . mk_substs ( iter:: once ( Kind :: from ( main_ret_ty) ) )
1041+ ) . unwrap ( ) ;
1042+
1043+ self . output . push ( create_fn_mono_item ( start_instance) ) ;
1044+ }
10061045}
10071046
10081047fn item_has_type_parameters < ' a , ' tcx > ( tcx : TyCtxt < ' a , ' tcx , ' tcx > , def_id : DefId ) -> bool {
0 commit comments