@@ -6,9 +6,10 @@ use crate::mbe::macro_parser::{NamedMatch, NamedMatch::*};
6
6
use crate :: mbe:: metavar_expr:: { MetaVarExprConcatElem , RAW_IDENT_ERR } ;
7
7
use crate :: mbe:: { self , KleeneOp , MetaVarExpr } ;
8
8
use 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 } ;
11
11
use rustc_ast:: tokenstream:: { DelimSpacing , DelimSpan , Spacing , TokenStream , TokenTree } ;
12
+ use rustc_ast:: ExprKind ;
12
13
use rustc_data_structures:: fx:: FxHashMap ;
13
14
use rustc_errors:: { pluralize, Diag , DiagCtxtHandle , PResult } ;
14
15
use rustc_parse:: lexer:: nfc_normalize;
@@ -17,7 +18,7 @@ use rustc_session::parse::ParseSess;
17
18
use rustc_session:: parse:: SymbolGallery ;
18
19
use rustc_span:: hygiene:: { LocalExpnId , Transparency } ;
19
20
use 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 } ;
21
22
use smallvec:: { smallvec, SmallVec } ;
22
23
use std:: mem;
23
24
@@ -691,12 +692,12 @@ fn transcribe_metavar_expr<'a>(
691
692
MetaVarExpr :: Concat ( ref elements) => {
692
693
let mut concatenated = String :: new ( ) ;
693
694
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) ?,
698
699
} ;
699
- concatenated. push_str ( & string ) ;
700
+ concatenated. push_str ( symbol . as_str ( ) ) ;
700
701
}
701
702
let symbol = nfc_normalize ( & concatenated) ;
702
703
let concatenated_span = visited_span ( ) ;
@@ -750,32 +751,42 @@ fn transcribe_metavar_expr<'a>(
750
751
Ok ( ( ) )
751
752
}
752
753
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 > (
755
756
dcx : DiagCtxtHandle < ' a > ,
756
757
ident : Ident ,
757
758
interp : & FxHashMap < MacroRulesNormalizedIdent , NamedMatch > ,
758
- ) -> PResult < ' a , String > {
759
+ ) -> PResult < ' a , Symbol > {
759
760
if let NamedMatch :: MatchedSingle ( pnr) = matched_from_ident ( dcx, ident, interp) ? {
760
761
if let ParseNtResult :: Ident ( nt_ident, is_raw) = pnr {
761
762
if let IdentIsRaw :: Yes = is_raw {
762
763
return Err ( dcx. struct_span_err ( ident. span , RAW_IDENT_ERR ) ) ;
763
764
}
764
- return Ok ( nt_ident. to_string ( ) ) ;
765
+ return Ok ( nt_ident. name ) ;
765
766
}
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 ) ;
773
774
}
774
- return Ok ( token_ident. to_string ( ) ) ;
775
+
776
+ if let TokenKind :: Literal ( Lit { kind : LitKind :: Str , symbol, suffix : None } ) = kind {
777
+ return Ok ( * symbol) ;
778
+ }
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) ;
775
786
}
776
787
}
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 ) )
781
792
}
0 commit comments