@@ -87,6 +87,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
87
87
let mut link_ordinal_span = None ;
88
88
let mut no_sanitize_span = None ;
89
89
let mut mixed_export_name_no_mangle_lint_state = MixedExportNameAndNoMangleState :: default ( ) ;
90
+ let mut no_mangle_span = None ;
90
91
91
92
for attr in attrs. iter ( ) {
92
93
// In some cases, attribute are only valid on functions, but it's the `check_attr`
@@ -139,6 +140,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
139
140
}
140
141
sym:: naked => codegen_fn_attrs. flags |= CodegenFnAttrFlags :: NAKED ,
141
142
sym:: no_mangle => {
143
+ no_mangle_span = Some ( attr. span ( ) ) ;
142
144
if tcx. opt_item_name ( did. to_def_id ( ) ) . is_some ( ) {
143
145
codegen_fn_attrs. flags |= CodegenFnAttrFlags :: NO_MANGLE ;
144
146
mixed_export_name_no_mangle_lint_state. track_no_mangle (
@@ -608,11 +610,55 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
608
610
// strippable by the linker.
609
611
//
610
612
// Additionally weak lang items have predetermined symbol names.
611
- if let Some ( ( name, _ ) ) = lang_items:: extract ( attrs)
613
+ if let Some ( ( name, span ) ) = lang_items:: extract ( attrs)
612
614
&& let Some ( lang_item) = LangItem :: from_name ( name)
613
615
{
616
+ let has_no_mangle = codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: NO_MANGLE ) ;
614
617
if WEAK_LANG_ITEMS . contains ( & lang_item) {
615
618
codegen_fn_attrs. flags |= CodegenFnAttrFlags :: RUSTC_STD_INTERNAL_SYMBOL ;
619
+ if has_no_mangle {
620
+ // This should never use the default as `no_mangle` is present in the attributes list
621
+ let no_mangle_span = no_mangle_span. unwrap_or_default ( ) ;
622
+ let label_attr = format ! ( "this defines it as the `{}` item" , lang_item. name( ) ) ;
623
+ let label = format ! ( "is the {} item" , lang_item. name( ) ) ;
624
+ let mut err = tcx. dcx ( )
625
+ . struct_span_err ( no_mangle_span, "`#[no_mangle]` cannot be used on weak language items" )
626
+ . with_note ( "The linker requires specific names for internal language items," )
627
+ . with_note ( "like panic handlers, eh personality functions or eh catch typeinfo variables." )
628
+ . with_span_label ( tcx. def_span ( did) , label)
629
+ . with_span_label ( span, label_attr) ;
630
+ if let Some ( link_name) = lang_item. link_name ( ) {
631
+ let renamed =
632
+ format ! ( "In this case it is automatically renamed to `{}`" , link_name) ;
633
+ err = err. with_note ( renamed) ;
634
+ }
635
+ err. emit ( ) ;
636
+ }
637
+ } else {
638
+ if has_no_mangle {
639
+ // This should never use the default as `no_mangle` is present in the attributes list
640
+ let no_mangle_span = no_mangle_span. unwrap_or_default ( ) ;
641
+ let label_attr = format ! ( "this defines it as the `{}` item" , lang_item. name( ) ) ;
642
+ let label = format ! ( "is the {} item" , lang_item. name( ) ) ;
643
+ let mut warn = tcx
644
+ . dcx ( )
645
+ . struct_span_warn (
646
+ no_mangle_span,
647
+ "`#[no_mangle]` should not be used on std internal language items" ,
648
+ )
649
+ . with_note ( "The linker requires specific names for internal language items," )
650
+ . with_note ( "as they might require a specific link name in the future." )
651
+ . with_span_label ( tcx. def_span ( did) , label)
652
+ . with_span_label ( span, label_attr) ;
653
+ if let Some ( link_name) = lang_item. link_name ( ) {
654
+ let renamed = format ! (
655
+ "In this case this should be automatically renamed to `{}`" ,
656
+ link_name
657
+ ) ;
658
+ warn = warn. with_note ( renamed) ;
659
+ }
660
+ warn. emit ( ) ;
661
+ }
616
662
}
617
663
if let Some ( link_name) = lang_item. link_name ( ) {
618
664
codegen_fn_attrs. export_name = Some ( link_name) ;
0 commit comments