@@ -10,7 +10,7 @@ use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind};
1010use rustc_attr:: { self as attr, Deprecation , Stability } ;
1111use rustc_data_structures:: fx:: FxHashMap ;
1212use rustc_data_structures:: sync:: { self , Lrc } ;
13- use rustc_errors:: { DiagnosticBuilder , ErrorReported } ;
13+ use rustc_errors:: { Applicability , DiagnosticBuilder , ErrorReported } ;
1414use rustc_lint_defs:: builtin:: PROC_MACRO_BACK_COMPAT ;
1515use rustc_lint_defs:: BuiltinLintDiagnostics ;
1616use rustc_parse:: { self , nt_to_tokenstream, parser, MACRO_ARGUMENTS } ;
@@ -1136,36 +1136,51 @@ impl<'a> ExtCtxt<'a> {
11361136}
11371137
11381138/// Extracts a string literal from the macro expanded version of `expr`,
1139- /// emitting `err_msg` if `expr` is not a string literal. This does not stop
1140- /// compilation on error, merely emits a non-fatal error and returns `None`.
1139+ /// returning a diagnostic error of `err_msg` if `expr` is not a string literal.
1140+ /// The returned bool indicates whether an applicable suggestion has already been
1141+ /// added to the diagnostic to avoid emitting multiple suggestions. `Err(None)`
1142+ /// indicates that an ast error was encountered.
11411143pub fn expr_to_spanned_string < ' a > (
11421144 cx : & ' a mut ExtCtxt < ' _ > ,
11431145 expr : P < ast:: Expr > ,
11441146 err_msg : & str ,
1145- ) -> Result < ( Symbol , ast:: StrStyle , Span ) , Option < DiagnosticBuilder < ' a > > > {
1147+ ) -> Result < ( Symbol , ast:: StrStyle , Span ) , Option < ( DiagnosticBuilder < ' a > , bool ) > > {
11461148 // Perform eager expansion on the expression.
11471149 // We want to be able to handle e.g., `concat!("foo", "bar")`.
11481150 let expr = cx. expander ( ) . fully_expand_fragment ( AstFragment :: Expr ( expr) ) . make_expr ( ) ;
11491151
11501152 Err ( match expr. kind {
11511153 ast:: ExprKind :: Lit ( ref l) => match l. kind {
11521154 ast:: LitKind :: Str ( s, style) => return Ok ( ( s, style, expr. span ) ) ,
1155+ ast:: LitKind :: ByteStr ( _) => {
1156+ let mut err = cx. struct_span_err ( l. span , err_msg) ;
1157+ err. span_suggestion (
1158+ expr. span . shrink_to_lo ( ) ,
1159+ "consider removing the leading `b`" ,
1160+ String :: new ( ) ,
1161+ Applicability :: MaybeIncorrect ,
1162+ ) ;
1163+ Some ( ( err, true ) )
1164+ }
11531165 ast:: LitKind :: Err ( _) => None ,
1154- _ => Some ( cx. struct_span_err ( l. span , err_msg) ) ,
1166+ _ => Some ( ( cx. struct_span_err ( l. span , err_msg) , false ) ) ,
11551167 } ,
11561168 ast:: ExprKind :: Err => None ,
1157- _ => Some ( cx. struct_span_err ( expr. span , err_msg) ) ,
1169+ _ => Some ( ( cx. struct_span_err ( expr. span , err_msg) , false ) ) ,
11581170 } )
11591171}
11601172
1173+ /// Extracts a string literal from the macro expanded version of `expr`,
1174+ /// emitting `err_msg` if `expr` is not a string literal. This does not stop
1175+ /// compilation on error, merely emits a non-fatal error and returns `None`.
11611176pub fn expr_to_string (
11621177 cx : & mut ExtCtxt < ' _ > ,
11631178 expr : P < ast:: Expr > ,
11641179 err_msg : & str ,
11651180) -> Option < ( Symbol , ast:: StrStyle ) > {
11661181 expr_to_spanned_string ( cx, expr, err_msg)
11671182 . map_err ( |err| {
1168- err. map ( |mut err| {
1183+ err. map ( |( mut err, _ ) | {
11691184 err. emit ( ) ;
11701185 } )
11711186 } )
0 commit comments