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