1+ use rustc_hir:: LangItem ;
12use rustc_middle:: mir:: visit:: Visitor ;
2- use rustc_middle:: mir:: { Const , ConstOperand , Location } ;
3- use rustc_middle:: ty:: ConstKind ;
3+ use rustc_middle:: mir:: { self , Const , ConstOperand , Location } ;
4+ use rustc_middle:: ty:: { self , ConstKind , Instance , InstanceDef , TyCtxt } ;
45
56pub struct RequiredConstsVisitor < ' a , ' tcx > {
7+ tcx : TyCtxt < ' tcx > ,
8+ body : & ' a mir:: Body < ' tcx > ,
69 required_consts : & ' a mut Vec < ConstOperand < ' tcx > > ,
10+ required_fns : & ' a mut Vec < Instance < ' tcx > > ,
711}
812
913impl < ' a , ' tcx > RequiredConstsVisitor < ' a , ' tcx > {
10- pub fn new ( required_consts : & ' a mut Vec < ConstOperand < ' tcx > > ) -> Self {
11- RequiredConstsVisitor { required_consts }
14+ pub fn new (
15+ tcx : TyCtxt < ' tcx > ,
16+ body : & ' a mir:: Body < ' tcx > ,
17+ required_consts : & ' a mut Vec < ConstOperand < ' tcx > > ,
18+ required_fns : & ' a mut Vec < Instance < ' tcx > > ,
19+ ) -> Self {
20+ RequiredConstsVisitor { tcx, body, required_consts, required_fns }
1221 }
1322}
1423
@@ -21,7 +30,34 @@ impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
2130 _ => bug ! ( "only ConstKind::Param/Value should be encountered here, got {:#?}" , c) ,
2231 } ,
2332 Const :: Unevaluated ( ..) => self . required_consts . push ( * constant) ,
24- Const :: Val ( ..) => { }
33+ Const :: Val ( _val, ty) => {
34+ // This is how function items get referenced: via zero-sized constants of `FnDef` type
35+ if let ty:: FnDef ( def_id, args) = ty. kind ( ) {
36+ debug ! ( "adding to required_fns: {def_id:?}" ) ;
37+ // FIXME maybe we shouldn't use `Instance`? We can't use `Instance::new`, it is
38+ // for codegen. But `Instance` feels like the right representation... Check what
39+ // the regular collector does.
40+ self . required_fns . push ( Instance { def : InstanceDef :: Item ( * def_id) , args } ) ;
41+ }
42+ }
43+ }
44+ }
45+
46+ fn visit_terminator ( & mut self , terminator : & mir:: Terminator < ' tcx > , location : Location ) {
47+ self . super_terminator ( terminator, location) ;
48+
49+ match terminator. kind {
50+ // We don't need to handle `Call` as we already handled all function type operands in
51+ // `visit_constant`. But we do need to handle `Drop`.
52+ mir:: TerminatorKind :: Drop { place, .. } => {
53+ let ty = place. ty ( self . body , self . tcx ) . ty ;
54+ let def_id = self . tcx . require_lang_item ( LangItem :: DropInPlace , None ) ;
55+ let args = self . tcx . mk_args ( & [ ty. into ( ) ] ) ;
56+ // FIXME: same as above (we cannot use `Instance::resolve_drop_in_place` as this is
57+ // still generic).
58+ self . required_fns . push ( Instance { def : InstanceDef :: Item ( def_id) , args } ) ;
59+ }
60+ _ => { }
2561 }
2662 }
2763}
0 commit comments