@@ -15,24 +15,24 @@ use rustc_ast::ast;
1515use rustc_errors:: Applicability ;
1616use rustc_hir as hir;
1717use rustc_hir:: intravisit:: { self , Visitor } ;
18+ use rustc_hir:: { TraitItem , TraitItemKind } ;
1819use rustc_lint:: { LateContext , LateLintPass , Lint , LintContext } ;
1920use rustc_middle:: hir:: map:: Map ;
2021use rustc_middle:: lint:: in_external_macro;
21- use rustc_middle:: ty:: subst:: GenericArgKind ;
22- use rustc_middle:: ty:: { self , Ty , TyS } ;
22+ use rustc_middle:: ty:: { self , TraitRef , Ty , TyS } ;
2323use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
2424use rustc_span:: source_map:: Span ;
2525use rustc_span:: symbol:: { sym, SymbolStr } ;
2626
2727use crate :: consts:: { constant, Constant } ;
2828use crate :: utils:: usage:: mutated_variables;
2929use crate :: utils:: {
30- get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro, is_copy ,
31- is_ctor_or_promotable_const_function, is_expn_of, is_type_diagnostic_item, iter_input_pats, last_path_segment ,
32- match_def_path, match_qpath, match_trait_method, match_type, match_var, method_calls, method_chain_args , paths ,
33- remove_blocks, return_ty, single_segment_path, snippet, snippet_with_applicability, snippet_with_macro_callsite ,
34- span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then , sugg , walk_ptrs_ty ,
35- walk_ptrs_ty_depth, SpanlessEq ,
30+ contains_ty , get_arg_name, get_parent_expr, get_trait_def_id, has_iter_method, higher, implements_trait, in_macro,
31+ is_copy , is_ctor_or_promotable_const_function, is_expn_of, is_type_diagnostic_item, iter_input_pats,
32+ last_path_segment , match_def_path, match_qpath, match_trait_method, match_type, match_var, method_calls,
33+ method_chain_args , paths , remove_blocks, return_ty, single_segment_path, snippet, snippet_with_applicability,
34+ snippet_with_macro_callsite , span_lint, span_lint_and_help, span_lint_and_note, span_lint_and_sugg,
35+ span_lint_and_then , sugg , walk_ptrs_ty , walk_ptrs_ty_depth, SpanlessEq ,
3636} ;
3737
3838declare_clippy_lint ! {
@@ -724,6 +724,7 @@ declare_clippy_lint! {
724724 /// **Known problems:** None.
725725 ///
726726 /// **Example:**
727+ /// In an impl block:
727728 /// ```rust
728729 /// # struct Foo;
729730 /// # struct NotAFoo;
@@ -736,25 +737,40 @@ declare_clippy_lint! {
736737 ///
737738 /// ```rust
738739 /// # struct Foo;
739- /// # struct FooError ;
740+ /// struct Bar(Foo) ;
740741 /// impl Foo {
741- /// // Good. Return type contains `Self`
742- /// fn new() -> Result<Foo, FooError> {
743- /// # Ok (Foo)
742+ /// // Bad. The type name must contain `Self`
743+ /// fn new() -> Bar {
744+ /// # Bar (Foo)
744745 /// }
745746 /// }
746747 /// ```
747748 ///
748749 /// ```rust
749750 /// # struct Foo;
750- /// struct Bar(Foo) ;
751+ /// # struct FooError ;
751752 /// impl Foo {
752- /// // Bad. The type name must contain `Self`.
753- /// fn new() -> Bar {
754- /// # Bar (Foo)
753+ /// // Good. Return type contains `Self`
754+ /// fn new() -> Result<Foo, FooError> {
755+ /// # Ok (Foo)
755756 /// }
756757 /// }
757758 /// ```
759+ ///
760+ /// Or in a trait definition:
761+ /// ```rust
762+ /// pub trait Trait {
763+ /// // Bad. The type name must contain `Self`
764+ /// fn new();
765+ /// }
766+ /// ```
767+ ///
768+ /// ```rust
769+ /// pub trait Trait {
770+ /// // Good. Return type contains `Self`
771+ /// fn new() -> Self;
772+ /// }
773+ /// ```
758774 pub NEW_RET_NO_SELF ,
759775 style,
760776 "not returning type containing `Self` in a `new` method"
@@ -1631,19 +1647,16 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
16311647 }
16321648 }
16331649
1650+ // if this impl block implements a trait, lint in trait definition instead
1651+ if let hir:: ItemKind :: Impl { of_trait : Some ( _) , .. } = item. kind {
1652+ return ;
1653+ }
1654+
16341655 if let hir:: ImplItemKind :: Fn ( _, _) = impl_item. kind {
16351656 let ret_ty = return_ty ( cx, impl_item. hir_id ) ;
16361657
1637- let contains_self_ty = |ty : Ty < ' tcx > | {
1638- ty. walk ( ) . any ( |inner| match inner. unpack ( ) {
1639- GenericArgKind :: Type ( inner_ty) => TyS :: same_type ( self_ty, inner_ty) ,
1640-
1641- GenericArgKind :: Lifetime ( _) | GenericArgKind :: Const ( _) => false ,
1642- } )
1643- } ;
1644-
16451658 // walk the return type and check for Self (this does not check associated types)
1646- if contains_self_ty ( ret_ty) {
1659+ if contains_ty ( ret_ty, self_ty ) {
16471660 return ;
16481661 }
16491662
@@ -1653,7 +1666,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
16531666 for & ( predicate, _span) in cx. tcx . predicates_of ( def_id) . predicates {
16541667 if let ty:: PredicateAtom :: Projection ( projection_predicate) = predicate. skip_binders ( ) {
16551668 // walk the associated type and check for Self
1656- if contains_self_ty ( projection_predicate. ty ) {
1669+ if contains_ty ( projection_predicate. ty , self_ty ) {
16571670 return ;
16581671 }
16591672 }
@@ -1670,6 +1683,26 @@ impl<'tcx> LateLintPass<'tcx> for Methods {
16701683 }
16711684 }
16721685 }
1686+
1687+ fn check_trait_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx TraitItem < ' _ > ) {
1688+ if_chain ! {
1689+ if !in_external_macro( cx. tcx. sess, item. span) ;
1690+ if item. ident. name == sym!( new) ;
1691+ if let TraitItemKind :: Fn ( _, _) = item. kind;
1692+ let ret_ty = return_ty( cx, item. hir_id) ;
1693+ let self_ty = TraitRef :: identity( cx. tcx, item. hir_id. owner. to_def_id( ) ) . self_ty( ) ;
1694+ if !contains_ty( ret_ty, self_ty) ;
1695+
1696+ then {
1697+ span_lint(
1698+ cx,
1699+ NEW_RET_NO_SELF ,
1700+ item. span,
1701+ "methods called `new` usually return `Self`" ,
1702+ ) ;
1703+ }
1704+ }
1705+ }
16731706}
16741707
16751708/// Checks for the `OR_FUN_CALL` lint.
0 commit comments