1
+ use rustc_hir:: LangItem ;
1
2
use 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 } ;
4
5
5
6
pub struct RequiredConstsVisitor < ' a , ' tcx > {
7
+ tcx : TyCtxt < ' tcx > ,
8
+ body : & ' a mir:: Body < ' tcx > ,
6
9
required_consts : & ' a mut Vec < ConstOperand < ' tcx > > ,
10
+ required_fns : & ' a mut Vec < Instance < ' tcx > > ,
7
11
}
8
12
9
13
impl < ' 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 }
12
21
}
13
22
}
14
23
@@ -21,7 +30,31 @@ impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'_, 'tcx> {
21
30
_ => bug ! ( "only ConstKind::Param/Value should be encountered here, got {:#?}" , c) ,
22
31
} ,
23
32
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
+ _ => { }
25
58
}
26
59
}
27
60
}
0 commit comments