@@ -3,16 +3,13 @@ use std::collections::BTreeMap;
3
3
use std:: ops:: { Deref , DerefMut } ;
4
4
use std:: sync:: LazyLock ;
5
5
6
- use itertools:: Itertools ;
7
6
use private:: Sealed ;
8
- use rustc_ast:: { self as ast, LitKind , MetaItemLit , NodeId } ;
7
+ use rustc_ast:: { self as ast, MetaItemLit , NodeId } ;
9
8
use rustc_errors:: { DiagCtxtHandle , Diagnostic } ;
10
9
use rustc_feature:: { AttributeTemplate , Features } ;
11
10
use rustc_hir:: attrs:: AttributeKind ;
12
11
use rustc_hir:: lints:: { AttributeLint , AttributeLintKind } ;
13
- use rustc_hir:: {
14
- AttrArgs , AttrItem , AttrPath , Attribute , HashIgnoredAttrId , HirId , MethodKind , Target ,
15
- } ;
12
+ use rustc_hir:: { AttrArgs , AttrItem , AttrPath , Attribute , HashIgnoredAttrId , HirId , Target } ;
16
13
use rustc_session:: Session ;
17
14
use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span , Symbol , sym} ;
18
15
@@ -64,11 +61,9 @@ use crate::attributes::traits::{
64
61
} ;
65
62
use crate :: attributes:: transparency:: TransparencyParser ;
66
63
use crate :: attributes:: { AttributeParser as _, Combine , Single , WithoutArgs } ;
67
- use crate :: context:: MaybeWarn :: { Allow , Error , Warn } ;
68
64
use crate :: parser:: { ArgParser , MetaItemParser , PathParser } ;
69
- use crate :: session_diagnostics:: {
70
- AttributeParseError , AttributeParseErrorReason , InvalidTarget , UnknownMetaItem ,
71
- } ;
65
+ use crate :: session_diagnostics:: { AttributeParseError , AttributeParseErrorReason , UnknownMetaItem } ;
66
+ use crate :: target_checking:: AllowedTargets ;
72
67
73
68
type GroupType < S > = LazyLock < GroupTypeInner < S > > ;
74
69
@@ -651,69 +646,11 @@ impl ShouldEmit {
651
646
}
652
647
}
653
648
654
- #[ derive( Debug ) ]
655
- pub ( crate ) enum AllowedTargets {
656
- AllowList ( & ' static [ MaybeWarn ] ) ,
657
- AllowListWarnRest ( & ' static [ MaybeWarn ] ) ,
658
- }
659
-
660
- pub ( crate ) enum AllowedResult {
661
- Allowed ,
662
- Warn ,
663
- Error ,
664
- }
665
-
666
- impl AllowedTargets {
667
- pub ( crate ) fn is_allowed ( & self , target : Target ) -> AllowedResult {
668
- match self {
669
- AllowedTargets :: AllowList ( list) => {
670
- if list. contains ( & Allow ( target) ) {
671
- AllowedResult :: Allowed
672
- } else if list. contains ( & Warn ( target) ) {
673
- AllowedResult :: Warn
674
- } else {
675
- AllowedResult :: Error
676
- }
677
- }
678
- AllowedTargets :: AllowListWarnRest ( list) => {
679
- if list. contains ( & Allow ( target) ) {
680
- AllowedResult :: Allowed
681
- } else if list. contains ( & Error ( target) ) {
682
- AllowedResult :: Error
683
- } else {
684
- AllowedResult :: Warn
685
- }
686
- }
687
- }
688
- }
689
-
690
- pub ( crate ) fn allowed_targets ( & self ) -> Vec < Target > {
691
- match self {
692
- AllowedTargets :: AllowList ( list) => list,
693
- AllowedTargets :: AllowListWarnRest ( list) => list,
694
- }
695
- . iter ( )
696
- . filter_map ( |target| match target {
697
- Allow ( target) => Some ( * target) ,
698
- Warn ( _) => None ,
699
- Error ( _) => None ,
700
- } )
701
- . collect ( )
702
- }
703
- }
704
-
705
- #[ derive( Debug , Eq , PartialEq ) ]
706
- pub ( crate ) enum MaybeWarn {
707
- Allow ( Target ) ,
708
- Warn ( Target ) ,
709
- Error ( Target ) ,
710
- }
711
-
712
649
/// Context created once, for example as part of the ast lowering
713
650
/// context, through which all attributes can be lowered.
714
651
pub struct AttributeParser < ' sess , S : Stage = Late > {
715
652
pub ( crate ) tools : Vec < Symbol > ,
716
- features : Option < & ' sess Features > ,
653
+ pub ( crate ) features : Option < & ' sess Features > ,
717
654
sess : & ' sess Session ,
718
655
stage : S ,
719
656
@@ -900,9 +837,9 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
900
837
let parser = MetaItemParser :: from_attr ( n, self . dcx ( ) ) ;
901
838
let path = parser. path ( ) ;
902
839
let args = parser. args ( ) ;
903
- let parts = path. segments ( ) . map ( |i| i. name ) . collect :: < Vec < _ > > ( ) ;
840
+ let path_parts = path. segments ( ) . map ( |i| i. name ) . collect :: < Vec < _ > > ( ) ;
904
841
905
- if let Some ( accepts) = S :: parsers ( ) . accepters . get ( parts . as_slice ( ) ) {
842
+ if let Some ( accepts) = S :: parsers ( ) . accepters . get ( path_parts . as_slice ( ) ) {
906
843
for accept in accepts {
907
844
let mut cx: AcceptContext < ' _ , ' sess , S > = AcceptContext {
908
845
shared : SharedContext {
@@ -919,44 +856,14 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
919
856
( accept. accept_fn ) ( & mut cx, args) ;
920
857
921
858
if self . stage . should_emit ( ) . should_emit ( ) {
922
- match accept. allowed_targets . is_allowed ( target) {
923
- AllowedResult :: Allowed => { }
924
- AllowedResult :: Warn => {
925
- let allowed_targets =
926
- accept. allowed_targets . allowed_targets ( ) ;
927
- let ( applied, only) = allowed_targets_applied (
928
- allowed_targets,
929
- target,
930
- self . features ,
931
- ) ;
932
- emit_lint ( AttributeLint {
933
- id : target_id,
934
- span : attr. span ,
935
- kind : AttributeLintKind :: InvalidTarget {
936
- name : parts[ 0 ] ,
937
- target,
938
- only : if only { "only " } else { "" } ,
939
- applied,
940
- } ,
941
- } ) ;
942
- }
943
- AllowedResult :: Error => {
944
- let allowed_targets =
945
- accept. allowed_targets . allowed_targets ( ) ;
946
- let ( applied, only) = allowed_targets_applied (
947
- allowed_targets,
948
- target,
949
- self . features ,
950
- ) ;
951
- self . dcx ( ) . emit_err ( InvalidTarget {
952
- span : attr. span ,
953
- name : parts[ 0 ] ,
954
- target : target. plural_name ( ) ,
955
- only : if only { "only " } else { "" } ,
956
- applied,
957
- } ) ;
958
- }
959
- }
859
+ self . check_target (
860
+ path. get_attribute_path ( ) ,
861
+ attr. span ,
862
+ & accept. allowed_targets ,
863
+ target,
864
+ target_id,
865
+ & mut emit_lint,
866
+ ) ;
960
867
}
961
868
}
962
869
} else {
@@ -1044,158 +951,3 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
1044
951
}
1045
952
}
1046
953
}
1047
-
1048
- /// Takes a list of `allowed_targets` for an attribute, and the `target` the attribute was applied to.
1049
- /// Does some heuristic-based filtering to remove uninteresting targets, and formats the targets into a string
1050
- pub ( crate ) fn allowed_targets_applied (
1051
- mut allowed_targets : Vec < Target > ,
1052
- target : Target ,
1053
- features : Option < & Features > ,
1054
- ) -> ( String , bool ) {
1055
- // Remove unstable targets from `allowed_targets` if their features are not enabled
1056
- if let Some ( features) = features {
1057
- if !features. fn_delegation ( ) {
1058
- allowed_targets. retain ( |t| !matches ! ( t, Target :: Delegation { .. } ) ) ;
1059
- }
1060
- if !features. stmt_expr_attributes ( ) {
1061
- allowed_targets. retain ( |t| !matches ! ( t, Target :: Expression | Target :: Statement ) ) ;
1062
- }
1063
- }
1064
-
1065
- // We define groups of "similar" targets.
1066
- // If at least two of the targets are allowed, and the `target` is not in the group,
1067
- // we collapse the entire group to a single entry to simplify the target list
1068
- const FUNCTION_LIKE : & [ Target ] = & [
1069
- Target :: Fn ,
1070
- Target :: Closure ,
1071
- Target :: ForeignFn ,
1072
- Target :: Method ( MethodKind :: Inherent ) ,
1073
- Target :: Method ( MethodKind :: Trait { body : false } ) ,
1074
- Target :: Method ( MethodKind :: Trait { body : true } ) ,
1075
- Target :: Method ( MethodKind :: TraitImpl ) ,
1076
- ] ;
1077
- const METHOD_LIKE : & [ Target ] = & [
1078
- Target :: Method ( MethodKind :: Inherent ) ,
1079
- Target :: Method ( MethodKind :: Trait { body : false } ) ,
1080
- Target :: Method ( MethodKind :: Trait { body : true } ) ,
1081
- Target :: Method ( MethodKind :: TraitImpl ) ,
1082
- ] ;
1083
- const IMPL_LIKE : & [ Target ] =
1084
- & [ Target :: Impl { of_trait : false } , Target :: Impl { of_trait : true } ] ;
1085
- const ADT_LIKE : & [ Target ] = & [ Target :: Struct , Target :: Enum ] ;
1086
-
1087
- let mut added_fake_targets = Vec :: new ( ) ;
1088
- filter_targets (
1089
- & mut allowed_targets,
1090
- FUNCTION_LIKE ,
1091
- "functions" ,
1092
- target,
1093
- & mut added_fake_targets,
1094
- ) ;
1095
- filter_targets ( & mut allowed_targets, METHOD_LIKE , "methods" , target, & mut added_fake_targets) ;
1096
- filter_targets ( & mut allowed_targets, IMPL_LIKE , "impl blocks" , target, & mut added_fake_targets) ;
1097
- filter_targets ( & mut allowed_targets, ADT_LIKE , "data types" , target, & mut added_fake_targets) ;
1098
-
1099
- // If there is now only 1 target left, show that as the only possible target
1100
- (
1101
- added_fake_targets
1102
- . iter ( )
1103
- . copied ( )
1104
- . chain ( allowed_targets. iter ( ) . map ( |t| t. plural_name ( ) ) )
1105
- . join ( ", " ) ,
1106
- allowed_targets. len ( ) + added_fake_targets. len ( ) == 1 ,
1107
- )
1108
- }
1109
-
1110
- fn filter_targets (
1111
- allowed_targets : & mut Vec < Target > ,
1112
- target_group : & ' static [ Target ] ,
1113
- target_group_name : & ' static str ,
1114
- target : Target ,
1115
- added_fake_targets : & mut Vec < & ' static str > ,
1116
- ) {
1117
- if target_group. contains ( & target) {
1118
- return ;
1119
- }
1120
- if allowed_targets. iter ( ) . filter ( |at| target_group. contains ( at) ) . count ( ) < 2 {
1121
- return ;
1122
- }
1123
- allowed_targets. retain ( |t| !target_group. contains ( t) ) ;
1124
- added_fake_targets. push ( target_group_name) ;
1125
- }
1126
-
1127
- /// This is the list of all targets to which a attribute can be applied
1128
- /// This is used for:
1129
- /// - `rustc_dummy`, which can be applied to all targets
1130
- /// - Attributes that are not parted to the new target system yet can use this list as a placeholder
1131
- pub ( crate ) const ALL_TARGETS : & ' static [ MaybeWarn ] = & [
1132
- Allow ( Target :: ExternCrate ) ,
1133
- Allow ( Target :: Use ) ,
1134
- Allow ( Target :: Static ) ,
1135
- Allow ( Target :: Const ) ,
1136
- Allow ( Target :: Fn ) ,
1137
- Allow ( Target :: Closure ) ,
1138
- Allow ( Target :: Mod ) ,
1139
- Allow ( Target :: ForeignMod ) ,
1140
- Allow ( Target :: GlobalAsm ) ,
1141
- Allow ( Target :: TyAlias ) ,
1142
- Allow ( Target :: Enum ) ,
1143
- Allow ( Target :: Variant ) ,
1144
- Allow ( Target :: Struct ) ,
1145
- Allow ( Target :: Field ) ,
1146
- Allow ( Target :: Union ) ,
1147
- Allow ( Target :: Trait ) ,
1148
- Allow ( Target :: TraitAlias ) ,
1149
- Allow ( Target :: Impl { of_trait : false } ) ,
1150
- Allow ( Target :: Impl { of_trait : true } ) ,
1151
- Allow ( Target :: Expression ) ,
1152
- Allow ( Target :: Statement ) ,
1153
- Allow ( Target :: Arm ) ,
1154
- Allow ( Target :: AssocConst ) ,
1155
- Allow ( Target :: Method ( MethodKind :: Inherent ) ) ,
1156
- Allow ( Target :: Method ( MethodKind :: Trait { body : false } ) ) ,
1157
- Allow ( Target :: Method ( MethodKind :: Trait { body : true } ) ) ,
1158
- Allow ( Target :: Method ( MethodKind :: TraitImpl ) ) ,
1159
- Allow ( Target :: AssocTy ) ,
1160
- Allow ( Target :: ForeignFn ) ,
1161
- Allow ( Target :: ForeignStatic ) ,
1162
- Allow ( Target :: ForeignTy ) ,
1163
- Allow ( Target :: MacroDef ) ,
1164
- Allow ( Target :: Param ) ,
1165
- Allow ( Target :: PatField ) ,
1166
- Allow ( Target :: ExprField ) ,
1167
- Allow ( Target :: WherePredicate ) ,
1168
- Allow ( Target :: MacroCall ) ,
1169
- Allow ( Target :: Crate ) ,
1170
- Allow ( Target :: Delegation { mac : false } ) ,
1171
- Allow ( Target :: Delegation { mac : true } ) ,
1172
- ] ;
1173
-
1174
- /// Parse a single integer.
1175
- ///
1176
- /// Used by attributes that take a single integer as argument, such as
1177
- /// `#[link_ordinal]` and `#[rustc_layout_scalar_valid_range_start]`.
1178
- /// `cx` is the context given to the attribute.
1179
- /// `args` is the parser for the attribute arguments.
1180
- pub ( crate ) fn parse_single_integer < S : Stage > (
1181
- cx : & mut AcceptContext < ' _ , ' _ , S > ,
1182
- args : & ArgParser < ' _ > ,
1183
- ) -> Option < u128 > {
1184
- let Some ( list) = args. list ( ) else {
1185
- cx. expected_list ( cx. attr_span ) ;
1186
- return None ;
1187
- } ;
1188
- let Some ( single) = list. single ( ) else {
1189
- cx. expected_single_argument ( list. span ) ;
1190
- return None ;
1191
- } ;
1192
- let Some ( lit) = single. lit ( ) else {
1193
- cx. expected_integer_literal ( single. span ( ) ) ;
1194
- return None ;
1195
- } ;
1196
- let LitKind :: Int ( num, _ty) = lit. kind else {
1197
- cx. expected_integer_literal ( single. span ( ) ) ;
1198
- return None ;
1199
- } ;
1200
- Some ( num. 0 )
1201
- }
0 commit comments