Skip to content

Commit 1999a31

Browse files
committed
Fix borrow and deref
1 parent da3995f commit 1999a31

File tree

11 files changed

+67
-32
lines changed

11 files changed

+67
-32
lines changed

compiler/rustc_lint/src/noop_method_call.rs

+6-12
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ declare_lint! {
1515
///
1616
/// ```rust
1717
/// # #![allow(unused)]
18+
/// #![deny(noop_method_call)]
1819
/// struct Foo;
1920
/// let foo = &Foo;
2021
/// let clone: &Foo = foo.clone();
@@ -30,7 +31,7 @@ declare_lint! {
3031
/// calling `clone` on a `&T` where `T` does not implement clone, actually doesn't do anything
3132
/// as references are copy. This lint detects these calls and warns the user about them.
3233
pub NOOP_METHOD_CALL,
33-
Warn,
34+
Allow,
3435
"detects the use of well-known noop methods"
3536
}
3637

@@ -50,7 +51,9 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
5051
Some((DefKind::AssocFn, did)) => match cx.tcx.trait_of_item(did) {
5152
// Check that we're dealing with a trait method for one of the traits we care about.
5253
Some(trait_id)
53-
if [sym::Clone].iter().any(|s| cx.tcx.is_diagnostic_item(*s, trait_id)) =>
54+
if [sym::Clone, sym::Deref, sym::Borrow]
55+
.iter()
56+
.any(|s| cx.tcx.is_diagnostic_item(*s, trait_id)) =>
5457
{
5558
(trait_id, did)
5659
}
@@ -71,20 +74,11 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
7174
_ => return,
7275
};
7376
// (Re)check that it implements the noop diagnostic.
74-
for (s, peel_ref) in [(sym::noop_method_clone, false)].iter() {
77+
for s in [sym::noop_method_clone, sym::noop_method_deref, sym::noop_method_borrow].iter() {
7578
if cx.tcx.is_diagnostic_item(*s, i.def_id()) {
7679
let method = &call.ident.name;
7780
let receiver = &elements[0];
7881
let receiver_ty = cx.typeck_results().expr_ty(receiver);
79-
let receiver_ty = match receiver_ty.kind() {
80-
// Remove one borrow from the receiver if appropriate to positively verify that
81-
// the receiver `&self` type and the return type are the same, depending on the
82-
// involved trait being checked.
83-
ty::Ref(_, ty, _) if *peel_ref => ty,
84-
// When it comes to `Clone` we need to check the `receiver_ty` directly.
85-
// FIXME: we must come up with a better strategy for this.
86-
_ => receiver_ty,
87-
};
8882
let expr_ty = cx.typeck_results().expr_ty_adjusted(expr);
8983
if receiver_ty != expr_ty {
9084
// This lint will only trigger if the receiver type and resulting expression \

compiler/rustc_span/src/symbol.rs

+3
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,7 @@ symbols! {
142142
Decodable,
143143
Decoder,
144144
Default,
145+
Deref,
145146
Encodable,
146147
Encoder,
147148
Eq,
@@ -790,7 +791,9 @@ symbols! {
790791
none_error,
791792
nontemporal_store,
792793
nontrapping_dash_fptoint: "nontrapping-fptoint",
794+
noop_method_borrow,
793795
noop_method_clone,
796+
noop_method_deref,
794797
noreturn,
795798
nostack,
796799
not,

library/core/src/borrow.rs

+2
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,7 @@
153153
/// [`HashMap<K, V>`]: ../../std/collections/struct.HashMap.html
154154
/// [`String`]: ../../std/string/struct.String.html
155155
#[stable(feature = "rust1", since = "1.0.0")]
156+
#[rustc_diagnostic_item = "Borrow"]
156157
pub trait Borrow<Borrowed: ?Sized> {
157158
/// Immutably borrows from an owned value.
158159
///
@@ -205,6 +206,7 @@ pub trait BorrowMut<Borrowed: ?Sized>: Borrow<Borrowed> {
205206

206207
#[stable(feature = "rust1", since = "1.0.0")]
207208
impl<T: ?Sized> Borrow<T> for T {
209+
#[rustc_diagnostic_item = "noop_method_borrow"]
208210
fn borrow(&self) -> &T {
209211
self
210212
}

library/core/src/ops/deref.rs

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
#[doc(alias = "*")]
6161
#[doc(alias = "&*")]
6262
#[stable(feature = "rust1", since = "1.0.0")]
63+
#[rustc_diagnostic_item = "Deref"]
6364
pub trait Deref {
6465
/// The resulting type after dereferencing.
6566
#[stable(feature = "rust1", since = "1.0.0")]
@@ -78,6 +79,7 @@ pub trait Deref {
7879
impl<T: ?Sized> Deref for &T {
7980
type Target = T;
8081

82+
#[rustc_diagnostic_item = "noop_method_deref"]
8183
fn deref(&self) -> &T {
8284
*self
8385
}

library/core/tests/clone.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![cfg_attr(not(bootstrap), allow(noop_method_call))]
2-
31
#[test]
42
fn test_borrowed_clone() {
53
let x = 5;

src/test/ui/issues/issue-11820.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// run-pass
22
// pretty-expanded FIXME #23616
33

4-
#![allow(noop_method_call)]
5-
64
struct NoClone;
75

86
fn main() {

src/test/ui/lint/noop-method-call.rs

+25-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
// check-pass
22

33
#![allow(unused)]
4+
#![warn(noop_method_call)]
45

5-
struct NonCloneType<T>(T);
6+
use std::borrow::Borrow;
7+
use std::ops::Deref;
8+
9+
struct PlainType<T>(T);
610

711
#[derive(Clone)]
812
struct CloneType<T>(T);
913

1014
fn main() {
11-
let non_clone_type_ref = &NonCloneType(1u32);
12-
let non_clone_type_ref_clone: &NonCloneType<u32> = non_clone_type_ref.clone();
15+
let non_clone_type_ref = &PlainType(1u32);
16+
let non_clone_type_ref_clone: &PlainType<u32> = non_clone_type_ref.clone();
1317
//~^ WARNING call to `.clone()` on a reference in this situation does nothing
1418

1519
let clone_type_ref = &CloneType(1u32);
@@ -20,15 +24,31 @@ fn main() {
2024
let clone_type_ref = &&CloneType(1u32);
2125
let clone_type_ref_clone: &CloneType<u32> = clone_type_ref.clone();
2226

27+
let non_deref_type = &PlainType(1u32);
28+
let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref();
29+
//~^ WARNING call to `.deref()` on a reference in this situation does nothing
30+
31+
// Dereferencing a &&T does not warn since it has collapsed the double reference
32+
let non_deref_type = &&PlainType(1u32);
33+
let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref();
34+
35+
let non_borrow_type = &PlainType(1u32);
36+
let non_borrow_type_borrow: &PlainType<u32> = non_borrow_type.borrow();
37+
//~^ WARNING call to `.borrow()` on a reference in this situation does nothing
38+
39+
// Borrowing a &&T does not warn since it has collapsed the double reference
40+
let non_borrow_type = &&PlainType(1u32);
41+
let non_borrow_type_borrow: &PlainType<u32> = non_borrow_type.borrow();
42+
2343
let xs = ["a", "b", "c"];
2444
let _v: Vec<&str> = xs.iter().map(|x| x.clone()).collect(); // ok, but could use `*x` instead
2545
}
2646

27-
fn generic<T>(non_clone_type: &NonCloneType<T>) {
47+
fn generic<T>(non_clone_type: &PlainType<T>) {
2848
non_clone_type.clone();
2949
}
3050

31-
fn non_generic(non_clone_type: &NonCloneType<u32>) {
51+
fn non_generic(non_clone_type: &PlainType<u32>) {
3252
non_clone_type.clone();
3353
//~^ WARNING call to `.clone()` on a reference in this situation does nothing
3454
}
+28-8
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,39 @@
11
warning: call to `.clone()` on a reference in this situation does nothing
2-
--> $DIR/noop-method-call.rs:12:74
2+
--> $DIR/noop-method-call.rs:16:71
33
|
4-
LL | let non_clone_type_ref_clone: &NonCloneType<u32> = non_clone_type_ref.clone();
5-
| ^^^^^^^^ unnecessary method call
4+
LL | let non_clone_type_ref_clone: &PlainType<u32> = non_clone_type_ref.clone();
5+
| ^^^^^^^^ unnecessary method call
66
|
7-
= note: `#[warn(noop_method_call)]` on by default
8-
= note: the type `&NonCloneType<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed
7+
note: the lint level is defined here
8+
--> $DIR/noop-method-call.rs:4:9
9+
|
10+
LL | #![warn(noop_method_call)]
11+
| ^^^^^^^^^^^^^^^^
12+
= note: the type `&PlainType<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed
13+
14+
warning: call to `.deref()` on a reference in this situation does nothing
15+
--> $DIR/noop-method-call.rs:28:63
16+
|
17+
LL | let non_deref_type_deref: &PlainType<u32> = non_deref_type.deref();
18+
| ^^^^^^^^ unnecessary method call
19+
|
20+
= note: the type `&PlainType<u32>` which `deref` is being called on is the same as the type returned from `deref`, so the method call does not do anything and can be removed
21+
22+
warning: call to `.borrow()` on a reference in this situation does nothing
23+
--> $DIR/noop-method-call.rs:36:66
24+
|
25+
LL | let non_borrow_type_borrow: &PlainType<u32> = non_borrow_type.borrow();
26+
| ^^^^^^^^^ unnecessary method call
27+
|
28+
= note: the type `&PlainType<u32>` which `borrow` is being called on is the same as the type returned from `borrow`, so the method call does not do anything and can be removed
929

1030
warning: call to `.clone()` on a reference in this situation does nothing
11-
--> $DIR/noop-method-call.rs:32:19
31+
--> $DIR/noop-method-call.rs:52:19
1232
|
1333
LL | non_clone_type.clone();
1434
| ^^^^^^^^ unnecessary method call
1535
|
16-
= note: the type `&NonCloneType<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed
36+
= note: the type `&PlainType<u32>` which `clone` is being called on is the same as the type returned from `clone`, so the method call does not do anything and can be removed
1737

18-
warning: 2 warnings emitted
38+
warning: 4 warnings emitted
1939

src/test/ui/underscore-imports/cycle.rs

-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,5 @@ mod y {
1414

1515
pub fn main() {
1616
use x::*;
17-
#[allow(noop_method_call)]
1817
(&0).deref();
1918
}

src/test/ui/underscore-imports/macro-expanded.rs

-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// check-pass
44

55
#![feature(decl_macro, rustc_attrs)]
6-
#![allow(noop_method_call)]
76

87
mod x {
98
pub use std::ops::Not as _;

src/tools/clippy/tests/ui/unnecessary_clone.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// does not test any rustfixable lints
22

33
#![warn(clippy::clone_on_ref_ptr)]
4-
#![allow(unused, noop_method_call, clippy::redundant_clone, clippy::unnecessary_wraps)]
4+
#![allow(unused, clippy::redundant_clone, clippy::unnecessary_wraps)]
55

66
use std::cell::RefCell;
77
use std::rc::{self, Rc};

0 commit comments

Comments
 (0)