@@ -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