|
| 1 | +use rustc_hir::def_id::DefId; |
1 | 2 | use rustc_middle::mir::visit::Visitor; |
2 | 3 | use rustc_middle::mir::{self, ConstOperand, Location, MentionedItem, MirPass}; |
3 | 4 | use rustc_middle::ty::{self, adjustment::PointerCoercion, TyCtxt}; |
@@ -34,10 +35,12 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> { |
34 | 35 | let const_ = constant.const_; |
35 | 36 | // This is how function items get referenced: via constants of `FnDef` type. This handles |
36 | 37 | // both functions that are called and those that are just turned to function pointers. |
37 | | - if let ty::FnDef(def_id, args) = const_.ty().kind() { |
| 38 | + if let ty::FnDef(def_id, args) = *const_.ty().kind() |
| 39 | + && may_codegen_locally(self.tcx, def_id) |
| 40 | + { |
38 | 41 | debug!("adding to required_items: {def_id:?}"); |
39 | 42 | self.mentioned_items |
40 | | - .push(Spanned { node: MentionedItem::Fn(*def_id, args), span: constant.span }); |
| 43 | + .push(Spanned { node: MentionedItem::Fn(def_id, args), span: constant.span }); |
41 | 44 | } |
42 | 45 | } |
43 | 46 |
|
@@ -95,3 +98,29 @@ impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> { |
95 | 98 | } |
96 | 99 | } |
97 | 100 | } |
| 101 | + |
| 102 | +/// Returns `true` if we should codegen an item in the local crate, or returns `false` if we |
| 103 | +/// can just link to the upstream crate and therefore don't need a mono item. |
| 104 | +/// |
| 105 | +/// This is an approximation of the collector's `should_codegen_locally`, in the sense that this |
| 106 | +/// here may return `true` even if `should_codegen_locally` says `false`. The point is to let us |
| 107 | +/// filter out items that definitely will not be considered by the collector. |
| 108 | +fn may_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool { |
| 109 | + if tcx.is_foreign_item(def_id) { |
| 110 | + // Foreign items are always linked against, there's no way of instantiating them. |
| 111 | + return false; |
| 112 | + } |
| 113 | + |
| 114 | + if def_id.is_local() { |
| 115 | + // Local items cannot be referred to locally without monomorphizing them locally. |
| 116 | + return true; |
| 117 | + } |
| 118 | + |
| 119 | + if tcx.is_reachable_non_generic(def_id) { |
| 120 | + // We can link to the item in question, no instance needed in this crate. |
| 121 | + return false; |
| 122 | + } |
| 123 | + |
| 124 | + // Conservative fall-back. |
| 125 | + true |
| 126 | +} |
0 commit comments