@@ -3,19 +3,20 @@ use std::str::FromStr;
3
3
use rustc_abi:: { Align , ExternAbi } ;
4
4
use rustc_ast:: expand:: autodiff_attrs:: { AutoDiffAttrs , DiffActivity , DiffMode } ;
5
5
use rustc_ast:: { LitKind , MetaItem , MetaItemInner , attr} ;
6
- use rustc_hir:: attrs:: { AttributeKind , InlineAttr , InstructionSetAttr , UsedBy } ;
6
+ use rustc_hir:: attrs:: { AttributeKind , InlineAttr , InstructionSetAttr , Linkage , UsedBy } ;
7
7
use rustc_hir:: def:: DefKind ;
8
8
use rustc_hir:: def_id:: { DefId , LOCAL_CRATE , LocalDefId } ;
9
9
use rustc_hir:: { self as hir, Attribute , LangItem , find_attr, lang_items} ;
10
10
use rustc_middle:: middle:: codegen_fn_attrs:: {
11
11
CodegenFnAttrFlags , CodegenFnAttrs , PatchableFunctionEntry ,
12
12
} ;
13
+ use rustc_middle:: mir:: mono:: Visibility ;
13
14
use rustc_middle:: query:: Providers ;
14
15
use rustc_middle:: span_bug;
15
- use rustc_middle:: ty:: { self as ty, TyCtxt } ;
16
+ use rustc_middle:: ty:: { self as ty, Instance , TyCtxt } ;
16
17
use rustc_session:: lint;
17
18
use rustc_session:: parse:: feature_err;
18
- use rustc_span:: { Ident , Span , sym} ;
19
+ use rustc_span:: { Ident , Span , Symbol , sym} ;
19
20
use rustc_target:: spec:: SanitizerSet ;
20
21
21
22
use crate :: errors;
@@ -315,6 +316,39 @@ fn process_builtin_attrs(
315
316
AttributeKind :: ObjcSelector { methname, .. } => {
316
317
codegen_fn_attrs. objc_selector = Some ( * methname) ;
317
318
}
319
+ AttributeKind :: EiiImpls ( impls) => {
320
+ for i in impls {
321
+ let extern_item = find_attr ! (
322
+ tcx. get_all_attrs( i. eii_macro) ,
323
+ AttributeKind :: EiiExternTarget ( target) => target. eii_extern_target
324
+ )
325
+ . expect ( "eii should have declaration macro with extern target attribute" ) ;
326
+
327
+ let symbol_name = tcx. symbol_name ( Instance :: mono ( tcx, extern_item) ) ;
328
+
329
+ // this is to prevent a bug where a single crate defines both the default and explicit implementation
330
+ // for an EII. In that case, both of them may be part of the same final object file. I'm not 100% sure
331
+ // what happens, either rustc deduplicates the symbol or llvm, or it's random/order-dependent.
332
+ // However, the fact that the default one of has weak linkage isn't considered and you sometimes get that
333
+ // the default implementation is used while an explicit implementation is given.
334
+ if
335
+ // if this is a default impl
336
+ i. is_default
337
+ // iterate over all implementations *in the current crate*
338
+ // (this is ok since we generate codegen fn attrs in the local crate)
339
+ // if any of them is *not default* then don't emit the alias.
340
+ && tcx. externally_implementable_items ( LOCAL_CRATE ) . get ( & i. eii_macro ) . expect ( "at least one" ) . 1 . iter ( ) . any ( |( _, imp) | !imp. is_default )
341
+ {
342
+ continue ;
343
+ }
344
+
345
+ codegen_fn_attrs. foreign_item_symbol_aliases . push ( (
346
+ Symbol :: intern ( symbol_name. name ) ,
347
+ if i. is_default { Linkage :: LinkOnceAny } else { Linkage :: External } ,
348
+ Visibility :: Default ,
349
+ ) ) ;
350
+ }
351
+ }
318
352
_ => { }
319
353
}
320
354
}
0 commit comments