@@ -52,7 +52,10 @@ pub enum InstanceDef<'tcx> {
52
52
/// `<[mut closure] as FnOnce>::call_once`
53
53
ClosureOnceShim { call_once : DefId } ,
54
54
55
- /// `drop_in_place::<T>; None` for empty drop glue.
55
+ /// `real_drop_in_place::<T>`.
56
+ /// The `DefId` is for `real_drop_in_place`.
57
+ /// The `Option<Ty<'tcx>>` is either `Some(T)`, or `None` for empty drop
58
+ /// glue.
56
59
DropGlue ( DefId , Option < Ty < ' tcx > > ) ,
57
60
58
61
///`<T as Clone>::clone` shim.
@@ -108,11 +111,28 @@ impl<'tcx> InstanceDef<'tcx> {
108
111
if self . is_inline ( tcx) {
109
112
return true
110
113
}
111
- if let ty:: InstanceDef :: DropGlue ( ..) = * self {
112
- // Drop glue wants to be instantiated at every codegen
114
+ if let ty:: InstanceDef :: DropGlue ( .., Some ( ty ) ) = * self {
115
+ // Drop glue generally wants to be instantiated at every codegen
113
116
// unit, but without an #[inline] hint. We should make this
114
117
// available to normal end-users.
115
- return true
118
+ if tcx. sess . opts . incremental . is_none ( ) {
119
+ return true ;
120
+ }
121
+ // When compiling with incremental, we can generate a *lot* of
122
+ // codegen units. Including drop glue into all of them has a
123
+ // considerable compile time cost.
124
+ //
125
+ // We include enums without destructors to allow, say, optimizing
126
+ // drops of `Option::None` before LTO. We also respect the intent of
127
+ // `#[inline]` on `Drop::drop` implementations.
128
+ return ty. ty_adt_def ( )
129
+ . map_or ( true , |adt_def| {
130
+ adt_def. destructor ( tcx)
131
+ . map_or (
132
+ adt_def. is_enum ( ) ,
133
+ |dtor| tcx. codegen_fn_attrs ( dtor. did ) . requests_inline ( ) ,
134
+ )
135
+ } )
116
136
}
117
137
tcx. codegen_fn_attrs ( self . def_id ( ) ) . requests_inline ( )
118
138
}
0 commit comments