1mod autodiff;
209
210use std::cell::OnceCell;
211
212use rustc_data_structures::fx::FxIndexMap;
213use rustc_data_structures::sync::{MTLock, par_for_each_in};
214use rustc_data_structures::unord::{UnordMap, UnordSet};
215use rustc_hir as hir;
216use rustc_hir::attrs::InlineAttr;
217use rustc_hir::def::DefKind;
218use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
219use rustc_hir::lang_items::LangItem;
220use rustc_hir::limit::Limit;
221use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
222use rustc_middle::mir::interpret::{AllocId, ErrorHandled, GlobalAlloc, Scalar};
223use rustc_middle::mir::mono::{CollectionMode, InstantiationMode, MonoItem};
224use rustc_middle::mir::visit::Visitor as MirVisitor;
225use rustc_middle::mir::{self, Location, MentionedItem, traversal};
226use rustc_middle::query::TyCtxtAt;
227use rustc_middle::ty::adjustment::{CustomCoerceUnsized, PointerCoercion};
228use rustc_middle::ty::layout::ValidityRequirement;
229use rustc_middle::ty::{
230 self, GenericArgs, GenericParamDefKind, Instance, InstanceKind, Ty, TyCtxt, TypeFoldable,
231 TypeVisitableExt, VtblEntry,
232};
233use rustc_middle::util::Providers;
234use rustc_middle::{bug, span_bug};
235use rustc_session::config::{DebugInfo, EntryFnType};
236use rustc_span::source_map::{Spanned, dummy_spanned, respan};
237use rustc_span::{DUMMY_SP, Span};
238use tracing::{debug, instrument, trace};
239
240use crate::collector::autodiff::collect_autodiff_fn;
241use crate::errors::{
242 self, EncounteredErrorWhileInstantiating, EncounteredErrorWhileInstantiatingGlobalAsm,
243 NoOptimizedMir, RecursionLimit,
244};
245
246#[derive(PartialEq)]
247pub(crate) enum MonoItemCollectionStrategy {
248 Eager,
249 Lazy,
250}
251
252struct SharedState<'tcx> {
254 visited: MTLock<UnordSet<MonoItem<'tcx>>>,
256 mentioned: MTLock<UnordSet<MonoItem<'tcx>>>,
259 usage_map: MTLock<UsageMap<'tcx>>,
261}
262
263pub(crate) struct UsageMap<'tcx> {
264 pub used_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
266
267 user_map: UnordMap<MonoItem<'tcx>, Vec<MonoItem<'tcx>>>,
269}
270
271impl<'tcx> UsageMap<'tcx> {
272 fn new() -> UsageMap<'tcx> {
273 UsageMap { used_map: Default::default(), user_map: Default::default() }
274 }
275
276 fn record_used<'a>(&mut self, user_item: MonoItem<'tcx>, used_items: &'a MonoItems<'tcx>)
277 where
278 'tcx: 'a,
279 {
280 for used_item in used_items.items() {
281 self.user_map.entry(used_item).or_default().push(user_item);
282 }
283
284 assert!(self.used_map.insert(user_item, used_items.items().collect()).is_none());
285 }
286
287 pub(crate) fn get_user_items(&self, item: MonoItem<'tcx>) -> &[MonoItem<'tcx>] {
288 self.user_map.get(&item).map(|items| items.as_slice()).unwrap_or(&[])
289 }
290
291 pub(crate) fn for_each_inlined_used_item<F>(
293 &self,
294 tcx: TyCtxt<'tcx>,
295 item: MonoItem<'tcx>,
296 mut f: F,
297 ) where
298 F: FnMut(MonoItem<'tcx>),
299 {
300 let used_items = self.used_map.get(&item).unwrap();
301 for used_item in used_items.iter() {
302 let is_inlined = used_item.instantiation_mode(tcx) == InstantiationMode::LocalCopy;
303 if is_inlined {
304 f(*used_item);
305 }
306 }
307 }
308}
309
310struct MonoItems<'tcx> {
311 items: FxIndexMap<MonoItem<'tcx>, Span>,
314}
315
316impl<'tcx> MonoItems<'tcx> {
317 fn new() -> Self {
318 Self { items: FxIndexMap::default() }
319 }
320
321 fn is_empty(&self) -> bool {
322 self.items.is_empty()
323 }
324
325 fn push(&mut self, item: Spanned<MonoItem<'tcx>>) {
326 self.items.entry(item.node).or_insert(item.span);
329 }
330
331 fn items(&self) -> impl Iterator<Item = MonoItem<'tcx>> {
332 self.items.keys().cloned()
333 }
334}
335
336impl<'tcx> IntoIterator for MonoItems<'tcx> {
337 type Item = Spanned<MonoItem<'tcx>>;
338 type IntoIter = impl Iterator<Item = Spanned<MonoItem<'tcx>>>;
339
340 fn into_iter(self) -> Self::IntoIter {
341 self.items.into_iter().map(|(item, span)| respan(span, item))
342 }
343}
344
345impl<'tcx> Extend<Spanned<MonoItem<'tcx>>> for MonoItems<'tcx> {
346 fn extend<I>(&mut self, iter: I)
347 where
348 I: IntoIterator<Item = Spanned<MonoItem<'tcx>>>,
349 {
350 for item in iter {
351 self.push(item)
352 }
353 }
354}
355
356fn collect_items_root<'tcx>(
357 tcx: TyCtxt<'tcx>,
358 starting_item: Spanned<MonoItem<'tcx>>,
359 state: &SharedState<'tcx>,
360 recursion_limit: Limit,
361) {
362 if !state.visited.lock_mut().insert(starting_item.node) {
363 return;
365 }
366 let mut recursion_depths = DefIdMap::default();
367 collect_items_rec(
368 tcx,
369 starting_item,
370 state,
371 &mut recursion_depths,
372 recursion_limit,
373 CollectionMode::UsedItems,
374 );
375}
376
377#[instrument(skip(tcx, state, recursion_depths, recursion_limit), level = "debug")]
383fn collect_items_rec<'tcx>(
384 tcx: TyCtxt<'tcx>,
385 starting_item: Spanned<MonoItem<'tcx>>,
386 state: &SharedState<'tcx>,
387 recursion_depths: &mut DefIdMap<usize>,
388 recursion_limit: Limit,
389 mode: CollectionMode,
390) {
391 let mut used_items = MonoItems::new();
392 let mut mentioned_items = MonoItems::new();
393 let recursion_depth_reset;
394
395 let error_count = tcx.dcx().err_count();
419
420 match starting_item.node {
424 MonoItem::Static(def_id) => {
425 recursion_depth_reset = None;
426
427 if mode == CollectionMode::UsedItems {
430 let instance = Instance::mono(tcx, def_id);
431
432 debug_assert!(tcx.should_codegen_locally(instance));
434
435 let DefKind::Static { nested, .. } = tcx.def_kind(def_id) else { bug!() };
436 if !nested {
438 let ty = instance.ty(tcx, ty::TypingEnv::fully_monomorphized());
439 visit_drop_use(tcx, ty, true, starting_item.span, &mut used_items);
440 }
441
442 if let Ok(alloc) = tcx.eval_static_initializer(def_id) {
443 for &prov in alloc.inner().provenance().ptrs().values() {
444 collect_alloc(tcx, prov.alloc_id(), &mut used_items);
445 }
446 }
447
448 if tcx.needs_thread_local_shim(def_id) {
449 used_items.push(respan(
450 starting_item.span,
451 MonoItem::Fn(Instance {
452 def: InstanceKind::ThreadLocalShim(def_id),
453 args: GenericArgs::empty(),
454 }),
455 ));
456 }
457 }
458
459 }
463 MonoItem::Fn(instance) => {
464 debug_assert!(tcx.should_codegen_locally(instance));
466
467 recursion_depth_reset = Some(check_recursion_limit(
469 tcx,
470 instance,
471 starting_item.span,
472 recursion_depths,
473 recursion_limit,
474 ));
475
476 rustc_data_structures::stack::ensure_sufficient_stack(|| {
477 let (used, mentioned) = tcx.items_of_instance((instance, mode));
478 used_items.extend(used.into_iter().copied());
479 mentioned_items.extend(mentioned.into_iter().copied());
480 });
481 }
482 MonoItem::GlobalAsm(item_id) => {
483 assert!(
484 mode == CollectionMode::UsedItems,
485 "should never encounter global_asm when collecting mentioned items"
486 );
487 recursion_depth_reset = None;
488
489 let item = tcx.hir_item(item_id);
490 if let hir::ItemKind::GlobalAsm { asm, .. } = item.kind {
491 for (op, op_sp) in asm.operands {
492 match *op {
493 hir::InlineAsmOperand::Const { .. } => {
494 }
498 hir::InlineAsmOperand::SymFn { expr } => {
499 let fn_ty = tcx.typeck(item_id.owner_id).expr_ty(expr);
500 visit_fn_use(tcx, fn_ty, false, *op_sp, &mut used_items);
501 }
502 hir::InlineAsmOperand::SymStatic { path: _, def_id } => {
503 let instance = Instance::mono(tcx, def_id);
504 if tcx.should_codegen_locally(instance) {
505 trace!("collecting static {:?}", def_id);
506 used_items.push(dummy_spanned(MonoItem::Static(def_id)));
507 }
508 }
509 hir::InlineAsmOperand::In { .. }
510 | hir::InlineAsmOperand::Out { .. }
511 | hir::InlineAsmOperand::InOut { .. }
512 | hir::InlineAsmOperand::SplitInOut { .. }
513 | hir::InlineAsmOperand::Label { .. } => {
514 span_bug!(*op_sp, "invalid operand type for global_asm!")
515 }
516 }
517 }
518 } else {
519 span_bug!(item.span, "Mismatch between hir::Item type and MonoItem type")
520 }
521
522 }
524 };
525
526 if tcx.dcx().err_count() > error_count
529 && starting_item.node.is_generic_fn()
530 && starting_item.node.is_user_defined()
531 {
532 match starting_item.node {
533 MonoItem::Fn(instance) => tcx.dcx().emit_note(EncounteredErrorWhileInstantiating {
534 span: starting_item.span,
535 kind: "fn",
536 instance,
537 }),
538 MonoItem::Static(def_id) => tcx.dcx().emit_note(EncounteredErrorWhileInstantiating {
539 span: starting_item.span,
540 kind: "static",
541 instance: Instance::new_raw(def_id, GenericArgs::empty()),
542 }),
543 MonoItem::GlobalAsm(_) => {
544 tcx.dcx().emit_note(EncounteredErrorWhileInstantiatingGlobalAsm {
545 span: starting_item.span,
546 })
547 }
548 }
549 }
550 if mode == CollectionMode::UsedItems {
556 state.usage_map.lock_mut().record_used(starting_item.node, &used_items);
557 }
558
559 {
560 let mut visited = OnceCell::default();
561 if mode == CollectionMode::UsedItems {
562 used_items
563 .items
564 .retain(|k, _| visited.get_mut_or_init(|| state.visited.lock_mut()).insert(*k));
565 }
566
567 let mut mentioned = OnceCell::default();
568 mentioned_items.items.retain(|k, _| {
569 !visited.get_or_init(|| state.visited.lock()).contains(k)
570 && mentioned.get_mut_or_init(|| state.mentioned.lock_mut()).insert(*k)
571 });
572 }
573 if mode == CollectionMode::MentionedItems {
574 assert!(used_items.is_empty(), "'mentioned' collection should never encounter used items");
575 } else {
576 for used_item in used_items {
577 collect_items_rec(
578 tcx,
579 used_item,
580 state,
581 recursion_depths,
582 recursion_limit,
583 CollectionMode::UsedItems,
584 );
585 }
586 }
587
588 for mentioned_item in mentioned_items {
591 collect_items_rec(
592 tcx,
593 mentioned_item,
594 state,
595 recursion_depths,
596 recursion_limit,
597 CollectionMode::MentionedItems,
598 );
599 }
600
601 if let Some((def_id, depth)) = recursion_depth_reset {
602 recursion_depths.insert(def_id, depth);
603 }
604}
605
606fn check_recursion_limit<'tcx>(
607 tcx: TyCtxt<'tcx>,
608 instance: Instance<'tcx>,
609 span: Span,
610 recursion_depths: &mut DefIdMap<usize>,
611 recursion_limit: Limit,
612) -> (DefId, usize) {
613 let def_id = instance.def_id();
614 let recursion_depth = recursion_depths.get(&def_id).cloned().unwrap_or(0);
615 debug!(" => recursion depth={}", recursion_depth);
616
617 let adjusted_recursion_depth = if tcx.is_lang_item(def_id, LangItem::DropInPlace) {
618 recursion_depth / 4
621 } else {
622 recursion_depth
623 };
624
625 if !recursion_limit.value_within_limit(adjusted_recursion_depth) {
629 let def_span = tcx.def_span(def_id);
630 let def_path_str = tcx.def_path_str(def_id);
631 tcx.dcx().emit_fatal(RecursionLimit { span, instance, def_span, def_path_str });
632 }
633
634 recursion_depths.insert(def_id, recursion_depth + 1);
635
636 (def_id, recursion_depth)
637}
638
639struct MirUsedCollector<'a, 'tcx> {
640 tcx: TyCtxt<'tcx>,
641 body: &'a mir::Body<'tcx>,
642 used_items: &'a mut MonoItems<'tcx>,
643 used_mentioned_items: &'a mut UnordSet<MentionedItem<'tcx>>,
646 instance: Instance<'tcx>,
647}
648
649impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
650 fn monomorphize<T>(&self, value: T) -> T
651 where
652 T: TypeFoldable<TyCtxt<'tcx>>,
653 {
654 trace!("monomorphize: self.instance={:?}", self.instance);
655 self.instance.instantiate_mir_and_normalize_erasing_regions(
656 self.tcx,
657 ty::TypingEnv::fully_monomorphized(),
658 ty::EarlyBinder::bind(value),
659 )
660 }
661
662 fn eval_constant(&mut self, constant: &mir::ConstOperand<'tcx>) -> Option<mir::ConstValue> {
664 let const_ = self.monomorphize(constant.const_);
665 match const_.eval(self.tcx, ty::TypingEnv::fully_monomorphized(), constant.span) {
670 Ok(v) => Some(v),
671 Err(ErrorHandled::TooGeneric(..)) => span_bug!(
672 constant.span,
673 "collection encountered polymorphic constant: {:?}",
674 const_
675 ),
676 Err(err @ ErrorHandled::Reported(..)) => {
677 err.emit_note(self.tcx);
678 return None;
679 }
680 }
681 }
682}
683
684impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
685 fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
686 debug!("visiting rvalue {:?}", *rvalue);
687
688 let span = self.body.source_info(location).span;
689
690 match *rvalue {
691 mir::Rvalue::Cast(
695 mir::CastKind::PointerCoercion(PointerCoercion::Unsize, _),
696 ref operand,
697 target_ty,
698 ) => {
699 let source_ty = operand.ty(self.body, self.tcx);
700 self.used_mentioned_items
702 .insert(MentionedItem::UnsizeCast { source_ty, target_ty });
703 let target_ty = self.monomorphize(target_ty);
704 let source_ty = self.monomorphize(source_ty);
705 let (source_ty, target_ty) =
706 find_tails_for_unsizing(self.tcx.at(span), source_ty, target_ty);
707 if target_ty.is_trait() && !source_ty.is_trait() {
711 create_mono_items_for_vtable_methods(
712 self.tcx,
713 target_ty,
714 source_ty,
715 span,
716 self.used_items,
717 );
718 }
719 }
720 mir::Rvalue::Cast(
721 mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, _),
722 ref operand,
723 _,
724 ) => {
725 let fn_ty = operand.ty(self.body, self.tcx);
726 self.used_mentioned_items.insert(MentionedItem::Fn(fn_ty));
728 let fn_ty = self.monomorphize(fn_ty);
729 visit_fn_use(self.tcx, fn_ty, false, span, self.used_items);
730 }
731 mir::Rvalue::Cast(
732 mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_), _),
733 ref operand,
734 _,
735 ) => {
736 let source_ty = operand.ty(self.body, self.tcx);
737 self.used_mentioned_items.insert(MentionedItem::Closure(source_ty));
739 let source_ty = self.monomorphize(source_ty);
740 if let ty::Closure(def_id, args) = *source_ty.kind() {
741 let instance =
742 Instance::resolve_closure(self.tcx, def_id, args, ty::ClosureKind::FnOnce);
743 if self.tcx.should_codegen_locally(instance) {
744 self.used_items.push(create_fn_mono_item(self.tcx, instance, span));
745 }
746 } else {
747 bug!()
748 }
749 }
750 mir::Rvalue::ThreadLocalRef(def_id) => {
751 assert!(self.tcx.is_thread_local_static(def_id));
752 let instance = Instance::mono(self.tcx, def_id);
753 if self.tcx.should_codegen_locally(instance) {
754 trace!("collecting thread-local static {:?}", def_id);
755 self.used_items.push(respan(span, MonoItem::Static(def_id)));
756 }
757 }
758 _ => { }
759 }
760
761 self.super_rvalue(rvalue, location);
762 }
763
764 #[instrument(skip(self), level = "debug")]
767 fn visit_const_operand(&mut self, constant: &mir::ConstOperand<'tcx>, _location: Location) {
768 let Some(val) = self.eval_constant(constant) else { return };
770 collect_const_value(self.tcx, val, self.used_items);
771 }
772
773 fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, location: Location) {
774 debug!("visiting terminator {:?} @ {:?}", terminator, location);
775 let source = self.body.source_info(location).span;
776
777 let tcx = self.tcx;
778 let push_mono_lang_item = |this: &mut Self, lang_item: LangItem| {
779 let instance = Instance::mono(tcx, tcx.require_lang_item(lang_item, source));
780 if tcx.should_codegen_locally(instance) {
781 this.used_items.push(create_fn_mono_item(tcx, instance, source));
782 }
783 };
784
785 match terminator.kind {
786 mir::TerminatorKind::Call { ref func, .. }
787 | mir::TerminatorKind::TailCall { ref func, .. } => {
788 let callee_ty = func.ty(self.body, tcx);
789 self.used_mentioned_items.insert(MentionedItem::Fn(callee_ty));
791 let callee_ty = self.monomorphize(callee_ty);
792
793 let force_indirect_call =
798 if matches!(terminator.kind, mir::TerminatorKind::TailCall { .. })
799 && let &ty::FnDef(def_id, args) = callee_ty.kind()
800 && let instance = ty::Instance::expect_resolve(
801 self.tcx,
802 ty::TypingEnv::fully_monomorphized(),
803 def_id,
804 args,
805 source,
806 )
807 && instance.def.requires_caller_location(self.tcx)
808 {
809 true
810 } else {
811 false
812 };
813
814 visit_fn_use(
815 self.tcx,
816 callee_ty,
817 !force_indirect_call,
818 source,
819 &mut self.used_items,
820 )
821 }
822 mir::TerminatorKind::Drop { ref place, .. } => {
823 let ty = place.ty(self.body, self.tcx).ty;
824 self.used_mentioned_items.insert(MentionedItem::Drop(ty));
826 let ty = self.monomorphize(ty);
827 visit_drop_use(self.tcx, ty, true, source, self.used_items);
828 }
829 mir::TerminatorKind::InlineAsm { ref operands, .. } => {
830 for op in operands {
831 match *op {
832 mir::InlineAsmOperand::SymFn { ref value } => {
833 let fn_ty = value.const_.ty();
834 self.used_mentioned_items.insert(MentionedItem::Fn(fn_ty));
836 let fn_ty = self.monomorphize(fn_ty);
837 visit_fn_use(self.tcx, fn_ty, false, source, self.used_items);
838 }
839 mir::InlineAsmOperand::SymStatic { def_id } => {
840 let instance = Instance::mono(self.tcx, def_id);
841 if self.tcx.should_codegen_locally(instance) {
842 trace!("collecting asm sym static {:?}", def_id);
843 self.used_items.push(respan(source, MonoItem::Static(def_id)));
844 }
845 }
846 _ => {}
847 }
848 }
849 }
850 mir::TerminatorKind::Assert { ref msg, .. } => match &**msg {
851 mir::AssertKind::BoundsCheck { .. } => {
852 push_mono_lang_item(self, LangItem::PanicBoundsCheck);
853 }
854 mir::AssertKind::MisalignedPointerDereference { .. } => {
855 push_mono_lang_item(self, LangItem::PanicMisalignedPointerDereference);
856 }
857 mir::AssertKind::NullPointerDereference => {
858 push_mono_lang_item(self, LangItem::PanicNullPointerDereference);
859 }
860 mir::AssertKind::InvalidEnumConstruction(_) => {
861 push_mono_lang_item(self, LangItem::PanicInvalidEnumConstruction);
862 }
863 _ => {
864 push_mono_lang_item(self, msg.panic_function());
865 }
866 },
867 mir::TerminatorKind::UnwindTerminate(reason) => {
868 push_mono_lang_item(self, reason.lang_item());
869 }
870 mir::TerminatorKind::Goto { .. }
871 | mir::TerminatorKind::SwitchInt { .. }
872 | mir::TerminatorKind::UnwindResume
873 | mir::TerminatorKind::Return
874 | mir::TerminatorKind::Unreachable => {}
875 mir::TerminatorKind::CoroutineDrop
876 | mir::TerminatorKind::Yield { .. }
877 | mir::TerminatorKind::FalseEdge { .. }
878 | mir::TerminatorKind::FalseUnwind { .. } => bug!(),
879 }
880
881 if let Some(mir::UnwindAction::Terminate(reason)) = terminator.unwind() {
882 push_mono_lang_item(self, reason.lang_item());
883 }
884
885 self.super_terminator(terminator, location);
886 }
887}
888
889fn visit_drop_use<'tcx>(
890 tcx: TyCtxt<'tcx>,
891 ty: Ty<'tcx>,
892 is_direct_call: bool,
893 source: Span,
894 output: &mut MonoItems<'tcx>,
895) {
896 let instance = Instance::resolve_drop_in_place(tcx, ty);
897 visit_instance_use(tcx, instance, is_direct_call, source, output);
898}
899
900fn visit_fn_use<'tcx>(
903 tcx: TyCtxt<'tcx>,
904 ty: Ty<'tcx>,
905 is_direct_call: bool,
906 source: Span,
907 output: &mut MonoItems<'tcx>,
908) {
909 if let ty::FnDef(def_id, args) = *ty.kind() {
910 let instance = if is_direct_call {
911 ty::Instance::expect_resolve(
912 tcx,
913 ty::TypingEnv::fully_monomorphized(),
914 def_id,
915 args,
916 source,
917 )
918 } else {
919 match ty::Instance::resolve_for_fn_ptr(
920 tcx,
921 ty::TypingEnv::fully_monomorphized(),
922 def_id,
923 args,
924 ) {
925 Some(instance) => instance,
926 _ => bug!("failed to resolve instance for {ty}"),
927 }
928 };
929 visit_instance_use(tcx, instance, is_direct_call, source, output);
930 }
931}
932
933fn visit_instance_use<'tcx>(
934 tcx: TyCtxt<'tcx>,
935 instance: ty::Instance<'tcx>,
936 is_direct_call: bool,
937 source: Span,
938 output: &mut MonoItems<'tcx>,
939) {
940 debug!("visit_item_use({:?}, is_direct_call={:?})", instance, is_direct_call);
941 if !tcx.should_codegen_locally(instance) {
942 return;
943 }
944 if let Some(intrinsic) = tcx.intrinsic(instance.def_id()) {
945 collect_autodiff_fn(tcx, instance, intrinsic, output);
946
947 if let Some(_requirement) = ValidityRequirement::from_intrinsic(intrinsic.name) {
948 let def_id = tcx.require_lang_item(LangItem::PanicNounwind, source);
953 let panic_instance = Instance::mono(tcx, def_id);
954 if tcx.should_codegen_locally(panic_instance) {
955 output.push(create_fn_mono_item(tcx, panic_instance, source));
956 }
957 } else if !intrinsic.must_be_overridden {
958 let instance = ty::Instance::new_raw(instance.def_id(), instance.args);
963 if tcx.should_codegen_locally(instance) {
964 output.push(create_fn_mono_item(tcx, instance, source));
965 }
966 }
967 }
968
969 match instance.def {
970 ty::InstanceKind::Virtual(..) | ty::InstanceKind::Intrinsic(_) => {
971 if !is_direct_call {
972 bug!("{:?} being reified", instance);
973 }
974 }
975 ty::InstanceKind::ThreadLocalShim(..) => {
976 bug!("{:?} being reified", instance);
977 }
978 ty::InstanceKind::DropGlue(_, None) => {
979 if !is_direct_call {
984 output.push(create_fn_mono_item(tcx, instance, source));
985 }
986 }
987 ty::InstanceKind::DropGlue(_, Some(_))
988 | ty::InstanceKind::FutureDropPollShim(..)
989 | ty::InstanceKind::AsyncDropGlue(_, _)
990 | ty::InstanceKind::AsyncDropGlueCtorShim(_, _)
991 | ty::InstanceKind::VTableShim(..)
992 | ty::InstanceKind::ReifyShim(..)
993 | ty::InstanceKind::ClosureOnceShim { .. }
994 | ty::InstanceKind::ConstructCoroutineInClosureShim { .. }
995 | ty::InstanceKind::Item(..)
996 | ty::InstanceKind::FnPtrShim(..)
997 | ty::InstanceKind::CloneShim(..)
998 | ty::InstanceKind::FnPtrAddrShim(..) => {
999 output.push(create_fn_mono_item(tcx, instance, source));
1000 }
1001 }
1002}
1003
1004fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> bool {
1007 let Some(def_id) = instance.def.def_id_if_not_guaranteed_local_codegen() else {
1008 return true;
1009 };
1010
1011 if tcx.is_foreign_item(def_id) {
1012 return false;
1014 }
1015
1016 if tcx.def_kind(def_id).has_codegen_attrs()
1017 && matches!(tcx.codegen_fn_attrs(def_id).inline, InlineAttr::Force { .. })
1018 {
1019 tcx.dcx().delayed_bug("attempt to codegen `#[rustc_force_inline]` item");
1022 }
1023
1024 if def_id.is_local() {
1025 return true;
1027 }
1028
1029 if tcx.is_reachable_non_generic(def_id) || instance.upstream_monomorphization(tcx).is_some() {
1030 return false;
1032 }
1033
1034 if let DefKind::Static { .. } = tcx.def_kind(def_id) {
1035 return false;
1037 }
1038
1039 if !tcx.is_mir_available(def_id) {
1040 tcx.dcx().emit_fatal(NoOptimizedMir {
1041 span: tcx.def_span(def_id),
1042 crate_name: tcx.crate_name(def_id.krate),
1043 instance: instance.to_string(),
1044 });
1045 }
1046
1047 true
1048}
1049
1050fn find_tails_for_unsizing<'tcx>(
1092 tcx: TyCtxtAt<'tcx>,
1093 source_ty: Ty<'tcx>,
1094 target_ty: Ty<'tcx>,
1095) -> (Ty<'tcx>, Ty<'tcx>) {
1096 let typing_env = ty::TypingEnv::fully_monomorphized();
1097 debug_assert!(!source_ty.has_param(), "{source_ty} should be fully monomorphic");
1098 debug_assert!(!target_ty.has_param(), "{target_ty} should be fully monomorphic");
1099
1100 match (source_ty.kind(), target_ty.kind()) {
1101 (
1102 &ty::Ref(_, source_pointee, _),
1103 &ty::Ref(_, target_pointee, _) | &ty::RawPtr(target_pointee, _),
1104 )
1105 | (&ty::RawPtr(source_pointee, _), &ty::RawPtr(target_pointee, _)) => {
1106 tcx.struct_lockstep_tails_for_codegen(source_pointee, target_pointee, typing_env)
1107 }
1108
1109 (_, _)
1112 if let Some(source_boxed) = source_ty.boxed_ty()
1113 && let Some(target_boxed) = target_ty.boxed_ty() =>
1114 {
1115 tcx.struct_lockstep_tails_for_codegen(source_boxed, target_boxed, typing_env)
1116 }
1117
1118 (&ty::Adt(source_adt_def, source_args), &ty::Adt(target_adt_def, target_args)) => {
1119 assert_eq!(source_adt_def, target_adt_def);
1120 let CustomCoerceUnsized::Struct(coerce_index) =
1121 match crate::custom_coerce_unsize_info(tcx, source_ty, target_ty) {
1122 Ok(ccu) => ccu,
1123 Err(e) => {
1124 let e = Ty::new_error(tcx.tcx, e);
1125 return (e, e);
1126 }
1127 };
1128 let coerce_field = &source_adt_def.non_enum_variant().fields[coerce_index];
1129 let source_field =
1131 tcx.normalize_erasing_regions(typing_env, coerce_field.ty(*tcx, source_args));
1132 let target_field =
1133 tcx.normalize_erasing_regions(typing_env, coerce_field.ty(*tcx, target_args));
1134 find_tails_for_unsizing(tcx, source_field, target_field)
1135 }
1136
1137 _ => bug!(
1138 "find_vtable_types_for_unsizing: invalid coercion {:?} -> {:?}",
1139 source_ty,
1140 target_ty
1141 ),
1142 }
1143}
1144
1145#[instrument(skip(tcx), level = "debug", ret)]
1146fn create_fn_mono_item<'tcx>(
1147 tcx: TyCtxt<'tcx>,
1148 instance: Instance<'tcx>,
1149 source: Span,
1150) -> Spanned<MonoItem<'tcx>> {
1151 let def_id = instance.def_id();
1152 if tcx.sess.opts.unstable_opts.profile_closures
1153 && def_id.is_local()
1154 && tcx.is_closure_like(def_id)
1155 {
1156 crate::util::dump_closure_profile(tcx, instance);
1157 }
1158
1159 respan(source, MonoItem::Fn(instance))
1160}
1161
1162fn create_mono_items_for_vtable_methods<'tcx>(
1165 tcx: TyCtxt<'tcx>,
1166 trait_ty: Ty<'tcx>,
1167 impl_ty: Ty<'tcx>,
1168 source: Span,
1169 output: &mut MonoItems<'tcx>,
1170) {
1171 assert!(!trait_ty.has_escaping_bound_vars() && !impl_ty.has_escaping_bound_vars());
1172
1173 let ty::Dynamic(trait_ty, ..) = trait_ty.kind() else {
1174 bug!("create_mono_items_for_vtable_methods: {trait_ty:?} not a trait type");
1175 };
1176 if let Some(principal) = trait_ty.principal() {
1177 let trait_ref =
1178 tcx.instantiate_bound_regions_with_erased(principal.with_self_ty(tcx, impl_ty));
1179 assert!(!trait_ref.has_escaping_bound_vars());
1180
1181 let entries = tcx.vtable_entries(trait_ref);
1183 debug!(?entries);
1184 let methods = entries
1185 .iter()
1186 .filter_map(|entry| match entry {
1187 VtblEntry::MetadataDropInPlace
1188 | VtblEntry::MetadataSize
1189 | VtblEntry::MetadataAlign
1190 | VtblEntry::Vacant => None,
1191 VtblEntry::TraitVPtr(_) => {
1192 None
1194 }
1195 VtblEntry::Method(instance) => {
1196 Some(*instance).filter(|instance| tcx.should_codegen_locally(*instance))
1197 }
1198 })
1199 .map(|item| create_fn_mono_item(tcx, item, source));
1200 output.extend(methods);
1201 }
1202
1203 if impl_ty.needs_drop(tcx, ty::TypingEnv::fully_monomorphized()) {
1208 visit_drop_use(tcx, impl_ty, false, source, output);
1209 }
1210}
1211
1212fn collect_alloc<'tcx>(tcx: TyCtxt<'tcx>, alloc_id: AllocId, output: &mut MonoItems<'tcx>) {
1214 match tcx.global_alloc(alloc_id) {
1215 GlobalAlloc::Static(def_id) => {
1216 assert!(!tcx.is_thread_local_static(def_id));
1217 let instance = Instance::mono(tcx, def_id);
1218 if tcx.should_codegen_locally(instance) {
1219 trace!("collecting static {:?}", def_id);
1220 output.push(dummy_spanned(MonoItem::Static(def_id)));
1221 }
1222 }
1223 GlobalAlloc::Memory(alloc) => {
1224 trace!("collecting {:?} with {:#?}", alloc_id, alloc);
1225 let ptrs = alloc.inner().provenance().ptrs();
1226 if !ptrs.is_empty() {
1228 rustc_data_structures::stack::ensure_sufficient_stack(move || {
1229 for &prov in ptrs.values() {
1230 collect_alloc(tcx, prov.alloc_id(), output);
1231 }
1232 });
1233 }
1234 }
1235 GlobalAlloc::Function { instance, .. } => {
1236 if tcx.should_codegen_locally(instance) {
1237 trace!("collecting {:?} with {:#?}", alloc_id, instance);
1238 output.push(create_fn_mono_item(tcx, instance, DUMMY_SP));
1239 }
1240 }
1241 GlobalAlloc::VTable(ty, dyn_ty) => {
1242 let alloc_id = tcx.vtable_allocation((
1243 ty,
1244 dyn_ty
1245 .principal()
1246 .map(|principal| tcx.instantiate_bound_regions_with_erased(principal)),
1247 ));
1248 collect_alloc(tcx, alloc_id, output)
1249 }
1250 GlobalAlloc::TypeId { .. } => {}
1251 }
1252}
1253
1254#[instrument(skip(tcx), level = "debug")]
1258fn collect_items_of_instance<'tcx>(
1259 tcx: TyCtxt<'tcx>,
1260 instance: Instance<'tcx>,
1261 mode: CollectionMode,
1262) -> (MonoItems<'tcx>, MonoItems<'tcx>) {
1263 tcx.ensure_ok().check_mono_item(instance);
1265
1266 let body = tcx.instance_mir(instance.def);
1267 let mut used_items = MonoItems::new();
1278 let mut mentioned_items = MonoItems::new();
1279 let mut used_mentioned_items = Default::default();
1280 let mut collector = MirUsedCollector {
1281 tcx,
1282 body,
1283 used_items: &mut used_items,
1284 used_mentioned_items: &mut used_mentioned_items,
1285 instance,
1286 };
1287
1288 if mode == CollectionMode::UsedItems {
1289 if tcx.sess.opts.debuginfo == DebugInfo::Full {
1290 for var_debug_info in &body.var_debug_info {
1291 collector.visit_var_debug_info(var_debug_info);
1292 }
1293 }
1294 for (bb, data) in traversal::mono_reachable(body, tcx, instance) {
1295 collector.visit_basic_block_data(bb, data)
1296 }
1297 }
1298
1299 for const_op in body.required_consts() {
1302 if let Some(val) = collector.eval_constant(const_op) {
1303 collect_const_value(tcx, val, &mut mentioned_items);
1304 }
1305 }
1306
1307 for item in body.mentioned_items() {
1310 if !collector.used_mentioned_items.contains(&item.node) {
1311 let item_mono = collector.monomorphize(item.node);
1312 visit_mentioned_item(tcx, &item_mono, item.span, &mut mentioned_items);
1313 }
1314 }
1315
1316 (used_items, mentioned_items)
1317}
1318
1319fn items_of_instance<'tcx>(
1320 tcx: TyCtxt<'tcx>,
1321 (instance, mode): (Instance<'tcx>, CollectionMode),
1322) -> (&'tcx [Spanned<MonoItem<'tcx>>], &'tcx [Spanned<MonoItem<'tcx>>]) {
1323 let (used_items, mentioned_items) = collect_items_of_instance(tcx, instance, mode);
1324
1325 let used_items = tcx.arena.alloc_from_iter(used_items);
1326 let mentioned_items = tcx.arena.alloc_from_iter(mentioned_items);
1327
1328 (used_items, mentioned_items)
1329}
1330
1331#[instrument(skip(tcx, span, output), level = "debug")]
1333fn visit_mentioned_item<'tcx>(
1334 tcx: TyCtxt<'tcx>,
1335 item: &MentionedItem<'tcx>,
1336 span: Span,
1337 output: &mut MonoItems<'tcx>,
1338) {
1339 match *item {
1340 MentionedItem::Fn(ty) => {
1341 if let ty::FnDef(def_id, args) = *ty.kind() {
1342 let instance = Instance::expect_resolve(
1343 tcx,
1344 ty::TypingEnv::fully_monomorphized(),
1345 def_id,
1346 args,
1347 span,
1348 );
1349 visit_instance_use(tcx, instance, true, span, output);
1354 }
1355 }
1356 MentionedItem::Drop(ty) => {
1357 visit_drop_use(tcx, ty, true, span, output);
1358 }
1359 MentionedItem::UnsizeCast { source_ty, target_ty } => {
1360 let (source_ty, target_ty) =
1361 find_tails_for_unsizing(tcx.at(span), source_ty, target_ty);
1362 if target_ty.is_trait() && !source_ty.is_trait() {
1366 create_mono_items_for_vtable_methods(tcx, target_ty, source_ty, span, output);
1367 }
1368 }
1369 MentionedItem::Closure(source_ty) => {
1370 if let ty::Closure(def_id, args) = *source_ty.kind() {
1371 let instance =
1372 Instance::resolve_closure(tcx, def_id, args, ty::ClosureKind::FnOnce);
1373 if tcx.should_codegen_locally(instance) {
1374 output.push(create_fn_mono_item(tcx, instance, span));
1375 }
1376 } else {
1377 bug!()
1378 }
1379 }
1380 }
1381}
1382
1383#[instrument(skip(tcx, output), level = "debug")]
1384fn collect_const_value<'tcx>(
1385 tcx: TyCtxt<'tcx>,
1386 value: mir::ConstValue,
1387 output: &mut MonoItems<'tcx>,
1388) {
1389 match value {
1390 mir::ConstValue::Scalar(Scalar::Ptr(ptr, _size)) => {
1391 collect_alloc(tcx, ptr.provenance.alloc_id(), output)
1392 }
1393 mir::ConstValue::Indirect { alloc_id, .. }
1394 | mir::ConstValue::Slice { alloc_id, meta: _ } => collect_alloc(tcx, alloc_id, output),
1395 _ => {}
1396 }
1397}
1398
1399#[instrument(skip(tcx, mode), level = "debug")]
1406fn collect_roots(tcx: TyCtxt<'_>, mode: MonoItemCollectionStrategy) -> Vec<MonoItem<'_>> {
1407 debug!("collecting roots");
1408 let mut roots = MonoItems::new();
1409
1410 {
1411 let entry_fn = tcx.entry_fn(());
1412
1413 debug!("collect_roots: entry_fn = {:?}", entry_fn);
1414
1415 let mut collector = RootCollector { tcx, strategy: mode, entry_fn, output: &mut roots };
1416
1417 let crate_items = tcx.hir_crate_items(());
1418
1419 for id in crate_items.free_items() {
1420 collector.process_item(id);
1421 }
1422
1423 for id in crate_items.impl_items() {
1424 collector.process_impl_item(id);
1425 }
1426
1427 for id in crate_items.nested_bodies() {
1428 collector.process_nested_body(id);
1429 }
1430
1431 collector.push_extra_entry_roots();
1432 }
1433
1434 roots
1438 .into_iter()
1439 .filter_map(|Spanned { node: mono_item, .. }| {
1440 mono_item.is_instantiable(tcx).then_some(mono_item)
1441 })
1442 .collect()
1443}
1444
1445struct RootCollector<'a, 'tcx> {
1446 tcx: TyCtxt<'tcx>,
1447 strategy: MonoItemCollectionStrategy,
1448 output: &'a mut MonoItems<'tcx>,
1449 entry_fn: Option<(DefId, EntryFnType)>,
1450}
1451
1452impl<'v> RootCollector<'_, 'v> {
1453 fn process_item(&mut self, id: hir::ItemId) {
1454 match self.tcx.def_kind(id.owner_id) {
1455 DefKind::Enum | DefKind::Struct | DefKind::Union => {
1456 if self.strategy == MonoItemCollectionStrategy::Eager
1457 && !self.tcx.generics_of(id.owner_id).requires_monomorphization(self.tcx)
1458 {
1459 debug!("RootCollector: ADT drop-glue for `{id:?}`",);
1460 let id_args =
1461 ty::GenericArgs::for_item(self.tcx, id.owner_id.to_def_id(), |param, _| {
1462 match param.kind {
1463 GenericParamDefKind::Lifetime => {
1464 self.tcx.lifetimes.re_erased.into()
1465 }
1466 GenericParamDefKind::Type { .. }
1467 | GenericParamDefKind::Const { .. } => {
1468 unreachable!(
1469 "`own_requires_monomorphization` check means that \
1470 we should have no type/const params"
1471 )
1472 }
1473 }
1474 });
1475
1476 if self.tcx.instantiate_and_check_impossible_predicates((
1479 id.owner_id.to_def_id(),
1480 id_args,
1481 )) {
1482 return;
1483 }
1484
1485 let ty =
1486 self.tcx.type_of(id.owner_id.to_def_id()).instantiate(self.tcx, id_args);
1487 assert!(!ty.has_non_region_param());
1488 visit_drop_use(self.tcx, ty, true, DUMMY_SP, self.output);
1489 }
1490 }
1491 DefKind::GlobalAsm => {
1492 debug!(
1493 "RootCollector: ItemKind::GlobalAsm({})",
1494 self.tcx.def_path_str(id.owner_id)
1495 );
1496 self.output.push(dummy_spanned(MonoItem::GlobalAsm(id)));
1497 }
1498 DefKind::Static { .. } => {
1499 let def_id = id.owner_id.to_def_id();
1500 debug!("RootCollector: ItemKind::Static({})", self.tcx.def_path_str(def_id));
1501 self.output.push(dummy_spanned(MonoItem::Static(def_id)));
1502 }
1503 DefKind::Const => {
1504 if self.strategy == MonoItemCollectionStrategy::Eager {
1510 if !self.tcx.generics_of(id.owner_id).own_requires_monomorphization()
1511 && let Ok(val) = self.tcx.const_eval_poly(id.owner_id.to_def_id())
1512 {
1513 collect_const_value(self.tcx, val, self.output);
1514 }
1515 }
1516 }
1517 DefKind::Impl { .. } => {
1518 if self.strategy == MonoItemCollectionStrategy::Eager {
1519 create_mono_items_for_default_impls(self.tcx, id, self.output);
1520 }
1521 }
1522 DefKind::Fn => {
1523 self.push_if_root(id.owner_id.def_id);
1524 }
1525 _ => {}
1526 }
1527 }
1528
1529 fn process_impl_item(&mut self, id: hir::ImplItemId) {
1530 if matches!(self.tcx.def_kind(id.owner_id), DefKind::AssocFn) {
1531 self.push_if_root(id.owner_id.def_id);
1532 }
1533 }
1534
1535 fn process_nested_body(&mut self, def_id: LocalDefId) {
1536 match self.tcx.def_kind(def_id) {
1537 DefKind::Closure => {
1538 let is_pub_fn_coroutine =
1540 match *self.tcx.type_of(def_id).instantiate_identity().kind() {
1541 ty::Coroutine(cor_id, _args) => {
1542 let tcx = self.tcx;
1543 let parent_id = tcx.parent(cor_id);
1544 tcx.def_kind(parent_id) == DefKind::Fn
1545 && tcx.asyncness(parent_id).is_async()
1546 && tcx.visibility(parent_id).is_public()
1547 }
1548 ty::Closure(..) | ty::CoroutineClosure(..) => false,
1549 _ => unreachable!(),
1550 };
1551 if (self.strategy == MonoItemCollectionStrategy::Eager || is_pub_fn_coroutine)
1552 && !self
1553 .tcx
1554 .generics_of(self.tcx.typeck_root_def_id(def_id.to_def_id()))
1555 .requires_monomorphization(self.tcx)
1556 {
1557 let instance = match *self.tcx.type_of(def_id).instantiate_identity().kind() {
1558 ty::Closure(def_id, args)
1559 | ty::Coroutine(def_id, args)
1560 | ty::CoroutineClosure(def_id, args) => {
1561 Instance::new_raw(def_id, self.tcx.erase_and_anonymize_regions(args))
1562 }
1563 _ => unreachable!(),
1564 };
1565 let Ok(instance) = self.tcx.try_normalize_erasing_regions(
1566 ty::TypingEnv::fully_monomorphized(),
1567 instance,
1568 ) else {
1569 return;
1571 };
1572 let mono_item = create_fn_mono_item(self.tcx, instance, DUMMY_SP);
1573 if mono_item.node.is_instantiable(self.tcx) {
1574 self.output.push(mono_item);
1575 }
1576 }
1577 }
1578 _ => {}
1579 }
1580 }
1581
1582 fn is_root(&self, def_id: LocalDefId) -> bool {
1583 !self.tcx.generics_of(def_id).requires_monomorphization(self.tcx)
1584 && match self.strategy {
1585 MonoItemCollectionStrategy::Eager => {
1586 !matches!(self.tcx.codegen_fn_attrs(def_id).inline, InlineAttr::Force { .. })
1587 }
1588 MonoItemCollectionStrategy::Lazy => {
1589 self.entry_fn.and_then(|(id, _)| id.as_local()) == Some(def_id)
1590 || self.tcx.is_reachable_non_generic(def_id)
1591 || self
1592 .tcx
1593 .codegen_fn_attrs(def_id)
1594 .flags
1595 .contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
1596 }
1597 }
1598 }
1599
1600 #[instrument(skip(self), level = "debug")]
1603 fn push_if_root(&mut self, def_id: LocalDefId) {
1604 if self.is_root(def_id) {
1605 debug!("found root");
1606
1607 let instance = Instance::mono(self.tcx, def_id.to_def_id());
1608 self.output.push(create_fn_mono_item(self.tcx, instance, DUMMY_SP));
1609 }
1610 }
1611
1612 fn push_extra_entry_roots(&mut self) {
1618 let Some((main_def_id, EntryFnType::Main { .. })) = self.entry_fn else {
1619 return;
1620 };
1621
1622 let main_instance = Instance::mono(self.tcx, main_def_id);
1623 if self.tcx.should_codegen_locally(main_instance) {
1624 self.output.push(create_fn_mono_item(
1625 self.tcx,
1626 main_instance,
1627 self.tcx.def_span(main_def_id),
1628 ));
1629 }
1630
1631 let Some(start_def_id) = self.tcx.lang_items().start_fn() else {
1632 self.tcx.dcx().emit_fatal(errors::StartNotFound);
1633 };
1634 let main_ret_ty = self.tcx.fn_sig(main_def_id).no_bound_vars().unwrap().output();
1635
1636 let main_ret_ty = self.tcx.normalize_erasing_regions(
1642 ty::TypingEnv::fully_monomorphized(),
1643 main_ret_ty.no_bound_vars().unwrap(),
1644 );
1645
1646 let start_instance = Instance::expect_resolve(
1647 self.tcx,
1648 ty::TypingEnv::fully_monomorphized(),
1649 start_def_id,
1650 self.tcx.mk_args(&[main_ret_ty.into()]),
1651 DUMMY_SP,
1652 );
1653
1654 self.output.push(create_fn_mono_item(self.tcx, start_instance, DUMMY_SP));
1655 }
1656}
1657
1658#[instrument(level = "debug", skip(tcx, output))]
1659fn create_mono_items_for_default_impls<'tcx>(
1660 tcx: TyCtxt<'tcx>,
1661 item: hir::ItemId,
1662 output: &mut MonoItems<'tcx>,
1663) {
1664 let Some(impl_) = tcx.impl_trait_header(item.owner_id) else {
1665 return;
1666 };
1667
1668 if matches!(impl_.polarity, ty::ImplPolarity::Negative) {
1669 return;
1670 }
1671
1672 if tcx.generics_of(item.owner_id).own_requires_monomorphization() {
1673 return;
1674 }
1675
1676 let only_region_params = |param: &ty::GenericParamDef, _: &_| match param.kind {
1682 GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(),
1683 GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
1684 unreachable!(
1685 "`own_requires_monomorphization` check means that \
1686 we should have no type/const params"
1687 )
1688 }
1689 };
1690 let impl_args = GenericArgs::for_item(tcx, item.owner_id.to_def_id(), only_region_params);
1691 let trait_ref = impl_.trait_ref.instantiate(tcx, impl_args);
1692
1693 if tcx.instantiate_and_check_impossible_predicates((item.owner_id.to_def_id(), impl_args)) {
1703 return;
1704 }
1705
1706 let typing_env = ty::TypingEnv::fully_monomorphized();
1707 let trait_ref = tcx.normalize_erasing_regions(typing_env, trait_ref);
1708 let overridden_methods = tcx.impl_item_implementor_ids(item.owner_id);
1709 for method in tcx.provided_trait_methods(trait_ref.def_id) {
1710 if overridden_methods.contains_key(&method.def_id) {
1711 continue;
1712 }
1713
1714 if tcx.generics_of(method.def_id).own_requires_monomorphization() {
1715 continue;
1716 }
1717
1718 let args = trait_ref.args.extend_to(tcx, method.def_id, only_region_params);
1722 let instance = ty::Instance::expect_resolve(tcx, typing_env, method.def_id, args, DUMMY_SP);
1723
1724 let mono_item = create_fn_mono_item(tcx, instance, DUMMY_SP);
1725 if mono_item.node.is_instantiable(tcx) && tcx.should_codegen_locally(instance) {
1726 output.push(mono_item);
1727 }
1728 }
1729}
1730
1731#[instrument(skip(tcx, strategy), level = "debug")]
1736pub(crate) fn collect_crate_mono_items<'tcx>(
1737 tcx: TyCtxt<'tcx>,
1738 strategy: MonoItemCollectionStrategy,
1739) -> (Vec<MonoItem<'tcx>>, UsageMap<'tcx>) {
1740 let _prof_timer = tcx.prof.generic_activity("monomorphization_collector");
1741
1742 let roots = tcx
1743 .sess
1744 .time("monomorphization_collector_root_collections", || collect_roots(tcx, strategy));
1745
1746 debug!("building mono item graph, beginning at roots");
1747
1748 let state = SharedState {
1749 visited: MTLock::new(UnordSet::default()),
1750 mentioned: MTLock::new(UnordSet::default()),
1751 usage_map: MTLock::new(UsageMap::new()),
1752 };
1753 let recursion_limit = tcx.recursion_limit();
1754
1755 tcx.sess.time("monomorphization_collector_graph_walk", || {
1756 par_for_each_in(roots, |root| {
1757 collect_items_root(tcx, dummy_spanned(*root), &state, recursion_limit);
1758 });
1759 });
1760
1761 let mono_items = tcx.with_stable_hashing_context(move |ref hcx| {
1764 state.visited.into_inner().into_sorted(hcx, true)
1765 });
1766
1767 (mono_items, state.usage_map.into_inner())
1768}
1769
1770pub(crate) fn provide(providers: &mut Providers) {
1771 providers.hooks.should_codegen_locally = should_codegen_locally;
1772 providers.items_of_instance = items_of_instance;
1773}