@@ -54,11 +54,11 @@ use crate::lints::{
54
54
BuiltinExplicitOutlives , BuiltinExplicitOutlivesSuggestion , BuiltinFeatureIssueNote ,
55
55
BuiltinIncompleteFeatures , BuiltinIncompleteFeaturesHelp , BuiltinInternalFeatures ,
56
56
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 ,
62
62
} ;
63
63
use crate :: nonstandard_style:: { MethodLateContext , method_context} ;
64
64
use crate :: {
@@ -992,36 +992,69 @@ declare_lint! {
992
992
"generic items must be mangled"
993
993
}
994
994
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 ] ) ;
996
1019
997
1020
impl < ' tcx > LateLintPass < ' tcx > for InvalidNoMangleItems {
998
1021
fn check_item ( & mut self , cx : & LateContext < ' _ > , it : & hir:: Item < ' _ > ) {
999
1022
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
+ }
1016
1052
}
1017
1053
}
1018
- }
1019
- } ;
1054
+ } ;
1020
1055
match it. kind {
1021
1056
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 ) ;
1025
1058
}
1026
1059
hir:: ItemKind :: Const ( ..) => {
1027
1060
if attr:: contains_name ( attrs, sym:: no_mangle) {
@@ -1048,16 +1081,12 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
1048
1081
hir:: ItemKind :: Impl ( hir:: Impl { generics, items, .. } ) => {
1049
1082
for it in * items {
1050
1083
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
+ ) ;
1061
1090
}
1062
1091
}
1063
1092
}
0 commit comments