diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a98217f625a..327943af4171 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6065,6 +6065,7 @@ Released 2018-09-13 [`mut_mut`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_mut [`mut_mutex_lock`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_mutex_lock [`mut_range_bound`]: https://rust-lang.github.io/rust-clippy/master/index.html#mut_range_bound +[`mutable_borrow_of_copy`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutable_borrow_of_copy [`mutable_key_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type [`mutex_atomic`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_atomic [`mutex_integer`]: https://rust-lang.github.io/rust-clippy/master/index.html#mutex_integer @@ -6512,6 +6513,7 @@ Released 2018-09-13 [`cargo-ignore-publish`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cargo-ignore-publish [`check-incompatible-msrv-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-incompatible-msrv-in-tests [`check-inconsistent-struct-field-initializers`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-inconsistent-struct-field-initializers +[`check-mutable-borrow-of-copy-in-tests`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-mutable-borrow-of-copy-in-tests [`check-private-items`]: https://doc.rust-lang.org/clippy/lint_configuration.html#check-private-items [`cognitive-complexity-threshold`]: https://doc.rust-lang.org/clippy/lint_configuration.html#cognitive-complexity-threshold [`disallowed-macros`]: https://doc.rust-lang.org/clippy/lint_configuration.html#disallowed-macros diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 7c850b4b023a..0d9f65630f9d 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -462,6 +462,16 @@ fn main() { * [`inconsistent_struct_constructor`](https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_struct_constructor) +## `check-mutable-borrow-of-copy-in-tests` +Whether to search for mutable borrows of freshly copied data in tests. + +**Default Value:** `true` + +--- +**Affected lints:** +* [`mutable_borrow_of_copy`](https://rust-lang.github.io/rust-clippy/master/index.html#mutable_borrow_of_copy) + + ## `check-private-items` Whether to also run the listed lints on private items. diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 87158cec42b2..172957143d94 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -563,6 +563,9 @@ define_Conf! { /// [from rust-clippy#11846]: https://github.com/rust-lang/rust-clippy/issues/11846#issuecomment-1820747924 #[lints(inconsistent_struct_constructor)] check_inconsistent_struct_field_initializers: bool = false, + /// Whether to search for mutable borrows of freshly copied data in tests. + #[lints(mutable_borrow_of_copy)] + check_mutable_borrow_of_copy_in_tests: bool = true, /// Whether to also run the listed lints on private items. #[lints(missing_errors_doc, missing_panics_doc, missing_safety_doc, unnecessary_safety_doc)] check_private_items: bool = false, diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 5fcb851dfebc..4f5be23a8e9e 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -527,6 +527,7 @@ pub static LINTS: &[&crate::LintInfo] = &[ crate::mut_key::MUTABLE_KEY_TYPE_INFO, crate::mut_mut::MUT_MUT_INFO, crate::mut_reference::UNNECESSARY_MUT_PASSED_INFO, + crate::mutable_borrow_of_copy::MUTABLE_BORROW_OF_COPY_INFO, crate::mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL_INFO, crate::mutex_atomic::MUTEX_ATOMIC_INFO, crate::mutex_atomic::MUTEX_INTEGER_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 92eb3d7a7c59..a53daa962893 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -252,6 +252,7 @@ mod multiple_unsafe_ops_per_block; mod mut_key; mod mut_mut; mod mut_reference; +mod mutable_borrow_of_copy; mod mutable_debug_assertion; mod mutex_atomic; mod needless_arbitrary_self_type; @@ -946,5 +947,6 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { store.register_late_pass(|_| Box::new(single_option_map::SingleOptionMap)); store.register_late_pass(move |_| Box::new(redundant_test_prefix::RedundantTestPrefix)); store.register_late_pass(|_| Box::new(cloned_ref_to_slice_refs::ClonedRefToSliceRefs::new(conf))); + store.register_late_pass(|_| Box::new(mutable_borrow_of_copy::MutableBorrowOfCopy::new(conf))); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/clippy_lints/src/mutable_borrow_of_copy.rs b/clippy_lints/src/mutable_borrow_of_copy.rs new file mode 100644 index 000000000000..5ddc57f6de4f --- /dev/null +++ b/clippy_lints/src/mutable_borrow_of_copy.rs @@ -0,0 +1,113 @@ +use clippy_config::Conf; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::ty::is_copy; +use clippy_utils::{get_enclosing_block, is_in_test, path_to_local}; +use rustc_ast::BindingMode; +use rustc_errors::Applicability; +use rustc_hir::{Block, BorrowKind, Expr, ExprKind, Mutability, Node, PatKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_session::impl_lint_pass; + +declare_clippy_lint! { + /// ### What it does + /// Checks for taking a mutable reference on a freshly copied variable due to the use of a block returning a value implementing `Copy`. + /// + /// ### Why is this bad? + /// Using a block will make a copy of the block result if its type + /// implements `Copy`. This might be an indication of a failed attempt + /// to borrow a variable. + /// + /// ### Example + /// ```no_run + /// # unsafe fn unsafe_func(_: &mut i32) {} + /// let mut a = 10; + /// let double_a_ref = &mut unsafe { // Unsafe block needed to call `unsafe_func` + /// unsafe_func(&mut a); + /// a + /// }; + /// ``` + /// If you intend to take a reference on `a` and you need the block, + /// create the reference inside the block instead: + /// ```no_run + /// # unsafe fn unsafe_func(_: &mut i32) {} + /// let mut a = 10; + /// let double_a_ref = unsafe { // Unsafe block needed to call `unsafe_func` + /// unsafe_func(&mut a); + /// &mut a + /// }; + /// ``` + #[clippy::version = "1.89.0"] + pub MUTABLE_BORROW_OF_COPY, + suspicious, + "mutable borrow of a data which was just copied" +} + +pub struct MutableBorrowOfCopy { + check_in_tests: bool, +} + +impl MutableBorrowOfCopy { + pub const fn new(conf: &Conf) -> Self { + Self { + check_in_tests: conf.check_mutable_borrow_of_copy_in_tests, + } + } +} + +impl_lint_pass!(MutableBorrowOfCopy => [MUTABLE_BORROW_OF_COPY]); + +impl LateLintPass<'_> for MutableBorrowOfCopy { + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + if !expr.span.from_expansion() + && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, sub_expr) = expr.kind + && let ExprKind::Block(block, _) = sub_expr.kind + && !block.targeted_by_break + && block.span.eq_ctxt(expr.span) + && let Some(block_expr) = block.expr + && let block_ty = cx.typeck_results().expr_ty_adjusted(block_expr) + && is_copy(cx, block_ty) + && is_copied_defined_outside_block(cx, block_expr, block) + && (self.check_in_tests || !is_in_test(cx.tcx, expr.hir_id)) + { + span_lint_and_then( + cx, + MUTABLE_BORROW_OF_COPY, + expr.span, + "mutable borrow of a value which was just copied", + |diag| { + diag.multipart_suggestion( + "try building the reference inside the block", + vec![ + (expr.span.until(block.span), String::new()), + (block_expr.span.shrink_to_lo(), String::from("&mut ")), + ], + Applicability::MaybeIncorrect, + ); + }, + ); + } + } +} + +/// Checks if `expr` denotes a mutable variable defined outside `block`. This peels away field +/// accesses or indexing of such a variable first. +fn is_copied_defined_outside_block(cx: &LateContext<'_>, mut expr: &Expr<'_>, block: &Block<'_>) -> bool { + while let ExprKind::Field(base, _) | ExprKind::Index(base, _, _) = expr.kind { + expr = base; + } + if let Some(mut current) = path_to_local(expr) + && let Node::Pat(pat) = cx.tcx.hir_node(current) + && matches!(pat.kind, PatKind::Binding(BindingMode::MUT, ..)) + { + // Scan enclosing blocks until we find `block` (if so, the local is defined within it), or we loop + // or can't find blocks anymore. + loop { + match get_enclosing_block(cx, current).map(|b| b.hir_id) { + Some(parent) if parent == block.hir_id => return false, + Some(parent) if parent != current => current = parent, + _ => return true, + } + } + } + false +} diff --git a/tests/ui-toml/mutable_borrow_of_copy/clippy.toml b/tests/ui-toml/mutable_borrow_of_copy/clippy.toml new file mode 100644 index 000000000000..b5c9f7655919 --- /dev/null +++ b/tests/ui-toml/mutable_borrow_of_copy/clippy.toml @@ -0,0 +1 @@ +check-mutable-borrow-of-copy-in-tests = false diff --git a/tests/ui-toml/mutable_borrow_of_copy/mutable_borrow_of_copy.fixed b/tests/ui-toml/mutable_borrow_of_copy/mutable_borrow_of_copy.fixed new file mode 100644 index 000000000000..2f32915e5dba --- /dev/null +++ b/tests/ui-toml/mutable_borrow_of_copy/mutable_borrow_of_copy.fixed @@ -0,0 +1,10 @@ +#[test] +fn in_test() { + let mut a = [10; 2]; + let _ = &mut { a }; // Do not lint +} + +fn main() { + let mut a = [10; 2]; + let _ = { &mut a }; //~ mutable_borrow_of_copy +} diff --git a/tests/ui-toml/mutable_borrow_of_copy/mutable_borrow_of_copy.rs b/tests/ui-toml/mutable_borrow_of_copy/mutable_borrow_of_copy.rs new file mode 100644 index 000000000000..fb8374246288 --- /dev/null +++ b/tests/ui-toml/mutable_borrow_of_copy/mutable_borrow_of_copy.rs @@ -0,0 +1,10 @@ +#[test] +fn in_test() { + let mut a = [10; 2]; + let _ = &mut { a }; // Do not lint +} + +fn main() { + let mut a = [10; 2]; + let _ = &mut { a }; //~ mutable_borrow_of_copy +} diff --git a/tests/ui-toml/mutable_borrow_of_copy/mutable_borrow_of_copy.stderr b/tests/ui-toml/mutable_borrow_of_copy/mutable_borrow_of_copy.stderr new file mode 100644 index 000000000000..494a300b09c0 --- /dev/null +++ b/tests/ui-toml/mutable_borrow_of_copy/mutable_borrow_of_copy.stderr @@ -0,0 +1,16 @@ +error: mutable borrow of a value which was just copied + --> tests/ui-toml/mutable_borrow_of_copy/mutable_borrow_of_copy.rs:9:13 + | +LL | let _ = &mut { a }; + | ^^^^^^^^^^ + | + = note: `-D clippy::mutable-borrow-of-copy` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::mutable_borrow_of_copy)]` +help: try building the reference inside the block + | +LL - let _ = &mut { a }; +LL + let _ = { &mut a }; + | + +error: aborting due to 1 previous error + diff --git a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr index 6ee77ebd8ece..2e6fdea6cc0d 100644 --- a/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr +++ b/tests/ui-toml/toml_unknown_key/conf_unknown_key.stderr @@ -33,6 +33,7 @@ error: error reading Clippy's configuration file: unknown field `foobar`, expect cargo-ignore-publish check-incompatible-msrv-in-tests check-inconsistent-struct-field-initializers + check-mutable-borrow-of-copy-in-tests check-private-items cognitive-complexity-threshold disallowed-macros @@ -127,6 +128,7 @@ error: error reading Clippy's configuration file: unknown field `barfoo`, expect cargo-ignore-publish check-incompatible-msrv-in-tests check-inconsistent-struct-field-initializers + check-mutable-borrow-of-copy-in-tests check-private-items cognitive-complexity-threshold disallowed-macros @@ -221,6 +223,7 @@ error: error reading Clippy's configuration file: unknown field `allow_mixed_uni cargo-ignore-publish check-incompatible-msrv-in-tests check-inconsistent-struct-field-initializers + check-mutable-borrow-of-copy-in-tests check-private-items cognitive-complexity-threshold disallowed-macros diff --git a/tests/ui/mutable_borrow_of_copy.fixed b/tests/ui/mutable_borrow_of_copy.fixed new file mode 100644 index 000000000000..cd6063f7ee52 --- /dev/null +++ b/tests/ui/mutable_borrow_of_copy.fixed @@ -0,0 +1,109 @@ +#![warn(clippy::mutable_borrow_of_copy)] +#![allow(clippy::deref_addrof)] + +fn main() { + let mut a = [0u8; 2]; + let _ = { &mut a }; //~ mutable_borrow_of_copy + + let _ = &mut 'label: { + // Block is targeted by break + if a[0] == 1 { + break 'label 42u8; + } + a[0] + }; + + let mut a = vec![0u8; 2]; + let _ = &mut { a }; // `a` is not `Copy` + + let a = [0u8; 2]; + let _ = &mut { a }; // `a` is not mutable + + let _ = &mut { 42 }; // Do not lint on non-place expression + + let _ = &mut {}; // Do not lint on empty block + + macro_rules! mac { + ($a:expr) => {{ a }}; + } + let _ = &mut mac!(a); // Do not lint on borrowed macro result + + macro_rules! mac2 { + // Do not lint, as it depends on `Copy`-ness of `a` + ($x:expr) => { + &mut unsafe { $x } + }; + } + let mut a = 0u8; + let _ = &mut mac2!(a); + + let _ = &mut { + // Do not lint, the variable is defined inside the block + let mut a: [i32; 5] = (1, 2, 3, 4, 5).into(); + a + }; + + let _ = &mut { + // Do not lint, the variable is defined inside the block + { + let mut a: [i32; 5] = (1, 2, 3, 4, 5).into(); + a + } + }; + + struct S { + a: u32, + } + + let mut s = S { a: 0 }; + let _ = { + //~^ mutable_borrow_of_copy + s.a = 32; + &mut s.a + }; + + let _ = &mut { + // Do not lint, the variable is defined inside the block + let mut s = S { a: 0 }; + s.a + }; + + let mut c = (10, 20); + let _ = { + //~^ ERROR: mutable borrow + &mut c.0 + }; + + let _ = &mut { + // Do not lint, the variable is defined inside the block + let mut c = (10, 20); + c.0 + }; + + let mut t = [10, 20]; + let _ = { + //~^ ERROR: mutable borrow + &mut t[0] + }; + + let _ = &mut { + // Do not lint, the variable is defined inside the block + let mut t = [10, 20]; + t[0] + }; + + unsafe fn unsafe_func(_: &mut i32) {} + let mut a = 10; + // Unsafe block needed to call `unsafe_func` + let double_a_ref = unsafe { + //~^ ERROR: mutable borrow + unsafe_func(&mut a); + &mut a + }; +} + +#[test] +fn in_test() { + let mut a = [10; 2]; + let _ = { &mut a }; //~ ERROR: mutable borrow +} diff --git a/tests/ui/mutable_borrow_of_copy.rs b/tests/ui/mutable_borrow_of_copy.rs new file mode 100644 index 000000000000..b1c107b9ab7b --- /dev/null +++ b/tests/ui/mutable_borrow_of_copy.rs @@ -0,0 +1,109 @@ +#![warn(clippy::mutable_borrow_of_copy)] +#![allow(clippy::deref_addrof)] + +fn main() { + let mut a = [0u8; 2]; + let _ = &mut { a }; //~ mutable_borrow_of_copy + + let _ = &mut 'label: { + // Block is targeted by break + if a[0] == 1 { + break 'label 42u8; + } + a[0] + }; + + let mut a = vec![0u8; 2]; + let _ = &mut { a }; // `a` is not `Copy` + + let a = [0u8; 2]; + let _ = &mut { a }; // `a` is not mutable + + let _ = &mut { 42 }; // Do not lint on non-place expression + + let _ = &mut {}; // Do not lint on empty block + + macro_rules! mac { + ($a:expr) => {{ a }}; + } + let _ = &mut mac!(a); // Do not lint on borrowed macro result + + macro_rules! mac2 { + // Do not lint, as it depends on `Copy`-ness of `a` + ($x:expr) => { + &mut unsafe { $x } + }; + } + let mut a = 0u8; + let _ = &mut mac2!(a); + + let _ = &mut { + // Do not lint, the variable is defined inside the block + let mut a: [i32; 5] = (1, 2, 3, 4, 5).into(); + a + }; + + let _ = &mut { + // Do not lint, the variable is defined inside the block + { + let mut a: [i32; 5] = (1, 2, 3, 4, 5).into(); + a + } + }; + + struct S { + a: u32, + } + + let mut s = S { a: 0 }; + let _ = &mut { + //~^ mutable_borrow_of_copy + s.a = 32; + s.a + }; + + let _ = &mut { + // Do not lint, the variable is defined inside the block + let mut s = S { a: 0 }; + s.a + }; + + let mut c = (10, 20); + let _ = &mut { + //~^ ERROR: mutable borrow + c.0 + }; + + let _ = &mut { + // Do not lint, the variable is defined inside the block + let mut c = (10, 20); + c.0 + }; + + let mut t = [10, 20]; + let _ = &mut { + //~^ ERROR: mutable borrow + t[0] + }; + + let _ = &mut { + // Do not lint, the variable is defined inside the block + let mut t = [10, 20]; + t[0] + }; + + unsafe fn unsafe_func(_: &mut i32) {} + let mut a = 10; + // Unsafe block needed to call `unsafe_func` + let double_a_ref = &mut unsafe { + //~^ ERROR: mutable borrow + unsafe_func(&mut a); + a + }; +} + +#[test] +fn in_test() { + let mut a = [10; 2]; + let _ = &mut { a }; //~ ERROR: mutable borrow +} diff --git a/tests/ui/mutable_borrow_of_copy.stderr b/tests/ui/mutable_borrow_of_copy.stderr new file mode 100644 index 000000000000..62f070a65741 --- /dev/null +++ b/tests/ui/mutable_borrow_of_copy.stderr @@ -0,0 +1,100 @@ +error: mutable borrow of a value which was just copied + --> tests/ui/mutable_borrow_of_copy.rs:6:13 + | +LL | let _ = &mut { a }; + | ^^^^^^^^^^ + | + = note: `-D clippy::mutable-borrow-of-copy` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::mutable_borrow_of_copy)]` +help: try building the reference inside the block + | +LL - let _ = &mut { a }; +LL + let _ = { &mut a }; + | + +error: mutable borrow of a value which was just copied + --> tests/ui/mutable_borrow_of_copy.rs:59:13 + | +LL | let _ = &mut { + | _____________^ +LL | | +LL | | s.a = 32; +LL | | s.a +LL | | }; + | |_____^ + | +help: try building the reference inside the block + | +LL ~ let _ = { +LL | +LL | s.a = 32; +LL ~ &mut s.a + | + +error: mutable borrow of a value which was just copied + --> tests/ui/mutable_borrow_of_copy.rs:72:13 + | +LL | let _ = &mut { + | _____________^ +LL | | +LL | | c.0 +LL | | }; + | |_____^ + | +help: try building the reference inside the block + | +LL ~ let _ = { +LL | +LL ~ &mut c.0 + | + +error: mutable borrow of a value which was just copied + --> tests/ui/mutable_borrow_of_copy.rs:84:13 + | +LL | let _ = &mut { + | _____________^ +LL | | +LL | | t[0] +LL | | }; + | |_____^ + | +help: try building the reference inside the block + | +LL ~ let _ = { +LL | +LL ~ &mut t[0] + | + +error: mutable borrow of a value which was just copied + --> tests/ui/mutable_borrow_of_copy.rs:98:24 + | +LL | let double_a_ref = &mut unsafe { + | ________________________^ +LL | | +LL | | unsafe_func(&mut a); +LL | | a +LL | | }; + | |_____^ + | +help: try building the reference inside the block + | +LL ~ let double_a_ref = unsafe { +LL | +LL | unsafe_func(&mut a); +LL ~ &mut a + | + +error: mutable borrow of a value which was just copied + --> tests/ui/mutable_borrow_of_copy.rs:108:13 + | +LL | let _ = &mut { a }; + | ^^^^^^^^^^ + | +help: try building the reference inside the block + | +LL - let _ = &mut { a }; +LL + let _ = { &mut a }; + | + +error: aborting due to 6 previous errors + diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed index 54cad2e393fd..87454b1ca1c8 100644 --- a/tests/ui/needless_borrow.fixed +++ b/tests/ui/needless_borrow.fixed @@ -5,7 +5,8 @@ clippy::unnecessary_mut_passed, clippy::unnecessary_to_owned, clippy::unnecessary_literal_unwrap, - clippy::needless_lifetimes + clippy::needless_lifetimes, + clippy::mutable_borrow_of_copy )] #![warn(clippy::needless_borrow)] diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index b698c6bfc969..11b930e97d06 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -5,7 +5,8 @@ clippy::unnecessary_mut_passed, clippy::unnecessary_to_owned, clippy::unnecessary_literal_unwrap, - clippy::needless_lifetimes + clippy::needless_lifetimes, + clippy::mutable_borrow_of_copy )] #![warn(clippy::needless_borrow)] diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index 172d36bd73a0..540add2bda4b 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -1,5 +1,5 @@ error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:16:15 + --> tests/ui/needless_borrow.rs:17:15 | LL | let _ = x(&&a); // warn | ^^^ help: change this to: `&a` @@ -8,163 +8,163 @@ LL | let _ = x(&&a); // warn = help: to override `-D warnings` add `#[allow(clippy::needless_borrow)]` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:22:13 + --> tests/ui/needless_borrow.rs:23:13 | LL | mut_ref(&mut &mut b); // warn | ^^^^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:36:13 + --> tests/ui/needless_borrow.rs:37:13 | LL | &&a | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:39:15 + --> tests/ui/needless_borrow.rs:40:15 | LL | 46 => &&a, | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:46:27 + --> tests/ui/needless_borrow.rs:47:27 | LL | break &ref_a; | ^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:54:15 + --> tests/ui/needless_borrow.rs:55:15 | LL | let _ = x(&&&a); | ^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:56:15 + --> tests/ui/needless_borrow.rs:57:15 | LL | let _ = x(&mut &&a); | ^^^^^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:58:15 + --> tests/ui/needless_borrow.rs:59:15 | LL | let _ = x(&&&mut b); | ^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:60:15 + --> tests/ui/needless_borrow.rs:61:15 | LL | let _ = x(&&ref_a); | ^^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:64:11 + --> tests/ui/needless_borrow.rs:65:11 | LL | x(&b); | ^^ help: change this to: `b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:72:13 + --> tests/ui/needless_borrow.rs:73:13 | LL | mut_ref(&mut x); | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:74:13 + --> tests/ui/needless_borrow.rs:75:13 | LL | mut_ref(&mut &mut x); | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:76:23 + --> tests/ui/needless_borrow.rs:77:23 | LL | let y: &mut i32 = &mut x; | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:78:23 + --> tests/ui/needless_borrow.rs:79:23 | LL | let y: &mut i32 = &mut &mut x; | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:88:14 + --> tests/ui/needless_borrow.rs:89:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:95:14 + --> tests/ui/needless_borrow.rs:96:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:108:13 + --> tests/ui/needless_borrow.rs:109:13 | LL | let _ = (&x).0; | ^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:119:5 + --> tests/ui/needless_borrow.rs:120:5 | LL | (&&()).foo(); | ^^^^^^ help: change this to: `(&())` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:129:5 + --> tests/ui/needless_borrow.rs:130:5 | LL | (&&5).foo(); | ^^^^^ help: change this to: `(&5)` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:156:23 + --> tests/ui/needless_borrow.rs:157:23 | LL | let x: (&str,) = (&"",); | ^^^ help: change this to: `""` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:199:13 + --> tests/ui/needless_borrow.rs:200:13 | LL | (&self.f)() | ^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:209:13 + --> tests/ui/needless_borrow.rs:210:13 | LL | (&mut self.f)() | ^^^^^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:247:22 + --> tests/ui/needless_borrow.rs:248:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:255:22 + --> tests/ui/needless_borrow.rs:256:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:260:22 + --> tests/ui/needless_borrow.rs:261:22 | LL | let _ = &mut (&mut x.u).x; | ^^^^^^^^^^ help: change this to: `x.u` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:262:22 + --> tests/ui/needless_borrow.rs:263:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:284:23 + --> tests/ui/needless_borrow.rs:285:23 | LL | option.unwrap_or((&x.0,)); | ^^^^ help: change this to: `x.0` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:291:13 + --> tests/ui/needless_borrow.rs:292:13 | LL | let _ = (&slice).len(); | ^^^^^^^^ help: change this to: `slice`