mentioned_items: record all callee and coerced closure types, whether they are FnDef/Closure or not
They may become FnDef during monomorphization!
This commit is contained in:
parent
f1ec494c32
commit
0d6a16ac4b
15 changed files with 355 additions and 76 deletions
|
@ -723,15 +723,9 @@ impl<'tcx> Inliner<'tcx> {
|
|||
// some extra work here to save the monomorphization collector work later. It helps a lot,
|
||||
// since monomorphization can avoid a lot of work when the "mentioned items" are similar to
|
||||
// the actually used items. By doing this we can entirely avoid visiting the callee!
|
||||
let callee_item = {
|
||||
// We need to reconstruct the `required_item` for the callee so that we can find and
|
||||
// remove it.
|
||||
let func_ty = func.ty(caller_body, self.tcx);
|
||||
match func_ty.kind() {
|
||||
ty::FnDef(def_id, args) => MentionedItem::Fn(*def_id, args),
|
||||
_ => bug!(),
|
||||
}
|
||||
};
|
||||
// We need to reconstruct the `required_item` for the callee so that we can find and
|
||||
// remove it.
|
||||
let callee_item = MentionedItem::Fn(func.ty(caller_body, self.tcx));
|
||||
if let Some(idx) =
|
||||
caller_body.mentioned_items.iter().position(|item| item.node == callee_item)
|
||||
{
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use rustc_middle::mir::visit::Visitor;
|
||||
use rustc_middle::mir::{self, ConstOperand, Location, MentionedItem, MirPass};
|
||||
use rustc_middle::ty::{self, adjustment::PointerCoercion, TyCtxt};
|
||||
use rustc_middle::mir::{self, Location, MentionedItem, MirPass};
|
||||
use rustc_middle::ty::{adjustment::PointerCoercion, TyCtxt};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::source_map::Spanned;
|
||||
|
||||
|
@ -29,27 +29,36 @@ impl<'tcx> MirPass<'tcx> for MentionedItems {
|
|||
}
|
||||
}
|
||||
|
||||
// This visitor is carefully in sync with the one in `rustc_monomorphize::collector`. We are
|
||||
// visiting the exact same places but then instead of monomorphizing and creating `MonoItems`, we
|
||||
// have to remain generic and just recording the relevant information in `mentioned_items`, where it
|
||||
// will then be monomorphized later during "mentioned items" collection.
|
||||
impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
|
||||
fn visit_constant(&mut self, constant: &ConstOperand<'tcx>, _: Location) {
|
||||
let const_ = constant.const_;
|
||||
// This is how function items get referenced: via constants of `FnDef` type. This handles
|
||||
// both functions that are called and those that are just turned to function pointers.
|
||||
if let ty::FnDef(def_id, args) = const_.ty().kind() {
|
||||
debug!("adding to required_items: {def_id:?}");
|
||||
self.mentioned_items
|
||||
.push(Spanned { node: MentionedItem::Fn(*def_id, args), span: constant.span });
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
|
||||
self.super_terminator(terminator, location);
|
||||
match terminator.kind {
|
||||
// We don't need to handle `Call` as we already handled all function type operands in
|
||||
// `visit_constant`. But we do need to handle `Drop`.
|
||||
let span = || self.body.source_info(location).span;
|
||||
match &terminator.kind {
|
||||
mir::TerminatorKind::Call { func, .. } => {
|
||||
let callee_ty = func.ty(self.body, self.tcx);
|
||||
self.mentioned_items
|
||||
.push(Spanned { node: MentionedItem::Fn(callee_ty), span: span() });
|
||||
}
|
||||
mir::TerminatorKind::Drop { place, .. } => {
|
||||
let ty = place.ty(self.body, self.tcx).ty;
|
||||
let span = self.body.source_info(location).span;
|
||||
self.mentioned_items.push(Spanned { node: MentionedItem::Drop(ty), span });
|
||||
self.mentioned_items.push(Spanned { node: MentionedItem::Drop(ty), span: span() });
|
||||
}
|
||||
mir::TerminatorKind::InlineAsm { ref operands, .. } => {
|
||||
for op in operands {
|
||||
match *op {
|
||||
mir::InlineAsmOperand::SymFn { ref value } => {
|
||||
self.mentioned_items.push(Spanned {
|
||||
node: MentionedItem::Fn(value.const_.ty()),
|
||||
span: span(),
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -57,6 +66,7 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
|
|||
|
||||
fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
|
||||
self.super_rvalue(rvalue, location);
|
||||
let span = || self.body.source_info(location).span;
|
||||
match *rvalue {
|
||||
// We need to detect unsizing casts that required vtables.
|
||||
mir::Rvalue::Cast(
|
||||
|
@ -65,13 +75,14 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
|
|||
target_ty,
|
||||
)
|
||||
| mir::Rvalue::Cast(mir::CastKind::DynStar, ref operand, target_ty) => {
|
||||
let span = self.body.source_info(location).span;
|
||||
// This isn't monomorphized yet so we can't tell what the actual types are -- just
|
||||
// add everything.
|
||||
self.mentioned_items.push(Spanned {
|
||||
node: MentionedItem::UnsizeCast {
|
||||
source_ty: operand.ty(self.body, self.tcx),
|
||||
target_ty,
|
||||
},
|
||||
span,
|
||||
span: span(),
|
||||
});
|
||||
}
|
||||
// Similarly, record closures that are turned into function pointers.
|
||||
|
@ -80,17 +91,19 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
|
|||
ref operand,
|
||||
_,
|
||||
) => {
|
||||
let span = self.body.source_info(location).span;
|
||||
let source_ty = operand.ty(self.body, self.tcx);
|
||||
match *source_ty.kind() {
|
||||
ty::Closure(def_id, args) => {
|
||||
self.mentioned_items
|
||||
.push(Spanned { node: MentionedItem::Closure(def_id, args), span });
|
||||
}
|
||||
_ => bug!(),
|
||||
}
|
||||
self.mentioned_items
|
||||
.push(Spanned { node: MentionedItem::Closure(source_ty), span: span() });
|
||||
}
|
||||
// And finally, function pointer reification casts.
|
||||
mir::Rvalue::Cast(
|
||||
mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer),
|
||||
ref operand,
|
||||
_,
|
||||
) => {
|
||||
let fn_ty = operand.ty(self.body, self.tcx);
|
||||
self.mentioned_items.push(Spanned { node: MentionedItem::Fn(fn_ty), span: span() });
|
||||
}
|
||||
// Function pointer casts are already handled by `visit_constant` above.
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue