@@ -6,9 +6,10 @@ use crate::mbe::macro_parser::{NamedMatch, NamedMatch::*};
66use crate :: mbe:: metavar_expr:: { MetaVarExprConcatElem , RAW_IDENT_ERR } ;
77use crate :: mbe:: { self , KleeneOp , MetaVarExpr } ;
88use rustc_ast:: mut_visit:: { self , MutVisitor } ;
9- use rustc_ast:: token:: IdentIsRaw ;
10- use rustc_ast:: token:: { self , Delimiter , Token , TokenKind } ;
9+ use rustc_ast:: token:: { self , Delimiter , Nonterminal , Token , TokenKind } ;
10+ use rustc_ast:: token:: { IdentIsRaw , Lit , LitKind } ;
1111use rustc_ast:: tokenstream:: { DelimSpacing , DelimSpan , Spacing , TokenStream , TokenTree } ;
12+ use rustc_ast:: ExprKind ;
1213use rustc_data_structures:: fx:: FxHashMap ;
1314use rustc_errors:: { pluralize, Diag , DiagCtxtHandle , PResult } ;
1415use rustc_parse:: lexer:: nfc_normalize;
@@ -17,7 +18,7 @@ use rustc_session::parse::ParseSess;
1718use rustc_session:: parse:: SymbolGallery ;
1819use rustc_span:: hygiene:: { LocalExpnId , Transparency } ;
1920use rustc_span:: symbol:: { sym, Ident , MacroRulesNormalizedIdent } ;
20- use rustc_span:: { with_metavar_spans, Span , SyntaxContext } ;
21+ use rustc_span:: { with_metavar_spans, Span , Symbol , SyntaxContext } ;
2122use smallvec:: { smallvec, SmallVec } ;
2223use std:: mem;
2324
@@ -691,12 +692,12 @@ fn transcribe_metavar_expr<'a>(
691692 MetaVarExpr :: Concat ( ref elements) => {
692693 let mut concatenated = String :: new ( ) ;
693694 for element in elements. into_iter ( ) {
694- let string = match element {
695- MetaVarExprConcatElem :: Ident ( elem) => elem. to_string ( ) ,
696- MetaVarExprConcatElem :: Literal ( elem) => elem. as_str ( ) . into ( ) ,
697- MetaVarExprConcatElem :: Var ( elem) => extract_ident ( dcx, * elem, interp) ?,
695+ let symbol = match element {
696+ MetaVarExprConcatElem :: Ident ( elem) => & elem. name ,
697+ MetaVarExprConcatElem :: Literal ( elem) => elem,
698+ MetaVarExprConcatElem :: Var ( elem) => extract_var_symbol ( dcx, * elem, interp) ?,
698699 } ;
699- concatenated. push_str ( & string ) ;
700+ concatenated. push_str ( symbol . as_str ( ) ) ;
700701 }
701702 let symbol = nfc_normalize ( & concatenated) ;
702703 let concatenated_span = visited_span ( ) ;
@@ -750,32 +751,42 @@ fn transcribe_metavar_expr<'a>(
750751 Ok ( ( ) )
751752}
752753
753- /// Extracts an identifier that can be originated from a `$var:ident` variable or from a token tree .
754- fn extract_ident < ' a > (
754+ /// Extracts an metavariable symbol that can be an identifier, a token tree or a literal .
755+ fn extract_var_symbol < ' a , ' interp > (
755756 dcx : DiagCtxtHandle < ' a > ,
756757 ident : Ident ,
757- interp : & FxHashMap < MacroRulesNormalizedIdent , NamedMatch > ,
758- ) -> PResult < ' a , String > {
758+ interp : & ' interp FxHashMap < MacroRulesNormalizedIdent , NamedMatch > ,
759+ ) -> PResult < ' a , & ' interp Symbol > {
759760 if let NamedMatch :: MatchedSingle ( pnr) = matched_from_ident ( dcx, ident, interp) ? {
760761 if let ParseNtResult :: Ident ( nt_ident, is_raw) = pnr {
761762 if let IdentIsRaw :: Yes = is_raw {
762763 return Err ( dcx. struct_span_err ( ident. span , RAW_IDENT_ERR ) ) ;
763764 }
764- return Ok ( nt_ident. to_string ( ) ) ;
765+ return Ok ( & nt_ident. name ) ;
765766 }
766- if let ParseNtResult :: Tt ( TokenTree :: Token (
767- Token { kind : TokenKind :: Ident ( token_ident, is_raw) , .. } ,
768- _,
769- ) ) = pnr
770- {
771- if let IdentIsRaw :: Yes = is_raw {
772- return Err ( dcx. struct_span_err ( ident. span , RAW_IDENT_ERR ) ) ;
767+
768+ if let ParseNtResult :: Tt ( TokenTree :: Token ( Token { kind, .. } , _) ) = pnr {
769+ if let TokenKind :: Ident ( symbol, is_raw) = kind {
770+ if let IdentIsRaw :: Yes = is_raw {
771+ return Err ( dcx. struct_span_err ( ident. span , RAW_IDENT_ERR ) ) ;
772+ }
773+ return Ok ( symbol) ;
774+ }
775+
776+ if let TokenKind :: Literal ( Lit { kind : LitKind :: Str , symbol, suffix : None } ) = kind {
777+ return Ok ( symbol) ;
773778 }
774- return Ok ( token_ident. to_string ( ) ) ;
779+ }
780+
781+ if let ParseNtResult :: Nt ( nt) = pnr
782+ && let Nonterminal :: NtLiteral ( expr) = & * * nt
783+ && let ExprKind :: Lit ( Lit { kind : LitKind :: Str , symbol, suffix : None } ) = & expr. kind
784+ {
785+ return Ok ( symbol) ;
775786 }
776787 }
777- Err ( dcx. struct_span_err (
778- ident . span ,
779- "`${concat(..)}` currently only accepts identifiers or meta-variables as parameters" ,
780- ) )
788+ Err ( dcx
789+ . struct_err ( "metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt`" )
790+ . with_note ( " currently only string literals are supported" )
791+ . with_span ( ident . span ) )
781792}
0 commit comments