1- use std:: cmp;
21use std:: collections:: BTreeSet ;
32use std:: sync:: Arc ;
43use std:: time:: { Duration , Instant } ;
4+ use std:: { cmp, iter} ;
55
66use itertools:: Itertools ;
77use rustc_abi:: FIRST_VARIANT ;
88use rustc_ast:: expand:: allocator:: {
99 ALLOC_ERROR_HANDLER , ALLOCATOR_METHODS , AllocatorKind , AllocatorMethod , AllocatorMethodInput ,
1010 AllocatorTy ,
1111} ;
12- use rustc_data_structures:: fx:: { FxHashMap , FxIndexSet } ;
12+ use rustc_data_structures:: fx:: { FxHashMap , FxIndexMap , FxIndexSet } ;
1313use rustc_data_structures:: profiling:: { get_resident_set_size, print_time_passes_entry} ;
1414use rustc_data_structures:: sync:: { IntoDynSyncSend , par_map} ;
1515use rustc_data_structures:: unord:: UnordMap ;
16- use rustc_hir:: attrs:: { DebuggerVisualizerType , OptimizeAttr } ;
17- use rustc_hir:: def_id:: { DefId , LOCAL_CRATE } ;
16+ use rustc_hir:: attrs:: { DebuggerVisualizerType , EiiDecl , EiiImpl , OptimizeAttr } ;
17+ use rustc_hir:: def_id:: { CrateNum , DefId , LOCAL_CRATE } ;
1818use rustc_hir:: lang_items:: LangItem ;
1919use rustc_hir:: { ItemId , Target , find_attr} ;
2020use rustc_middle:: middle:: codegen_fn_attrs:: CodegenFnAttrs ;
2121use rustc_middle:: middle:: debugger_visualizer:: DebuggerVisualizerFile ;
22- use rustc_middle:: middle:: dependency_format:: Dependencies ;
22+ use rustc_middle:: middle:: dependency_format:: { Dependencies , Linkage } ;
2323use rustc_middle:: middle:: exported_symbols:: { self , SymbolExportKind } ;
2424use rustc_middle:: middle:: lang_items;
2525use rustc_middle:: mir:: BinOp ;
@@ -49,7 +49,10 @@ use crate::meth::load_vtable;
4949use crate :: mir:: operand:: OperandValue ;
5050use crate :: mir:: place:: PlaceRef ;
5151use crate :: traits:: * ;
52- use crate :: { CachedModuleCodegen , CodegenLintLevels , CrateInfo , ModuleCodegen , errors, meth, mir} ;
52+ use crate :: {
53+ CachedModuleCodegen , CodegenLintLevels , CrateInfo , EiiLinkageImplInfo , EiiLinkageInfo ,
54+ ModuleCodegen , errors, meth, mir,
55+ } ;
5356
5457pub ( crate ) fn bin_op_to_icmp_predicate ( op : BinOp , signed : bool ) -> IntPredicate {
5558 match ( op, signed) {
@@ -895,6 +898,63 @@ pub fn is_call_from_compiler_builtins_to_upstream_monomorphization<'tcx>(
895898 && !tcx. should_codegen_locally ( instance)
896899}
897900
901+ fn collect_eii_linkage ( tcx : TyCtxt < ' _ > ) -> Vec < EiiLinkageInfo > {
902+ #[ derive( Debug ) ]
903+ struct FoundImpl {
904+ imp : EiiImpl ,
905+ impl_crate : CrateNum ,
906+ }
907+
908+ #[ derive( Debug ) ]
909+ struct FoundEii {
910+ decl : EiiDecl ,
911+ impls : FxIndexMap < DefId , FoundImpl > ,
912+ }
913+
914+ let mut eiis = FxIndexMap :: < DefId , FoundEii > :: default ( ) ;
915+
916+ for & cnum in tcx. crates ( ( ) ) . iter ( ) . chain ( iter:: once ( & LOCAL_CRATE ) ) {
917+ for ( did, ( decl, impls) ) in tcx. externally_implementable_items ( cnum) {
918+ eiis. entry ( * did)
919+ . or_insert_with ( || FoundEii { decl : * decl, impls : Default :: default ( ) } )
920+ . impls
921+ . extend (
922+ impls
923+ . into_iter ( )
924+ . map ( |( did, imp) | ( * did, FoundImpl { imp : * imp, impl_crate : cnum } ) ) ,
925+ ) ;
926+ }
927+ }
928+
929+ eiis. into_iter ( )
930+ . filter_map ( |( _, FoundEii { decl, impls } ) | {
931+ let explicit_impl_count = impls. values ( ) . filter ( |imp| !imp. imp . is_default ) . count ( ) ;
932+ let has_default_impl = impls. values ( ) . any ( |imp| imp. imp . is_default ) ;
933+ // Only this case needs the link-time check. Missing impls and
934+ // duplicate explicit impls are handled in `rustc_passes`.
935+ ( explicit_impl_count == 1 && has_default_impl) . then ( || EiiLinkageInfo {
936+ name : decl. name . name ,
937+ impls : impls
938+ . into_iter ( )
939+ . map ( |( impl_did, FoundImpl { imp, impl_crate } ) | EiiLinkageImplInfo {
940+ span : tcx. def_span ( impl_did) ,
941+ impl_crate,
942+ is_default : imp. is_default ,
943+ } )
944+ . collect ( ) ,
945+ } )
946+ } )
947+ . collect ( )
948+ }
949+
950+ fn eii_linkage_needed ( dependency_formats : & Dependencies ) -> bool {
951+ dependency_formats. values ( ) . any ( |formats| {
952+ formats
953+ . iter ( )
954+ . any ( |& linkage| matches ! ( linkage, Linkage :: Dynamic | Linkage :: IncludedFromDylib ) )
955+ } )
956+ }
957+
898958impl CrateInfo {
899959 pub fn new ( tcx : TyCtxt < ' _ > , target_cpu : String ) -> CrateInfo {
900960 let crate_types = tcx. crate_types ( ) . to_vec ( ) ;
@@ -906,6 +966,13 @@ impl CrateInfo {
906966 crate_types. iter ( ) . map ( |& c| ( c, crate :: back:: linker:: linked_symbols ( tcx, c) ) ) . collect ( ) ;
907967 let local_crate_name = tcx. crate_name ( LOCAL_CRATE ) ;
908968 let windows_subsystem = find_attr ! ( tcx, crate , WindowsSubsystem ( kind) => * kind) ;
969+ let dependency_formats = Arc :: clone ( tcx. dependency_formats ( ( ) ) ) ;
970+ let eii_linkage = if eii_linkage_needed ( & dependency_formats) {
971+ let eii_linkage = collect_eii_linkage ( tcx) ;
972+ ( !eii_linkage. is_empty ( ) ) . then_some ( eii_linkage)
973+ } else {
974+ None
975+ } ;
909976
910977 // This list is used when generating the command line to pass through to
911978 // system linker. The linker expects undefined symbols on the left of the
@@ -950,7 +1017,8 @@ impl CrateInfo {
9501017 crate_name : UnordMap :: with_capacity ( n_crates) ,
9511018 used_crates,
9521019 used_crate_source : UnordMap :: with_capacity ( n_crates) ,
953- dependency_formats : Arc :: clone ( tcx. dependency_formats ( ( ) ) ) ,
1020+ dependency_formats,
1021+ eii_linkage,
9541022 windows_subsystem,
9551023 natvis_debugger_visualizers : Default :: default ( ) ,
9561024 lint_levels : CodegenLintLevels :: from_tcx ( tcx) ,
0 commit comments