@@ -202,10 +202,11 @@ use rustc::mir::repr as mir;
202202use rustc:: mir:: visit as mir_visit;
203203use rustc:: mir:: visit:: Visitor as MirVisitor ;
204204
205+ use rustc_const_eval as const_eval;
206+
205207use syntax:: abi:: Abi ;
206208use errors;
207209use syntax_pos:: DUMMY_SP ;
208- use syntax:: ast:: NodeId ;
209210use base:: custom_coerce_unsize_info;
210211use context:: SharedCrateContext ;
211212use common:: { fulfill_obligation, normalize_and_test_predicates, type_is_sized} ;
@@ -543,9 +544,46 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
543544 debug ! ( "visiting operand {:?}" , * operand) ;
544545
545546 let callee = match * operand {
546- mir:: Operand :: Constant ( mir:: Constant { ty : & ty:: TyS {
547- sty : ty:: TyFnDef ( def_id, substs, _) , ..
548- } , .. } ) => Some ( ( def_id, substs) ) ,
547+ mir:: Operand :: Constant ( ref constant) => {
548+ if let ty:: TyFnDef ( def_id, substs, _) = constant. ty . sty {
549+ // This is something that can act as a callee, proceed
550+ Some ( ( def_id, substs) )
551+ } else {
552+ // This is not a callee, but we still have to look for
553+ // references to `const` items
554+ if let mir:: Literal :: Item { def_id, substs } = constant. literal {
555+ let tcx = self . scx . tcx ( ) ;
556+ let substs = monomorphize:: apply_param_substs ( tcx,
557+ self . param_substs ,
558+ & substs) ;
559+
560+ // If the constant referred to here is an associated
561+ // item of a trait, we need to resolve it to the actual
562+ // constant in the corresponding impl. Luckily
563+ // const_eval::lookup_const_by_id() does that for us.
564+ if let Some ( ( expr, _) ) = const_eval:: lookup_const_by_id ( tcx,
565+ def_id,
566+ Some ( substs) ) {
567+ // The hir::Expr we get here is the initializer of
568+ // the constant, what we really want is the item
569+ // DefId.
570+ let const_node_id = tcx. map . get_parent ( expr. id ) ;
571+ let def_id = if tcx. map . is_inlined_node_id ( const_node_id) {
572+ tcx. sess . cstore . defid_for_inlined_node ( const_node_id) . unwrap ( )
573+ } else {
574+ tcx. map . local_def_id ( const_node_id)
575+ } ;
576+
577+ collect_const_item_neighbours ( self . scx ,
578+ def_id,
579+ substs,
580+ self . output ) ;
581+ }
582+ }
583+
584+ None
585+ }
586+ }
549587 _ => None
550588 } ;
551589
@@ -1117,10 +1155,8 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
11171155 self . output . push ( TransItem :: Static ( item. id ) ) ;
11181156 }
11191157 hir:: ItemConst ( ..) => {
1120- debug ! ( "RootCollector: ItemConst({})" ,
1121- def_id_to_string( self . scx. tcx( ) ,
1122- self . scx. tcx( ) . map. local_def_id( item. id) ) ) ;
1123- add_roots_for_const_item ( self . scx , item. id , self . output ) ;
1158+ // const items only generate translation items if they are
1159+ // actually used somewhere. Just declaring them is insufficient.
11241160 }
11251161 hir:: ItemFn ( _, _, _, _, ref generics, _) => {
11261162 if !generics. is_type_parameterized ( ) {
@@ -1244,23 +1280,21 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
12441280// There are no translation items for constants themselves but their
12451281// initializers might still contain something that produces translation items,
12461282// such as cast that introduce a new vtable.
1247- fn add_roots_for_const_item < ' a , ' tcx > ( scx : & SharedCrateContext < ' a , ' tcx > ,
1248- const_item_node_id : NodeId ,
1249- output : & mut Vec < TransItem < ' tcx > > )
1283+ fn collect_const_item_neighbours < ' a , ' tcx > ( scx : & SharedCrateContext < ' a , ' tcx > ,
1284+ def_id : DefId ,
1285+ substs : & ' tcx Substs < ' tcx > ,
1286+ output : & mut Vec < TransItem < ' tcx > > )
12501287{
1251- let def_id = scx. tcx ( ) . map . local_def_id ( const_item_node_id) ;
1252-
12531288 // Scan the MIR in order to find function calls, closures, and
12541289 // drop-glue
12551290 let mir = errors:: expect ( scx. sess ( ) . diagnostic ( ) , scx. get_mir ( def_id) ,
12561291 || format ! ( "Could not find MIR for const: {:?}" , def_id) ) ;
12571292
1258- let empty_substs = scx. empty_substs_for_def_id ( def_id) ;
12591293 let visitor = MirNeighborCollector {
12601294 scx : scx,
12611295 mir : & mir,
12621296 output : output,
1263- param_substs : empty_substs
1297+ param_substs : substs
12641298 } ;
12651299
12661300 visit_mir_and_promoted ( visitor, & mir) ;
0 commit comments