@@ -4,15 +4,12 @@ use std::ops::{Deref, DerefMut};
4
4
use std:: sync:: LazyLock ;
5
5
6
6
use private:: Sealed ;
7
- use rustc_ast:: { self as ast, LitKind , MetaItemLit , NodeId , Safety } ;
7
+ use rustc_ast:: { self as ast, LitKind , MetaItemLit , NodeId } ;
8
8
use rustc_attr_data_structures:: AttributeKind ;
9
9
use rustc_attr_data_structures:: lints:: { AttributeLint , AttributeLintKind } ;
10
- use rustc_errors:: { Applicability , DiagCtxtHandle , Diagnostic } ;
11
- use rustc_feature:: {
12
- AttributeSafety , AttributeTemplate , BUILTIN_ATTRIBUTE_MAP , BuiltinAttribute , Features ,
13
- } ;
10
+ use rustc_errors:: { DiagCtxtHandle , Diagnostic } ;
11
+ use rustc_feature:: { AttributeTemplate , Features } ;
14
12
use rustc_hir:: { AttrArgs , AttrItem , AttrPath , Attribute , HashIgnoredAttrId , HirId } ;
15
- use rustc_parse:: validate_attr:: { is_attr_template_compatible, parse_meta} ;
16
13
use rustc_session:: Session ;
17
14
use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span , Symbol , sym} ;
18
15
@@ -59,10 +56,7 @@ use crate::attributes::traits::{
59
56
use crate :: attributes:: transparency:: TransparencyParser ;
60
57
use crate :: attributes:: { AttributeParser as _, Combine , Single , WithoutArgs } ;
61
58
use crate :: parser:: { ArgParser , MetaItemParser , PathParser } ;
62
- use crate :: session_diagnostics:: {
63
- AttributeParseError , AttributeParseErrorReason , InvalidAttrUnsafe , UnknownMetaItem ,
64
- UnsafeAttrOutsideUnsafe , UnsafeAttrOutsideUnsafeSuggestion ,
65
- } ;
59
+ use crate :: session_diagnostics:: { AttributeParseError , AttributeParseErrorReason , UnknownMetaItem } ;
66
60
67
61
macro_rules! group_type {
68
62
( $stage: ty) => {
@@ -753,6 +747,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
753
747
& self . sess
754
748
}
755
749
750
+ pub ( crate ) fn stage ( & self ) -> & S {
751
+ & self . stage
752
+ }
753
+
756
754
pub ( crate ) fn features ( & self ) -> & ' sess Features {
757
755
self . features . expect ( "features not available at this point in the compiler" )
758
756
}
@@ -897,201 +895,6 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
897
895
attributes
898
896
}
899
897
900
- fn validate_attribute (
901
- & self ,
902
- attr : & ast:: Attribute ,
903
- target_id : S :: Id ,
904
- emit_lint : & mut impl FnMut ( AttributeLint < S :: Id > ) ,
905
- check_attr_template : bool ,
906
- ) -> bool {
907
- if !self . stage . should_emit_errors ( ) {
908
- return true ;
909
- }
910
- let ast:: AttrKind :: Normal ( normal) = & attr. kind else { return true } ;
911
- if attr. has_name ( sym:: cfg_trace) || attr. has_name ( sym:: cfg_attr_trace) {
912
- return true ;
913
- }
914
- self . check_attribute_safety ( attr, target_id, emit_lint) ;
915
-
916
- let builtin_attr_info =
917
- attr. ident ( ) . and_then ( |ident| BUILTIN_ATTRIBUTE_MAP . get ( & ident. name ) ) ;
918
- if ( builtin_attr_info. is_none ( ) || attr. has_name ( sym:: rustc_dummy) )
919
- && !matches ! ( normal. item. args, rustc_ast:: AttrArgs :: Eq { .. } )
920
- {
921
- return true ;
922
- }
923
-
924
- // FIXME
925
- let meta = match parse_meta ( & self . sess . psess , attr) {
926
- Ok ( meta) => meta,
927
- Err ( err) => {
928
- err. emit ( ) ;
929
- return false ;
930
- }
931
- } ;
932
- if check_attr_template {
933
- return true ;
934
- }
935
-
936
- if let Some ( BuiltinAttribute { name, template, .. } ) = builtin_attr_info {
937
- // FIXME when all attributes are parsed, this check can be removed
938
- if !is_attr_template_compatible ( & template, & meta. kind ) {
939
- self . emit_malformed_unparsed_attribute (
940
- attr. style , meta. span , * name, * template, target_id, emit_lint,
941
- ) ;
942
- return false
943
- }
944
- }
945
-
946
- true
947
- }
948
-
949
- fn check_attribute_safety (
950
- & self ,
951
- attr : & ast:: Attribute ,
952
- id : S :: Id ,
953
- emit_lint : & mut impl FnMut ( AttributeLint < S :: Id > ) ,
954
- ) {
955
- let builtin_attr_info =
956
- attr. ident ( ) . and_then ( |ident| BUILTIN_ATTRIBUTE_MAP . get ( & ident. name ) ) ;
957
-
958
- let builtin_attr_safety = builtin_attr_info. map ( |x| x. safety ) ;
959
-
960
- let attr_item = attr. get_normal_item ( ) ;
961
- match ( builtin_attr_safety, attr_item. unsafety ) {
962
- // - Unsafe builtin attribute
963
- // - User wrote `#[unsafe(..)]`, which is permitted on any edition
964
- ( Some ( AttributeSafety :: Unsafe { .. } ) , Safety :: Unsafe ( ..) ) => {
965
- // OK
966
- }
967
-
968
- // - Unsafe builtin attribute
969
- // - User did not write `#[unsafe(..)]`
970
- ( Some ( AttributeSafety :: Unsafe { unsafe_since } ) , Safety :: Default ) => {
971
- let path_span = attr_item. path . span ;
972
-
973
- // If the `attr_item`'s span is not from a macro, then just suggest
974
- // wrapping it in `unsafe(...)`. Otherwise, we suggest putting the
975
- // `unsafe(`, `)` right after and right before the opening and closing
976
- // square bracket respectively.
977
- let diag_span = attr_item. span ( ) ;
978
-
979
- // Attributes can be safe in earlier editions, and become unsafe in later ones.
980
- //
981
- // Use the span of the attribute's name to determine the edition: the span of the
982
- // attribute as a whole may be inaccurate if it was emitted by a macro.
983
- //
984
- // See https://github.com/rust-lang/rust/issues/142182.
985
- let emit_error = match unsafe_since {
986
- None => true ,
987
- Some ( unsafe_since) => path_span. edition ( ) >= unsafe_since,
988
- } ;
989
-
990
- if emit_error {
991
- self . dcx ( ) . emit_err ( UnsafeAttrOutsideUnsafe {
992
- span : path_span,
993
- suggestion : UnsafeAttrOutsideUnsafeSuggestion {
994
- left : diag_span. shrink_to_lo ( ) ,
995
- right : diag_span. shrink_to_hi ( ) ,
996
- } ,
997
- } ) ;
998
- } else {
999
- emit_lint ( AttributeLint {
1000
- id,
1001
- span : path_span,
1002
- kind : AttributeLintKind :: UnsafeAttrOutsideUnsafe {
1003
- attribute_name_span : path_span,
1004
- sugg_spans : ( diag_span. shrink_to_lo ( ) , diag_span. shrink_to_hi ( ) ) ,
1005
- } ,
1006
- } ) ;
1007
- }
1008
- }
1009
-
1010
- // - Normal builtin attribute, or any non-builtin attribute
1011
- // - All non-builtin attributes are currently considered safe; writing `#[unsafe(..)]` is
1012
- // not permitted on non-builtin attributes or normal builtin attributes
1013
- ( Some ( AttributeSafety :: Normal ) | None , Safety :: Unsafe ( unsafe_span) ) => {
1014
- self . dcx ( ) . emit_err ( InvalidAttrUnsafe {
1015
- span : unsafe_span,
1016
- name : attr_item. path . clone ( ) ,
1017
- } ) ;
1018
- }
1019
-
1020
- // - Normal builtin attribute
1021
- // - No explicit `#[unsafe(..)]` written.
1022
- ( Some ( AttributeSafety :: Normal ) , Safety :: Default ) => {
1023
- // OK
1024
- }
1025
-
1026
- // - Non-builtin attribute
1027
- // - No explicit `#[unsafe(..)]` written.
1028
- ( None , Safety :: Default ) => {
1029
- // OK
1030
- }
1031
-
1032
- (
1033
- Some ( AttributeSafety :: Unsafe { .. } | AttributeSafety :: Normal ) | None ,
1034
- Safety :: Safe ( ..) ,
1035
- ) => {
1036
- self . sess . psess . dcx ( ) . span_delayed_bug (
1037
- attr_item. span ( ) ,
1038
- "`check_attribute_safety` does not expect `Safety::Safe` on attributes" ,
1039
- ) ;
1040
- }
1041
- }
1042
- }
1043
-
1044
- fn emit_malformed_unparsed_attribute (
1045
- & self ,
1046
- style : ast:: AttrStyle ,
1047
- span : Span ,
1048
- name : Symbol ,
1049
- template : AttributeTemplate ,
1050
- target_id : S :: Id ,
1051
- emit_lint : & mut impl FnMut ( AttributeLint < S :: Id > ) ,
1052
- ) {
1053
- // Some of previously accepted forms were used in practice,
1054
- // report them as warnings for now.
1055
- let should_warn = |name| matches ! ( name, sym:: doc | sym:: link | sym:: test | sym:: bench) ;
1056
-
1057
- let error_msg = format ! ( "malformed `{name}` attribute input" ) ;
1058
- let mut suggestions = vec ! [ ] ;
1059
- let inner = if style == ast:: AttrStyle :: Inner { "!" } else { "" } ;
1060
- if template. word {
1061
- suggestions. push ( format ! ( "#{inner}[{name}]" ) ) ;
1062
- }
1063
- if let Some ( descr) = template. list {
1064
- suggestions. push ( format ! ( "#{inner}[{name}({descr})]" ) ) ;
1065
- }
1066
- suggestions. extend ( template. one_of . iter ( ) . map ( |& word| format ! ( "#{inner}[{name}({word})]" ) ) ) ;
1067
- if let Some ( descr) = template. name_value_str {
1068
- suggestions. push ( format ! ( "#{inner}[{name} = \" {descr}\" ]" ) ) ;
1069
- }
1070
- if should_warn ( name) {
1071
- emit_lint ( AttributeLint {
1072
- id : target_id,
1073
- span,
1074
- kind : AttributeLintKind :: IllFormedAttributeInput { suggestions } ,
1075
- } ) ;
1076
- } else {
1077
- suggestions. sort ( ) ;
1078
- self . sess
1079
- . dcx ( )
1080
- . struct_span_err ( span, error_msg)
1081
- . with_span_suggestions (
1082
- span,
1083
- if suggestions. len ( ) == 1 {
1084
- "must be of the form"
1085
- } else {
1086
- "the following are the possible correct uses"
1087
- } ,
1088
- suggestions,
1089
- Applicability :: HasPlaceholders ,
1090
- )
1091
- . emit ( ) ;
1092
- }
1093
- }
1094
-
1095
898
/// Returns whether there is a parser for an attribute with this name
1096
899
pub fn is_parsed_attribute ( path : & [ Symbol ] ) -> bool {
1097
900
Late :: parsers ( ) . 0 . contains_key ( path)
0 commit comments