@@ -653,6 +653,7 @@ pub(crate) mod parsing {
653653 use crate :: parse:: { Parse , ParseStream } ;
654654 use crate :: path:: Path ;
655655 use crate :: { mac, token} ;
656+ use proc_macro2:: Ident ;
656657 use std:: fmt:: { self , Display } ;
657658
658659 pub ( crate ) fn parse_inner ( input : ParseStream , attrs : & mut Vec < Attribute > ) -> Result < ( ) > {
@@ -685,27 +686,38 @@ pub(crate) mod parsing {
685686 #[ cfg_attr( docsrs, doc( cfg( feature = "parsing" ) ) ) ]
686687 impl Parse for Meta {
687688 fn parse ( input : ParseStream ) -> Result < Self > {
688- let path = input . call ( Path :: parse_mod_style ) ?;
689+ let path = parse_outermost_meta_path ( input ) ?;
689690 parse_meta_after_path ( path, input)
690691 }
691692 }
692693
693694 #[ cfg_attr( docsrs, doc( cfg( feature = "parsing" ) ) ) ]
694695 impl Parse for MetaList {
695696 fn parse ( input : ParseStream ) -> Result < Self > {
696- let path = input . call ( Path :: parse_mod_style ) ?;
697+ let path = parse_outermost_meta_path ( input ) ?;
697698 parse_meta_list_after_path ( path, input)
698699 }
699700 }
700701
701702 #[ cfg_attr( docsrs, doc( cfg( feature = "parsing" ) ) ) ]
702703 impl Parse for MetaNameValue {
703704 fn parse ( input : ParseStream ) -> Result < Self > {
704- let path = input . call ( Path :: parse_mod_style ) ?;
705+ let path = parse_outermost_meta_path ( input ) ?;
705706 parse_meta_name_value_after_path ( path, input)
706707 }
707708 }
708709
710+ // Unlike meta::parse_meta_path which accepts arbitrary keywords in the path,
711+ // only the `unsafe` keyword is accepted as an attribute's outermost path.
712+ fn parse_outermost_meta_path ( input : ParseStream ) -> Result < Path > {
713+ if input. peek ( Token ! [ unsafe ] ) {
714+ let unsafe_token: Token ! [ unsafe ] = input. parse ( ) ?;
715+ Ok ( Path :: from ( Ident :: new ( "unsafe" , unsafe_token. span ) ) )
716+ } else {
717+ Path :: parse_mod_style ( input)
718+ }
719+ }
720+
709721 pub ( crate ) fn parse_meta_after_path ( path : Path , input : ParseStream ) -> Result < Meta > {
710722 if input. peek ( token:: Paren ) || input. peek ( token:: Bracket ) || input. peek ( token:: Brace ) {
711723 parse_meta_list_after_path ( path, input) . map ( Meta :: List )
0 commit comments