@@ -202,10 +202,11 @@ use rustc::mir::repr as mir;
202
202
use rustc:: mir:: visit as mir_visit;
203
203
use rustc:: mir:: visit:: Visitor as MirVisitor ;
204
204
205
+ use rustc_const_eval as const_eval;
206
+
205
207
use syntax:: abi:: Abi ;
206
208
use errors;
207
209
use syntax_pos:: DUMMY_SP ;
208
- use syntax:: ast:: NodeId ;
209
210
use base:: custom_coerce_unsize_info;
210
211
use context:: SharedCrateContext ;
211
212
use common:: { fulfill_obligation, normalize_and_test_predicates, type_is_sized} ;
@@ -543,9 +544,46 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
543
544
debug ! ( "visiting operand {:?}" , * operand) ;
544
545
545
546
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
+ }
549
587
_ => None
550
588
} ;
551
589
@@ -1117,10 +1155,8 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
1117
1155
self . output . push ( TransItem :: Static ( item. id ) ) ;
1118
1156
}
1119
1157
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.
1124
1160
}
1125
1161
hir:: ItemFn ( _, _, _, _, ref generics, _) => {
1126
1162
if !generics. is_type_parameterized ( ) {
@@ -1244,23 +1280,21 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1244
1280
// There are no translation items for constants themselves but their
1245
1281
// initializers might still contain something that produces translation items,
1246
1282
// 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 > > )
1250
1287
{
1251
- let def_id = scx. tcx ( ) . map . local_def_id ( const_item_node_id) ;
1252
-
1253
1288
// Scan the MIR in order to find function calls, closures, and
1254
1289
// drop-glue
1255
1290
let mir = errors:: expect ( scx. sess ( ) . diagnostic ( ) , scx. get_mir ( def_id) ,
1256
1291
|| format ! ( "Could not find MIR for const: {:?}" , def_id) ) ;
1257
1292
1258
- let empty_substs = scx. empty_substs_for_def_id ( def_id) ;
1259
1293
let visitor = MirNeighborCollector {
1260
1294
scx : scx,
1261
1295
mir : & mir,
1262
1296
output : output,
1263
- param_substs : empty_substs
1297
+ param_substs : substs
1264
1298
} ;
1265
1299
1266
1300
visit_mir_and_promoted ( visitor, & mir) ;
0 commit comments