@@ -9,7 +9,7 @@ use rustc_ast::{
99 self as ast, AttrArgs , Attribute , DelimArgs , MetaItem , MetaItemInner , MetaItemKind , Safety ,
1010} ;
1111use rustc_errors:: { Applicability , PResult } ;
12- use rustc_feature:: { AttributeTemplate , BUILTIN_ATTRIBUTE_MAP , BuiltinAttribute } ;
12+ use rustc_feature:: { AttributeTemplate , BUILTIN_ATTRIBUTE_MAP , BuiltinAttribute , template } ;
1313use rustc_hir:: AttrPath ;
1414use rustc_hir:: lints:: AttributeLintKind ;
1515use rustc_parse:: parse_in;
@@ -31,14 +31,22 @@ pub fn check_attr(psess: &ParseSess, attr: &Attribute) {
3131 // Check input tokens for built-in and key-value attributes.
3232 match builtin_attr_info {
3333 // `rustc_dummy` doesn't have any restrictions specific to built-in attributes.
34- Some ( BuiltinAttribute { name, template , .. } ) => {
34+ Some ( BuiltinAttribute { name, .. } ) => {
3535 if AttributeParser :: < Late > :: is_parsed_attribute ( slice:: from_ref ( & name) ) {
3636 return ;
3737 }
3838 match parse_meta ( psess, attr) {
3939 // Don't check safety again, we just did that
4040 Ok ( meta) => {
41- check_builtin_meta_item ( psess, & meta, attr. style , * name, * template, false )
41+ // The only unparsed builtin attributes that are left are the lint attributes, so we can hardcode the template here
42+ let lint_attrs = [ sym:: forbid, sym:: allow, sym:: warn, sym:: deny, sym:: expect] ;
43+ assert ! ( lint_attrs. contains( name) ) ;
44+
45+ let template = template ! (
46+ List : & [ "lint1" , "lint1, lint2, ..." , r#"lint1, lint2, lint3, reason = "...""# ] ,
47+ "https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
48+ ) ;
49+ check_builtin_meta_item ( psess, & meta, attr. style , * name, template, false )
4250 }
4351 Err ( err) => {
4452 err. emit ( ) ;
0 commit comments