@@ -9,7 +9,7 @@ use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind};
99use rustc_attr:: { self as attr, Deprecation , Stability } ;
1010use rustc_data_structures:: fx:: FxHashMap ;
1111use rustc_data_structures:: sync:: { self , Lrc } ;
12- use rustc_errors:: { DiagnosticBuilder , ErrorReported } ;
12+ use rustc_errors:: { Applicability , DiagnosticBuilder , ErrorReported } ;
1313use rustc_lint_defs:: builtin:: PROC_MACRO_BACK_COMPAT ;
1414use rustc_lint_defs:: BuiltinLintDiagnostics ;
1515use rustc_parse:: { self , nt_to_tokenstream, parser, MACRO_ARGUMENTS } ;
@@ -1133,36 +1133,51 @@ impl<'a> ExtCtxt<'a> {
11331133}
11341134
11351135/// Extracts a string literal from the macro expanded version of `expr`,
1136- /// emitting `err_msg` if `expr` is not a string literal. This does not stop
1137- /// compilation on error, merely emits a non-fatal error and returns `None`.
1136+ /// returning a diagnostic error of `err_msg` if `expr` is not a string literal.
1137+ /// The returned bool indicates whether an applicable suggestion has already been
1138+ /// added to the diagnostic to avoid emitting multiple suggestions. `Err(None)`
1139+ /// indicates that an ast error was encountered.
11381140pub fn expr_to_spanned_string < ' a > (
11391141 cx : & ' a mut ExtCtxt < ' _ > ,
11401142 expr : P < ast:: Expr > ,
11411143 err_msg : & str ,
1142- ) -> Result < ( Symbol , ast:: StrStyle , Span ) , Option < DiagnosticBuilder < ' a > > > {
1144+ ) -> Result < ( Symbol , ast:: StrStyle , Span ) , Option < ( DiagnosticBuilder < ' a > , bool ) > > {
11431145 // Perform eager expansion on the expression.
11441146 // We want to be able to handle e.g., `concat!("foo", "bar")`.
11451147 let expr = cx. expander ( ) . fully_expand_fragment ( AstFragment :: Expr ( expr) ) . make_expr ( ) ;
11461148
11471149 Err ( match expr. kind {
11481150 ast:: ExprKind :: Lit ( ref l) => match l. kind {
11491151 ast:: LitKind :: Str ( s, style) => return Ok ( ( s, style, expr. span ) ) ,
1152+ ast:: LitKind :: ByteStr ( _) => {
1153+ let mut err = cx. struct_span_err ( l. span , err_msg) ;
1154+ err. span_suggestion (
1155+ expr. span . shrink_to_lo ( ) ,
1156+ "consider removing the leading `b`" ,
1157+ String :: new ( ) ,
1158+ Applicability :: MaybeIncorrect ,
1159+ ) ;
1160+ Some ( ( err, true ) )
1161+ }
11501162 ast:: LitKind :: Err ( _) => None ,
1151- _ => Some ( cx. struct_span_err ( l. span , err_msg) ) ,
1163+ _ => Some ( ( cx. struct_span_err ( l. span , err_msg) , false ) ) ,
11521164 } ,
11531165 ast:: ExprKind :: Err => None ,
1154- _ => Some ( cx. struct_span_err ( expr. span , err_msg) ) ,
1166+ _ => Some ( ( cx. struct_span_err ( expr. span , err_msg) , false ) ) ,
11551167 } )
11561168}
11571169
1170+ /// Extracts a string literal from the macro expanded version of `expr`,
1171+ /// emitting `err_msg` if `expr` is not a string literal. This does not stop
1172+ /// compilation on error, merely emits a non-fatal error and returns `None`.
11581173pub fn expr_to_string (
11591174 cx : & mut ExtCtxt < ' _ > ,
11601175 expr : P < ast:: Expr > ,
11611176 err_msg : & str ,
11621177) -> Option < ( Symbol , ast:: StrStyle ) > {
11631178 expr_to_spanned_string ( cx, expr, err_msg)
11641179 . map_err ( |err| {
1165- err. map ( |mut err| {
1180+ err. map ( |( mut err, _ ) | {
11661181 err. emit ( ) ;
11671182 } )
11681183 } )
0 commit comments