From 83a0ed6f9d6fa50bfc4bbf780767ad4c131065e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 17 Nov 2024 23:30:20 +0000 Subject: [PATCH 1/2] Provide more context on `Fn` closure modifying binding When modifying a binding from inside of an `Fn` closure, point at the binding definition and suggest using an `std::sync` type that would allow the code to compile. ``` error[E0594]: cannot assign to `counter`, as it is a captured variable in a `Fn` closure --> f703.rs:6:9 | 4 | let mut counter = 0; | ----------- `counter` declared here, outside the closure 5 | let x: Box = Box::new(|| { | -- in this closure 6 | counter += 1; | ^^^^^^^^^^^^ cannot assign | = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value ``` --- .../src/diagnostics/mutability_errors.rs | 85 +++++++++++++++++-- .../async-closures/wrong-fn-kind.stderr | 4 + .../borrow-immutable-upvar-mutation.stderr | 13 +++ .../borrow-raw-address-of-mutability.stderr | 4 + tests/ui/borrowck/mutability-errors.stderr | 24 +++++- ...bility-violation-with-closure-21600.stderr | 9 ++ ...wrong-closure-arg-suggestion-125325.stderr | 9 ++ tests/ui/nll/closure-captures.stderr | 10 ++- ...sures-mutated-upvar-from-fn-closure.stderr | 4 + 9 files changed, 149 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 5d9416b59fcec..9e48c8ee1478e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -5,6 +5,7 @@ use core::ops::ControlFlow; use hir::{ExprKind, Param}; use rustc_abi::FieldIdx; +use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, BindingMode, ByRef, Node}; @@ -121,8 +122,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } } - PlaceRef { local: _, projection: [proj_base @ .., ProjectionElem::Deref] } => { - if the_place_err.local == ty::CAPTURE_STRUCT_LOCAL + PlaceRef { local, projection: [proj_base @ .., ProjectionElem::Deref] } => { + if local == ty::CAPTURE_STRUCT_LOCAL && proj_base.is_empty() && !self.upvars.is_empty() { @@ -136,10 +137,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ", as `Fn` closures cannot mutate their captured variables".to_string() } } else { - let source = self.borrowed_content_source(PlaceRef { - local: the_place_err.local, - projection: proj_base, - }); + let source = + self.borrowed_content_source(PlaceRef { local, projection: proj_base }); let pointer_type = source.describe_for_immutable_place(self.infcx.tcx); opt_source = Some(source); if let Some(desc) = self.describe_place(access_place.as_ref()) { @@ -506,6 +505,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { PlaceRef { local, projection: [ProjectionElem::Deref] } if local == ty::CAPTURE_STRUCT_LOCAL && !self.upvars.is_empty() => { + self.point_at_binding_outside_closure(&mut err, local, access_place); self.expected_fn_found_fn_mut_call(&mut err, span, act); } @@ -923,6 +923,76 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } + /// When modifying a binding from inside of an `Fn` closure, point at the binding definition + /// and suggest using an `std::sync` type that would allow the code to compile. + fn point_at_binding_outside_closure( + &self, + err: &mut Diag<'_>, + local: Local, + access_place: Place<'tcx>, + ) { + let place = access_place.as_ref(); + for (index, elem) in place.projection.into_iter().enumerate() { + if let ProjectionElem::Deref = elem { + if index == 0 { + if self.body.local_decls[local].is_ref_for_guard() { + continue; + } + if let LocalInfo::StaticRef { .. } = *self.body.local_decls[local].local_info() + { + continue; + } + } + if let Some(field) = self.is_upvar_field_projection(PlaceRef { + local, + projection: place.projection.split_at(index + 1).0, + }) { + let var_index = field.index(); + let upvar = self.upvars[var_index]; + if let Some(hir_id) = upvar.info.capture_kind_expr_id { + let node = self.infcx.tcx.hir_node(hir_id); + if let hir::Node::Expr(expr) = node + && let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind + && let hir::def::Res::Local(hir_id) = path.res + && let hir::Node::Pat(pat) = self.infcx.tcx.hir_node(hir_id) + { + let hir = self.infcx.tcx.hir(); + let def_id = hir.enclosing_body_owner(self.mir_hir_id()); + let typeck_results = self.infcx.tcx.typeck(def_id); + let ty = typeck_results.node_type_opt(expr.hir_id); + if let Some(ty) = ty { + let mutex = format!("std::sync::atomic::Mutex<{ty}>"); + let mutex = mutex.as_str(); + let suggestions: FxHashMap<_, _> = [ + (self.infcx.tcx.types.isize, "std::sync::atomic::AtomicIsize"), + (self.infcx.tcx.types.usize, "std::sync::atomic::AtomicUsize"), + (self.infcx.tcx.types.i64, "std::sync::atomic::AtomicI64"), + (self.infcx.tcx.types.u64, "std::sync::atomic::AtomicU64"), + (self.infcx.tcx.types.i32, "std::sync::atomic::AtomicI32"), + (self.infcx.tcx.types.u32, "std::sync::atomic::AtomicU32"), + (self.infcx.tcx.types.i16, "std::sync::atomic::AtomicI16"), + (self.infcx.tcx.types.u16, "std::sync::atomic::AtomicU16"), + (self.infcx.tcx.types.i8, "std::sync::atomic::AtomicI8"), + (self.infcx.tcx.types.u8, "std::sync::atomic::AtomicU8"), + (self.infcx.tcx.types.bool, "std::sync::atomic::AtomicBool"), + ] + .into_iter() + .collect(); + let ty = suggestions.get(&ty).unwrap_or(&mutex); + err.help(format!("consider using `{ty}` instead, which allows for multiple threads to access and modify the value")); + } + let name = upvar.to_string(self.infcx.tcx); + err.span_label( + pat.span, + format!("`{name}` declared here, outside the closure"), + ); + break; + } + } + } + } + } + } /// Targeted error when encountering an `FnMut` closure where an `Fn` closure was expected. fn expected_fn_found_fn_mut_call(&self, err: &mut Diag<'_>, sp: Span, act: &str) { err.span_label(sp, format!("cannot {act}")); @@ -935,6 +1005,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { let def_id = tcx.hir_enclosing_body_owner(fn_call_id); let mut look_at_return = true; + err.span_label(closure_span, "in this closure"); // If the HIR node is a function or method call gets the def ID // of the called function or method and the span and args of the call expr let get_call_details = || { @@ -1005,7 +1076,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let Some(span) = arg { err.span_label(span, "change this to accept `FnMut` instead of `Fn`"); err.span_label(call_span, "expects `Fn` instead of `FnMut`"); - err.span_label(closure_span, "in this closure"); look_at_return = false; } } @@ -1032,7 +1102,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { sig.decl.output.span(), "change this to return `FnMut` instead of `Fn`", ); - err.span_label(closure_span, "in this closure"); } _ => {} } diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr index 95f314214cc65..bb59b7be0d180 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr @@ -25,6 +25,8 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F LL | fn needs_async_fn(_: impl AsyncFn()) {} | -------------- change this to accept `FnMut` instead of `Fn` ... +LL | let mut x = 1; + | ----- `x` declared here, outside the closure LL | needs_async_fn(async || { | -------------- ^^^^^^^^ | | | @@ -34,6 +36,8 @@ LL | needs_async_fn(async || { LL | LL | x += 1; | - mutable borrow occurs due to use of `x` in closure + | + = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value error: aborting due to 2 previous errors diff --git a/tests/ui/borrowck/borrow-immutable-upvar-mutation.stderr b/tests/ui/borrowck/borrow-immutable-upvar-mutation.stderr index a0eaf1f163b02..5ac801466d6ca 100644 --- a/tests/ui/borrowck/borrow-immutable-upvar-mutation.stderr +++ b/tests/ui/borrowck/borrow-immutable-upvar-mutation.stderr @@ -4,11 +4,15 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closu LL | fn to_fn>(f: F) -> F { | - change this to accept `FnMut` instead of `Fn` ... +LL | let mut x = 0; + | ----- `x` declared here, outside the closure LL | let _f = to_fn(|| x = 42); | ----- -- ^^^^^^ cannot assign | | | | | in this closure | expects `Fn` instead of `FnMut` + | + = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:24:31 @@ -16,11 +20,15 @@ error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `F LL | fn to_fn>(f: F) -> F { | - change this to accept `FnMut` instead of `Fn` ... +LL | let mut y = 0; + | ----- `y` declared here, outside the closure LL | let _g = to_fn(|| set(&mut y)); | ----- -- ^^^^^^ cannot borrow as mutable | | | | | in this closure | expects `Fn` instead of `FnMut` + | + = help: consider using `std::sync::atomic::AtomicUsize` instead, which allows for multiple threads to access and modify the value error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:29:22 @@ -28,11 +36,16 @@ error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closu LL | fn to_fn>(f: F) -> F { | - change this to accept `FnMut` instead of `Fn` ... +LL | let mut z = 0; + | ----- `z` declared here, outside the closure +... LL | to_fn(|| z = 42); | ----- -- ^^^^^^ cannot assign | | | | | in this closure | expects `Fn` instead of `FnMut` + | + = help: consider using `std::sync::atomic::AtomicUsize` instead, which allows for multiple threads to access and modify the value error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:36:32 diff --git a/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr b/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr index f81a8c99376f0..0c3625eaa8737 100644 --- a/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr +++ b/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -40,12 +40,16 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F LL | fn make_fn(f: F) -> F { f } | - change this to accept `FnMut` instead of `Fn` ... +LL | let mut x = 0; + | ----- `x` declared here, outside the closure LL | let f = make_fn(|| { | ------- -- in this closure | | | expects `Fn` instead of `FnMut` LL | let y = &raw mut x; | ^^^^^^^^^^ cannot borrow as mutable + | + = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-raw-address-of-mutability.rs:35:17 diff --git a/tests/ui/borrowck/mutability-errors.stderr b/tests/ui/borrowck/mutability-errors.stderr index 3cab3ccb993c9..53244a59901a1 100644 --- a/tests/ui/borrowck/mutability-errors.stderr +++ b/tests/ui/borrowck/mutability-errors.stderr @@ -139,20 +139,26 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closu | LL | fn fn_ref(f: F) -> F { f } | - change this to accept `FnMut` instead of `Fn` -... +LL | +LL | fn ref_closure(mut x: (i32,)) { + | ----- `x` declared here, outside the closure LL | fn_ref(|| { | ------ -- in this closure | | | expects `Fn` instead of `FnMut` LL | x = (1,); | ^^^^^^^^ cannot assign + | + = help: consider using `std::sync::atomic::Mutex<(i32,)>` instead, which allows for multiple threads to access and modify the value error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables --> $DIR/mutability-errors.rs:41:9 | LL | fn fn_ref(f: F) -> F { f } | - change this to accept `FnMut` instead of `Fn` -... +LL | +LL | fn ref_closure(mut x: (i32,)) { + | ----- `x` declared here, outside the closure LL | fn_ref(|| { | ------ -- in this closure | | @@ -160,13 +166,17 @@ LL | fn_ref(|| { LL | x = (1,); LL | x.0 = 1; | ^^^^^^^ cannot assign + | + = help: consider using `std::sync::atomic::Mutex<(i32,)>` instead, which allows for multiple threads to access and modify the value error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/mutability-errors.rs:42:9 | LL | fn fn_ref(f: F) -> F { f } | - change this to accept `FnMut` instead of `Fn` -... +LL | +LL | fn ref_closure(mut x: (i32,)) { + | ----- `x` declared here, outside the closure LL | fn_ref(|| { | ------ -- in this closure | | @@ -174,13 +184,17 @@ LL | fn_ref(|| { ... LL | &mut x; | ^^^^^^ cannot borrow as mutable + | + = help: consider using `std::sync::atomic::Mutex<(i32,)>` instead, which allows for multiple threads to access and modify the value error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables --> $DIR/mutability-errors.rs:43:9 | LL | fn fn_ref(f: F) -> F { f } | - change this to accept `FnMut` instead of `Fn` -... +LL | +LL | fn ref_closure(mut x: (i32,)) { + | ----- `x` declared here, outside the closure LL | fn_ref(|| { | ------ -- in this closure | | @@ -188,6 +202,8 @@ LL | fn_ref(|| { ... LL | &mut x.0; | ^^^^^^^^ cannot borrow as mutable + | + = help: consider using `std::sync::atomic::Mutex<(i32,)>` instead, which allows for multiple threads to access and modify the value error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/mutability-errors.rs:46:9 diff --git a/tests/ui/closures/aliasability-violation-with-closure-21600.stderr b/tests/ui/closures/aliasability-violation-with-closure-21600.stderr index 2d2397a2141d9..1787b48b19135 100644 --- a/tests/ui/closures/aliasability-violation-with-closure-21600.stderr +++ b/tests/ui/closures/aliasability-violation-with-closure-21600.stderr @@ -4,11 +4,16 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F LL | fn call_it(f: F) where F: Fn() { f(); } | - change this to accept `FnMut` instead of `Fn` ... +LL | let mut x = A; + | ----- `x` declared here, outside the closure +... LL | call_it(|| x.gen_mut()); | ------- -- ^ cannot borrow as mutable | | | | | in this closure | expects `Fn` instead of `FnMut` + | + = help: consider using `std::sync::atomic::Mutex` instead, which allows for multiple threads to access and modify the value error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/aliasability-violation-with-closure-21600.rs:15:17 @@ -16,6 +21,8 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F LL | fn call_it(f: F) where F: Fn() { f(); } | - change this to accept `FnMut` instead of `Fn` ... +LL | let mut x = A; + | ----- `x` declared here, outside the closure LL | call_it(|| { | ------- -- in this closure | | @@ -25,6 +32,8 @@ LL | call_it(|| x.gen_mut()); | ^^ - mutable borrow occurs due to use of `x` in closure | | | cannot borrow as mutable + | + = help: consider using `std::sync::atomic::Mutex` instead, which allows for multiple threads to access and modify the value error: aborting due to 2 previous errors diff --git a/tests/ui/closures/wrong-closure-arg-suggestion-125325.stderr b/tests/ui/closures/wrong-closure-arg-suggestion-125325.stderr index e0cce8c4b3143..3fc86efe734e3 100644 --- a/tests/ui/closures/wrong-closure-arg-suggestion-125325.stderr +++ b/tests/ui/closures/wrong-closure-arg-suggestion-125325.stderr @@ -4,12 +4,16 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closu LL | fn assoc_func(&self, _f: impl Fn()) -> usize { | --------- change this to accept `FnMut` instead of `Fn` ... +LL | let mut x = (); + | ----- `x` declared here, outside the closure LL | s.assoc_func(|| x = ()); | --------------^^^^^^- | | | | | | | cannot assign | | in this closure | expects `Fn` instead of `FnMut` + | + = help: consider using `std::sync::atomic::Mutex<()>` instead, which allows for multiple threads to access and modify the value error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/wrong-closure-arg-suggestion-125325.rs:25:13 @@ -17,11 +21,16 @@ error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closu LL | fn func(_f: impl Fn()) -> usize { | --------- change this to accept `FnMut` instead of `Fn` ... +LL | let mut x = (); + | ----- `x` declared here, outside the closure +... LL | func(|| x = ()) | ---- -- ^^^^^^ cannot assign | | | | | in this closure | expects `Fn` instead of `FnMut` + | + = help: consider using `std::sync::atomic::Mutex<()>` instead, which allows for multiple threads to access and modify the value error: aborting due to 2 previous errors diff --git a/tests/ui/nll/closure-captures.stderr b/tests/ui/nll/closure-captures.stderr index 828974c517e60..c9b44e70779d5 100644 --- a/tests/ui/nll/closure-captures.stderr +++ b/tests/ui/nll/closure-captures.stderr @@ -47,7 +47,9 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F | LL | fn fn_ref(f: F) -> F { f } | - change this to accept `FnMut` instead of `Fn` -... +LL | +LL | fn two_closures_ref_mut(mut x: i32) { + | ----- `x` declared here, outside the closure LL | fn_ref(|| { | ------ -- in this closure | | @@ -56,6 +58,8 @@ LL | || | ^^ cannot borrow as mutable LL | x = 1;} | - mutable borrow occurs due to use of `x` in closure + | + = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:31:9 @@ -89,6 +93,8 @@ error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `F LL | fn fn_ref(f: F) -> F { f } | - change this to accept `FnMut` instead of `Fn` ... +LL | fn two_closures_ref(x: i32) { + | - `x` declared here, outside the closure LL | fn_ref(|| { | ------ -- in this closure | | @@ -97,6 +103,8 @@ LL | || | ^^ cannot borrow as mutable LL | x = 1;} | - mutable borrow occurs due to use of `x` in closure + | + = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/closure-captures.rs:43:5 diff --git a/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr b/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr index cbe42861d5ee2..a526021a0caa1 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr @@ -4,12 +4,16 @@ error[E0594]: cannot assign to `counter`, as it is a captured variable in a `Fn` LL | fn call(f: F) where F : Fn() { | - change this to accept `FnMut` instead of `Fn` ... +LL | let mut counter = 0; + | ----------- `counter` declared here, outside the closure LL | call(|| { | ---- -- in this closure | | | expects `Fn` instead of `FnMut` LL | counter += 1; | ^^^^^^^^^^^^ cannot assign + | + = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value error: aborting due to 1 previous error From 8e1b82b9a0f00a75b98f90d789cef2d42a6daf19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 11 Aug 2025 00:02:42 +0000 Subject: [PATCH 2/2] Remove suggestion to use atomics --- .../src/diagnostics/mutability_errors.rs | 29 +------------------ .../async-closures/wrong-fn-kind.stderr | 2 -- .../borrow-immutable-upvar-mutation.stderr | 6 ---- .../borrow-raw-address-of-mutability.stderr | 2 -- tests/ui/borrowck/mutability-errors.stderr | 8 ----- ...bility-violation-with-closure-21600.stderr | 4 --- ...wrong-closure-arg-suggestion-125325.stderr | 4 --- tests/ui/nll/closure-captures.stderr | 4 --- ...sures-mutated-upvar-from-fn-closure.stderr | 2 -- 9 files changed, 1 insertion(+), 60 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 9e48c8ee1478e..f271dbbbabdf8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -5,7 +5,6 @@ use core::ops::ControlFlow; use hir::{ExprKind, Param}; use rustc_abi::FieldIdx; -use rustc_data_structures::fx::FxHashMap; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, BindingMode, ByRef, Node}; @@ -923,8 +922,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } - /// When modifying a binding from inside of an `Fn` closure, point at the binding definition - /// and suggest using an `std::sync` type that would allow the code to compile. + /// When modifying a binding from inside of an `Fn` closure, point at the binding definition. fn point_at_binding_outside_closure( &self, err: &mut Diag<'_>, @@ -956,31 +954,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { && let hir::def::Res::Local(hir_id) = path.res && let hir::Node::Pat(pat) = self.infcx.tcx.hir_node(hir_id) { - let hir = self.infcx.tcx.hir(); - let def_id = hir.enclosing_body_owner(self.mir_hir_id()); - let typeck_results = self.infcx.tcx.typeck(def_id); - let ty = typeck_results.node_type_opt(expr.hir_id); - if let Some(ty) = ty { - let mutex = format!("std::sync::atomic::Mutex<{ty}>"); - let mutex = mutex.as_str(); - let suggestions: FxHashMap<_, _> = [ - (self.infcx.tcx.types.isize, "std::sync::atomic::AtomicIsize"), - (self.infcx.tcx.types.usize, "std::sync::atomic::AtomicUsize"), - (self.infcx.tcx.types.i64, "std::sync::atomic::AtomicI64"), - (self.infcx.tcx.types.u64, "std::sync::atomic::AtomicU64"), - (self.infcx.tcx.types.i32, "std::sync::atomic::AtomicI32"), - (self.infcx.tcx.types.u32, "std::sync::atomic::AtomicU32"), - (self.infcx.tcx.types.i16, "std::sync::atomic::AtomicI16"), - (self.infcx.tcx.types.u16, "std::sync::atomic::AtomicU16"), - (self.infcx.tcx.types.i8, "std::sync::atomic::AtomicI8"), - (self.infcx.tcx.types.u8, "std::sync::atomic::AtomicU8"), - (self.infcx.tcx.types.bool, "std::sync::atomic::AtomicBool"), - ] - .into_iter() - .collect(); - let ty = suggestions.get(&ty).unwrap_or(&mutex); - err.help(format!("consider using `{ty}` instead, which allows for multiple threads to access and modify the value")); - } let name = upvar.to_string(self.infcx.tcx); err.span_label( pat.span, diff --git a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr index bb59b7be0d180..dd0f4da5dd32b 100644 --- a/tests/ui/async-await/async-closures/wrong-fn-kind.stderr +++ b/tests/ui/async-await/async-closures/wrong-fn-kind.stderr @@ -36,8 +36,6 @@ LL | needs_async_fn(async || { LL | LL | x += 1; | - mutable borrow occurs due to use of `x` in closure - | - = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value error: aborting due to 2 previous errors diff --git a/tests/ui/borrowck/borrow-immutable-upvar-mutation.stderr b/tests/ui/borrowck/borrow-immutable-upvar-mutation.stderr index 5ac801466d6ca..4e40ebf738e3b 100644 --- a/tests/ui/borrowck/borrow-immutable-upvar-mutation.stderr +++ b/tests/ui/borrowck/borrow-immutable-upvar-mutation.stderr @@ -11,8 +11,6 @@ LL | let _f = to_fn(|| x = 42); | | | | | in this closure | expects `Fn` instead of `FnMut` - | - = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value error[E0596]: cannot borrow `y` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:24:31 @@ -27,8 +25,6 @@ LL | let _g = to_fn(|| set(&mut y)); | | | | | in this closure | expects `Fn` instead of `FnMut` - | - = help: consider using `std::sync::atomic::AtomicUsize` instead, which allows for multiple threads to access and modify the value error[E0594]: cannot assign to `z`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:29:22 @@ -44,8 +40,6 @@ LL | to_fn(|| z = 42); | | | | | in this closure | expects `Fn` instead of `FnMut` - | - = help: consider using `std::sync::atomic::AtomicUsize` instead, which allows for multiple threads to access and modify the value error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/borrow-immutable-upvar-mutation.rs:36:32 diff --git a/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr b/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr index 0c3625eaa8737..c4b97950727ac 100644 --- a/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr +++ b/tests/ui/borrowck/borrow-raw-address-of-mutability.stderr @@ -48,8 +48,6 @@ LL | let f = make_fn(|| { | expects `Fn` instead of `FnMut` LL | let y = &raw mut x; | ^^^^^^^^^^ cannot borrow as mutable - | - = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/borrow-raw-address-of-mutability.rs:35:17 diff --git a/tests/ui/borrowck/mutability-errors.stderr b/tests/ui/borrowck/mutability-errors.stderr index 53244a59901a1..7307e1f2a86b2 100644 --- a/tests/ui/borrowck/mutability-errors.stderr +++ b/tests/ui/borrowck/mutability-errors.stderr @@ -148,8 +148,6 @@ LL | fn_ref(|| { | expects `Fn` instead of `FnMut` LL | x = (1,); | ^^^^^^^^ cannot assign - | - = help: consider using `std::sync::atomic::Mutex<(i32,)>` instead, which allows for multiple threads to access and modify the value error[E0594]: cannot assign to `x.0`, as `Fn` closures cannot mutate their captured variables --> $DIR/mutability-errors.rs:41:9 @@ -166,8 +164,6 @@ LL | fn_ref(|| { LL | x = (1,); LL | x.0 = 1; | ^^^^^^^ cannot assign - | - = help: consider using `std::sync::atomic::Mutex<(i32,)>` instead, which allows for multiple threads to access and modify the value error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/mutability-errors.rs:42:9 @@ -184,8 +180,6 @@ LL | fn_ref(|| { ... LL | &mut x; | ^^^^^^ cannot borrow as mutable - | - = help: consider using `std::sync::atomic::Mutex<(i32,)>` instead, which allows for multiple threads to access and modify the value error[E0596]: cannot borrow `x.0` as mutable, as `Fn` closures cannot mutate their captured variables --> $DIR/mutability-errors.rs:43:9 @@ -202,8 +196,6 @@ LL | fn_ref(|| { ... LL | &mut x.0; | ^^^^^^^^ cannot borrow as mutable - | - = help: consider using `std::sync::atomic::Mutex<(i32,)>` instead, which allows for multiple threads to access and modify the value error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/mutability-errors.rs:46:9 diff --git a/tests/ui/closures/aliasability-violation-with-closure-21600.stderr b/tests/ui/closures/aliasability-violation-with-closure-21600.stderr index 1787b48b19135..2f4135b12fa5a 100644 --- a/tests/ui/closures/aliasability-violation-with-closure-21600.stderr +++ b/tests/ui/closures/aliasability-violation-with-closure-21600.stderr @@ -12,8 +12,6 @@ LL | call_it(|| x.gen_mut()); | | | | | in this closure | expects `Fn` instead of `FnMut` - | - = help: consider using `std::sync::atomic::Mutex` instead, which allows for multiple threads to access and modify the value error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/aliasability-violation-with-closure-21600.rs:15:17 @@ -32,8 +30,6 @@ LL | call_it(|| x.gen_mut()); | ^^ - mutable borrow occurs due to use of `x` in closure | | | cannot borrow as mutable - | - = help: consider using `std::sync::atomic::Mutex` instead, which allows for multiple threads to access and modify the value error: aborting due to 2 previous errors diff --git a/tests/ui/closures/wrong-closure-arg-suggestion-125325.stderr b/tests/ui/closures/wrong-closure-arg-suggestion-125325.stderr index 3fc86efe734e3..f419f7c1b44d3 100644 --- a/tests/ui/closures/wrong-closure-arg-suggestion-125325.stderr +++ b/tests/ui/closures/wrong-closure-arg-suggestion-125325.stderr @@ -12,8 +12,6 @@ LL | s.assoc_func(|| x = ()); | | | cannot assign | | in this closure | expects `Fn` instead of `FnMut` - | - = help: consider using `std::sync::atomic::Mutex<()>` instead, which allows for multiple threads to access and modify the value error[E0594]: cannot assign to `x`, as it is a captured variable in a `Fn` closure --> $DIR/wrong-closure-arg-suggestion-125325.rs:25:13 @@ -29,8 +27,6 @@ LL | func(|| x = ()) | | | | | in this closure | expects `Fn` instead of `FnMut` - | - = help: consider using `std::sync::atomic::Mutex<()>` instead, which allows for multiple threads to access and modify the value error: aborting due to 2 previous errors diff --git a/tests/ui/nll/closure-captures.stderr b/tests/ui/nll/closure-captures.stderr index c9b44e70779d5..80ac033351aaa 100644 --- a/tests/ui/nll/closure-captures.stderr +++ b/tests/ui/nll/closure-captures.stderr @@ -58,8 +58,6 @@ LL | || | ^^ cannot borrow as mutable LL | x = 1;} | - mutable borrow occurs due to use of `x` in closure - | - = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value error[E0596]: cannot borrow `x` as mutable, as it is a captured variable in a `Fn` closure --> $DIR/closure-captures.rs:31:9 @@ -103,8 +101,6 @@ LL | || | ^^ cannot borrow as mutable LL | x = 1;} | - mutable borrow occurs due to use of `x` in closure - | - = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value error[E0594]: cannot assign to `x`, as it is not declared as mutable --> $DIR/closure-captures.rs:43:5 diff --git a/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr b/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr index a526021a0caa1..f82faeea516f8 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-mutated-upvar-from-fn-closure.stderr @@ -12,8 +12,6 @@ LL | call(|| { | expects `Fn` instead of `FnMut` LL | counter += 1; | ^^^^^^^^^^^^ cannot assign - | - = help: consider using `std::sync::atomic::AtomicI32` instead, which allows for multiple threads to access and modify the value error: aborting due to 1 previous error