diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 097eca0af578..ae7b24f758bc 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1012,7 +1012,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ); store.register_late_pass(move || box trivially_copy_pass_by_ref); store.register_late_pass(|| box try_err::TryErr); - store.register_late_pass(|| box use_self::UseSelf); + store.register_late_pass(|| box use_self::UseSelf::default()); store.register_late_pass(|| box bytecount::ByteCount); store.register_late_pass(|| box infinite_iter::InfiniteIter); store.register_late_pass(|| box inline_fn_without_body::InlineFnWithoutBody); diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index e6942276504a..af6a8898d642 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -2,20 +2,15 @@ use crate::utils; use crate::utils::snippet_opt; use crate::utils::span_lint_and_sugg; use if_chain::if_chain; + use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::intravisit::{walk_expr, walk_impl_item, walk_ty, NestedVisitorMap, Visitor}; -use rustc_hir::{ - def, Expr, ExprKind, FnDecl, FnRetTy, FnSig, GenericArg, ImplItem, ImplItemKind, ItemKind, Node, Path, PathSegment, - QPath, TyKind, -}; +use rustc_hir::{def, Expr, ExprKind, GenericArg, HirId, Item, ItemKind, Node, Path, PathSegment, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; -use rustc_middle::hir::map::Map; use rustc_middle::lint::in_external_macro; -use rustc_middle::ty; use rustc_middle::ty::Ty; -use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::{BytePos, Span}; use rustc_typeck::hir_ty_to_ty; @@ -53,7 +48,18 @@ declare_clippy_lint! { "unnecessary structure name repetition whereas `Self` is applicable" } -declare_lint_pass!(UseSelf => [USE_SELF]); +#[derive(Default)] +pub struct UseSelf { + stack: Vec, +} + +#[derive(Debug, PartialEq, Eq)] +enum StackItem { + Check { hir_id: HirId }, + NoCheck, +} + +impl_lint_pass!(UseSelf => [USE_SELF]); const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; @@ -70,7 +76,7 @@ fn span_lint(cx: &LateContext<'_>, span: Span) { } #[allow(clippy::cast_possible_truncation)] -fn span_lint_until_last_segment<'tcx>(cx: &LateContext<'tcx>, span: Span, segment: &'tcx PathSegment<'tcx>) { +fn span_lint_until_last_segment(cx: &LateContext<'_>, span: Span, segment: &PathSegment<'_>) { let sp = span.with_hi(segment.ident.span.lo()); // remove the trailing :: let span_without_last_segment = match snippet_opt(cx, sp) { @@ -83,13 +89,13 @@ fn span_lint_until_last_segment<'tcx>(cx: &LateContext<'tcx>, span: Span, segmen span_lint(cx, span_without_last_segment); } -fn span_lint_on_path_until_last_segment<'tcx>(cx: &LateContext<'tcx>, path: &'tcx Path<'tcx>) { +fn span_lint_on_path_until_last_segment(cx: &LateContext<'_>, path: &Path<'_>) { if path.segments.len() > 1 { span_lint_until_last_segment(cx, path.span, path.segments.last().unwrap()); } } -fn span_lint_on_qpath_resolved<'tcx>(cx: &LateContext<'tcx>, qpath: &'tcx QPath<'tcx>, until_last_segment: bool) { +fn span_lint_on_qpath_resolved(cx: &LateContext<'_>, qpath: &QPath<'_>, until_last_segment: bool) { if let QPath::Resolved(_, path) = qpath { if until_last_segment { span_lint_on_path_until_last_segment(cx, path); @@ -99,209 +105,177 @@ fn span_lint_on_qpath_resolved<'tcx>(cx: &LateContext<'tcx>, qpath: &'tcx QPath< } } -struct BodyVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - self_ty: Ty<'tcx>, -} - -impl<'a, 'tcx> BodyVisitor<'a, 'tcx> { - fn check_trait_method_impl_decl( - &mut self, - impl_item: &ImplItem<'tcx>, - impl_decl: &'tcx FnDecl<'tcx>, - impl_trait_ref: ty::TraitRef<'tcx>, - ) { - let tcx = self.cx.tcx; - let trait_method = tcx - .associated_items(impl_trait_ref.def_id) - .find_by_name_and_kind(tcx, impl_item.ident, ty::AssocKind::Fn, impl_trait_ref.def_id) - .expect("impl method matches a trait method"); - - let trait_method_sig = tcx.fn_sig(trait_method.def_id); - let trait_method_sig = tcx.erase_late_bound_regions(&trait_method_sig); - - let output_hir_ty = if let FnRetTy::Return(ty) = &impl_decl.output { - Some(&**ty) +fn ty_from_hir_id<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId) -> Ty<'tcx> { + if_chain! { + if let Some(node) = cx.tcx.hir().find(hir_id); + if let Node::Ty(hir_ty) = node; + then { + hir_ty_to_ty(cx.tcx, hir_ty) } else { - None - }; - - // `impl_hir_ty` (of type `hir::Ty`) represents the type written in the signature. - // `trait_ty` (of type `ty::Ty`) is the semantic type for the signature in the trait. - // We use `impl_hir_ty` to see if the type was written as `Self`, - // `hir_ty_to_ty(...)` to check semantic types of paths, and - // `trait_ty` to determine which parts of the signature in the trait, mention - // the type being implemented verbatim (as opposed to `Self`). - for (impl_hir_ty, trait_ty) in impl_decl - .inputs - .iter() - .chain(output_hir_ty) - .zip(trait_method_sig.inputs_and_output) - { - // Check if the input/output type in the trait method specifies the implemented - // type verbatim, and only suggest `Self` if that isn't the case. - // This avoids suggestions to e.g. replace `Vec` with `Vec`, - // in an `impl Trait for u8`, when the trait always uses `Vec`. - // See also https://github.com/rust-lang/rust-clippy/issues/2894. - let self_ty = impl_trait_ref.self_ty(); - if !trait_ty.walk().any(|inner| inner == self_ty.into()) { - self.visit_ty(&impl_hir_ty); - } + unreachable!("This function should only be called with `HirId`s that are for sure `Node::Ty`") } } } -impl<'a, 'tcx> Visitor<'tcx> for BodyVisitor<'a, 'tcx> { - type Map = Map<'tcx>; - - fn nested_visit_map(&mut self) -> NestedVisitorMap { - NestedVisitorMap::OnlyBodies(self.cx.tcx.hir()) +fn in_impl(cx: &LateContext<'tcx>, hir_ty: &hir::Ty<'_>) -> bool { + let map = cx.tcx.hir(); + let parent = map.get_parent_node(hir_ty.hir_id); + if_chain! { + if let Some(Node::Item(item)) = map.find(parent); + if let ItemKind::Impl { .. } = item.kind; + then { + true + } else { + false + } } +} - fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) { - fn expr_ty_matches<'tcx>(expr: &'tcx Expr<'tcx>, self_ty: Ty<'tcx>, cx: &LateContext<'tcx>) -> bool { - let def_id = expr.hir_id.owner; - if cx.tcx.has_typeck_results(def_id) { - cx.tcx.typeck(def_id).expr_ty_opt(expr) == Some(self_ty) - } else { - false - } - } - match expr.kind { - ExprKind::Struct(QPath::Resolved(_, path), ..) => { - if expr_ty_matches(expr, self.self_ty, self.cx) { - match path.res { - def::Res::SelfTy(..) => (), - def::Res::Def(DefKind::Variant, _) => span_lint_on_path_until_last_segment(self.cx, path), - _ => { - span_lint(self.cx, path.span); - }, - } +impl<'tcx> LateLintPass<'tcx> for UseSelf { + fn check_item(&mut self, _: &LateContext<'tcx>, item: &Item<'_>) { + // NB: If you push something on the stack in this method, remember to also pop it in the + // `check_item_post` method. + use ItemKind::*; + match item.kind { + Impl { + self_ty: hir_self_ty, .. + } => { + let should_check = if let TyKind::Path(QPath::Resolved(_, ref item_path)) = hir_self_ty.kind { + let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; + parameters.as_ref().map_or(true, |params| { + !params.parenthesized && !params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))) + }) + } else { + false + }; + if should_check { + self.stack.push(StackItem::Check { + hir_id: hir_self_ty.hir_id, + }); + } else { + self.stack.push(StackItem::NoCheck); } }, - // tuple struct instantiation (`Foo(arg)` or `Enum::Foo(arg)`) - ExprKind::Call(fun, _) => { - if let Expr { - kind: ExprKind::Path(ref qpath), - .. - } = fun - { - if expr_ty_matches(expr, self.self_ty, self.cx) { - let res = utils::qpath_res(self.cx, qpath, fun.hir_id); - - if let def::Res::Def(DefKind::Ctor(ctor_of, _), ..) = res { - match ctor_of { - def::CtorOf::Variant => { - span_lint_on_qpath_resolved(self.cx, qpath, true); - }, - def::CtorOf::Struct => { - span_lint_on_qpath_resolved(self.cx, qpath, false); - }, + Static(..) | Const(..) | Fn(..) | Enum(..) | Struct(..) | Union(..) | Trait(..) => { + self.stack.push(StackItem::NoCheck); + }, + _ => (), + } + } + fn check_item_post(&mut self, _: &LateContext<'_>, item: &Item<'_>) { + use ItemKind::*; + match item.kind { + Impl { + self_ty: hir_self_ty, .. + } => { + let _popped_stack_item = self.stack.pop(); + debug_assert!( + { + _popped_stack_item == Some(StackItem::NoCheck) + || if let Some(StackItem::Check { hir_id, .. }) = _popped_stack_item { + hir_self_ty.hir_id == hir_id + } else { + false } - } - } - } + }, + "unexpected self type on top of stack: {:?}", + _popped_stack_item + ); }, - // unit enum variants (`Enum::A`) - ExprKind::Path(ref qpath) => { - if expr_ty_matches(expr, self.self_ty, self.cx) { - span_lint_on_qpath_resolved(self.cx, qpath, true); - } + Static(..) | Const(..) | Fn(..) | Enum(..) | Struct(..) | Union(..) | Trait(..) => { + self.stack.pop(); }, _ => (), } - walk_expr(self, expr); } -} - -struct FnSigVisitor<'a, 'tcx> { - cx: &'a LateContext<'tcx>, - self_ty: Ty<'tcx>, -} - -impl<'a, 'tcx> Visitor<'tcx> for FnSigVisitor<'a, 'tcx> { - type Map = Map<'tcx>; + fn check_ty(&mut self, cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>) { + if in_external_macro(cx.sess(), hir_ty.span) | in_impl(cx, hir_ty) { + return; + } - fn nested_visit_map(&mut self) -> NestedVisitorMap { - NestedVisitorMap::None - } + if let Some(StackItem::Check { hir_id }) = self.stack.last() { + let self_ty = ty_from_hir_id(cx, *hir_id); - fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'tcx>) { - if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind { - match path.res { - def::Res::SelfTy(..) => {}, - _ => { - match self.cx.tcx.hir().find(self.cx.tcx.hir().get_parent_node(hir_ty.hir_id)) { - Some(Node::Expr(Expr { - kind: ExprKind::Path(QPath::TypeRelative(_, segment)), - .. - })) => { - // The following block correctly identifies applicable lint locations - // but `hir_ty_to_ty` calls cause odd ICEs. - // - if hir_ty_to_ty(self.cx.tcx, hir_ty) == self.self_ty { - // fixme: this span manipulation should not be necessary - // @flip1995 found an ast lowering issue in - // https://github.com/rust-lang/rust/blob/master/src/librustc_ast_lowering/path.rs#l142-l162 - span_lint_until_last_segment(self.cx, hir_ty.span, segment); - } - }, + if hir_ty_to_ty(cx.tcx, hir_ty) == self_ty { + if let TyKind::Path(QPath::Resolved(_, path)) = hir_ty.kind { + match path.res { + def::Res::SelfTy(..) => {}, _ => { - if hir_ty_to_ty(self.cx.tcx, hir_ty) == self.self_ty { - span_lint(self.cx, hir_ty.span) + // FIXME: this span manipulation should not be necessary + // @flip1995 found an ast lowering issue in + // https://github.com/rust-lang/rust/blob/master/src/librustc_ast_lowering/path.rs#l142-l162 + match cx.tcx.hir().find(cx.tcx.hir().get_parent_node(hir_ty.hir_id)) { + Some(Node::Expr(Expr { + kind: ExprKind::Path(QPath::TypeRelative(_, segment)), + .. + })) => span_lint_until_last_segment(cx, hir_ty.span, segment), + _ => span_lint(cx, hir_ty.span), } }, } - }, + } } } - - walk_ty(self, hir_ty); } -} + fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { + fn expr_ty_matches(expr: &Expr<'_>, self_ty: Ty<'_>, cx: &LateContext<'_>) -> bool { + let def_id = expr.hir_id.owner; + if cx.tcx.has_typeck_results(def_id) { + cx.tcx.typeck(def_id).expr_ty_opt(expr) == Some(self_ty) + } else { + false + } + } -impl<'tcx> LateLintPass<'tcx> for UseSelf { - fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { - if in_external_macro(cx.sess(), impl_item.span) { + if in_external_macro(cx.sess(), expr.span) { return; } - let parent_id = cx.tcx.hir().get_parent_item(impl_item.hir_id); - let imp = cx.tcx.hir().expect_item(parent_id); - - if_chain! { - if let ItemKind::Impl { self_ty: hir_self_ty, .. } = imp.kind; - if let TyKind::Path(QPath::Resolved(_, ref item_path)) = hir_self_ty.kind; - then { - let parameters = &item_path.segments.last().expect(SEGMENTS_MSG).args; - let should_check = parameters.as_ref().map_or( - true, - |params| !params.parenthesized - &&!params.args.iter().any(|arg| matches!(arg, GenericArg::Lifetime(_))) - ); + if let Some(StackItem::Check { hir_id }) = self.stack.last() { + let self_ty = ty_from_hir_id(cx, *hir_id); - // TODO: don't short-circuit upon lifetime parameters - if should_check { - let self_ty = hir_ty_to_ty(cx.tcx, hir_self_ty); - let body_visitor = &mut BodyVisitor { cx, self_ty }; - let fn_sig_visitor = &mut FnSigVisitor { cx, self_ty }; + match &expr.kind { + ExprKind::Struct(QPath::Resolved(_, path), ..) => { + if expr_ty_matches(expr, self_ty, cx) { + match path.res { + def::Res::SelfTy(..) => (), + def::Res::Def(DefKind::Variant, _) => span_lint_on_path_until_last_segment(cx, path), + _ => { + span_lint(cx, path.span); + }, + } + } + }, + // tuple struct instantiation (`Foo(arg)` or `Enum::Foo(arg)`) + ExprKind::Call(fun, _) => { + if let Expr { + kind: ExprKind::Path(ref qpath), + .. + } = fun + { + if expr_ty_matches(expr, self_ty, cx) { + let res = utils::qpath_res(cx, qpath, fun.hir_id); - let tcx = cx.tcx; - let impl_def_id = tcx.hir().local_def_id(imp.hir_id); - let impl_trait_ref = tcx.impl_trait_ref(impl_def_id); - if_chain! { - if let Some(impl_trait_ref) = impl_trait_ref; - if let ImplItemKind::Fn(FnSig { decl: impl_decl, .. }, impl_body_id) = &impl_item.kind; - then { - body_visitor.check_trait_method_impl_decl(impl_item, impl_decl, impl_trait_ref); - let body = tcx.hir().body(*impl_body_id); - body_visitor.visit_body(body); - } else { - walk_impl_item(body_visitor, impl_item); - walk_impl_item(fn_sig_visitor, impl_item); + if let def::Res::Def(DefKind::Ctor(ctor_of, _), ..) = res { + match ctor_of { + def::CtorOf::Variant => { + span_lint_on_qpath_resolved(cx, qpath, true); + }, + def::CtorOf::Struct => { + span_lint_on_qpath_resolved(cx, qpath, false); + }, + } + } } } - } + }, + // unit enum variants (`Enum::A`) + ExprKind::Path(qpath) => { + if expr_ty_matches(expr, self_ty, cx) { + span_lint_on_qpath_resolved(cx, &qpath, true); + } + }, + _ => (), } } } diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index dee39897a4e1..2dc087805eed 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -16,15 +16,15 @@ mod use_self { } fn test() -> Self { // FIXME: applicable here - Foo::new() + Self::new() } } impl Default for Foo { // FIXME: applicable here - fn default() -> Foo { + fn default() -> Self { // FIXME: applicable here - Foo::new() + Self::new() } } } @@ -93,7 +93,7 @@ mod existential { // TyKind::Def (used for `impl Trait` types) does not include type parameters yet. // See documentation in rustc_hir::hir::TyKind. // The hir tree walk stops at `impl Iterator` level and does not inspect &Foo. - fn bad(foos: &[Self]) -> impl Iterator { + fn bad(foos: &[Self]) -> impl Iterator { foos.iter() } @@ -215,9 +215,9 @@ mod rustfix { fn fun_2() { // FIXME: applicable here - nested::A::fun_1(); + Self::fun_1(); // FIXME: applicable here - nested::A::A; + Self::A; Self {}; } @@ -239,7 +239,7 @@ mod issue3567 { impl Test for TestStruct { fn test() -> TestStruct { // FIXME: applicable here - TestStruct::from_something() + Self::from_something() } } } @@ -254,13 +254,13 @@ mod paths_created_by_lowering { const B: usize = 1; // FIXME: applicable here - async fn g() -> S { + async fn g() -> Self { Self {} } fn f<'a>(&self, p: &'a [u8]) -> &'a [u8] { // FIXME: applicable here twice - &p[S::A..S::B] + &p[Self::A..Self::B] } } diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index 4d213316cf53..89508aa17934 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -1,16 +1,16 @@ error: unnecessary structure name repetition - --> $DIR/use_self.rs:15:13 + --> $DIR/use_self.rs:14:21 | -LL | Foo {} - | ^^^ help: use the applicable keyword: `Self` +LL | fn new() -> Foo { + | ^^^ help: use the applicable keyword: `Self` | = note: `-D clippy::use-self` implied by `-D warnings` error: unnecessary structure name repetition - --> $DIR/use_self.rs:14:21 + --> $DIR/use_self.rs:15:13 | -LL | fn new() -> Foo { - | ^^^ help: use the applicable keyword: `Self` +LL | Foo {} + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:17:22 @@ -18,12 +18,36 @@ error: unnecessary structure name repetition LL | fn test() -> Foo { | ^^^ help: use the applicable keyword: `Self` +error: unnecessary structure name repetition + --> $DIR/use_self.rs:19:13 + | +LL | Foo::new() + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:25:25 + | +LL | fn default() -> Foo { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:27:13 + | +LL | Foo::new() + | ^^^ help: use the applicable keyword: `Self` + error: unnecessary structure name repetition --> $DIR/use_self.rs:96:24 | LL | fn bad(foos: &[Foo]) -> impl Iterator { | ^^^ help: use the applicable keyword: `Self` +error: unnecessary structure name repetition + --> $DIR/use_self.rs:96:55 + | +LL | fn bad(foos: &[Foo]) -> impl Iterator { + | ^^^ help: use the applicable keyword: `Self` + error: unnecessary structure name repetition --> $DIR/use_self.rs:111:13 | @@ -31,10 +55,10 @@ LL | TS(0) | ^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:120:17 + --> $DIR/use_self.rs:119:25 | -LL | Foo {} - | ^^^ help: use the applicable keyword: `Self` +LL | fn new() -> Foo { + | ^^^ help: use the applicable keyword: `Self` ... LL | use_self_expand!(); // Should lint in local macros | ------------------- in this macro invocation @@ -42,22 +66,16 @@ LL | use_self_expand!(); // Should lint in local macros = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: unnecessary structure name repetition - --> $DIR/use_self.rs:119:25 + --> $DIR/use_self.rs:120:17 | -LL | fn new() -> Foo { - | ^^^ help: use the applicable keyword: `Self` +LL | Foo {} + | ^^^ help: use the applicable keyword: `Self` ... LL | use_self_expand!(); // Should lint in local macros | ------------------- in this macro invocation | = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) -error: unnecessary structure name repetition - --> $DIR/use_self.rs:144:21 - | -LL | Bar { foo: Foo {} } - | ^^^ help: use the applicable keyword: `Self` - error: unnecessary structure name repetition --> $DIR/use_self.rs:143:29 | @@ -65,10 +83,10 @@ LL | fn bar() -> Bar { | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:156:13 + --> $DIR/use_self.rs:144:21 | -LL | Foo {} - | ^^^ help: use the applicable keyword: `Self` +LL | Bar { foo: Foo {} } + | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:155:21 @@ -76,6 +94,12 @@ error: unnecessary structure name repetition LL | fn baz() -> Foo { | ^^^ help: use the applicable keyword: `Self` +error: unnecessary structure name repetition + --> $DIR/use_self.rs:156:13 + | +LL | Foo {} + | ^^^ help: use the applicable keyword: `Self` + error: unnecessary structure name repetition --> $DIR/use_self.rs:173:21 | @@ -94,12 +118,36 @@ error: unnecessary structure name repetition LL | let _ = Enum::A; | ^^^^ help: use the applicable keyword: `Self` +error: unnecessary structure name repetition + --> $DIR/use_self.rs:218:13 + | +LL | nested::A::fun_1(); + | ^^^^^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:220:13 + | +LL | nested::A::A; + | ^^^^^^^^^ help: use the applicable keyword: `Self` + error: unnecessary structure name repetition --> $DIR/use_self.rs:222:13 | LL | nested::A {}; | ^^^^^^^^^ help: use the applicable keyword: `Self` +error: unnecessary structure name repetition + --> $DIR/use_self.rs:242:13 + | +LL | TestStruct::from_something() + | ^^^^^^^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:257:25 + | +LL | async fn g() -> S { + | ^ help: use the applicable keyword: `Self` + error: unnecessary structure name repetition --> $DIR/use_self.rs:258:13 | @@ -107,10 +155,16 @@ LL | S {} | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:287:13 + --> $DIR/use_self.rs:263:16 | -LL | Foo { value } - | ^^^ help: use the applicable keyword: `Self` +LL | &p[S::A..S::B] + | ^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:263:22 + | +LL | &p[S::A..S::B] + | ^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition --> $DIR/use_self.rs:286:29 @@ -118,6 +172,12 @@ error: unnecessary structure name repetition LL | fn foo(value: T) -> Foo { | ^^^^^^ help: use the applicable keyword: `Self` +error: unnecessary structure name repetition + --> $DIR/use_self.rs:287:13 + | +LL | Foo { value } + | ^^^ help: use the applicable keyword: `Self` + error: unnecessary structure name repetition --> $DIR/use_self.rs:324:21 | @@ -130,5 +190,5 @@ error: unnecessary structure name repetition LL | type To = T::To; | ^^^^^ help: use the applicable keyword: `Self` -error: aborting due to 20 previous errors +error: aborting due to 30 previous errors diff --git a/tests/ui/use_self_trait.fixed b/tests/ui/use_self_trait.fixed index 680a0623839e..53f1ff2f8c47 100644 --- a/tests/ui/use_self_trait.fixed +++ b/tests/ui/use_self_trait.fixed @@ -18,29 +18,29 @@ trait SelfTrait { struct Bad; impl SelfTrait for Bad { - fn refs(p1: &Bad) -> &Bad { + fn refs(p1: &Self) -> &Self { p1 } - fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { + fn ref_refs<'a>(p1: &'a &'a Self) -> &'a &'a Self { p1 } - fn mut_refs(p1: &mut Bad) -> &mut Bad { + fn mut_refs(p1: &mut Self) -> &mut Self { p1 } - fn nested(_p1: Box, _p2: (&u8, &Bad)) {} + fn nested(_p1: Box, _p2: (&u8, &Self)) {} - fn vals(_: Bad) -> Bad { - Bad::default() + fn vals(_: Self) -> Self { + Self::default() } } impl Mul for Bad { type Output = Self; - fn mul(self, rhs: Bad) -> Bad { + fn mul(self, rhs: Self) -> Self { rhs } } diff --git a/tests/ui/use_self_trait.stderr b/tests/ui/use_self_trait.stderr index 5409ccedf859..55af3ff2a93d 100644 --- a/tests/ui/use_self_trait.stderr +++ b/tests/ui/use_self_trait.stderr @@ -1,10 +1,88 @@ +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:21:18 + | +LL | fn refs(p1: &Bad) -> &Bad { + | ^^^ help: use the applicable keyword: `Self` + | + = note: `-D clippy::use-self` implied by `-D warnings` + +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:21:27 + | +LL | fn refs(p1: &Bad) -> &Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:25:33 + | +LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:25:49 + | +LL | fn ref_refs<'a>(p1: &'a &'a Bad) -> &'a &'a Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:29:26 + | +LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:29:39 + | +LL | fn mut_refs(p1: &mut Bad) -> &mut Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:33:24 + | +LL | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:33:42 + | +LL | fn nested(_p1: Box, _p2: (&u8, &Bad)) {} + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:35:16 + | +LL | fn vals(_: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:35:24 + | +LL | fn vals(_: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:36:9 + | +LL | Bad::default() + | ^^^ help: use the applicable keyword: `Self` + error: unnecessary structure name repetition --> $DIR/use_self_trait.rs:41:19 | LL | type Output = Bad; | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:43:23 | - = note: `-D clippy::use-self` implied by `-D warnings` +LL | fn mul(self, rhs: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self_trait.rs:43:31 + | +LL | fn mul(self, rhs: Bad) -> Bad { + | ^^^ help: use the applicable keyword: `Self` -error: aborting due to previous error +error: aborting due to 14 previous errors