Provide structured suggestion for dropped temp value

This commit is contained in:
Esteban Küber 2022-07-14 17:12:01 -07:00
parent 0fe5390a88
commit 20b5aaf111
20 changed files with 205 additions and 35 deletions

View file

@ -1500,7 +1500,38 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
| BorrowExplanation::UsedLaterInLoop(..)
| BorrowExplanation::UsedLaterWhenDropped { .. } => {
// Only give this note and suggestion if it could be relevant.
err.note("consider using a `let` binding to create a longer lived value");
let sm = self.infcx.tcx.sess.source_map();
let mut suggested = false;
let msg = "consider using a `let` binding to create a longer lived value";
if let Some(scope) =
self.body.source_scopes.get(self.body.source_info(location).scope)
&& let ClearCrossCrate::Set(scope_data) = &scope.local_data
&& let Some(node) = self.infcx.tcx.hir().find(scope_data.lint_root)
&& let Some(id) = node.body_id()
&& let hir::ExprKind::Block(block, _) = self.infcx.tcx.hir().body(id).value.kind
{
for stmt in block.stmts {
if 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,
);
suggested = true;
break;
}
}
}
if !suggested {
err.note(msg);
}
}
_ => {}
}

View file

@ -0,0 +1,14 @@
// run-rustfix
use std::collections::HashMap;
fn main() {
let tmp: Box<_>;
let mut buggy_map: HashMap<usize, &usize> = HashMap::new();
let binding = Box::new(1);
buggy_map.insert(42, &*binding); //~ ERROR temporary value dropped while borrowed
// but it is ok if we use a temporary
tmp = Box::new(2);
buggy_map.insert(43, &*tmp);
}

View file

@ -1,9 +1,7 @@
// run-rustfix
use std::collections::HashMap;
fn main() {
let tmp: Box<_>;
let mut buggy_map: HashMap<usize, &usize> = HashMap::new();

View file

@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/borrowck-borrowed-uniq-rvalue.rs:10:28
--> $DIR/borrowck-borrowed-uniq-rvalue.rs:8:28
|
LL | buggy_map.insert(42, &*Box::new(1));
| ^^^^^^^^^^^ - temporary value is freed at the end of this statement
@ -9,7 +9,11 @@ LL | buggy_map.insert(42, &*Box::new(1));
LL | buggy_map.insert(43, &*tmp);
| --------------------------- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = Box::new(1);
LL ~ buggy_map.insert(42, &*binding);
|
error: aborting due to previous error

View file

@ -9,7 +9,11 @@ LL | let x1 = arg(&AddFlags(1));
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = AddFlags(1);
LL ~ let x1 = arg(&binding);
|
error[E0716]: temporary value dropped while borrowed
--> $DIR/cleanup-rvalue-scopes-cf.rs:27:14
@ -22,7 +26,11 @@ LL | let x2 = AddFlags(1).get();
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = AddFlags(1);
LL ~ let x2 = binding.get();
|
error[E0716]: temporary value dropped while borrowed
--> $DIR/cleanup-rvalue-scopes-cf.rs:28:21
@ -35,7 +43,11 @@ LL | let x3 = &*arg(&AddFlags(1));
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = AddFlags(1);
LL ~ let x3 = &*arg(&binding);
|
error[E0716]: temporary value dropped while borrowed
--> $DIR/cleanup-rvalue-scopes-cf.rs:29:24
@ -48,7 +60,11 @@ LL | let ref x4 = *arg(&AddFlags(1));
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = AddFlags(1);
LL ~ let ref x4 = *arg(&binding);
|
error[E0716]: temporary value dropped while borrowed
--> $DIR/cleanup-rvalue-scopes-cf.rs:30:24
@ -61,7 +77,11 @@ LL | let &ref x5 = arg(&AddFlags(1));
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = AddFlags(1);
LL ~ let &ref x5 = arg(&binding);
|
error[E0716]: temporary value dropped while borrowed
--> $DIR/cleanup-rvalue-scopes-cf.rs:31:14
@ -74,7 +94,11 @@ LL | let x6 = AddFlags(1).get();
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = AddFlags(1);
LL ~ let x6 = binding.get();
|
error[E0716]: temporary value dropped while borrowed
--> $DIR/cleanup-rvalue-scopes-cf.rs:32:44
@ -87,7 +111,11 @@ LL |
LL | (x1, x2, x3, x4, x5, x6, x7);
| -- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = AddFlags(1);
LL ~ let StackBox { f: x7 } = StackBox { f: binding.get() };
|
error: aborting due to 7 previous errors

View file

@ -0,0 +1,9 @@
// run-rustfix
fn id<T>(x: T) -> T { x }
fn main() {
let x = Some(3);
let binding = id(5);
let y = x.as_ref().unwrap_or(&binding); //~ ERROR
let _ = &y;
}

View file

@ -1,7 +1,8 @@
// run-rustfix
fn id<T>(x: T) -> T { x }
fn main() {
let x = Some(3);
let y = x.as_ref().unwrap_or(&id(5)); //~ ERROR
&y;
let _ = &y;
}

View file

@ -1,14 +1,18 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/issue-11493.rs:5:35
--> $DIR/issue-11493.rs:6:35
|
LL | let y = x.as_ref().unwrap_or(&id(5));
| ^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
LL | &y;
| -- borrow later used here
LL | let _ = &y;
| -- borrow later used here
|
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = id(5);
LL ~ let y = x.as_ref().unwrap_or(&binding);
|
= note: consider using a `let` binding to create a longer lived value
error: aborting due to previous error

View file

@ -0,0 +1,17 @@
// run-rustfix
use std::cell::RefCell;
fn main() {
let mut r = 0;
let s = 0;
let x = RefCell::new((&mut r,s));
let binding = x.borrow();
let val: &_ = binding.0;
//~^ ERROR temporary value dropped while borrowed [E0716]
//~| NOTE temporary value is freed at the end of this statement
//~| NOTE creates a temporary which is freed while still in use
//~| HELP consider using a `let` binding to create a longer lived value
println!("{}", val);
//~^ borrow later used here
}

View file

@ -1,3 +1,4 @@
// run-rustfix
use std::cell::RefCell;
fn main() {
@ -9,7 +10,7 @@ fn main() {
//~^ ERROR temporary value dropped while borrowed [E0716]
//~| NOTE temporary value is freed at the end of this statement
//~| NOTE creates a temporary which is freed while still in use
//~| NOTE consider using a `let` binding to create a longer lived value
//~| HELP consider using a `let` binding to create a longer lived value
println!("{}", val);
//~^ borrow later used here
}

View file

@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/issue-36082.rs:8:19
--> $DIR/issue-36082.rs:9:19
|
LL | let val: &_ = x.borrow().0;
| ^^^^^^^^^^ - temporary value is freed at the end of this statement
@ -9,7 +9,11 @@ LL | let val: &_ = x.borrow().0;
LL | println!("{}", val);
| --- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = x.borrow();
LL ~ let val: &_ = binding.0;
|
error: aborting due to previous error

View file

@ -9,7 +9,13 @@ LL | });
LL | println!("{:?}", x);
| - borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = (v,);
LL ~ let x = gimme({
LL | let v = 22;
LL ~ &binding
|
error: aborting due to previous error

View file

@ -20,9 +20,9 @@ fn f() {
//~^ ERROR temporary value dropped while borrowed
//~| NOTE creates a temporary which is freed while still in use
//~| NOTE temporary value is freed at the end of this statement
//~| NOTE consider using a `let` binding to create a longer lived value
//~| HELP consider using a `let` binding to create a longer lived value
{
{ //~ HELP consider using a `let` binding to create a longer lived value
let mut v4 = Vec::new(); // (sub) statement 0
@ -30,7 +30,6 @@ fn f() {
//~^ ERROR temporary value dropped while borrowed
//~| NOTE creates a temporary which is freed while still in use
//~| NOTE temporary value is freed at the end of this statement
//~| NOTE consider using a `let` binding to create a longer lived value
v4.use_ref();
//~^ NOTE borrow later used here
} // (statement 7)
@ -41,7 +40,7 @@ fn f() {
//~^ ERROR temporary value dropped while borrowed
//~| NOTE creates a temporary which is freed while still in use
//~| NOTE temporary value is freed at the end of this statement
//~| NOTE consider using a `let` binding to create a longer lived value
//~| HELP consider using a `let` binding to create a longer lived value
v1.push(&old[0]);

View file

@ -21,7 +21,11 @@ LL | v3.push(&id('x')); // statement 6
LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref();
| -- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = id('x');
LL ~ v3.push(&binding); // statement 6
|
error[E0716]: temporary value dropped while borrowed
--> $DIR/borrowck-let-suggestion-suffixes.rs:29:18
@ -34,10 +38,18 @@ LL | v4.push(&id('y'));
LL | v4.use_ref();
| ------------ borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = id('y');
LL ~ {
LL |
LL | let mut v4 = Vec::new(); // (sub) statement 0
LL |
LL ~ v4.push(&binding);
|
error[E0716]: temporary value dropped while borrowed
--> $DIR/borrowck-let-suggestion-suffixes.rs:40:14
--> $DIR/borrowck-let-suggestion-suffixes.rs:39:14
|
LL | v5.push(&id('z'));
| ^^^^^^^ - temporary value is freed at the end of this statement
@ -47,7 +59,11 @@ LL | v5.push(&id('z'));
LL | (v1, v2, v3, /* v4 is above. */ v5).use_ref();
| -- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = id('z');
LL ~ v5.push(&binding);
|
error: aborting due to 4 previous errors

View file

@ -0,0 +1,13 @@
// run-rustfix
fn main() {
let msg;
let binding = Some("Hello".to_string());
match binding {
//~^ ERROR temporary value dropped while borrowed
Some(ref m) => {
msg = m;
},
None => { panic!() }
}
println!("{}", *msg);
}

View file

@ -1,3 +1,4 @@
// run-rustfix
fn main() {
let msg;
match Some("Hello".to_string()) {

View file

@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/borrowck-ref-into-rvalue.rs:3:11
--> $DIR/borrowck-ref-into-rvalue.rs:4:11
|
LL | match Some("Hello".to_string()) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
@ -9,7 +9,11 @@ LL | }
LL | println!("{}", *msg);
| ---- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = Some("Hello".to_string());
LL ~ match binding {
|
error: aborting due to previous error

View file

@ -0,0 +1,14 @@
// run-rustfix
fn id<T>(x: T) -> T { x }
fn main() {
let binding = id(3);
let v = vec![
&binding
];
//~^^ ERROR temporary value dropped while borrowed
for &&x in &v {
println!("{}", x + 3);
}
}

View file

@ -1,3 +1,4 @@
// run-rustfix
fn id<T>(x: T) -> T { x }
fn main() {

View file

@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/issue-15480.rs:5:10
--> $DIR/issue-15480.rs:6:10
|
LL | &id(3)
| ^^^^^ creates a temporary which is freed while still in use
@ -9,7 +9,12 @@ LL | ];
LL | for &&x in &v {
| -- borrow later used here
|
= note: consider using a `let` binding to create a longer lived value
help: consider using a `let` binding to create a longer lived value
|
LL ~ let binding = id(3);
LL ~ let v = vec![
LL ~ &binding
|
error: aborting due to previous error