@@ -10,7 +10,7 @@ use rustc_ast::{self as ast, AstLike, Attribute, Item, NodeId, PatKind};
10
10
use rustc_attr:: { self as attr, Deprecation , Stability } ;
11
11
use rustc_data_structures:: fx:: FxHashMap ;
12
12
use rustc_data_structures:: sync:: { self , Lrc } ;
13
- use rustc_errors:: { DiagnosticBuilder , ErrorReported } ;
13
+ use rustc_errors:: { Applicability , DiagnosticBuilder , ErrorReported } ;
14
14
use rustc_lint_defs:: builtin:: PROC_MACRO_BACK_COMPAT ;
15
15
use rustc_lint_defs:: BuiltinLintDiagnostics ;
16
16
use rustc_parse:: { self , nt_to_tokenstream, parser, MACRO_ARGUMENTS } ;
@@ -1136,36 +1136,51 @@ impl<'a> ExtCtxt<'a> {
1136
1136
}
1137
1137
1138
1138
/// 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.
1141
1143
pub fn expr_to_spanned_string < ' a > (
1142
1144
cx : & ' a mut ExtCtxt < ' _ > ,
1143
1145
expr : P < ast:: Expr > ,
1144
1146
err_msg : & str ,
1145
- ) -> Result < ( Symbol , ast:: StrStyle , Span ) , Option < DiagnosticBuilder < ' a > > > {
1147
+ ) -> Result < ( Symbol , ast:: StrStyle , Span ) , Option < ( DiagnosticBuilder < ' a > , bool ) > > {
1146
1148
// Perform eager expansion on the expression.
1147
1149
// We want to be able to handle e.g., `concat!("foo", "bar")`.
1148
1150
let expr = cx. expander ( ) . fully_expand_fragment ( AstFragment :: Expr ( expr) ) . make_expr ( ) ;
1149
1151
1150
1152
Err ( match expr. kind {
1151
1153
ast:: ExprKind :: Lit ( ref l) => match l. kind {
1152
1154
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
+ }
1153
1165
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 ) ) ,
1155
1167
} ,
1156
1168
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 ) ) ,
1158
1170
} )
1159
1171
}
1160
1172
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`.
1161
1176
pub fn expr_to_string (
1162
1177
cx : & mut ExtCtxt < ' _ > ,
1163
1178
expr : P < ast:: Expr > ,
1164
1179
err_msg : & str ,
1165
1180
) -> Option < ( Symbol , ast:: StrStyle ) > {
1166
1181
expr_to_spanned_string ( cx, expr, err_msg)
1167
1182
. map_err ( |err| {
1168
- err. map ( |mut err| {
1183
+ err. map ( |( mut err, _ ) | {
1169
1184
err. emit ( ) ;
1170
1185
} )
1171
1186
} )
0 commit comments