@@ -19,8 +19,7 @@ use crate::ast::{
1919 self , AssocTyConstraint , AssocTyConstraintKind , NodeId , GenericParam , GenericParamKind ,
2020 PatKind , RangeEnd ,
2121} ;
22- use crate :: attr;
23- use crate :: early_buffered_lints:: BufferedEarlyLintId ;
22+ use crate :: attr:: { self , check_builtin_attribute, AttributeTemplate } ;
2423use crate :: source_map:: Spanned ;
2524use crate :: edition:: { ALL_EDITIONS , Edition } ;
2625use crate :: visit:: { self , FnKind , Visitor } ;
@@ -906,27 +905,6 @@ pub enum AttributeGate {
906905 Ungated ,
907906}
908907
909- /// A template that the attribute input must match.
910- /// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
911- #[ derive( Clone , Copy ) ]
912- pub struct AttributeTemplate {
913- word : bool ,
914- list : Option < & ' static str > ,
915- name_value_str : Option < & ' static str > ,
916- }
917-
918- impl AttributeTemplate {
919- /// Checks that the given meta-item is compatible with this template.
920- fn compatible ( & self , meta_item_kind : & ast:: MetaItemKind ) -> bool {
921- match meta_item_kind {
922- ast:: MetaItemKind :: Word => self . word ,
923- ast:: MetaItemKind :: List ( ..) => self . list . is_some ( ) ,
924- ast:: MetaItemKind :: NameValue ( lit) if lit. node . is_str ( ) => self . name_value_str . is_some ( ) ,
925- ast:: MetaItemKind :: NameValue ( ..) => false ,
926- }
927- }
928- }
929-
930908/// A convenience macro for constructing attribute templates.
931909/// E.g., `template!(Word, List: "description")` means that the attribute
932910/// supports forms `#[attr]` and `#[attr(description)]`.
@@ -1901,70 +1879,6 @@ impl<'a> PostExpansionVisitor<'a> {
19011879 Abi :: System => { }
19021880 }
19031881 }
1904-
1905- fn check_builtin_attribute ( & mut self , attr : & ast:: Attribute , name : Symbol ,
1906- template : AttributeTemplate ) {
1907- // Some special attributes like `cfg` must be checked
1908- // before the generic check, so we skip them here.
1909- let should_skip = |name| name == sym:: cfg;
1910- // Some of previously accepted forms were used in practice,
1911- // report them as warnings for now.
1912- let should_warn = |name| name == sym:: doc || name == sym:: ignore ||
1913- name == sym:: inline || name == sym:: link;
1914-
1915- match attr. parse_meta ( self . context . parse_sess ) {
1916- Ok ( meta) => if !should_skip ( name) && !template. compatible ( & meta. node ) {
1917- let error_msg = format ! ( "malformed `{}` attribute input" , name) ;
1918- let mut msg = "attribute must be of the form " . to_owned ( ) ;
1919- let mut suggestions = vec ! [ ] ;
1920- let mut first = true ;
1921- if template. word {
1922- first = false ;
1923- let code = format ! ( "#[{}]" , name) ;
1924- msg. push_str ( & format ! ( "`{}`" , & code) ) ;
1925- suggestions. push ( code) ;
1926- }
1927- if let Some ( descr) = template. list {
1928- if !first {
1929- msg. push_str ( " or " ) ;
1930- }
1931- first = false ;
1932- let code = format ! ( "#[{}({})]" , name, descr) ;
1933- msg. push_str ( & format ! ( "`{}`" , & code) ) ;
1934- suggestions. push ( code) ;
1935- }
1936- if let Some ( descr) = template. name_value_str {
1937- if !first {
1938- msg. push_str ( " or " ) ;
1939- }
1940- let code = format ! ( "#[{} = \" {}\" ]" , name, descr) ;
1941- msg. push_str ( & format ! ( "`{}`" , & code) ) ;
1942- suggestions. push ( code) ;
1943- }
1944- if should_warn ( name) {
1945- self . context . parse_sess . buffer_lint (
1946- BufferedEarlyLintId :: IllFormedAttributeInput ,
1947- meta. span ,
1948- ast:: CRATE_NODE_ID ,
1949- & msg,
1950- ) ;
1951- } else {
1952- self . context . parse_sess . span_diagnostic . struct_span_err ( meta. span , & error_msg)
1953- . span_suggestions (
1954- meta. span ,
1955- if suggestions. len ( ) == 1 {
1956- "must be of the form"
1957- } else {
1958- "the following are the possible correct uses"
1959- } ,
1960- suggestions. into_iter ( ) ,
1961- Applicability :: HasPlaceholders ,
1962- ) . emit ( ) ;
1963- }
1964- }
1965- Err ( mut err) => err. emit ( ) ,
1966- }
1967- }
19681882}
19691883
19701884impl < ' a > Visitor < ' a > for PostExpansionVisitor < ' a > {
@@ -2005,7 +1919,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
20051919 match attr_info {
20061920 // `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
20071921 Some ( & ( name, _, template, _) ) if name != sym:: rustc_dummy =>
2008- self . check_builtin_attribute ( attr, name, template) ,
1922+ check_builtin_attribute ( self . context . parse_sess , attr, name, template) ,
20091923 _ => if let Some ( TokenTree :: Token ( token) ) = attr. tokens . trees ( ) . next ( ) {
20101924 if token == token:: Eq {
20111925 // All key-value attributes are restricted to meta-item syntax.
0 commit comments