mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-10 07:04:18 +00:00
new_ret_no_self correctly lint impl return
This commit is contained in:
parent
2ef4af7db2
commit
a5e4805ecf
3 changed files with 59 additions and 14 deletions
|
@ -11,7 +11,7 @@
|
|||
use crate::rustc::hir;
|
||||
use crate::rustc::hir::def::Def;
|
||||
use crate::rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass};
|
||||
use crate::rustc::ty::{self, Ty};
|
||||
use crate::rustc::ty::{self, Ty, TyKind, Predicate};
|
||||
use crate::rustc::{declare_tool_lint, lint_array};
|
||||
use crate::rustc_errors::Applicability;
|
||||
use crate::syntax::ast;
|
||||
|
@ -933,9 +933,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
|
|||
|
||||
if let hir::ImplItemKind::Method(_, _) = implitem.node {
|
||||
let ret_ty = return_ty(cx, implitem.id);
|
||||
if name == "new" &&
|
||||
!same_tys(cx, ret_ty, ty) &&
|
||||
!ret_ty.is_impl_trait() {
|
||||
|
||||
// if return type is impl trait
|
||||
if let TyKind::Opaque(def_id, _) = ret_ty.sty {
|
||||
|
||||
// then one of the associated types must be Self
|
||||
for predicate in cx.tcx.predicates_of(def_id).predicates.iter() {
|
||||
match predicate {
|
||||
(Predicate::Projection(poly_projection_predicate), _) => {
|
||||
let binder = poly_projection_predicate.ty();
|
||||
let associated_type = binder.skip_binder();
|
||||
let associated_type_is_self_type = same_tys(cx, ty, associated_type);
|
||||
|
||||
// if the associated type is self, early return and do not trigger lint
|
||||
if associated_type_is_self_type { return; }
|
||||
},
|
||||
(_, _) => {},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if name == "new" && !same_tys(cx, ret_ty, ty) {
|
||||
span_lint(cx,
|
||||
NEW_RET_NO_SELF,
|
||||
implitem.span,
|
||||
|
|
|
@ -9,6 +9,11 @@ trait R {
|
|||
type Item;
|
||||
}
|
||||
|
||||
trait Q {
|
||||
type Item;
|
||||
type Item2;
|
||||
}
|
||||
|
||||
struct S;
|
||||
|
||||
impl R for S {
|
||||
|
@ -42,12 +47,26 @@ impl R for S3 {
|
|||
}
|
||||
|
||||
impl S3 {
|
||||
// should trigger the lint, but currently does not
|
||||
// should trigger the lint
|
||||
pub fn new(_: String) -> impl R<Item = u32> {
|
||||
S3
|
||||
}
|
||||
}
|
||||
|
||||
struct S4;
|
||||
|
||||
impl Q for S4 {
|
||||
type Item = u32;
|
||||
type Item2 = Self;
|
||||
}
|
||||
|
||||
impl S4 {
|
||||
// should not trigger the lint
|
||||
pub fn new(_: String) -> impl Q<Item = u32, Item2 = Self> {
|
||||
S4
|
||||
}
|
||||
}
|
||||
|
||||
struct T;
|
||||
|
||||
impl T {
|
||||
|
|
|
@ -1,20 +1,28 @@
|
|||
error: methods called `new` usually return `Self`
|
||||
--> $DIR/new_ret_no_self.rs:64:5
|
||||
--> $DIR/new_ret_no_self.rs:51:5
|
||||
|
|
||||
64 | / pub fn new() -> u32 {
|
||||
65 | | unimplemented!();
|
||||
66 | | }
|
||||
51 | / pub fn new(_: String) -> impl R<Item = u32> {
|
||||
52 | | S3
|
||||
53 | | }
|
||||
| |_____^
|
||||
|
|
||||
= note: `-D clippy::new-ret-no-self` implied by `-D warnings`
|
||||
|
||||
error: methods called `new` usually return `Self`
|
||||
--> $DIR/new_ret_no_self.rs:73:5
|
||||
--> $DIR/new_ret_no_self.rs:83:5
|
||||
|
|
||||
73 | / pub fn new(_: String) -> u32 {
|
||||
74 | | unimplemented!();
|
||||
75 | | }
|
||||
83 | / pub fn new() -> u32 {
|
||||
84 | | unimplemented!();
|
||||
85 | | }
|
||||
| |_____^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: methods called `new` usually return `Self`
|
||||
--> $DIR/new_ret_no_self.rs:92:5
|
||||
|
|
||||
92 | / pub fn new(_: String) -> u32 {
|
||||
93 | | unimplemented!();
|
||||
94 | | }
|
||||
| |_____^
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
Loading…
Reference in a new issue