@@ -4,15 +4,12 @@ use std::ops::{Deref, DerefMut};
44use std:: sync:: LazyLock ;
55
66use private:: Sealed ;
7- use rustc_ast:: { self as ast, LitKind , MetaItemLit , NodeId , Safety } ;
7+ use rustc_ast:: { self as ast, LitKind , MetaItemLit , NodeId } ;
88use rustc_attr_data_structures:: AttributeKind ;
99use 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 } ;
1412use rustc_hir:: { AttrArgs , AttrItem , AttrPath , Attribute , HashIgnoredAttrId , HirId } ;
15- use rustc_parse:: validate_attr:: { is_attr_template_compatible, parse_meta} ;
1613use rustc_session:: Session ;
1714use rustc_span:: { DUMMY_SP , ErrorGuaranteed , Span , Symbol , sym} ;
1815
@@ -59,10 +56,7 @@ use crate::attributes::traits::{
5956use crate :: attributes:: transparency:: TransparencyParser ;
6057use crate :: attributes:: { AttributeParser as _, Combine , Single , WithoutArgs } ;
6158use 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 } ;
6660
6761macro_rules! group_type {
6862 ( $stage: ty) => {
@@ -753,6 +747,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
753747 & self . sess
754748 }
755749
750+ pub ( crate ) fn stage ( & self ) -> & S {
751+ & self . stage
752+ }
753+
756754 pub ( crate ) fn features ( & self ) -> & ' sess Features {
757755 self . features . expect ( "features not available at this point in the compiler" )
758756 }
@@ -897,201 +895,6 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
897895 attributes
898896 }
899897
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-
1095898 /// Returns whether there is a parser for an attribute with this name
1096899 pub fn is_parsed_attribute ( path : & [ Symbol ] ) -> bool {
1097900 Late :: parsers ( ) . 0 . contains_key ( path)
0 commit comments