Rollup merge of #136032 - estebank:issue-136028, r=SparrowLii
Account for mutable borrow in argument suggestion ``` error: value assigned to `object` is never read --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:21:5 | LL | object = &mut object2; | ^^^^^^ | help: you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding | LL ~ fn change_object3(object: &mut Object) { LL | LL | let object2 = Object; LL ~ *object = object2; | ``` instead of ``` error: value assigned to `object` is never read --> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:21:5 | LL | object = &mut object2; | ^^^^^^ | help: you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding | LL ~ fn change_object3(object: &mut mut Object) { LL | LL | let object2 = Object; LL ~ *object = object2; | ``` Fix #136028.
This commit is contained in:
commit
64550d1ed8
6 changed files with 114 additions and 57 deletions
|
@ -851,32 +851,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
&& let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind
|
&& let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind
|
||||||
|
|
||||||
// Look for the type corresponding to the argument pattern we have in the argument list.
|
// Look for the type corresponding to the argument pattern we have in the argument list.
|
||||||
&& let Some(ty_sugg) = fn_decl
|
&& let Some(ty_ref) = fn_decl
|
||||||
.inputs
|
.inputs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|ty| {
|
.filter_map(|ty| match ty.kind {
|
||||||
if ty.span == *ty_span
|
hir::TyKind::Ref(lt, mut_ty) if ty.span == *ty_span => Some((lt, mut_ty)),
|
||||||
&& let hir::TyKind::Ref(lt, x) = ty.kind
|
_ => None,
|
||||||
{
|
|
||||||
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
|
|
||||||
Some((
|
|
||||||
x.ty.span.shrink_to_lo(),
|
|
||||||
format!(
|
|
||||||
"{}mut ",
|
|
||||||
if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " }
|
|
||||||
),
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.next()
|
.next()
|
||||||
{
|
{
|
||||||
let sugg = vec![
|
let mut sugg = if ty_ref.1.mutbl.is_mut() {
|
||||||
ty_sugg,
|
// Leave `&'name mut Ty` and `&mut Ty` as they are (#136028).
|
||||||
|
vec![]
|
||||||
|
} else {
|
||||||
|
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
|
||||||
|
vec![(
|
||||||
|
ty_ref.1.ty.span.shrink_to_lo(),
|
||||||
|
format!(
|
||||||
|
"{}mut ",
|
||||||
|
if ty_ref.0.ident.span.lo() == ty_ref.0.ident.span.hi() { "" } else { " " },
|
||||||
|
),
|
||||||
|
)]
|
||||||
|
};
|
||||||
|
sugg.extend([
|
||||||
(pat.span.until(ident.span), String::new()),
|
(pat.span.until(ident.span), String::new()),
|
||||||
(lhs.span.shrink_to_lo(), "*".to_string()),
|
(lhs.span.shrink_to_lo(), "*".to_string()),
|
||||||
];
|
]);
|
||||||
// We suggest changing the argument from `mut ident: &Ty` to `ident: &'_ mut Ty` and the
|
// We suggest changing the argument from `mut ident: &Ty` to `ident: &'_ mut Ty` and the
|
||||||
// assignment from `ident = val;` to `*ident = val;`.
|
// assignment from `ident = val;` to `*ident = val;`.
|
||||||
err.multipart_suggestion_verbose(
|
err.multipart_suggestion_verbose(
|
||||||
|
|
|
@ -1791,7 +1791,7 @@ pub(crate) struct UnusedAssign {
|
||||||
pub(crate) struct UnusedAssignSuggestion {
|
pub(crate) struct UnusedAssignSuggestion {
|
||||||
pub pre: &'static str,
|
pub pre: &'static str,
|
||||||
#[suggestion_part(code = "{pre}mut ")]
|
#[suggestion_part(code = "{pre}mut ")]
|
||||||
pub ty_span: Span,
|
pub ty_span: Option<Span>,
|
||||||
#[suggestion_part(code = "")]
|
#[suggestion_part(code = "")]
|
||||||
pub ty_ref_span: Span,
|
pub ty_ref_span: Span,
|
||||||
#[suggestion_part(code = "*")]
|
#[suggestion_part(code = "*")]
|
||||||
|
|
|
@ -1620,24 +1620,28 @@ impl<'tcx> Liveness<'_, 'tcx> {
|
||||||
&& let item = self.ir.tcx.hir_owner_node(item_id)
|
&& let item = self.ir.tcx.hir_owner_node(item_id)
|
||||||
&& let Some(fn_decl) = item.fn_decl()
|
&& let Some(fn_decl) = item.fn_decl()
|
||||||
&& let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind
|
&& let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind
|
||||||
&& let Some((ty_span, pre)) = fn_decl
|
&& let Some((lt, mut_ty)) = fn_decl
|
||||||
.inputs
|
.inputs
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|ty| {
|
.filter_map(|ty| {
|
||||||
if ty.span == *ty_span
|
if ty.span == *ty_span
|
||||||
&& let hir::TyKind::Ref(lt, mut_ty) = ty.kind
|
&& let hir::TyKind::Ref(lt, mut_ty) = ty.kind
|
||||||
{
|
{
|
||||||
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
|
Some((lt, mut_ty))
|
||||||
Some((
|
|
||||||
mut_ty.ty.span.shrink_to_lo(),
|
|
||||||
if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " },
|
|
||||||
))
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.next()
|
.next()
|
||||||
{
|
{
|
||||||
|
let ty_span = if mut_ty.mutbl.is_mut() {
|
||||||
|
// Leave `&'name mut Ty` and `&mut Ty` as they are (#136028).
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
|
||||||
|
Some(mut_ty.ty.span.shrink_to_lo())
|
||||||
|
};
|
||||||
|
let pre = if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " };
|
||||||
Some(errors::UnusedAssignSuggestion {
|
Some(errors::UnusedAssignSuggestion {
|
||||||
ty_span,
|
ty_span,
|
||||||
pre,
|
pre,
|
||||||
|
|
|
@ -1,17 +1,26 @@
|
||||||
//@ run-rustfix
|
//@ run-rustfix
|
||||||
#![deny(unused_assignments, unused_variables)]
|
#![deny(unused_assignments, unused_variables)]
|
||||||
|
#![allow(unused_mut)]
|
||||||
struct Object;
|
struct Object;
|
||||||
|
|
||||||
fn change_object(object: &mut Object) { //~ HELP you might have meant to mutate
|
fn change_object(object: &mut Object) { //~ HELP you might have meant to mutate
|
||||||
let object2 = Object;
|
let object2 = Object;
|
||||||
*object = object2; //~ ERROR mismatched types
|
*object = object2; //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_object2(object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used
|
fn change_object2(object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used
|
||||||
|
//~^ HELP you might have meant to mutate
|
||||||
|
let object2 = Object;
|
||||||
|
*object = object2;
|
||||||
|
//~^ ERROR `object2` does not live long enough
|
||||||
|
//~| ERROR value assigned to `object` is never read
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_object3(object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used
|
||||||
//~^ HELP you might have meant to mutate
|
//~^ HELP you might have meant to mutate
|
||||||
let object2 = Object;
|
let mut object2 = Object; //~ HELP consider changing this to be mutable
|
||||||
*object = object2;
|
*object = object2;
|
||||||
//~^ ERROR `object2` does not live long enough
|
//~^ ERROR cannot borrow `object2` as mutable
|
||||||
//~| ERROR value assigned to `object` is never read
|
//~| ERROR value assigned to `object` is never read
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,4 +28,5 @@ fn main() {
|
||||||
let mut object = Object;
|
let mut object = Object;
|
||||||
change_object(&mut object);
|
change_object(&mut object);
|
||||||
change_object2(&mut object);
|
change_object2(&mut object);
|
||||||
|
change_object3(&mut object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,26 @@
|
||||||
//@ run-rustfix
|
//@ run-rustfix
|
||||||
#![deny(unused_assignments, unused_variables)]
|
#![deny(unused_assignments, unused_variables)]
|
||||||
|
#![allow(unused_mut)]
|
||||||
struct Object;
|
struct Object;
|
||||||
|
|
||||||
fn change_object(mut object: &Object) { //~ HELP you might have meant to mutate
|
fn change_object(mut object: &Object) { //~ HELP you might have meant to mutate
|
||||||
let object2 = Object;
|
let object2 = Object;
|
||||||
object = object2; //~ ERROR mismatched types
|
object = object2; //~ ERROR mismatched types
|
||||||
}
|
}
|
||||||
|
|
||||||
fn change_object2(mut object: &Object) { //~ ERROR variable `object` is assigned to, but never used
|
fn change_object2(mut object: &Object) { //~ ERROR variable `object` is assigned to, but never used
|
||||||
|
//~^ HELP you might have meant to mutate
|
||||||
|
let object2 = Object;
|
||||||
|
object = &object2;
|
||||||
|
//~^ ERROR `object2` does not live long enough
|
||||||
|
//~| ERROR value assigned to `object` is never read
|
||||||
|
}
|
||||||
|
|
||||||
|
fn change_object3(mut object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used
|
||||||
//~^ HELP you might have meant to mutate
|
//~^ HELP you might have meant to mutate
|
||||||
let object2 = Object;
|
let object2 = Object; //~ HELP consider changing this to be mutable
|
||||||
object = &object2;
|
object = &mut object2;
|
||||||
//~^ ERROR `object2` does not live long enough
|
//~^ ERROR cannot borrow `object2` as mutable
|
||||||
//~| ERROR value assigned to `object` is never read
|
//~| ERROR value assigned to `object` is never read
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,4 +28,5 @@ fn main() {
|
||||||
let mut object = Object;
|
let mut object = Object;
|
||||||
change_object(&mut object);
|
change_object(&mut object);
|
||||||
change_object2(&mut object);
|
change_object2(&mut object);
|
||||||
|
change_object3(&mut object);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,24 @@
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:7:14
|
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:8:13
|
||||||
|
|
|
|
||||||
LL | fn change_object(mut object: &Object) {
|
LL | fn change_object(mut object: &Object) {
|
||||||
| ------- expected due to this parameter type
|
| ------- expected due to this parameter type
|
||||||
LL | let object2 = Object;
|
LL | let object2 = Object;
|
||||||
LL | object = object2;
|
LL | object = object2;
|
||||||
| ^^^^^^^ expected `&Object`, found `Object`
|
| ^^^^^^^ expected `&Object`, found `Object`
|
||||||
|
|
|
|
||||||
help: you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding
|
help: you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding
|
||||||
|
|
|
|
||||||
LL ~ fn change_object(object: &mut Object) {
|
LL ~ fn change_object(object: &mut Object) {
|
||||||
LL | let object2 = Object;
|
LL | let object2 = Object;
|
||||||
LL ~ *object = object2;
|
LL ~ *object = object2;
|
||||||
|
|
|
|
||||||
|
|
||||||
error: value assigned to `object` is never read
|
error: value assigned to `object` is never read
|
||||||
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:13:5
|
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:14:4
|
||||||
|
|
|
|
||||||
LL | object = &object2;
|
LL | object = &object2;
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
|
|
||||||
note: the lint level is defined here
|
note: the lint level is defined here
|
||||||
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:2:9
|
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:2:9
|
||||||
|
@ -29,12 +29,12 @@ help: you might have meant to mutate the pointed at value being passed in, inste
|
||||||
|
|
|
|
||||||
LL ~ fn change_object2(object: &mut Object) {
|
LL ~ fn change_object2(object: &mut Object) {
|
||||||
LL |
|
LL |
|
||||||
LL | let object2 = Object;
|
LL | let object2 = Object;
|
||||||
LL ~ *object = object2;
|
LL ~ *object = object2;
|
||||||
|
|
|
|
||||||
|
|
||||||
error: variable `object` is assigned to, but never used
|
error: variable `object` is assigned to, but never used
|
||||||
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:10:23
|
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:11:23
|
||||||
|
|
|
|
||||||
LL | fn change_object2(mut object: &Object) {
|
LL | fn change_object2(mut object: &Object) {
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
@ -47,23 +47,56 @@ LL | #![deny(unused_assignments, unused_variables)]
|
||||||
| ^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error[E0597]: `object2` does not live long enough
|
error[E0597]: `object2` does not live long enough
|
||||||
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:13:14
|
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:14:13
|
||||||
|
|
|
|
||||||
LL | fn change_object2(mut object: &Object) {
|
LL | fn change_object2(mut object: &Object) {
|
||||||
| - let's call the lifetime of this reference `'1`
|
| - let's call the lifetime of this reference `'1`
|
||||||
LL |
|
LL |
|
||||||
LL | let object2 = Object;
|
LL | let object2 = Object;
|
||||||
| ------- binding `object2` declared here
|
| ------- binding `object2` declared here
|
||||||
LL | object = &object2;
|
LL | object = &object2;
|
||||||
| ---------^^^^^^^^
|
| ---------^^^^^^^^
|
||||||
| | |
|
| | |
|
||||||
| | borrowed value does not live long enough
|
| | borrowed value does not live long enough
|
||||||
| assignment requires that `object2` is borrowed for `'1`
|
| assignment requires that `object2` is borrowed for `'1`
|
||||||
...
|
...
|
||||||
LL | }
|
LL | }
|
||||||
| - `object2` dropped here while still borrowed
|
| - `object2` dropped here while still borrowed
|
||||||
|
|
||||||
error: aborting due to 4 previous errors
|
error: value assigned to `object` is never read
|
||||||
|
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:22:5
|
||||||
|
|
|
||||||
|
LL | object = &mut object2;
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
help: you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding
|
||||||
|
|
|
||||||
|
LL ~ fn change_object3(object: &mut Object) {
|
||||||
|
LL |
|
||||||
|
LL | let object2 = Object;
|
||||||
|
LL ~ *object = object2;
|
||||||
|
|
|
||||||
|
|
||||||
Some errors have detailed explanations: E0308, E0597.
|
error: variable `object` is assigned to, but never used
|
||||||
|
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:19:23
|
||||||
|
|
|
||||||
|
LL | fn change_object3(mut object: &mut Object) {
|
||||||
|
| ^^^^^^
|
||||||
|
|
|
||||||
|
= note: consider using `_object` instead
|
||||||
|
|
||||||
|
error[E0596]: cannot borrow `object2` as mutable, as it is not declared as mutable
|
||||||
|
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:22:14
|
||||||
|
|
|
||||||
|
LL | object = &mut object2;
|
||||||
|
| ^^^^^^^^^^^^ cannot borrow as mutable
|
||||||
|
|
|
||||||
|
help: consider changing this to be mutable
|
||||||
|
|
|
||||||
|
LL | let mut object2 = Object;
|
||||||
|
| +++
|
||||||
|
|
||||||
|
error: aborting due to 7 previous errors
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0308, E0596, E0597.
|
||||||
For more information about an error, try `rustc --explain E0308`.
|
For more information about an error, try `rustc --explain E0308`.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue