1
1
use rustc_middle:: mir:: visit:: Visitor ;
2
2
use rustc_middle:: mir:: { self , Location , MentionedItem , MirPass } ;
3
- use rustc_middle:: ty:: Ty ;
4
3
use rustc_middle:: ty:: { self , adjustment:: PointerCoercion , TyCtxt } ;
5
4
use rustc_session:: Session ;
6
5
use rustc_span:: source_map:: Spanned ;
@@ -30,33 +29,44 @@ impl<'tcx> MirPass<'tcx> for MentionedItems {
30
29
}
31
30
}
32
31
32
+ // This visitor is carefully in sync with the one in `rustc_monomorphize::collector`. We are
33
+ // visiting the exact same places but then instead of monomorphizing and creating `MonoItems`, we
34
+ // have to remain generic and just recording the relevant information in `mentioned_items`, where it
35
+ // will then be monomorphized later during "mentioned items" collection.
33
36
impl < ' tcx > Visitor < ' tcx > for MentionedItemsVisitor < ' _ , ' tcx > {
34
- fn visit_ty ( & mut self , ty : Ty < ' tcx > , ty_context : mir:: visit:: TyContext ) {
35
- if let ty:: FnDef ( def_id, args) = ty. kind ( ) {
36
- debug ! ( "adding to required_items: {def_id:?}" ) ;
37
- self . mentioned_items . push ( Spanned {
38
- node : MentionedItem :: Fn ( * def_id, args) ,
39
- span : self . body . span_for_ty_context ( ty_context) ,
40
- } ) ;
41
- }
42
- }
43
-
44
37
fn visit_terminator ( & mut self , terminator : & mir:: Terminator < ' tcx > , location : Location ) {
45
38
self . super_terminator ( terminator, location) ;
46
- match terminator. kind {
47
- // We don't need to handle `Call` as we already handled all function type operands in
48
- // `visit_ty`. But we do need to handle `Drop`.
39
+ let span = || self . body . source_info ( location) . span ;
40
+ match & terminator. kind {
41
+ mir:: TerminatorKind :: Call { func, .. } => {
42
+ let callee_ty = func. ty ( self . body , self . tcx ) ;
43
+ self . mentioned_items
44
+ . push ( Spanned { node : MentionedItem :: Fn ( callee_ty) , span : span ( ) } ) ;
45
+ }
49
46
mir:: TerminatorKind :: Drop { place, .. } => {
50
47
let ty = place. ty ( self . body , self . tcx ) . ty ;
51
- let span = self . body . source_info ( location) . span ;
52
- self . mentioned_items . push ( Spanned { node : MentionedItem :: Drop ( ty) , span } ) ;
48
+ self . mentioned_items . push ( Spanned { node : MentionedItem :: Drop ( ty) , span : span ( ) } ) ;
49
+ }
50
+ mir:: TerminatorKind :: InlineAsm { ref operands, .. } => {
51
+ for op in operands {
52
+ match * op {
53
+ mir:: InlineAsmOperand :: SymFn { ref value } => {
54
+ self . mentioned_items . push ( Spanned {
55
+ node : MentionedItem :: Fn ( value. const_ . ty ( ) ) ,
56
+ span : span ( ) ,
57
+ } ) ;
58
+ }
59
+ _ => { }
60
+ }
61
+ }
53
62
}
54
63
_ => { }
55
64
}
56
65
}
57
66
58
67
fn visit_rvalue ( & mut self , rvalue : & mir:: Rvalue < ' tcx > , location : Location ) {
59
68
self . super_rvalue ( rvalue, location) ;
69
+ let span = || self . body . source_info ( location) . span ;
60
70
match * rvalue {
61
71
// We need to detect unsizing casts that required vtables.
62
72
mir:: Rvalue :: Cast (
@@ -65,13 +75,12 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
65
75
target_ty,
66
76
)
67
77
| mir:: Rvalue :: Cast ( mir:: CastKind :: DynStar , ref operand, target_ty) => {
68
- let span = self . body . source_info ( location) . span ;
69
78
self . mentioned_items . push ( Spanned {
70
79
node : MentionedItem :: UnsizeCast {
71
80
source_ty : operand. ty ( self . body , self . tcx ) ,
72
81
target_ty,
73
82
} ,
74
- span,
83
+ span : span ( ) ,
75
84
} ) ;
76
85
}
77
86
// Similarly, record closures that are turned into function pointers.
@@ -80,17 +89,26 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
80
89
ref operand,
81
90
_,
82
91
) => {
83
- let span = self . body . source_info ( location) . span ;
84
92
let source_ty = operand. ty ( self . body , self . tcx ) ;
85
93
match * source_ty. kind ( ) {
86
94
ty:: Closure ( def_id, args) => {
87
- self . mentioned_items
88
- . push ( Spanned { node : MentionedItem :: Closure ( def_id, args) , span } ) ;
95
+ self . mentioned_items . push ( Spanned {
96
+ node : MentionedItem :: Closure ( def_id, args) ,
97
+ span : span ( ) ,
98
+ } ) ;
89
99
}
90
100
_ => bug ! ( ) ,
91
101
}
92
102
}
93
- // Function pointer casts are already handled by `visit_ty` above.
103
+ // And finally, function pointer reification casts.
104
+ mir:: Rvalue :: Cast (
105
+ mir:: CastKind :: PointerCoercion ( PointerCoercion :: ReifyFnPointer ) ,
106
+ ref operand,
107
+ _,
108
+ ) => {
109
+ let fn_ty = operand. ty ( self . body , self . tcx ) ;
110
+ self . mentioned_items . push ( Spanned { node : MentionedItem :: Fn ( fn_ty) , span : span ( ) } ) ;
111
+ }
94
112
_ => { }
95
113
}
96
114
}
0 commit comments