mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 23:04:33 +00:00
Rollup merge of #114511 - chenyukang:yukang-fix-114374-fmt-args, r=b-naber
Remove the unhelpful let binding diag comes from FormatArguments Fixes #114374
This commit is contained in:
commit
b046541b62
@ -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;
|
||||
}
|
||||
|
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