Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1198,6 +1198,26 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
);
return;
}

// If `local` is a closure arg, and the type of the arg is not under
// local control, do not suggest to change its type.
if self.body.local_kind(local) == LocalKind::Arg
&& let InstanceKind::Item(def_id) = self.body.source.instance
&& let Some(Node::Expr(hir::Expr { hir_id, kind, .. })) =
self.infcx.tcx.hir_get_if_local(def_id)
&& let ExprKind::Closure(hir::Closure { kind: hir::ClosureKind::Closure, .. }) = kind
&& let Node::Expr(expr) = self.infcx.tcx.parent_hir_node(*hir_id)
&& let ExprKind::MethodCall(path_segment, _, _, _) = expr.kind
&& self
.infcx
.tcx
.typeck(path_segment.hir_id.owner.def_id)
.type_dependent_def_id(expr.hir_id)
.is_some_and(|def_id| !def_id.is_local())
{
return;
}

let decl_span = local_decl.source_info.span;

let (amp_mut_sugg, local_var_ty_info) = match *local_decl.local_info() {
Expand Down
4 changes: 1 addition & 3 deletions tests/ui/borrowck/issue-115259-suggest-iter-mut.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ error[E0596]: cannot borrow `**layer` as mutable, as it is behind a `&` referenc
--> $DIR/issue-115259-suggest-iter-mut.rs:15:65
|
LL | self.layers.iter().fold(0, |result, mut layer| result + layer.process())
| --------- ^^^^^ `layer` is a `&` reference, so it cannot be borrowed as mutable
| |
| consider changing this binding's type to be: `&mut Box<dyn Layer>`
| ^^^^^ `layer` is a `&` reference, so it cannot be borrowed as mutable
|
help: you may want to use `iter_mut` here
|
Expand Down
4 changes: 1 addition & 3 deletions tests/ui/borrowck/issue-62387-suggest-iter-mut-2.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ error[E0596]: cannot borrow `*container` as mutable, as it is behind a `&` refer
--> $DIR/issue-62387-suggest-iter-mut-2.rs:30:45
|
LL | vec.iter().flat_map(|container| container.things()).cloned().collect::<Vec<PathBuf>>();
| --------- ^^^^^^^^^ `container` is a `&` reference, so it cannot be borrowed as mutable
| |
| consider changing this binding's type to be: `&mut Container`
| ^^^^^^^^^ `container` is a `&` reference, so it cannot be borrowed as mutable
|
help: you may want to use `iter_mut` here
|
Expand Down
8 changes: 2 additions & 6 deletions tests/ui/borrowck/issue-62387-suggest-iter-mut.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
--> $DIR/issue-62387-suggest-iter-mut.rs:18:27
|
LL | v.iter().for_each(|a| a.double());
| - ^ `a` is a `&` reference, so it cannot be borrowed as mutable
| |
| consider changing this binding's type to be: `&mut A`
| ^ `a` is a `&` reference, so it cannot be borrowed as mutable
|
help: you may want to use `iter_mut` here
|
Expand All @@ -15,9 +13,7 @@ error[E0596]: cannot borrow `*a` as mutable, as it is behind a `&` reference
--> $DIR/issue-62387-suggest-iter-mut.rs:25:39
|
LL | v.iter().rev().rev().for_each(|a| a.double());
| - ^ `a` is a `&` reference, so it cannot be borrowed as mutable
| |
| consider changing this binding's type to be: `&mut A`
| ^ `a` is a `&` reference, so it cannot be borrowed as mutable
|
help: you may want to use `iter_mut` here
|
Expand Down
13 changes: 13 additions & 0 deletions tests/ui/borrowck/option-inspect-mutation.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//! Regression test for <https://github.com/rust-lang/rust/issues/128381>.
struct Struct {
field: u32,
}

fn main() {
let mut some_struct = Some(Struct { field: 42 });
some_struct.as_mut().inspect(|some_struct| {
some_struct.field *= 10; //~ ERROR cannot assign to `some_struct.field`, which is behind a `&` reference
// Users can't change type of `some_struct` param, so above error must not suggest it.
});
}
9 changes: 9 additions & 0 deletions tests/ui/borrowck/option-inspect-mutation.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
error[E0594]: cannot assign to `some_struct.field`, which is behind a `&` reference
--> $DIR/option-inspect-mutation.rs:10:9
|
LL | some_struct.field *= 10;
| ^^^^^^^^^^^^^^^^^^^^^^^ `some_struct` is a `&` reference, so it cannot be written to

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0594`.
4 changes: 1 addition & 3 deletions tests/ui/borrowck/suggest-as-ref-on-mut-closure.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
--> $DIR/suggest-as-ref-on-mut-closure.rs:12:26
|
LL | cb.as_ref().map(|cb| cb());
| -- ^^ `cb` is a `&` reference, so it cannot be borrowed as mutable
| |
| consider changing this binding's type to be: `&mut &mut dyn FnMut()`
| ^^ `cb` is a `&` reference, so it cannot be borrowed as mutable

error: aborting due to 2 previous errors

Expand Down
Loading