1
Fork 0

Remove the unhelpful let binding diag comes from FormatArguments

This commit is contained in:
yukang 2023-08-05 19:07:42 +08:00
parent a1e1dba9cc
commit 1f107b1ef3
3 changed files with 86 additions and 13 deletions

View file

@ -2130,21 +2130,27 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
/// misleading users in cases like `tests/ui/nll/borrowed-temporary-error.rs`.
/// We could expand the analysis to suggest hoising all of the relevant parts of
/// the users' code to make the code compile, but that could be too much.
struct NestedStatementVisitor {
/// We found the `prop_expr` by the way to check whether the expression is a `FormatArguments`,
/// which is a special case since it's generated by the compiler.
struct NestedStatementVisitor<'tcx> {
span: Span,
current: usize,
found: usize,
prop_expr: Option<&'tcx hir::Expr<'tcx>>,
}
impl<'tcx> Visitor<'tcx> for NestedStatementVisitor {
fn visit_block(&mut self, block: &hir::Block<'tcx>) {
impl<'tcx> Visitor<'tcx> for NestedStatementVisitor<'tcx> {
fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
self.current += 1;
walk_block(self, block);
self.current -= 1;
}
fn visit_expr(&mut self, expr: &hir::Expr<'tcx>) {
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
if self.span == expr.span.source_callsite() {
self.found = self.current;
if self.prop_expr.is_none() {
self.prop_expr = Some(expr);
}
}
walk_expr(self, expr);
}
@ -2162,22 +2168,40 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
span: proper_span,
current: 0,
found: 0,
prop_expr: None,
};
visitor.visit_stmt(stmt);
let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
let expr_ty: Option<Ty<'_>> = visitor.prop_expr.map(|expr| typeck_results.expr_ty(expr).peel_refs());
let is_format_arguments_item =
if let Some(expr_ty) = expr_ty
&& let ty::Adt(adt, _) = expr_ty.kind() {
self.infcx.tcx.lang_items().get(LangItem::FormatArguments) == Some(adt.did())
} else {
false
};
if visitor.found == 0
&& stmt.span.contains(proper_span)
&& let Some(p) = sm.span_to_margin(stmt.span)
&& let Ok(s) = sm.span_to_snippet(proper_span)
{
let addition = format!("let binding = {};\n{}", s, " ".repeat(p));
err.multipart_suggestion_verbose(
msg,
vec![
(stmt.span.shrink_to_lo(), addition),
(proper_span, "binding".to_string()),
],
Applicability::MaybeIncorrect,
);
if !is_format_arguments_item {
let addition = format!("let binding = {};\n{}", s, " ".repeat(p));
err.multipart_suggestion_verbose(
msg,
vec![
(stmt.span.shrink_to_lo(), addition),
(proper_span, "binding".to_string()),
],
Applicability::MaybeIncorrect,
);
} else {
err.note("the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used");
err.note("to learn more, visit <https://doc.rust-lang.org/std/macro.format_args.html>");
}
suggested = true;
break;
}