Skip to content

Commit bce1905

Browse files
Merge #3338
3338: new_ret_no_self false positives r=flip1995 a=JoshMcguigan ~~WORK IN PROGRESS~~ I plan to fix all of the false positives in #3313 in this PR, but I wanted to open it now to start gathering feedback. In this first commit, I've updated the lint to allow tuple return types as long as `Self` shows up at least once, in any position of the tuple. I believe this is the broadest possible interpretation of what should be allowed for tuple return types, but I would certainly be okay making the lint more strict. fixes #3313 Co-authored-by: Josh Mcguigan <[email protected]>
2 parents 319b75c + 30ffc17 commit bce1905

File tree

4 files changed

+110
-4
lines changed

4 files changed

+110
-4
lines changed

clippy_lints/src/methods/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -936,10 +936,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
936936
if let hir::ImplItemKind::Method(_, _) = implitem.node {
937937
let ret_ty = return_ty(cx, implitem.id);
938938

939-
// if return type is impl trait
939+
// walk the return type and check for Self (this does not check associated types)
940+
for inner_type in ret_ty.walk() {
941+
if same_tys(cx, ty, inner_type) { return; }
942+
}
943+
944+
// if return type is impl trait, check the associated types
940945
if let TyKind::Opaque(def_id, _) = ret_ty.sty {
941946

942-
// then one of the associated types must be Self
947+
// one of the associated types must be Self
943948
for predicate in cx.tcx.predicates_of(def_id).predicates.iter() {
944949
match predicate {
945950
(Predicate::Projection(poly_projection_predicate), _) => {

clippy_lints/src/types.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1920,7 +1920,6 @@ enum ImplicitHasherType<'tcx> {
19201920

19211921
impl<'tcx> ImplicitHasherType<'tcx> {
19221922
/// Checks that `ty` is a target type without a BuildHasher.
1923-
#[allow(clippy::new_ret_no_self)]
19241923
fn new<'a>(cx: &LateContext<'a, 'tcx>, hir_ty: &hir::Ty) -> Option<Self> {
19251924
if let TyKind::Path(QPath::Resolved(None, ref path)) = hir_ty.node {
19261925
let params: Vec<_> = path.segments.last().as_ref()?.args.as_ref()?

tests/ui/new_ret_no_self.rs

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,87 @@ impl V {
9191
unimplemented!();
9292
}
9393
}
94+
95+
struct TupleReturnerOk;
96+
97+
impl TupleReturnerOk {
98+
// should not trigger lint
99+
pub fn new() -> (Self, u32) { unimplemented!(); }
100+
}
101+
102+
struct TupleReturnerOk2;
103+
104+
impl TupleReturnerOk2 {
105+
// should not trigger lint (it doesn't matter which element in the tuple is Self)
106+
pub fn new() -> (u32, Self) { unimplemented!(); }
107+
}
108+
109+
struct TupleReturnerOk3;
110+
111+
impl TupleReturnerOk3 {
112+
// should not trigger lint (tuple can contain multiple Self)
113+
pub fn new() -> (Self, Self) { unimplemented!(); }
114+
}
115+
116+
struct TupleReturnerBad;
117+
118+
impl TupleReturnerBad {
119+
// should trigger lint
120+
pub fn new() -> (u32, u32) { unimplemented!(); }
121+
}
122+
123+
struct MutPointerReturnerOk;
124+
125+
impl MutPointerReturnerOk {
126+
// should not trigger lint
127+
pub fn new() -> *mut Self { unimplemented!(); }
128+
}
129+
130+
struct MutPointerReturnerOk2;
131+
132+
impl MutPointerReturnerOk2 {
133+
// should not trigger lint
134+
pub fn new() -> *const Self { unimplemented!(); }
135+
}
136+
137+
struct MutPointerReturnerBad;
138+
139+
impl MutPointerReturnerBad {
140+
// should trigger lint
141+
pub fn new() -> *mut V { unimplemented!(); }
142+
}
143+
144+
struct GenericReturnerOk;
145+
146+
impl GenericReturnerOk {
147+
// should not trigger lint
148+
pub fn new() -> Option<Self> { unimplemented!(); }
149+
}
150+
151+
struct GenericReturnerBad;
152+
153+
impl GenericReturnerBad {
154+
// should trigger lint
155+
pub fn new() -> Option<u32> { unimplemented!(); }
156+
}
157+
158+
struct NestedReturnerOk;
159+
160+
impl NestedReturnerOk {
161+
// should not trigger lint
162+
pub fn new() -> (Option<Self>, u32) { unimplemented!(); }
163+
}
164+
165+
struct NestedReturnerOk2;
166+
167+
impl NestedReturnerOk2 {
168+
// should not trigger lint
169+
pub fn new() -> ((Self, u32), u32) { unimplemented!(); }
170+
}
171+
172+
struct NestedReturnerOk3;
173+
174+
impl NestedReturnerOk3 {
175+
// should not trigger lint
176+
pub fn new() -> Option<(Self, u32)> { unimplemented!(); }
177+
}

tests/ui/new_ret_no_self.stderr

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,23 @@ error: methods called `new` usually return `Self`
2424
92 | | }
2525
| |_____^
2626

27-
error: aborting due to 3 previous errors
27+
error: methods called `new` usually return `Self`
28+
--> $DIR/new_ret_no_self.rs:120:5
29+
|
30+
120 | pub fn new() -> (u32, u32) { unimplemented!(); }
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
32+
33+
error: methods called `new` usually return `Self`
34+
--> $DIR/new_ret_no_self.rs:141:5
35+
|
36+
141 | pub fn new() -> *mut V { unimplemented!(); }
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
38+
39+
error: methods called `new` usually return `Self`
40+
--> $DIR/new_ret_no_self.rs:155:5
41+
|
42+
155 | pub fn new() -> Option<u32> { unimplemented!(); }
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44+
45+
error: aborting due to 6 previous errors
2846

0 commit comments

Comments
 (0)