Update the "borrow box" lint to avoid recommending the following
conversion:

```
  // Old
  pub fn f(&mut Box<T>) {...}

  // New
  pub fn f(&mut T) {...}
```

Given a mutable reference to a box, functions may want to change
"which" object the Box is pointing at.

This change avoids recommending removing the "Box" parameter
for mutable references.
This commit is contained in:
Sean Klein 2020-04-19 10:49:12 -04:00
parent f6b07db385
commit 0ef5dee3b8
3 changed files with 31 additions and 19 deletions

View file

@ -531,11 +531,12 @@ impl Types {
} else { } else {
format!("{} ", lt.name.ident().as_str()) format!("{} ", lt.name.ident().as_str())
}; };
let mutopt = if mut_ty.mutbl == Mutability::Mut {
"mut " if mut_ty.mutbl == Mutability::Mut {
} else { // Ignore `&mut Box<T>` types; see issue #2907 for
"" // details.
}; return;
}
let mut applicability = Applicability::MachineApplicable; let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,
@ -544,9 +545,8 @@ impl Types {
"you seem to be trying to use `&Box<T>`. Consider using just `&T`", "you seem to be trying to use `&Box<T>`. Consider using just `&T`",
"try", "try",
format!( format!(
"&{}{}{}", "&{}{}",
ltopt, ltopt,
mutopt,
&snippet_with_applicability(cx, inner.span, "..", &mut applicability) &snippet_with_applicability(cx, inner.span, "..", &mut applicability)
), ),
Applicability::Unspecified, Applicability::Unspecified,

View file

@ -4,6 +4,14 @@
#![allow(dead_code)] #![allow(dead_code)]
pub fn test1(foo: &mut Box<bool>) { pub fn test1(foo: &mut Box<bool>) {
// Although this function could be changed to "&mut bool",
// avoiding the Box, mutable references to boxes are not
// flagged by this lint.
//
// This omission is intentional: By passing a mutable Box,
// the memory location of the pointed-to object could be
// modified. By passing a mutable reference, the contents
// could change, but not the location.
println!("{:?}", foo) println!("{:?}", foo)
} }
@ -71,6 +79,16 @@ impl<'a> Test12 for Test11<'a> {
} }
} }
pub fn test13(boxed_slice: &mut Box<[i32]>) {
// Unconditionally replaces the box pointer.
//
// This cannot be accomplished if "&mut [i32]" is passed,
// and provides a test case where passing a reference to
// a Box is valid.
let mut data = vec![12];
*boxed_slice = data.into_boxed_slice();
}
fn main() { fn main() {
test1(&mut Box::new(false)); test1(&mut Box::new(false));
test2(); test2();

View file

@ -1,8 +1,8 @@
error: you seem to be trying to use `&Box<T>`. Consider using just `&T` error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> $DIR/borrow_box.rs:6:19 --> $DIR/borrow_box.rs:19:14
| |
LL | pub fn test1(foo: &mut Box<bool>) { LL | let foo: &Box<bool>;
| ^^^^^^^^^^^^^^ help: try: `&mut bool` | ^^^^^^^^^^ help: try: `&bool`
| |
note: the lint level is defined here note: the lint level is defined here
--> $DIR/borrow_box.rs:1:9 --> $DIR/borrow_box.rs:1:9
@ -11,22 +11,16 @@ LL | #![deny(clippy::borrowed_box)]
| ^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^
error: you seem to be trying to use `&Box<T>`. Consider using just `&T` error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> $DIR/borrow_box.rs:11:14 --> $DIR/borrow_box.rs:23:10
|
LL | let foo: &Box<bool>;
| ^^^^^^^^^^ help: try: `&bool`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> $DIR/borrow_box.rs:15:10
| |
LL | foo: &'a Box<bool>, LL | foo: &'a Box<bool>,
| ^^^^^^^^^^^^^ help: try: `&'a bool` | ^^^^^^^^^^^^^ help: try: `&'a bool`
error: you seem to be trying to use `&Box<T>`. Consider using just `&T` error: you seem to be trying to use `&Box<T>`. Consider using just `&T`
--> $DIR/borrow_box.rs:19:17 --> $DIR/borrow_box.rs:27:17
| |
LL | fn test4(a: &Box<bool>); LL | fn test4(a: &Box<bool>);
| ^^^^^^^^^^ help: try: `&bool` | ^^^^^^^^^^ help: try: `&bool`
error: aborting due to 4 previous errors error: aborting due to 3 previous errors