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,31 @@ 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+ // FIXME maybe we shouldn't use `Instance`? We can't use `Instance::new`, it is
37+ // for codegen. But `Instance` feels like the right representation... Check what
38+ // the regular collector does.
39+ self . required_fns . push ( Instance { def : InstanceDef :: Item ( * def_id) , args } ) ;
40+ }
41+ }
42+ }
43+ }
44+
45+ fn visit_terminator ( & mut self , terminator : & mir:: Terminator < ' tcx > , _location : Location ) {
46+ match terminator. kind {
47+ // We don't need to handle `Call` as we already handled all function type operands in
48+ // `visit_constant`. But we do need to handle `Drop`.
49+ mir:: TerminatorKind :: Drop { place, .. } => {
50+ let ty = place. ty ( self . body , self . tcx ) . ty ;
51+ let def_id = self . tcx . require_lang_item ( LangItem :: DropInPlace , None ) ;
52+ let args = self . tcx . mk_args ( & [ ty. into ( ) ] ) ;
53+ // FIXME: same as above (we cannot use `Instance::resolve_drop_in_place` as this is
54+ // still generic).
55+ self . required_fns . push ( Instance { def : InstanceDef :: Item ( def_id) , args } ) ;
56+ }
57+ _ => { }
2558 }
2659 }
2760}
0 commit comments