Skip to content

Commit 1321da5

Browse files
committed
Fix false positive with new_ret_no_self when returning Self with different generic arguments
1 parent f3de78e commit 1321da5

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

clippy_lints/src/methods/mod.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ mod zst_offset;
5454
use bind_instead_of_map::BindInsteadOfMap;
5555
use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg};
5656
use clippy_utils::source::snippet_with_applicability;
57-
use clippy_utils::ty::{contains_ty, implements_trait, is_copy, is_type_diagnostic_item};
57+
use clippy_utils::ty::{contains_adt, contains_ty, implements_trait, is_copy, is_type_diagnostic_item};
5858
use clippy_utils::{
5959
contains_return, get_trait_def_id, in_macro, iter_input_pats, match_def_path, match_qpath, method_calls,
6060
method_chain_args, paths, return_ty, single_segment_path, SpanlessEq,
@@ -1907,7 +1907,11 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
19071907
let ret_ty = return_ty(cx, impl_item.hir_id());
19081908

19091909
// walk the return type and check for Self (this does not check associated types)
1910-
if contains_ty(ret_ty, self_ty) {
1910+
if let Some(self_adt) = self_ty.ty_adt_def() {
1911+
if contains_adt(ret_ty, self_adt) {
1912+
return;
1913+
}
1914+
} else if contains_ty(ret_ty, self_ty) {
19111915
return;
19121916
}
19131917

@@ -1917,7 +1921,11 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
19171921
for &(predicate, _span) in cx.tcx.explicit_item_bounds(def_id) {
19181922
if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
19191923
// walk the associated type and check for Self
1920-
if contains_ty(projection_predicate.ty, self_ty) {
1924+
if let Some(self_adt) = self_ty.ty_adt_def() {
1925+
if contains_adt(projection_predicate.ty, self_adt) {
1926+
return;
1927+
}
1928+
} else if contains_ty(projection_predicate.ty, self_ty) {
19211929
return;
19221930
}
19231931
}

clippy_utils/src/ty.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use rustc_hir::{TyKind, Unsafety};
1111
use rustc_infer::infer::TyCtxtInferExt;
1212
use rustc_lint::LateContext;
1313
use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
14-
use rustc_middle::ty::{self, IntTy, Ty, TypeFoldable, UintTy};
14+
use rustc_middle::ty::{self, AdtDef, IntTy, Ty, TypeFoldable, UintTy};
1515
use rustc_span::sym;
1616
use rustc_span::symbol::Symbol;
1717
use rustc_span::DUMMY_SP;
@@ -43,6 +43,15 @@ pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool {
4343
})
4444
}
4545

46+
/// Walks into `ty` and returns `true` if any inner type is any instance of the given abstract data
47+
/// type.`
48+
pub fn contains_adt(ty: Ty<'_>, adt: &AdtDef) -> bool {
49+
ty.walk().any(|inner| match inner.unpack() {
50+
GenericArgKind::Type(inner_ty) => inner_ty.ty_adt_def() == Some(adt),
51+
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
52+
})
53+
}
54+
4655
/// Returns true if ty has `iter` or `iter_mut` methods
4756
pub fn has_iter_method(cx: &LateContext<'_>, probably_ref_ty: Ty<'_>) -> Option<Symbol> {
4857
// FIXME: instead of this hard-coded list, we should check if `<adt>::iter`

tests/ui/new_ret_no_self.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,3 +340,13 @@ mod issue5435 {
340340
}
341341
}
342342
}
343+
344+
// issue #1724
345+
struct RetOtherSelf<T>(T);
346+
struct RetOtherSelfWrapper<T>(T);
347+
348+
impl RetOtherSelf<T> {
349+
fn new(t: T) -> RetOtherSelf<RetOtherSelfWrapper<T>> {
350+
RetOtherSelf(RetOtherSelfWrapper(t))
351+
}
352+
}

0 commit comments

Comments
 (0)