@@ -54,11 +54,11 @@ use crate::lints::{
5454 BuiltinExplicitOutlives , BuiltinExplicitOutlivesSuggestion , BuiltinFeatureIssueNote ,
5555 BuiltinIncompleteFeatures , BuiltinIncompleteFeaturesHelp , BuiltinInternalFeatures ,
5656 BuiltinKeywordIdents , BuiltinMissingCopyImpl , BuiltinMissingDebugImpl , BuiltinMissingDoc ,
57- BuiltinMutablesTransmutes , BuiltinNoMangleGeneric , BuiltinNonShorthandFieldPatterns ,
58- BuiltinSpecialModuleNameUsed , BuiltinTrivialBounds , BuiltinTypeAliasBounds ,
59- BuiltinUngatedAsyncFnTrackCaller , BuiltinUnpermittedTypeInit , BuiltinUnpermittedTypeInitSub ,
60- BuiltinUnreachablePub , BuiltinUnsafe , BuiltinUnstableFeatures , BuiltinUnusedDocComment ,
61- BuiltinUnusedDocCommentSub , BuiltinWhileTrue , InvalidAsmLabel ,
57+ BuiltinMutablesTransmutes , BuiltinNoMangleOrExportNameGeneric ,
58+ BuiltinNonShorthandFieldPatterns , BuiltinSpecialModuleNameUsed , BuiltinTrivialBounds ,
59+ BuiltinTypeAliasBounds , BuiltinUngatedAsyncFnTrackCaller , BuiltinUnpermittedTypeInit ,
60+ BuiltinUnpermittedTypeInitSub , BuiltinUnreachablePub , BuiltinUnsafe , BuiltinUnstableFeatures ,
61+ BuiltinUnusedDocComment , BuiltinUnusedDocCommentSub , BuiltinWhileTrue , InvalidAsmLabel ,
6262} ;
6363use crate :: nonstandard_style:: { MethodLateContext , method_context} ;
6464use crate :: {
@@ -992,36 +992,69 @@ declare_lint! {
992992 "generic items must be mangled"
993993}
994994
995- declare_lint_pass ! ( InvalidNoMangleItems => [ NO_MANGLE_CONST_ITEMS , NO_MANGLE_GENERIC_ITEMS ] ) ;
995+ declare_lint ! {
996+ /// The `export_name_generic_items` lint detects using `#[export_name]` on generic functions.
997+ ///
998+ /// ### Example
999+ /// ```rust,compile_fail
1000+ /// #[export_name = "exported_name"]
1001+ /// fn foo<T>() {}
1002+ /// ```
1003+ ///
1004+ /// {{produces}}
1005+ ///
1006+ /// ### Explanation
1007+ ///
1008+ /// A function with generics must have its symbol mangled to accommodate
1009+ /// the generic parameter. The [`export_name` attribute] has no effect in
1010+ /// this situation, and should be removed.
1011+ ///
1012+ /// [`export_name` attribute]: https://doc.rust-lang.org/reference/abi.html#the-export_name-attribute
1013+ pub EXPORT_NAME_GENERIC_ITEMS ,
1014+ Warn ,
1015+ "generic items must be mangled, export_name would avoid mangling"
1016+ }
1017+
1018+ declare_lint_pass ! ( InvalidNoMangleItems => [ NO_MANGLE_CONST_ITEMS , NO_MANGLE_GENERIC_ITEMS , EXPORT_NAME_GENERIC_ITEMS ] ) ;
9961019
9971020impl < ' tcx > LateLintPass < ' tcx > for InvalidNoMangleItems {
9981021 fn check_item ( & mut self , cx : & LateContext < ' _ > , it : & hir:: Item < ' _ > ) {
9991022 let attrs = cx. tcx . hir_attrs ( it. hir_id ( ) ) ;
1000- let check_no_mangle_on_generic_fn = |no_mangle_attr : & hir:: Attribute ,
1001- impl_generics : Option < & hir:: Generics < ' _ > > ,
1002- generics : & hir:: Generics < ' _ > ,
1003- span| {
1004- for param in
1005- generics. params . iter ( ) . chain ( impl_generics. map ( |g| g. params ) . into_iter ( ) . flatten ( ) )
1006- {
1007- match param. kind {
1008- GenericParamKind :: Lifetime { .. } => { }
1009- GenericParamKind :: Type { .. } | GenericParamKind :: Const { .. } => {
1010- cx. emit_span_lint (
1011- NO_MANGLE_GENERIC_ITEMS ,
1012- span,
1013- BuiltinNoMangleGeneric { suggestion : no_mangle_attr. span ( ) } ,
1014- ) ;
1015- break ;
1023+ let check_no_mangle_or_export_name_on_generic_fn =
1024+ |attrs : & [ hir:: Attribute ] ,
1025+ impl_generics : Option < & hir:: Generics < ' _ > > ,
1026+ generics : & hir:: Generics < ' _ > ,
1027+ span| {
1028+ let ( lint, attr) =
1029+ if let Some ( export_name_attr) = attr:: find_by_name ( attrs, sym:: export_name) {
1030+ ( EXPORT_NAME_GENERIC_ITEMS , export_name_attr)
1031+ } else if let Some ( no_mangle_attr) = attr:: find_by_name ( attrs, sym:: no_mangle) {
1032+ ( NO_MANGLE_GENERIC_ITEMS , no_mangle_attr)
1033+ } else {
1034+ return ;
1035+ } ;
1036+
1037+ for param in generics
1038+ . params
1039+ . iter ( )
1040+ . chain ( impl_generics. map ( |g| g. params ) . into_iter ( ) . flatten ( ) )
1041+ {
1042+ match param. kind {
1043+ GenericParamKind :: Lifetime { .. } => { }
1044+ GenericParamKind :: Type { .. } | GenericParamKind :: Const { .. } => {
1045+ cx. emit_span_lint (
1046+ lint,
1047+ span,
1048+ BuiltinNoMangleOrExportNameGeneric { suggestion : attr. span ( ) } ,
1049+ ) ;
1050+ break ;
1051+ }
10161052 }
10171053 }
1018- }
1019- } ;
1054+ } ;
10201055 match it. kind {
10211056 hir:: ItemKind :: Fn { generics, .. } => {
1022- if let Some ( no_mangle_attr) = attr:: find_by_name ( attrs, sym:: no_mangle) {
1023- check_no_mangle_on_generic_fn ( no_mangle_attr, None , generics, it. span ) ;
1024- }
1057+ check_no_mangle_or_export_name_on_generic_fn ( attrs, None , generics, it. span ) ;
10251058 }
10261059 hir:: ItemKind :: Const ( ..) => {
10271060 if attr:: contains_name ( attrs, sym:: no_mangle) {
@@ -1048,16 +1081,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
10481081 hir:: ItemKind :: Impl ( hir:: Impl { generics, items, .. } ) => {
10491082 for it in * items {
10501083 if let hir:: AssocItemKind :: Fn { .. } = it. kind {
1051- if let Some ( no_mangle_attr) =
1052- attr:: find_by_name ( cx. tcx . hir_attrs ( it. id . hir_id ( ) ) , sym:: no_mangle)
1053- {
1054- check_no_mangle_on_generic_fn (
1055- no_mangle_attr,
1056- Some ( generics) ,
1057- cx. tcx . hir_get_generics ( it. id . owner_id . def_id ) . unwrap ( ) ,
1058- it. span ,
1059- ) ;
1060- }
1084+ check_no_mangle_or_export_name_on_generic_fn (
1085+ cx. tcx . hir_attrs ( it. id . hir_id ( ) ) ,
1086+ Some ( generics) ,
1087+ cx. tcx . hir_get_generics ( it. id . owner_id . def_id ) . unwrap ( ) ,
1088+ it. span ,
1089+ ) ;
10611090 }
10621091 }
10631092 }
0 commit comments