Skip to content

Commit 64550d1

Browse files
authored
Rollup merge of rust-lang#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 rust-lang#136028.
2 parents 182ccfa + 1dfc437 commit 64550d1

6 files changed

+114
-57
lines changed

compiler/rustc_hir_typeck/src/demand.rs

+19-19
Original file line numberDiff line numberDiff line change
@@ -851,32 +851,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
851851
&& let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind
852852

853853
// Look for the type corresponding to the argument pattern we have in the argument list.
854-
&& let Some(ty_sugg) = fn_decl
854+
&& let Some(ty_ref) = fn_decl
855855
.inputs
856856
.iter()
857-
.filter_map(|ty| {
858-
if ty.span == *ty_span
859-
&& let hir::TyKind::Ref(lt, x) = ty.kind
860-
{
861-
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
862-
Some((
863-
x.ty.span.shrink_to_lo(),
864-
format!(
865-
"{}mut ",
866-
if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " }
867-
),
868-
))
869-
} else {
870-
None
871-
}
857+
.filter_map(|ty| match ty.kind {
858+
hir::TyKind::Ref(lt, mut_ty) if ty.span == *ty_span => Some((lt, mut_ty)),
859+
_ => None,
872860
})
873861
.next()
874862
{
875-
let sugg = vec![
876-
ty_sugg,
863+
let mut sugg = if ty_ref.1.mutbl.is_mut() {
864+
// Leave `&'name mut Ty` and `&mut Ty` as they are (#136028).
865+
vec![]
866+
} else {
867+
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
868+
vec![(
869+
ty_ref.1.ty.span.shrink_to_lo(),
870+
format!(
871+
"{}mut ",
872+
if ty_ref.0.ident.span.lo() == ty_ref.0.ident.span.hi() { "" } else { " " },
873+
),
874+
)]
875+
};
876+
sugg.extend([
877877
(pat.span.until(ident.span), String::new()),
878878
(lhs.span.shrink_to_lo(), "*".to_string()),
879-
];
879+
]);
880880
// We suggest changing the argument from `mut ident: &Ty` to `ident: &'_ mut Ty` and the
881881
// assignment from `ident = val;` to `*ident = val;`.
882882
err.multipart_suggestion_verbose(

compiler/rustc_passes/src/errors.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1791,7 +1791,7 @@ pub(crate) struct UnusedAssign {
17911791
pub(crate) struct UnusedAssignSuggestion {
17921792
pub pre: &'static str,
17931793
#[suggestion_part(code = "{pre}mut ")]
1794-
pub ty_span: Span,
1794+
pub ty_span: Option<Span>,
17951795
#[suggestion_part(code = "")]
17961796
pub ty_ref_span: Span,
17971797
#[suggestion_part(code = "*")]

compiler/rustc_passes/src/liveness.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -1620,24 +1620,28 @@ impl<'tcx> Liveness<'_, 'tcx> {
16201620
&& let item = self.ir.tcx.hir_owner_node(item_id)
16211621
&& let Some(fn_decl) = item.fn_decl()
16221622
&& let hir::PatKind::Binding(hir::BindingMode::MUT, _hir_id, ident, _) = pat.kind
1623-
&& let Some((ty_span, pre)) = fn_decl
1623+
&& let Some((lt, mut_ty)) = fn_decl
16241624
.inputs
16251625
.iter()
16261626
.filter_map(|ty| {
16271627
if ty.span == *ty_span
16281628
&& let hir::TyKind::Ref(lt, mut_ty) = ty.kind
16291629
{
1630-
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
1631-
Some((
1632-
mut_ty.ty.span.shrink_to_lo(),
1633-
if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " },
1634-
))
1630+
Some((lt, mut_ty))
16351631
} else {
16361632
None
16371633
}
16381634
})
16391635
.next()
16401636
{
1637+
let ty_span = if mut_ty.mutbl.is_mut() {
1638+
// Leave `&'name mut Ty` and `&mut Ty` as they are (#136028).
1639+
None
1640+
} else {
1641+
// `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty`
1642+
Some(mut_ty.ty.span.shrink_to_lo())
1643+
};
1644+
let pre = if lt.ident.span.lo() == lt.ident.span.hi() { "" } else { " " };
16411645
Some(errors::UnusedAssignSuggestion {
16421646
ty_span,
16431647
pre,
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
11
//@ run-rustfix
22
#![deny(unused_assignments, unused_variables)]
3+
#![allow(unused_mut)]
34
struct Object;
45

56
fn change_object(object: &mut Object) { //~ HELP you might have meant to mutate
6-
let object2 = Object;
7-
*object = object2; //~ ERROR mismatched types
7+
let object2 = Object;
8+
*object = object2; //~ ERROR mismatched types
89
}
910

1011
fn change_object2(object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used
12+
//~^ HELP you might have meant to mutate
13+
let object2 = Object;
14+
*object = object2;
15+
//~^ ERROR `object2` does not live long enough
16+
//~| ERROR value assigned to `object` is never read
17+
}
18+
19+
fn change_object3(object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used
1120
//~^ HELP you might have meant to mutate
12-
let object2 = Object;
21+
let mut object2 = Object; //~ HELP consider changing this to be mutable
1322
*object = object2;
14-
//~^ ERROR `object2` does not live long enough
23+
//~^ ERROR cannot borrow `object2` as mutable
1524
//~| ERROR value assigned to `object` is never read
1625
}
1726

1827
fn main() {
1928
let mut object = Object;
2029
change_object(&mut object);
2130
change_object2(&mut object);
31+
change_object3(&mut object);
2232
}
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,32 @@
11
//@ run-rustfix
22
#![deny(unused_assignments, unused_variables)]
3+
#![allow(unused_mut)]
34
struct Object;
45

56
fn change_object(mut object: &Object) { //~ HELP you might have meant to mutate
6-
let object2 = Object;
7-
object = object2; //~ ERROR mismatched types
7+
let object2 = Object;
8+
object = object2; //~ ERROR mismatched types
89
}
910

1011
fn change_object2(mut object: &Object) { //~ ERROR variable `object` is assigned to, but never used
12+
//~^ HELP you might have meant to mutate
13+
let object2 = Object;
14+
object = &object2;
15+
//~^ ERROR `object2` does not live long enough
16+
//~| ERROR value assigned to `object` is never read
17+
}
18+
19+
fn change_object3(mut object: &mut Object) { //~ ERROR variable `object` is assigned to, but never used
1120
//~^ HELP you might have meant to mutate
12-
let object2 = Object;
13-
object = &object2;
14-
//~^ ERROR `object2` does not live long enough
21+
let object2 = Object; //~ HELP consider changing this to be mutable
22+
object = &mut object2;
23+
//~^ ERROR cannot borrow `object2` as mutable
1524
//~| ERROR value assigned to `object` is never read
1625
}
1726

1827
fn main() {
1928
let mut object = Object;
2029
change_object(&mut object);
2130
change_object2(&mut object);
31+
change_object3(&mut object);
2232
}
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
error[E0308]: mismatched types
2-
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:7:14
2+
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:8:13
33
|
44
LL | fn change_object(mut object: &Object) {
55
| ------- expected due to this parameter type
6-
LL | let object2 = Object;
7-
LL | object = object2;
8-
| ^^^^^^^ expected `&Object`, found `Object`
6+
LL | let object2 = Object;
7+
LL | object = object2;
8+
| ^^^^^^^ expected `&Object`, found `Object`
99
|
1010
help: you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding
1111
|
1212
LL ~ fn change_object(object: &mut Object) {
13-
LL | let object2 = Object;
14-
LL ~ *object = object2;
13+
LL | let object2 = Object;
14+
LL ~ *object = object2;
1515
|
1616

1717
error: value assigned to `object` is never read
18-
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:13:5
18+
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:14:4
1919
|
20-
LL | object = &object2;
21-
| ^^^^^^
20+
LL | object = &object2;
21+
| ^^^^^^
2222
|
2323
note: the lint level is defined here
2424
--> $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
2929
|
3030
LL ~ fn change_object2(object: &mut Object) {
3131
LL |
32-
LL | let object2 = Object;
33-
LL ~ *object = object2;
32+
LL | let object2 = Object;
33+
LL ~ *object = object2;
3434
|
3535

3636
error: variable `object` is assigned to, but never used
37-
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:10:23
37+
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:11:23
3838
|
3939
LL | fn change_object2(mut object: &Object) {
4040
| ^^^^^^
@@ -47,23 +47,56 @@ LL | #![deny(unused_assignments, unused_variables)]
4747
| ^^^^^^^^^^^^^^^^
4848

4949
error[E0597]: `object2` does not live long enough
50-
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:13:14
50+
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:14:13
5151
|
5252
LL | fn change_object2(mut object: &Object) {
5353
| - let's call the lifetime of this reference `'1`
5454
LL |
55-
LL | let object2 = Object;
56-
| ------- binding `object2` declared here
57-
LL | object = &object2;
58-
| ---------^^^^^^^^
59-
| | |
60-
| | borrowed value does not live long enough
61-
| assignment requires that `object2` is borrowed for `'1`
55+
LL | let object2 = Object;
56+
| ------- binding `object2` declared here
57+
LL | object = &object2;
58+
| ---------^^^^^^^^
59+
| | |
60+
| | borrowed value does not live long enough
61+
| assignment requires that `object2` is borrowed for `'1`
6262
...
6363
LL | }
6464
| - `object2` dropped here while still borrowed
6565

66-
error: aborting due to 4 previous errors
66+
error: value assigned to `object` is never read
67+
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:22:5
68+
|
69+
LL | object = &mut object2;
70+
| ^^^^^^
71+
|
72+
help: you might have meant to mutate the pointed at value being passed in, instead of changing the reference in the local binding
73+
|
74+
LL ~ fn change_object3(object: &mut Object) {
75+
LL |
76+
LL | let object2 = Object;
77+
LL ~ *object = object2;
78+
|
79+
80+
error: variable `object` is assigned to, but never used
81+
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:19:23
82+
|
83+
LL | fn change_object3(mut object: &mut Object) {
84+
| ^^^^^^
85+
|
86+
= note: consider using `_object` instead
87+
88+
error[E0596]: cannot borrow `object2` as mutable, as it is not declared as mutable
89+
--> $DIR/mut-arg-of-borrowed-type-meant-to-be-arg-of-mut-borrow.rs:22:14
90+
|
91+
LL | object = &mut object2;
92+
| ^^^^^^^^^^^^ cannot borrow as mutable
93+
|
94+
help: consider changing this to be mutable
95+
|
96+
LL | let mut object2 = Object;
97+
| +++
98+
99+
error: aborting due to 7 previous errors
67100

68-
Some errors have detailed explanations: E0308, E0597.
101+
Some errors have detailed explanations: E0308, E0596, E0597.
69102
For more information about an error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)