Remove the unhelpful let binding diag comes from FormatArguments
This commit is contained in:
parent
a1e1dba9cc
commit
1f107b1ef3
@ -2130,21 +2130,27 @@ fn report_temporary_value_does_not_live_long_enough(
|
|||||||
/// misleading users in cases like `tests/ui/nll/borrowed-temporary-error.rs`.
|
/// 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
|
/// 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.
|
/// 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,
|
span: Span,
|
||||||
current: usize,
|
current: usize,
|
||||||
found: usize,
|
found: usize,
|
||||||
|
prop_expr: Option<&'tcx hir::Expr<'tcx>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> Visitor<'tcx> for NestedStatementVisitor {
|
impl<'tcx> Visitor<'tcx> for NestedStatementVisitor<'tcx> {
|
||||||
fn visit_block(&mut self, block: &hir::Block<'tcx>) {
|
fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
|
||||||
self.current += 1;
|
self.current += 1;
|
||||||
walk_block(self, block);
|
walk_block(self, block);
|
||||||
self.current -= 1;
|
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() {
|
if self.span == expr.span.source_callsite() {
|
||||||
self.found = self.current;
|
self.found = self.current;
|
||||||
|
if self.prop_expr.is_none() {
|
||||||
|
self.prop_expr = Some(expr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
walk_expr(self, expr);
|
walk_expr(self, expr);
|
||||||
}
|
}
|
||||||
@ -2162,13 +2168,27 @@ fn visit_expr(&mut self, expr: &hir::Expr<'tcx>) {
|
|||||||
span: proper_span,
|
span: proper_span,
|
||||||
current: 0,
|
current: 0,
|
||||||
found: 0,
|
found: 0,
|
||||||
|
prop_expr: None,
|
||||||
};
|
};
|
||||||
visitor.visit_stmt(stmt);
|
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
|
if visitor.found == 0
|
||||||
&& stmt.span.contains(proper_span)
|
&& stmt.span.contains(proper_span)
|
||||||
&& let Some(p) = sm.span_to_margin(stmt.span)
|
&& let Some(p) = sm.span_to_margin(stmt.span)
|
||||||
&& let Ok(s) = sm.span_to_snippet(proper_span)
|
&& let Ok(s) = sm.span_to_snippet(proper_span)
|
||||||
{
|
{
|
||||||
|
if !is_format_arguments_item {
|
||||||
let addition = format!("let binding = {};\n{}", s, " ".repeat(p));
|
let addition = format!("let binding = {};\n{}", s, " ".repeat(p));
|
||||||
err.multipart_suggestion_verbose(
|
err.multipart_suggestion_verbose(
|
||||||
msg,
|
msg,
|
||||||
@ -2178,6 +2198,10 @@ fn visit_expr(&mut self, expr: &hir::Expr<'tcx>) {
|
|||||||
],
|
],
|
||||||
Applicability::MaybeIncorrect,
|
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;
|
suggested = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
16
tests/ui/borrowck/issue-114374-invalid-help-fmt-args.rs
Normal file
16
tests/ui/borrowck/issue-114374-invalid-help-fmt-args.rs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#![allow(dead_code)]
|
||||||
|
|
||||||
|
fn bar<'a>(_: std::fmt::Arguments<'a>) {}
|
||||||
|
fn main() {
|
||||||
|
let x = format_args!("a {} {} {}.", 1, format_args!("b{}!", 2), 3);
|
||||||
|
//~^ ERROR temporary value dropped while borrowed
|
||||||
|
|
||||||
|
bar(x);
|
||||||
|
|
||||||
|
let foo = format_args!("{}", "hi");
|
||||||
|
//~^ ERROR temporary value dropped while borrowed
|
||||||
|
bar(foo);
|
||||||
|
|
||||||
|
let foo = format_args!("hi"); // no placeholder in arguments, so no error
|
||||||
|
bar(foo);
|
||||||
|
}
|
33
tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr
Normal file
33
tests/ui/borrowck/issue-114374-invalid-help-fmt-args.stderr
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
error[E0716]: temporary value dropped while borrowed
|
||||||
|
--> $DIR/issue-114374-invalid-help-fmt-args.rs:5:13
|
||||||
|
|
|
||||||
|
LL | let x = format_args!("a {} {} {}.", 1, format_args!("b{}!", 2), 3);
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
|
||||||
|
| |
|
||||||
|
| creates a temporary value which is freed while still in use
|
||||||
|
...
|
||||||
|
LL | bar(x);
|
||||||
|
| - borrow later used here
|
||||||
|
|
|
||||||
|
= note: the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used
|
||||||
|
= note: to learn more, visit <https://doc.rust-lang.org/std/macro.format_args.html>
|
||||||
|
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error[E0716]: temporary value dropped while borrowed
|
||||||
|
--> $DIR/issue-114374-invalid-help-fmt-args.rs:10:15
|
||||||
|
|
|
||||||
|
LL | let foo = format_args!("{}", "hi");
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^- temporary value is freed at the end of this statement
|
||||||
|
| |
|
||||||
|
| creates a temporary value which is freed while still in use
|
||||||
|
LL |
|
||||||
|
LL | bar(foo);
|
||||||
|
| --- borrow later used here
|
||||||
|
|
|
||||||
|
= note: the result of `format_args!` can only be assigned directly if no placeholders in it's arguments are used
|
||||||
|
= note: to learn more, visit <https://doc.rust-lang.org/std/macro.format_args.html>
|
||||||
|
= note: this error originates in the macro `format_args` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0716`.
|
Loading…
Reference in New Issue
Block a user