From b71e7923747262bbae707b8a31fec9762116bcb4 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Sun, 17 Sep 2023 20:18:55 -0700 Subject: [PATCH 01/10] Add `ambiguous_method_calls` lint --- CHANGELOG.md | 1 + clippy_lints/src/ambiguous_method_calls.rs | 170 +++++++++++++++++++++ clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + tests/ui/ambiguous_method_calls.rs | 37 +++++ tests/ui/ambiguous_method_calls.stderr | 27 ++++ 6 files changed, 238 insertions(+) create mode 100644 clippy_lints/src/ambiguous_method_calls.rs create mode 100644 tests/ui/ambiguous_method_calls.rs create mode 100644 tests/ui/ambiguous_method_calls.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index db54bfbf0b32..c4c56efa31fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4776,6 +4776,7 @@ Released 2018-09-13 [`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_letter_range [`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped +[`ambiguous_method_calls`]: https://rust-lang.github.io/rust-clippy/master/index.html#ambiguous_method_calls [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant [`arc_with_non_send_sync`]: https://rust-lang.github.io/rust-clippy/master/index.html#arc_with_non_send_sync [`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects diff --git a/clippy_lints/src/ambiguous_method_calls.rs b/clippy_lints/src/ambiguous_method_calls.rs new file mode 100644 index 000000000000..eb25af5c9241 --- /dev/null +++ b/clippy_lints/src/ambiguous_method_calls.rs @@ -0,0 +1,170 @@ +use std::sync::{Mutex, OnceLock}; + +use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::is_trait_impl_item; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::intravisit::FnKind; +use rustc_hir::{Body, FnDecl}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::Ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; +use rustc_span::def_id::LocalDefId; +use rustc_span::symbol::Ident; +use rustc_span::{Span, SpanData, Symbol}; + +declare_clippy_lint! { + /// ### What it does + /// Looks for methods in trait impls and struct impls with the same name, + /// as well as method call sites. + /// + /// ### Why is this bad? + /// It is easy to accidentally override a trait method impl with a method + /// of the same name in a struct impl. Inherent methods are preferred if + /// the call site is unqualified, and naming conflicts will happen silently. + /// + /// ### Example + /// ```rust + /// trait MyTrait { + /// fn ambiguous(&self); + /// } + /// + /// struct Base; + /// + /// impl Base { + /// fn ambiguous(&self) { + /// println!("struct impl"); + /// } + /// } + /// + /// impl MyTrait for Base { + /// fn ambiguous(&self) { + /// println!("trait impl"); + /// } + /// } + /// + /// Base.ambiguous(); // prints "struct impl" + /// ``` + /// Use instead: + /// ```rust + /// trait MyTrait { + /// fn ambiguous(&self); + /// } + /// + /// struct Base; + /// + /// impl Base { + /// fn unambiguous(&self) { + /// println!("struct impl"); + /// } + /// } + /// + /// impl MyTrait for Base { + /// fn ambiguous(&self) { + /// println!("trait impl"); + /// } + /// } + /// + /// Base.unambiguous(); // prints "struct impl" + /// Base.ambiguous(); // prints "trait impl" + /// ``` + #[clippy::version = "1.74.0"] + pub AMBIGUOUS_METHOD_CALLS, + pedantic, + "declarations and calls for same-named methods in struct impls and trait impls" +} +declare_lint_pass!(AmbiguousMethodCalls => [AMBIGUOUS_METHOD_CALLS]); + +impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls { + fn check_fn( + &mut self, + cx: &LateContext<'tcx>, + kind: FnKind<'tcx>, + _: &'tcx FnDecl<'_>, + _: &'tcx Body<'_>, + _: Span, + def_id: LocalDefId, + ) { + let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); + let is_trait_impl = is_trait_impl_item(cx, hir_id); + + if let FnKind::Method(ident, _) = kind { + let parent_item = cx.tcx.hir().get_parent_item(hir_id).to_def_id(); + let parent_type = cx.tcx.type_of(parent_item).skip_binder(); + let parent_ty_str = format!("{parent_type}"); + + insert_method(is_trait_impl, parent_type, ident); + + if has_ambiguous_name(parent_type, ident) { + let trait_methods = trait_methods().lock().unwrap(); + let struct_methods = struct_methods().lock().unwrap(); + + span_lint( + cx, + AMBIGUOUS_METHOD_CALLS, + trait_methods.get(&(parent_ty_str.clone(), ident.name)).unwrap().span(), + "ambiguous trait method name", + ); + span_lint_and_help( + cx, + AMBIGUOUS_METHOD_CALLS, + struct_methods.get(&(parent_ty_str, ident.name)).unwrap().span(), + "ambiguous struct method name", + None, + "consider renaming the struct impl's method", + ); + } + } + } + + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'_>) { + if let rustc_hir::ExprKind::MethodCall(path, receiver, _, call_span) = &expr.kind { + let recv_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); + let recv_ty_str = format!("{recv_ty}"); + + let struct_methods = struct_methods().lock().unwrap(); + let trait_methods = trait_methods().lock().unwrap(); + if struct_methods.contains_key(&(recv_ty_str.clone(), path.ident.name)) + && trait_methods.contains_key(&(recv_ty_str, path.ident.name)) + { + span_lint_and_help( + cx, + AMBIGUOUS_METHOD_CALLS, + *call_span, + "ambiguous struct method call", + None, + "consider renaming the struct impl's method or explicitly qualifying the call site", + ); + } + } + } +} + +fn has_ambiguous_name<'tcx>(ty: Ty<'tcx>, ident: Ident) -> bool { + let ty_str = format!("{ty}"); + let trait_methods = trait_methods().lock().unwrap(); + let struct_methods = struct_methods().lock().unwrap(); + + trait_methods.contains_key(&(ty_str.clone(), ident.name)) && struct_methods.contains_key(&(ty_str, ident.name)) +} + +fn trait_methods() -> &'static Mutex> { + static NAMES: OnceLock>> = OnceLock::new(); + NAMES.get_or_init(|| Mutex::new(FxHashMap::default())) +} + +fn struct_methods() -> &'static Mutex> { + static NAMES: OnceLock>> = OnceLock::new(); + NAMES.get_or_init(|| Mutex::new(FxHashMap::default())) +} + +fn insert_method<'tcx>(is_trait_impl: bool, ty: Ty<'tcx>, ident: Ident) { + let ty_str = format!("{ty}"); + let mut trait_methods = trait_methods().lock().unwrap(); + let mut struct_methods = struct_methods().lock().unwrap(); + + if is_trait_impl { + trait_methods.insert((ty_str, ident.name), ident.span.data()); + } else { + struct_methods.insert((ty_str, ident.name), ident.span.data()); + } +} diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index b4b84b36044c..3f8580f391a7 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -40,6 +40,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::absolute_paths::ABSOLUTE_PATHS_INFO, crate::allow_attributes::ALLOW_ATTRIBUTES_INFO, crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO, + crate::ambiguous_method_calls::AMBIGUOUS_METHOD_CALLS_INFO, crate::approx_const::APPROX_CONSTANT_INFO, crate::arc_with_non_send_sync::ARC_WITH_NON_SEND_SYNC_INFO, crate::as_conversions::AS_CONVERSIONS_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 63a3fbcb8976..c4bf3cd4b9a8 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -70,6 +70,7 @@ mod renamed_lints; mod absolute_paths; mod allow_attributes; mod almost_complete_range; +mod ambiguous_method_calls; mod approx_const; mod arc_with_non_send_sync; mod as_conversions; @@ -1121,6 +1122,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); store.register_late_pass(move |_| Box::new(manual_hash_one::ManualHashOne::new(msrv()))); + store.register_late_pass(|_| Box::new(ambiguous_method_calls::AmbiguousMethodCalls)); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/tests/ui/ambiguous_method_calls.rs b/tests/ui/ambiguous_method_calls.rs new file mode 100644 index 000000000000..241e63605067 --- /dev/null +++ b/tests/ui/ambiguous_method_calls.rs @@ -0,0 +1,37 @@ +#![allow(dead_code)] +#![warn(clippy::ambiguous_method_calls)] + +trait MyTrait { + fn ambiguous(&self); +} + +struct Base; + +impl Base { + fn ambiguous(&self) { + println!("struct impl"); + } + + fn unambiguous(&self) { + println!("unambiguous struct impl"); + } +} + +impl MyTrait for Base { + fn ambiguous(&self) { + println!("trait impl"); + } +} + +struct Other; + +impl MyTrait for Other { + fn ambiguous(&self) { + println!("not actually ambiguous") + } +} + +fn main() { + Base.ambiguous(); + Other.ambiguous(); +} diff --git a/tests/ui/ambiguous_method_calls.stderr b/tests/ui/ambiguous_method_calls.stderr new file mode 100644 index 000000000000..2d02b3795285 --- /dev/null +++ b/tests/ui/ambiguous_method_calls.stderr @@ -0,0 +1,27 @@ +error: ambiguous trait method name + --> $DIR/ambiguous_method_calls.rs:21:8 + | +LL | fn ambiguous(&self) { + | ^^^^^^^^^ + | + = note: `-D clippy::ambiguous-method-calls` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::ambiguous_method_calls)]` + +error: ambiguous struct method name + --> $DIR/ambiguous_method_calls.rs:11:8 + | +LL | fn ambiguous(&self) { + | ^^^^^^^^^ + | + = help: consider renaming the struct impl's method + +error: ambiguous struct method call + --> $DIR/ambiguous_method_calls.rs:35:10 + | +LL | Base.ambiguous(); + | ^^^^^^^^^^^ + | + = help: consider renaming the struct impl's method or explicitly qualifying the call site + +error: aborting due to 3 previous errors + From eba66165fa12ab15769b9bc513b9239ac79661dd Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Tue, 19 Sep 2023 11:26:44 -0700 Subject: [PATCH 02/10] Fix ICE when linting default method impls in trait --- clippy_lints/src/ambiguous_method_calls.rs | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/ambiguous_method_calls.rs b/clippy_lints/src/ambiguous_method_calls.rs index eb25af5c9241..81a0e9e5633d 100644 --- a/clippy_lints/src/ambiguous_method_calls.rs +++ b/clippy_lints/src/ambiguous_method_calls.rs @@ -2,9 +2,10 @@ use std::sync::{Mutex, OnceLock}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::is_trait_impl_item; +use hir::intravisit::FnKind; +use hir::{Body, FnDecl}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::intravisit::FnKind; -use rustc_hir::{Body, FnDecl}; +use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; use rustc_middle::ty::Ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -88,8 +89,16 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls { let is_trait_impl = is_trait_impl_item(cx, hir_id); if let FnKind::Method(ident, _) = kind { - let parent_item = cx.tcx.hir().get_parent_item(hir_id).to_def_id(); - let parent_type = cx.tcx.type_of(parent_item).skip_binder(); + let parent_item = cx.tcx.hir().get_parent_item(hir_id); + + // Calling type_of on a method's default impl causes an ICE + if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(hir::HirId::from(parent_item)) { + if let hir::ItemKind::Trait(..) = item.kind { + return; + } + } + + let parent_type = cx.tcx.type_of(parent_item.to_def_id()).skip_binder(); let parent_ty_str = format!("{parent_type}"); insert_method(is_trait_impl, parent_type, ident); @@ -116,8 +125,8 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls { } } - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'_>) { - if let rustc_hir::ExprKind::MethodCall(path, receiver, _, call_span) = &expr.kind { + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { + if let hir::ExprKind::MethodCall(path, receiver, _, call_span) = &expr.kind { let recv_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); let recv_ty_str = format!("{recv_ty}"); From 67e286cd1f36f3942457b49854ae741b4e634073 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Tue, 19 Sep 2023 11:41:42 -0700 Subject: [PATCH 03/10] Elide a lifetime --- clippy_lints/src/ambiguous_method_calls.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/ambiguous_method_calls.rs b/clippy_lints/src/ambiguous_method_calls.rs index 81a0e9e5633d..c7f0123f5941 100644 --- a/clippy_lints/src/ambiguous_method_calls.rs +++ b/clippy_lints/src/ambiguous_method_calls.rs @@ -148,7 +148,7 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls { } } -fn has_ambiguous_name<'tcx>(ty: Ty<'tcx>, ident: Ident) -> bool { +fn has_ambiguous_name(ty: Ty<'_>, ident: Ident) -> bool { let ty_str = format!("{ty}"); let trait_methods = trait_methods().lock().unwrap(); let struct_methods = struct_methods().lock().unwrap(); @@ -166,7 +166,7 @@ fn struct_methods() -> &'static Mutex> { NAMES.get_or_init(|| Mutex::new(FxHashMap::default())) } -fn insert_method<'tcx>(is_trait_impl: bool, ty: Ty<'tcx>, ident: Ident) { +fn insert_method(is_trait_impl: bool, ty: Ty<'_>, ident: Ident) { let ty_str = format!("{ty}"); let mut trait_methods = trait_methods().lock().unwrap(); let mut struct_methods = struct_methods().lock().unwrap(); From f63e24dba800a6ee8ef42874d774ed9d02295302 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Tue, 19 Sep 2023 19:33:10 -0700 Subject: [PATCH 04/10] Fix visiting order --- clippy_lints/src/ambiguous_method_calls.rs | 139 +++++++++++---------- clippy_lints/src/lib.rs | 2 +- tests/ui/ambiguous_method_calls.rs | 27 +++- tests/ui/ambiguous_method_calls.stderr | 42 ++++++- 4 files changed, 128 insertions(+), 82 deletions(-) diff --git a/clippy_lints/src/ambiguous_method_calls.rs b/clippy_lints/src/ambiguous_method_calls.rs index c7f0123f5941..646dd5374e48 100644 --- a/clippy_lints/src/ambiguous_method_calls.rs +++ b/clippy_lints/src/ambiguous_method_calls.rs @@ -1,5 +1,3 @@ -use std::sync::{Mutex, OnceLock}; - use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; use clippy_utils::is_trait_impl_item; use hir::intravisit::FnKind; @@ -8,10 +6,10 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; 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::def_id::LocalDefId; use rustc_span::symbol::Ident; -use rustc_span::{Span, SpanData, Symbol}; +use rustc_span::{Span, Symbol}; declare_clippy_lint! { /// ### What it does @@ -73,7 +71,43 @@ declare_clippy_lint! { pedantic, "declarations and calls for same-named methods in struct impls and trait impls" } -declare_lint_pass!(AmbiguousMethodCalls => [AMBIGUOUS_METHOD_CALLS]); + +#[derive(Clone)] +pub struct AmbiguousMethodCalls { + trait_methods: FxHashMap<(String, Symbol), Span>, + inherent_methods: FxHashMap<(String, Symbol), Span>, + call_sites: FxHashMap<(String, Symbol), Vec>, +} + +impl AmbiguousMethodCalls { + pub fn new() -> Self { + Self { + trait_methods: FxHashMap::default(), + inherent_methods: FxHashMap::default(), + call_sites: FxHashMap::default(), + } + } + + fn insert_method(&mut self, is_trait_impl: bool, ty: Ty<'_>, ident: Ident) { + let ty_str = format!("{ty}"); + if is_trait_impl { + self.trait_methods.insert((ty_str, ident.name), ident.span); + } else { + self.inherent_methods.insert((ty_str, ident.name), ident.span); + } + } + + fn insert_call_site(&mut self, ty: Ty<'_>, ident: Ident, span: Span) { + let ty_str = format!("{ty}"); + if let Some(spans) = self.call_sites.get_mut(&(ty_str.clone(), ident.name)) { + spans.push(span); + } else { + self.call_sites.insert((ty_str, ident.name), vec![span]); + } + } +} + +impl_lint_pass!(AmbiguousMethodCalls => [AMBIGUOUS_METHOD_CALLS]); impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls { fn check_fn( @@ -85,95 +119,62 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls { _: Span, def_id: LocalDefId, ) { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); - let is_trait_impl = is_trait_impl_item(cx, hir_id); - if let FnKind::Method(ident, _) = kind { - let parent_item = cx.tcx.hir().get_parent_item(hir_id); + let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); + let is_trait_impl = is_trait_impl_item(cx, hir_id); + let parent_id = cx.tcx.hir().get_parent_item(hir_id); // Calling type_of on a method's default impl causes an ICE - if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(hir::HirId::from(parent_item)) { + if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(hir::HirId::from(parent_id)) { if let hir::ItemKind::Trait(..) = item.kind { return; } } - let parent_type = cx.tcx.type_of(parent_item.to_def_id()).skip_binder(); - let parent_ty_str = format!("{parent_type}"); + let parent_ty = cx.tcx.type_of(parent_id.to_def_id()).skip_binder(); + self.insert_method(is_trait_impl, parent_ty, ident); + } + } - insert_method(is_trait_impl, parent_type, ident); + fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { + if let hir::ExprKind::MethodCall(path, recv, _, call_span) = &expr.kind { + let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs(); - if has_ambiguous_name(parent_type, ident) { - let trait_methods = trait_methods().lock().unwrap(); - let struct_methods = struct_methods().lock().unwrap(); + self.insert_call_site(recv_ty, path.ident, *call_span); + } + } + fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { + for k in self.inherent_methods.keys() { + if self.trait_methods.contains_key(k) { span_lint( cx, AMBIGUOUS_METHOD_CALLS, - trait_methods.get(&(parent_ty_str.clone(), ident.name)).unwrap().span(), + *self.trait_methods.get(k).unwrap(), "ambiguous trait method name", ); span_lint_and_help( cx, AMBIGUOUS_METHOD_CALLS, - struct_methods.get(&(parent_ty_str, ident.name)).unwrap().span(), + *self.inherent_methods.get(k).unwrap(), "ambiguous struct method name", None, "consider renaming the struct impl's method", ); - } - } - } - - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if let hir::ExprKind::MethodCall(path, receiver, _, call_span) = &expr.kind { - let recv_ty = cx.typeck_results().expr_ty(receiver).peel_refs(); - let recv_ty_str = format!("{recv_ty}"); - let struct_methods = struct_methods().lock().unwrap(); - let trait_methods = trait_methods().lock().unwrap(); - if struct_methods.contains_key(&(recv_ty_str.clone(), path.ident.name)) - && trait_methods.contains_key(&(recv_ty_str, path.ident.name)) - { - span_lint_and_help( - cx, - AMBIGUOUS_METHOD_CALLS, - *call_span, - "ambiguous struct method call", - None, - "consider renaming the struct impl's method or explicitly qualifying the call site", - ); + if let Some(spans) = self.call_sites.get(k) { + for span in spans { + span_lint_and_help( + cx, + AMBIGUOUS_METHOD_CALLS, + *span, + "ambiguous struct method call", + None, + "consider renaming the struct impl's method or explicitly qualifying the call site", + ); + } + } } } } } - -fn has_ambiguous_name(ty: Ty<'_>, ident: Ident) -> bool { - let ty_str = format!("{ty}"); - let trait_methods = trait_methods().lock().unwrap(); - let struct_methods = struct_methods().lock().unwrap(); - - trait_methods.contains_key(&(ty_str.clone(), ident.name)) && struct_methods.contains_key(&(ty_str, ident.name)) -} - -fn trait_methods() -> &'static Mutex> { - static NAMES: OnceLock>> = OnceLock::new(); - NAMES.get_or_init(|| Mutex::new(FxHashMap::default())) -} - -fn struct_methods() -> &'static Mutex> { - static NAMES: OnceLock>> = OnceLock::new(); - NAMES.get_or_init(|| Mutex::new(FxHashMap::default())) -} - -fn insert_method(is_trait_impl: bool, ty: Ty<'_>, ident: Ident) { - let ty_str = format!("{ty}"); - let mut trait_methods = trait_methods().lock().unwrap(); - let mut struct_methods = struct_methods().lock().unwrap(); - - if is_trait_impl { - trait_methods.insert((ty_str, ident.name), ident.span.data()); - } else { - struct_methods.insert((ty_str, ident.name), ident.span.data()); - } -} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c4bf3cd4b9a8..31e3d14ac7ff 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1122,7 +1122,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); store.register_late_pass(move |_| Box::new(manual_hash_one::ManualHashOne::new(msrv()))); - store.register_late_pass(|_| Box::new(ambiguous_method_calls::AmbiguousMethodCalls)); + store.register_late_pass(|_| Box::new(ambiguous_method_calls::AmbiguousMethodCalls::new())); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/tests/ui/ambiguous_method_calls.rs b/tests/ui/ambiguous_method_calls.rs index 241e63605067..0519a5028bbe 100644 --- a/tests/ui/ambiguous_method_calls.rs +++ b/tests/ui/ambiguous_method_calls.rs @@ -1,17 +1,31 @@ #![allow(dead_code)] #![warn(clippy::ambiguous_method_calls)] +fn main() { + Base.ambiguous(); + Base.ambiguous(); + Base.also_ambiguous(); + + Base.unambiguous(); + + Other.ambiguous(); + Other.also_ambiguous(); +} + trait MyTrait { fn ambiguous(&self); + fn also_ambiguous(&self); } struct Base; impl Base { fn ambiguous(&self) { - println!("struct impl"); + println!("ambiguous struct impl"); } + fn also_ambiguous(&self) {} + fn unambiguous(&self) { println!("unambiguous struct impl"); } @@ -19,8 +33,10 @@ impl Base { impl MyTrait for Base { fn ambiguous(&self) { - println!("trait impl"); + println!("ambiguous trait impl"); } + + fn also_ambiguous(&self) {} } struct Other; @@ -29,9 +45,8 @@ impl MyTrait for Other { fn ambiguous(&self) { println!("not actually ambiguous") } -} -fn main() { - Base.ambiguous(); - Other.ambiguous(); + fn also_ambiguous(&self) { + println!("not actually ambiguous either") + } } diff --git a/tests/ui/ambiguous_method_calls.stderr b/tests/ui/ambiguous_method_calls.stderr index 2d02b3795285..e1a05c531169 100644 --- a/tests/ui/ambiguous_method_calls.stderr +++ b/tests/ui/ambiguous_method_calls.stderr @@ -1,14 +1,36 @@ error: ambiguous trait method name - --> $DIR/ambiguous_method_calls.rs:21:8 + --> $DIR/ambiguous_method_calls.rs:39:8 | -LL | fn ambiguous(&self) { - | ^^^^^^^^^ +LL | fn also_ambiguous(&self) {} + | ^^^^^^^^^^^^^^ | = note: `-D clippy::ambiguous-method-calls` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::ambiguous_method_calls)]` error: ambiguous struct method name - --> $DIR/ambiguous_method_calls.rs:11:8 + --> $DIR/ambiguous_method_calls.rs:27:8 + | +LL | fn also_ambiguous(&self) {} + | ^^^^^^^^^^^^^^ + | + = help: consider renaming the struct impl's method + +error: ambiguous struct method call + --> $DIR/ambiguous_method_calls.rs:7:10 + | +LL | Base.also_ambiguous(); + | ^^^^^^^^^^^^^^^^ + | + = help: consider renaming the struct impl's method or explicitly qualifying the call site + +error: ambiguous trait method name + --> $DIR/ambiguous_method_calls.rs:35:8 + | +LL | fn ambiguous(&self) { + | ^^^^^^^^^ + +error: ambiguous struct method name + --> $DIR/ambiguous_method_calls.rs:23:8 | LL | fn ambiguous(&self) { | ^^^^^^^^^ @@ -16,12 +38,20 @@ LL | fn ambiguous(&self) { = help: consider renaming the struct impl's method error: ambiguous struct method call - --> $DIR/ambiguous_method_calls.rs:35:10 + --> $DIR/ambiguous_method_calls.rs:5:10 + | +LL | Base.ambiguous(); + | ^^^^^^^^^^^ + | + = help: consider renaming the struct impl's method or explicitly qualifying the call site + +error: ambiguous struct method call + --> $DIR/ambiguous_method_calls.rs:6:10 | LL | Base.ambiguous(); | ^^^^^^^^^^^ | = help: consider renaming the struct impl's method or explicitly qualifying the call site -error: aborting due to 3 previous errors +error: aborting due to 7 previous errors From a233cb9731f8b227d1df5076d50ac3a5c0ac462a Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Wed, 20 Sep 2023 14:09:09 -0700 Subject: [PATCH 05/10] Fix lint iteration order --- clippy_lints/src/ambiguous_method_calls.rs | 13 ++-- tests/ui/ambiguous_method_calls.rs | 16 +++++ tests/ui/ambiguous_method_calls.stderr | 70 ++++++++++++++-------- 3 files changed, 69 insertions(+), 30 deletions(-) diff --git a/clippy_lints/src/ambiguous_method_calls.rs b/clippy_lints/src/ambiguous_method_calls.rs index 646dd5374e48..1e78c48cfaad 100644 --- a/clippy_lints/src/ambiguous_method_calls.rs +++ b/clippy_lints/src/ambiguous_method_calls.rs @@ -75,7 +75,7 @@ declare_clippy_lint! { #[derive(Clone)] pub struct AmbiguousMethodCalls { trait_methods: FxHashMap<(String, Symbol), Span>, - inherent_methods: FxHashMap<(String, Symbol), Span>, + inherent_methods: Vec<(String, Symbol, Span)>, call_sites: FxHashMap<(String, Symbol), Vec>, } @@ -83,7 +83,7 @@ impl AmbiguousMethodCalls { pub fn new() -> Self { Self { trait_methods: FxHashMap::default(), - inherent_methods: FxHashMap::default(), + inherent_methods: Vec::default(), call_sites: FxHashMap::default(), } } @@ -93,7 +93,7 @@ impl AmbiguousMethodCalls { if is_trait_impl { self.trait_methods.insert((ty_str, ident.name), ident.span); } else { - self.inherent_methods.insert((ty_str, ident.name), ident.span); + self.inherent_methods.push((ty_str, ident.name, ident.span)); } } @@ -145,7 +145,8 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls { } fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { - for k in self.inherent_methods.keys() { + for (ty, name, span) in &self.inherent_methods { + let k = &(ty.clone(), *name); if self.trait_methods.contains_key(k) { span_lint( cx, @@ -156,7 +157,7 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls { span_lint_and_help( cx, AMBIGUOUS_METHOD_CALLS, - *self.inherent_methods.get(k).unwrap(), + *span, "ambiguous struct method name", None, "consider renaming the struct impl's method", @@ -168,7 +169,7 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls { cx, AMBIGUOUS_METHOD_CALLS, *span, - "ambiguous struct method call", + "ambiguous method call", None, "consider renaming the struct impl's method or explicitly qualifying the call site", ); diff --git a/tests/ui/ambiguous_method_calls.rs b/tests/ui/ambiguous_method_calls.rs index 0519a5028bbe..ed515b1c5549 100644 --- a/tests/ui/ambiguous_method_calls.rs +++ b/tests/ui/ambiguous_method_calls.rs @@ -10,13 +10,23 @@ fn main() { Other.ambiguous(); Other.also_ambiguous(); + + Base.another(); + + ambiguous(); } +fn ambiguous() {} + trait MyTrait { fn ambiguous(&self); fn also_ambiguous(&self); } +trait Another { + fn another(&self); +} + struct Base; impl Base { @@ -29,6 +39,8 @@ impl Base { fn unambiguous(&self) { println!("unambiguous struct impl"); } + + fn another(&self) {} } impl MyTrait for Base { @@ -39,6 +51,10 @@ impl MyTrait for Base { fn also_ambiguous(&self) {} } +impl Another for Base { + fn another(&self) {} +} + struct Other; impl MyTrait for Other { diff --git a/tests/ui/ambiguous_method_calls.stderr b/tests/ui/ambiguous_method_calls.stderr index e1a05c531169..8d766ed1ffca 100644 --- a/tests/ui/ambiguous_method_calls.stderr +++ b/tests/ui/ambiguous_method_calls.stderr @@ -1,21 +1,51 @@ error: ambiguous trait method name - --> $DIR/ambiguous_method_calls.rs:39:8 + --> $DIR/ambiguous_method_calls.rs:47:8 | -LL | fn also_ambiguous(&self) {} - | ^^^^^^^^^^^^^^ +LL | fn ambiguous(&self) { + | ^^^^^^^^^ | = note: `-D clippy::ambiguous-method-calls` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::ambiguous_method_calls)]` error: ambiguous struct method name - --> $DIR/ambiguous_method_calls.rs:27:8 + --> $DIR/ambiguous_method_calls.rs:33:8 + | +LL | fn ambiguous(&self) { + | ^^^^^^^^^ + | + = help: consider renaming the struct impl's method + +error: ambiguous method call + --> $DIR/ambiguous_method_calls.rs:5:10 + | +LL | Base.ambiguous(); + | ^^^^^^^^^^^ + | + = help: consider renaming the struct impl's method or explicitly qualifying the call site + +error: ambiguous method call + --> $DIR/ambiguous_method_calls.rs:6:10 + | +LL | Base.ambiguous(); + | ^^^^^^^^^^^ + | + = help: consider renaming the struct impl's method or explicitly qualifying the call site + +error: ambiguous trait method name + --> $DIR/ambiguous_method_calls.rs:51:8 + | +LL | fn also_ambiguous(&self) {} + | ^^^^^^^^^^^^^^ + +error: ambiguous struct method name + --> $DIR/ambiguous_method_calls.rs:37:8 | LL | fn also_ambiguous(&self) {} | ^^^^^^^^^^^^^^ | = help: consider renaming the struct impl's method -error: ambiguous struct method call +error: ambiguous method call --> $DIR/ambiguous_method_calls.rs:7:10 | LL | Base.also_ambiguous(); @@ -24,34 +54,26 @@ LL | Base.also_ambiguous(); = help: consider renaming the struct impl's method or explicitly qualifying the call site error: ambiguous trait method name - --> $DIR/ambiguous_method_calls.rs:35:8 + --> $DIR/ambiguous_method_calls.rs:55:8 | -LL | fn ambiguous(&self) { - | ^^^^^^^^^ +LL | fn another(&self) {} + | ^^^^^^^ error: ambiguous struct method name - --> $DIR/ambiguous_method_calls.rs:23:8 + --> $DIR/ambiguous_method_calls.rs:43:8 | -LL | fn ambiguous(&self) { - | ^^^^^^^^^ +LL | fn another(&self) {} + | ^^^^^^^ | = help: consider renaming the struct impl's method -error: ambiguous struct method call - --> $DIR/ambiguous_method_calls.rs:5:10 - | -LL | Base.ambiguous(); - | ^^^^^^^^^^^ +error: ambiguous method call + --> $DIR/ambiguous_method_calls.rs:14:10 | - = help: consider renaming the struct impl's method or explicitly qualifying the call site - -error: ambiguous struct method call - --> $DIR/ambiguous_method_calls.rs:6:10 - | -LL | Base.ambiguous(); - | ^^^^^^^^^^^ +LL | Base.another(); + | ^^^^^^^^^ | = help: consider renaming the struct impl's method or explicitly qualifying the call site -error: aborting due to 7 previous errors +error: aborting due to 10 previous errors From a54c2da18e99b8b322eb1cc21b7a229625ab5445 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 22 Sep 2023 12:05:31 -0700 Subject: [PATCH 06/10] Store `Ty` in maps instead of `String` --- clippy_lints/src/ambiguous_method_calls.rs | 30 ++++++++++------------ 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/ambiguous_method_calls.rs b/clippy_lints/src/ambiguous_method_calls.rs index 1e78c48cfaad..a6100824aa89 100644 --- a/clippy_lints/src/ambiguous_method_calls.rs +++ b/clippy_lints/src/ambiguous_method_calls.rs @@ -73,13 +73,13 @@ declare_clippy_lint! { } #[derive(Clone)] -pub struct AmbiguousMethodCalls { - trait_methods: FxHashMap<(String, Symbol), Span>, - inherent_methods: Vec<(String, Symbol, Span)>, - call_sites: FxHashMap<(String, Symbol), Vec>, +pub struct AmbiguousMethodCalls<'tcx> { + trait_methods: FxHashMap<(Ty<'tcx>, Symbol), Span>, + inherent_methods: Vec<(Ty<'tcx>, Symbol, Span)>, + call_sites: FxHashMap<(Ty<'tcx>, Symbol), Vec>, } -impl AmbiguousMethodCalls { +impl<'tcx> AmbiguousMethodCalls<'tcx> { pub fn new() -> Self { Self { trait_methods: FxHashMap::default(), @@ -88,28 +88,26 @@ impl AmbiguousMethodCalls { } } - fn insert_method(&mut self, is_trait_impl: bool, ty: Ty<'_>, ident: Ident) { - let ty_str = format!("{ty}"); + fn insert_method(&mut self, is_trait_impl: bool, ty: Ty<'tcx>, ident: Ident) { if is_trait_impl { - self.trait_methods.insert((ty_str, ident.name), ident.span); + self.trait_methods.insert((ty, ident.name), ident.span); } else { - self.inherent_methods.push((ty_str, ident.name, ident.span)); + self.inherent_methods.push((ty, ident.name, ident.span)); } } - fn insert_call_site(&mut self, ty: Ty<'_>, ident: Ident, span: Span) { - let ty_str = format!("{ty}"); - if let Some(spans) = self.call_sites.get_mut(&(ty_str.clone(), ident.name)) { + fn insert_call_site(&mut self, ty: Ty<'tcx>, ident: Ident, span: Span) { + if let Some(spans) = self.call_sites.get_mut(&(ty, ident.name)) { spans.push(span); } else { - self.call_sites.insert((ty_str, ident.name), vec![span]); + self.call_sites.insert((ty, ident.name), vec![span]); } } } -impl_lint_pass!(AmbiguousMethodCalls => [AMBIGUOUS_METHOD_CALLS]); +impl_lint_pass!(AmbiguousMethodCalls<'_> => [AMBIGUOUS_METHOD_CALLS]); -impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls { +impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls<'tcx> { fn check_fn( &mut self, cx: &LateContext<'tcx>, @@ -146,7 +144,7 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls { fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { for (ty, name, span) in &self.inherent_methods { - let k = &(ty.clone(), *name); + let k = &(*ty, *name); if self.trait_methods.contains_key(k) { span_lint( cx, From 2e33169f34f23b9772987b772443cd51b69d68e6 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Sat, 23 Sep 2023 13:35:33 -0700 Subject: [PATCH 07/10] Remove call site linting --- clippy_lints/src/ambiguous_method_calls.rs | 57 ++++------------------ 1 file changed, 10 insertions(+), 47 deletions(-) diff --git a/clippy_lints/src/ambiguous_method_calls.rs b/clippy_lints/src/ambiguous_method_calls.rs index a6100824aa89..0ba3e901ca3b 100644 --- a/clippy_lints/src/ambiguous_method_calls.rs +++ b/clippy_lints/src/ambiguous_method_calls.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::is_trait_impl_item; use hir::intravisit::FnKind; use hir::{Body, FnDecl}; @@ -76,7 +76,6 @@ declare_clippy_lint! { pub struct AmbiguousMethodCalls<'tcx> { trait_methods: FxHashMap<(Ty<'tcx>, Symbol), Span>, inherent_methods: Vec<(Ty<'tcx>, Symbol, Span)>, - call_sites: FxHashMap<(Ty<'tcx>, Symbol), Vec>, } impl<'tcx> AmbiguousMethodCalls<'tcx> { @@ -84,7 +83,6 @@ impl<'tcx> AmbiguousMethodCalls<'tcx> { Self { trait_methods: FxHashMap::default(), inherent_methods: Vec::default(), - call_sites: FxHashMap::default(), } } @@ -95,14 +93,6 @@ impl<'tcx> AmbiguousMethodCalls<'tcx> { self.inherent_methods.push((ty, ident.name, ident.span)); } } - - fn insert_call_site(&mut self, ty: Ty<'tcx>, ident: Ident, span: Span) { - if let Some(spans) = self.call_sites.get_mut(&(ty, ident.name)) { - spans.push(span); - } else { - self.call_sites.insert((ty, ident.name), vec![span]); - } - } } impl_lint_pass!(AmbiguousMethodCalls<'_> => [AMBIGUOUS_METHOD_CALLS]); @@ -123,10 +113,10 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls<'tcx> { let parent_id = cx.tcx.hir().get_parent_item(hir_id); // Calling type_of on a method's default impl causes an ICE - if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(hir::HirId::from(parent_id)) { - if let hir::ItemKind::Trait(..) = item.kind { - return; - } + if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(hir::HirId::from(parent_id)) + && let hir::ItemKind::Trait(..) = item.kind + { + return; } let parent_ty = cx.tcx.type_of(parent_id.to_def_id()).skip_binder(); @@ -134,45 +124,18 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls<'tcx> { } } - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { - if let hir::ExprKind::MethodCall(path, recv, _, call_span) = &expr.kind { - let recv_ty = cx.typeck_results().expr_ty(recv).peel_refs(); - - self.insert_call_site(recv_ty, path.ident, *call_span); - } - } - fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { for (ty, name, span) in &self.inherent_methods { let k = &(*ty, *name); - if self.trait_methods.contains_key(k) { - span_lint( - cx, - AMBIGUOUS_METHOD_CALLS, - *self.trait_methods.get(k).unwrap(), - "ambiguous trait method name", - ); - span_lint_and_help( + if let Some(tm_span) = self.trait_methods.get(k) { + span_lint_and_note( cx, AMBIGUOUS_METHOD_CALLS, *span, - "ambiguous struct method name", - None, - "consider renaming the struct impl's method", + "ambiguous inherent method name", + Some(*tm_span), + "trait method defined here", ); - - if let Some(spans) = self.call_sites.get(k) { - for span in spans { - span_lint_and_help( - cx, - AMBIGUOUS_METHOD_CALLS, - *span, - "ambiguous method call", - None, - "consider renaming the struct impl's method or explicitly qualifying the call site", - ); - } - } } } } From d7ef001bb0fa971b94a509860995ae7db28b3566 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Sat, 23 Sep 2023 13:38:24 -0700 Subject: [PATCH 08/10] Rename to `ambiguous_method_names` --- CHANGELOG.md | 2 +- ...hod_calls.rs => ambiguous_method_names.rs} | 12 +-- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/lib.rs | 4 +- tests/ui/ambiguous_method_calls.stderr | 79 ------------------- ...hod_calls.rs => ambiguous_method_names.rs} | 15 +++- tests/ui/ambiguous_method_names.stderr | 40 ++++++++++ 7 files changed, 64 insertions(+), 90 deletions(-) rename clippy_lints/src/{ambiguous_method_calls.rs => ambiguous_method_names.rs} (93%) delete mode 100644 tests/ui/ambiguous_method_calls.stderr rename tests/ui/{ambiguous_method_calls.rs => ambiguous_method_names.rs} (84%) create mode 100644 tests/ui/ambiguous_method_names.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index c4c56efa31fb..3bd2defbc7a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4776,7 +4776,7 @@ Released 2018-09-13 [`almost_complete_letter_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_letter_range [`almost_complete_range`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_complete_range [`almost_swapped`]: https://rust-lang.github.io/rust-clippy/master/index.html#almost_swapped -[`ambiguous_method_calls`]: https://rust-lang.github.io/rust-clippy/master/index.html#ambiguous_method_calls +[`ambiguous_method_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#ambiguous_method_names [`approx_constant`]: https://rust-lang.github.io/rust-clippy/master/index.html#approx_constant [`arc_with_non_send_sync`]: https://rust-lang.github.io/rust-clippy/master/index.html#arc_with_non_send_sync [`arithmetic_side_effects`]: https://rust-lang.github.io/rust-clippy/master/index.html#arithmetic_side_effects diff --git a/clippy_lints/src/ambiguous_method_calls.rs b/clippy_lints/src/ambiguous_method_names.rs similarity index 93% rename from clippy_lints/src/ambiguous_method_calls.rs rename to clippy_lints/src/ambiguous_method_names.rs index 0ba3e901ca3b..2959712a5810 100644 --- a/clippy_lints/src/ambiguous_method_calls.rs +++ b/clippy_lints/src/ambiguous_method_names.rs @@ -67,18 +67,18 @@ declare_clippy_lint! { /// Base.ambiguous(); // prints "trait impl" /// ``` #[clippy::version = "1.74.0"] - pub AMBIGUOUS_METHOD_CALLS, + pub AMBIGUOUS_METHOD_NAMES, pedantic, "declarations and calls for same-named methods in struct impls and trait impls" } #[derive(Clone)] -pub struct AmbiguousMethodCalls<'tcx> { +pub struct AmbiguousMethodNames<'tcx> { trait_methods: FxHashMap<(Ty<'tcx>, Symbol), Span>, inherent_methods: Vec<(Ty<'tcx>, Symbol, Span)>, } -impl<'tcx> AmbiguousMethodCalls<'tcx> { +impl<'tcx> AmbiguousMethodNames<'tcx> { pub fn new() -> Self { Self { trait_methods: FxHashMap::default(), @@ -95,9 +95,9 @@ impl<'tcx> AmbiguousMethodCalls<'tcx> { } } -impl_lint_pass!(AmbiguousMethodCalls<'_> => [AMBIGUOUS_METHOD_CALLS]); +impl_lint_pass!(AmbiguousMethodNames<'_> => [AMBIGUOUS_METHOD_NAMES]); -impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls<'tcx> { +impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodNames<'tcx> { fn check_fn( &mut self, cx: &LateContext<'tcx>, @@ -130,7 +130,7 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodCalls<'tcx> { if let Some(tm_span) = self.trait_methods.get(k) { span_lint_and_note( cx, - AMBIGUOUS_METHOD_CALLS, + AMBIGUOUS_METHOD_NAMES, *span, "ambiguous inherent method name", Some(*tm_span), diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 3f8580f391a7..9e0eabddbab5 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -40,7 +40,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[ crate::absolute_paths::ABSOLUTE_PATHS_INFO, crate::allow_attributes::ALLOW_ATTRIBUTES_INFO, crate::almost_complete_range::ALMOST_COMPLETE_RANGE_INFO, - crate::ambiguous_method_calls::AMBIGUOUS_METHOD_CALLS_INFO, + crate::ambiguous_method_names::AMBIGUOUS_METHOD_NAMES_INFO, crate::approx_const::APPROX_CONSTANT_INFO, crate::arc_with_non_send_sync::ARC_WITH_NON_SEND_SYNC_INFO, crate::as_conversions::AS_CONVERSIONS_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 31e3d14ac7ff..c20a24ac3b76 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -70,7 +70,7 @@ mod renamed_lints; mod absolute_paths; mod allow_attributes; mod almost_complete_range; -mod ambiguous_method_calls; +mod ambiguous_method_names; mod approx_const; mod arc_with_non_send_sync; mod as_conversions; @@ -1122,7 +1122,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: )) }); store.register_late_pass(move |_| Box::new(manual_hash_one::ManualHashOne::new(msrv()))); - store.register_late_pass(|_| Box::new(ambiguous_method_calls::AmbiguousMethodCalls::new())); + store.register_late_pass(|_| Box::new(ambiguous_method_names::AmbiguousMethodNames::new())); // add lints here, do not remove this comment, it's used in `new_lint` } diff --git a/tests/ui/ambiguous_method_calls.stderr b/tests/ui/ambiguous_method_calls.stderr deleted file mode 100644 index 8d766ed1ffca..000000000000 --- a/tests/ui/ambiguous_method_calls.stderr +++ /dev/null @@ -1,79 +0,0 @@ -error: ambiguous trait method name - --> $DIR/ambiguous_method_calls.rs:47:8 - | -LL | fn ambiguous(&self) { - | ^^^^^^^^^ - | - = note: `-D clippy::ambiguous-method-calls` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::ambiguous_method_calls)]` - -error: ambiguous struct method name - --> $DIR/ambiguous_method_calls.rs:33:8 - | -LL | fn ambiguous(&self) { - | ^^^^^^^^^ - | - = help: consider renaming the struct impl's method - -error: ambiguous method call - --> $DIR/ambiguous_method_calls.rs:5:10 - | -LL | Base.ambiguous(); - | ^^^^^^^^^^^ - | - = help: consider renaming the struct impl's method or explicitly qualifying the call site - -error: ambiguous method call - --> $DIR/ambiguous_method_calls.rs:6:10 - | -LL | Base.ambiguous(); - | ^^^^^^^^^^^ - | - = help: consider renaming the struct impl's method or explicitly qualifying the call site - -error: ambiguous trait method name - --> $DIR/ambiguous_method_calls.rs:51:8 - | -LL | fn also_ambiguous(&self) {} - | ^^^^^^^^^^^^^^ - -error: ambiguous struct method name - --> $DIR/ambiguous_method_calls.rs:37:8 - | -LL | fn also_ambiguous(&self) {} - | ^^^^^^^^^^^^^^ - | - = help: consider renaming the struct impl's method - -error: ambiguous method call - --> $DIR/ambiguous_method_calls.rs:7:10 - | -LL | Base.also_ambiguous(); - | ^^^^^^^^^^^^^^^^ - | - = help: consider renaming the struct impl's method or explicitly qualifying the call site - -error: ambiguous trait method name - --> $DIR/ambiguous_method_calls.rs:55:8 - | -LL | fn another(&self) {} - | ^^^^^^^ - -error: ambiguous struct method name - --> $DIR/ambiguous_method_calls.rs:43:8 - | -LL | fn another(&self) {} - | ^^^^^^^ - | - = help: consider renaming the struct impl's method - -error: ambiguous method call - --> $DIR/ambiguous_method_calls.rs:14:10 - | -LL | Base.another(); - | ^^^^^^^^^ - | - = help: consider renaming the struct impl's method or explicitly qualifying the call site - -error: aborting due to 10 previous errors - diff --git a/tests/ui/ambiguous_method_calls.rs b/tests/ui/ambiguous_method_names.rs similarity index 84% rename from tests/ui/ambiguous_method_calls.rs rename to tests/ui/ambiguous_method_names.rs index ed515b1c5549..af1b7770d6a5 100644 --- a/tests/ui/ambiguous_method_calls.rs +++ b/tests/ui/ambiguous_method_names.rs @@ -1,5 +1,5 @@ #![allow(dead_code)] -#![warn(clippy::ambiguous_method_calls)] +#![warn(clippy::ambiguous_method_names)] fn main() { Base.ambiguous(); @@ -14,6 +14,9 @@ fn main() { Base.another(); ambiguous(); + + S::(42).f(); + S::(-42).f(); } fn ambiguous() {} @@ -66,3 +69,13 @@ impl MyTrait for Other { println!("not actually ambiguous either") } } + +struct S(T); + +impl S { + fn f(&self) {} +} + +impl S { + fn f(&self) {} +} diff --git a/tests/ui/ambiguous_method_names.stderr b/tests/ui/ambiguous_method_names.stderr new file mode 100644 index 000000000000..80b5a3c9fa48 --- /dev/null +++ b/tests/ui/ambiguous_method_names.stderr @@ -0,0 +1,40 @@ +error: ambiguous inherent method name + --> $DIR/ambiguous_method_names.rs:36:8 + | +LL | fn ambiguous(&self) { + | ^^^^^^^^^ + | +note: trait method defined here + --> $DIR/ambiguous_method_names.rs:50:8 + | +LL | fn ambiguous(&self) { + | ^^^^^^^^^ + = note: `-D clippy::ambiguous-method-names` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::ambiguous_method_names)]` + +error: ambiguous inherent method name + --> $DIR/ambiguous_method_names.rs:40:8 + | +LL | fn also_ambiguous(&self) {} + | ^^^^^^^^^^^^^^ + | +note: trait method defined here + --> $DIR/ambiguous_method_names.rs:54:8 + | +LL | fn also_ambiguous(&self) {} + | ^^^^^^^^^^^^^^ + +error: ambiguous inherent method name + --> $DIR/ambiguous_method_names.rs:46:8 + | +LL | fn another(&self) {} + | ^^^^^^^ + | +note: trait method defined here + --> $DIR/ambiguous_method_names.rs:58:8 + | +LL | fn another(&self) {} + | ^^^^^^^ + +error: aborting due to 3 previous errors + From 3e012b0ef89ad88d45063bd0acd7f12734a0db04 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Sat, 23 Sep 2023 17:35:17 -0700 Subject: [PATCH 09/10] Use `check_item` and `check_impl_item` --- clippy_lints/src/ambiguous_method_names.rs | 93 ++++++++++------------ tests/ui/ambiguous_method_names.rs | 74 ++++++++--------- tests/ui/ambiguous_method_names.stderr | 76 ++++++++++++++++-- 3 files changed, 144 insertions(+), 99 deletions(-) diff --git a/clippy_lints/src/ambiguous_method_names.rs b/clippy_lints/src/ambiguous_method_names.rs index 2959712a5810..6c824293ea42 100644 --- a/clippy_lints/src/ambiguous_method_names.rs +++ b/clippy_lints/src/ambiguous_method_names.rs @@ -1,15 +1,12 @@ use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::is_trait_impl_item; -use hir::intravisit::FnKind; -use hir::{Body, FnDecl}; -use rustc_data_structures::fx::FxHashMap; +use clippy_utils::ty::implements_trait; +use hir::{ImplItem, Item}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::Ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::def_id::LocalDefId; use rustc_span::symbol::Ident; -use rustc_span::{Span, Symbol}; declare_clippy_lint! { /// ### What it does @@ -73,69 +70,61 @@ declare_clippy_lint! { } #[derive(Clone)] -pub struct AmbiguousMethodNames<'tcx> { - trait_methods: FxHashMap<(Ty<'tcx>, Symbol), Span>, - inherent_methods: Vec<(Ty<'tcx>, Symbol, Span)>, +pub struct AmbiguousMethodNames { + // Keeps track of trait methods + trait_methods: Vec<(LocalDefId, Ident)>, + // Keeps track of inherent methods + inherent_methods: Vec<(LocalDefId, Ident)>, } -impl<'tcx> AmbiguousMethodNames<'tcx> { +impl AmbiguousMethodNames { pub fn new() -> Self { Self { - trait_methods: FxHashMap::default(), + trait_methods: Vec::default(), inherent_methods: Vec::default(), } } - - fn insert_method(&mut self, is_trait_impl: bool, ty: Ty<'tcx>, ident: Ident) { - if is_trait_impl { - self.trait_methods.insert((ty, ident.name), ident.span); - } else { - self.inherent_methods.push((ty, ident.name, ident.span)); - } - } } -impl_lint_pass!(AmbiguousMethodNames<'_> => [AMBIGUOUS_METHOD_NAMES]); - -impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodNames<'tcx> { - fn check_fn( - &mut self, - cx: &LateContext<'tcx>, - kind: FnKind<'tcx>, - _: &'tcx FnDecl<'_>, - _: &'tcx Body<'_>, - _: Span, - def_id: LocalDefId, - ) { - if let FnKind::Method(ident, _) = kind { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id); - let is_trait_impl = is_trait_impl_item(cx, hir_id); - let parent_id = cx.tcx.hir().get_parent_item(hir_id); +impl_lint_pass!(AmbiguousMethodNames => [AMBIGUOUS_METHOD_NAMES]); - // Calling type_of on a method's default impl causes an ICE - if let Some(hir::Node::Item(item)) = cx.tcx.hir().find(hir::HirId::from(parent_id)) - && let hir::ItemKind::Trait(..) = item.kind - { - return; +impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodNames { + // Check trait impls + fn check_item(&mut self, _: &LateContext<'tcx>, item: &'tcx Item<'_>) { + if let hir::ItemKind::Trait(_, _, _, _, tr_items) = item.kind { + for tr_item in tr_items { + if let hir::AssocItemKind::Fn { .. } = tr_item.kind { + self.trait_methods.push((item.owner_id.def_id, tr_item.ident)) + } } + } + } - let parent_ty = cx.tcx.type_of(parent_id.to_def_id()).skip_binder(); - self.insert_method(is_trait_impl, parent_ty, ident); + // Check inherent methods + fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) { + if let hir::ImplItemKind::Fn(..) = impl_item.kind { + let hir_id = cx.tcx.hir().local_def_id_to_hir_id(impl_item.owner_id.def_id); + if !is_trait_impl_item(cx, hir_id) { + let struct_id = cx.tcx.hir().get_parent_item(hir_id); + self.inherent_methods.push((struct_id.def_id, impl_item.ident)) + } } } fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { - for (ty, name, span) in &self.inherent_methods { - let k = &(*ty, *name); - if let Some(tm_span) = self.trait_methods.get(k) { - span_lint_and_note( - cx, - AMBIGUOUS_METHOD_NAMES, - *span, - "ambiguous inherent method name", - Some(*tm_span), - "trait method defined here", - ); + for (r#trait, ident) in &self.trait_methods { + for (r#struct, inherent_ident) in &self.inherent_methods { + let struct_ty = cx.tcx.type_of(r#struct.to_def_id()).skip_binder(); + if implements_trait(cx, struct_ty, r#trait.to_def_id(), &[]) && ident.name == inherent_ident.name { + span_lint_and_note( + cx, + AMBIGUOUS_METHOD_NAMES, + inherent_ident.span, + "ambiguous inherent method name", + Some(ident.span), + "trait method defined here", + ); + } } } } diff --git a/tests/ui/ambiguous_method_names.rs b/tests/ui/ambiguous_method_names.rs index af1b7770d6a5..0995f9cd821a 100644 --- a/tests/ui/ambiguous_method_names.rs +++ b/tests/ui/ambiguous_method_names.rs @@ -1,73 +1,69 @@ #![allow(dead_code)] #![warn(clippy::ambiguous_method_names)] -fn main() { - Base.ambiguous(); - Base.ambiguous(); - Base.also_ambiguous(); - - Base.unambiguous(); - - Other.ambiguous(); - Other.also_ambiguous(); - - Base.another(); - - ambiguous(); - - S::(42).f(); - S::(-42).f(); -} +fn main() {} fn ambiguous() {} trait MyTrait { fn ambiguous(&self); fn also_ambiguous(&self); + fn ambiguous_default(&self) {} } trait Another { fn another(&self); } -struct Base; - -impl Base { - fn ambiguous(&self) { - println!("ambiguous struct impl"); - } +struct A; +impl A { + fn ambiguous(&self) {} fn also_ambiguous(&self) {} + fn ambiguous_default(&self) {} + fn unambiguous(&self) {} + fn another(&self) {} +} - fn unambiguous(&self) { - println!("unambiguous struct impl"); - } +impl MyTrait for A { + fn ambiguous(&self) {} + fn also_ambiguous(&self) {} +} +impl Another for A { fn another(&self) {} } -impl MyTrait for Base { - fn ambiguous(&self) { - println!("ambiguous trait impl"); - } +struct B; + +impl B { + fn ambiguous(&self) {} + fn also_ambiguous(&self) {} + fn ambiguous_default(&self) {} + fn another(&self) {} +} +impl MyTrait for B { + fn ambiguous(&self) {} fn also_ambiguous(&self) {} } -impl Another for Base { +impl Another for B { fn another(&self) {} } -struct Other; +struct C; -impl MyTrait for Other { - fn ambiguous(&self) { - println!("not actually ambiguous") - } +impl MyTrait for C { + fn ambiguous(&self) {} + fn also_ambiguous(&self) {} +} - fn also_ambiguous(&self) { - println!("not actually ambiguous either") - } +struct D; + +impl D { + fn ambiguous(&self) {} + fn also_ambiguous(&self) {} } struct S(T); diff --git a/tests/ui/ambiguous_method_names.stderr b/tests/ui/ambiguous_method_names.stderr index 80b5a3c9fa48..bac17d2a2848 100644 --- a/tests/ui/ambiguous_method_names.stderr +++ b/tests/ui/ambiguous_method_names.stderr @@ -1,13 +1,13 @@ error: ambiguous inherent method name - --> $DIR/ambiguous_method_names.rs:36:8 + --> $DIR/ambiguous_method_names.rs:21:8 | -LL | fn ambiguous(&self) { +LL | fn ambiguous(&self) {} | ^^^^^^^^^ | note: trait method defined here - --> $DIR/ambiguous_method_names.rs:50:8 + --> $DIR/ambiguous_method_names.rs:9:8 | -LL | fn ambiguous(&self) { +LL | fn ambiguous(&self); | ^^^^^^^^^ = note: `-D clippy::ambiguous-method-names` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::ambiguous_method_names)]` @@ -15,26 +15,86 @@ LL | fn ambiguous(&self) { error: ambiguous inherent method name --> $DIR/ambiguous_method_names.rs:40:8 | +LL | fn ambiguous(&self) {} + | ^^^^^^^^^ + | +note: trait method defined here + --> $DIR/ambiguous_method_names.rs:9:8 + | +LL | fn ambiguous(&self); + | ^^^^^^^^^ + +error: ambiguous inherent method name + --> $DIR/ambiguous_method_names.rs:22:8 + | LL | fn also_ambiguous(&self) {} | ^^^^^^^^^^^^^^ | note: trait method defined here - --> $DIR/ambiguous_method_names.rs:54:8 + --> $DIR/ambiguous_method_names.rs:10:8 + | +LL | fn also_ambiguous(&self); + | ^^^^^^^^^^^^^^ + +error: ambiguous inherent method name + --> $DIR/ambiguous_method_names.rs:41:8 | LL | fn also_ambiguous(&self) {} | ^^^^^^^^^^^^^^ + | +note: trait method defined here + --> $DIR/ambiguous_method_names.rs:10:8 + | +LL | fn also_ambiguous(&self); + | ^^^^^^^^^^^^^^ + +error: ambiguous inherent method name + --> $DIR/ambiguous_method_names.rs:23:8 + | +LL | fn ambiguous_default(&self) {} + | ^^^^^^^^^^^^^^^^^ + | +note: trait method defined here + --> $DIR/ambiguous_method_names.rs:11:8 + | +LL | fn ambiguous_default(&self) {} + | ^^^^^^^^^^^^^^^^^ + +error: ambiguous inherent method name + --> $DIR/ambiguous_method_names.rs:42:8 + | +LL | fn ambiguous_default(&self) {} + | ^^^^^^^^^^^^^^^^^ + | +note: trait method defined here + --> $DIR/ambiguous_method_names.rs:11:8 + | +LL | fn ambiguous_default(&self) {} + | ^^^^^^^^^^^^^^^^^ error: ambiguous inherent method name - --> $DIR/ambiguous_method_names.rs:46:8 + --> $DIR/ambiguous_method_names.rs:25:8 | LL | fn another(&self) {} | ^^^^^^^ | note: trait method defined here - --> $DIR/ambiguous_method_names.rs:58:8 + --> $DIR/ambiguous_method_names.rs:15:8 + | +LL | fn another(&self); + | ^^^^^^^ + +error: ambiguous inherent method name + --> $DIR/ambiguous_method_names.rs:43:8 | LL | fn another(&self) {} | ^^^^^^^ + | +note: trait method defined here + --> $DIR/ambiguous_method_names.rs:15:8 + | +LL | fn another(&self); + | ^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 8 previous errors From b6f19988835eb001915a8c500915dd697c9b16b8 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Sun, 24 Sep 2023 14:07:07 -0700 Subject: [PATCH 10/10] Fix ICE when calling `implements_trait` --- clippy_lints/src/ambiguous_method_names.rs | 25 ++++++++++++++++------ tests/ui/ambiguous_method_names.rs | 4 ++++ tests/ui/ambiguous_method_names.stderr | 16 +++++++------- 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/ambiguous_method_names.rs b/clippy_lints/src/ambiguous_method_names.rs index 6c824293ea42..a5e83f81cc05 100644 --- a/clippy_lints/src/ambiguous_method_names.rs +++ b/clippy_lints/src/ambiguous_method_names.rs @@ -4,8 +4,9 @@ use clippy_utils::ty::implements_trait; use hir::{ImplItem, Item}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; -use rustc_span::def_id::LocalDefId; +use rustc_span::def_id::DefId; use rustc_span::symbol::Ident; declare_clippy_lint! { @@ -72,9 +73,9 @@ declare_clippy_lint! { #[derive(Clone)] pub struct AmbiguousMethodNames { // Keeps track of trait methods - trait_methods: Vec<(LocalDefId, Ident)>, + trait_methods: Vec<(DefId, Ident)>, // Keeps track of inherent methods - inherent_methods: Vec<(LocalDefId, Ident)>, + inherent_methods: Vec<(DefId, Ident)>, } impl AmbiguousMethodNames { @@ -94,7 +95,8 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodNames { if let hir::ItemKind::Trait(_, _, _, _, tr_items) = item.kind { for tr_item in tr_items { if let hir::AssocItemKind::Fn { .. } = tr_item.kind { - self.trait_methods.push((item.owner_id.def_id, tr_item.ident)) + self.trait_methods + .push((item.owner_id.def_id.to_def_id(), tr_item.ident)); } } } @@ -106,7 +108,8 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodNames { let hir_id = cx.tcx.hir().local_def_id_to_hir_id(impl_item.owner_id.def_id); if !is_trait_impl_item(cx, hir_id) { let struct_id = cx.tcx.hir().get_parent_item(hir_id); - self.inherent_methods.push((struct_id.def_id, impl_item.ident)) + self.inherent_methods + .push((struct_id.def_id.to_def_id(), impl_item.ident)); } } } @@ -114,8 +117,16 @@ impl<'tcx> LateLintPass<'tcx> for AmbiguousMethodNames { fn check_crate_post(&mut self, cx: &LateContext<'tcx>) { for (r#trait, ident) in &self.trait_methods { for (r#struct, inherent_ident) in &self.inherent_methods { - let struct_ty = cx.tcx.type_of(r#struct.to_def_id()).skip_binder(); - if implements_trait(cx, struct_ty, r#trait.to_def_id(), &[]) && ident.name == inherent_ident.name { + let struct_ty = cx.tcx.type_of(r#struct).skip_binder(); + let trait_ref = ty::TraitRef::identity(cx.tcx, *r#trait); + let args = &trait_ref.args[1..]; + if implements_trait( + cx, + struct_ty, + *r#trait, + &args[..cx.tcx.generics_of(r#trait).params.len() - 1], + ) && ident.name == inherent_ident.name + { span_lint_and_note( cx, AMBIGUOUS_METHOD_NAMES, diff --git a/tests/ui/ambiguous_method_names.rs b/tests/ui/ambiguous_method_names.rs index 0995f9cd821a..4b1963494963 100644 --- a/tests/ui/ambiguous_method_names.rs +++ b/tests/ui/ambiguous_method_names.rs @@ -15,6 +15,10 @@ trait Another { fn another(&self); } +trait G { + fn g(&self, a: T, b: U); +} + struct A; impl A { diff --git a/tests/ui/ambiguous_method_names.stderr b/tests/ui/ambiguous_method_names.stderr index bac17d2a2848..bc1dbb6e95b8 100644 --- a/tests/ui/ambiguous_method_names.stderr +++ b/tests/ui/ambiguous_method_names.stderr @@ -1,5 +1,5 @@ error: ambiguous inherent method name - --> $DIR/ambiguous_method_names.rs:21:8 + --> $DIR/ambiguous_method_names.rs:25:8 | LL | fn ambiguous(&self) {} | ^^^^^^^^^ @@ -13,7 +13,7 @@ LL | fn ambiguous(&self); = help: to override `-D warnings` add `#[allow(clippy::ambiguous_method_names)]` error: ambiguous inherent method name - --> $DIR/ambiguous_method_names.rs:40:8 + --> $DIR/ambiguous_method_names.rs:44:8 | LL | fn ambiguous(&self) {} | ^^^^^^^^^ @@ -25,7 +25,7 @@ LL | fn ambiguous(&self); | ^^^^^^^^^ error: ambiguous inherent method name - --> $DIR/ambiguous_method_names.rs:22:8 + --> $DIR/ambiguous_method_names.rs:26:8 | LL | fn also_ambiguous(&self) {} | ^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL | fn also_ambiguous(&self); | ^^^^^^^^^^^^^^ error: ambiguous inherent method name - --> $DIR/ambiguous_method_names.rs:41:8 + --> $DIR/ambiguous_method_names.rs:45:8 | LL | fn also_ambiguous(&self) {} | ^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | fn also_ambiguous(&self); | ^^^^^^^^^^^^^^ error: ambiguous inherent method name - --> $DIR/ambiguous_method_names.rs:23:8 + --> $DIR/ambiguous_method_names.rs:27:8 | LL | fn ambiguous_default(&self) {} | ^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL | fn ambiguous_default(&self) {} | ^^^^^^^^^^^^^^^^^ error: ambiguous inherent method name - --> $DIR/ambiguous_method_names.rs:42:8 + --> $DIR/ambiguous_method_names.rs:46:8 | LL | fn ambiguous_default(&self) {} | ^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL | fn ambiguous_default(&self) {} | ^^^^^^^^^^^^^^^^^ error: ambiguous inherent method name - --> $DIR/ambiguous_method_names.rs:25:8 + --> $DIR/ambiguous_method_names.rs:29:8 | LL | fn another(&self) {} | ^^^^^^^ @@ -85,7 +85,7 @@ LL | fn another(&self); | ^^^^^^^ error: ambiguous inherent method name - --> $DIR/ambiguous_method_names.rs:43:8 + --> $DIR/ambiguous_method_names.rs:47:8 | LL | fn another(&self) {} | ^^^^^^^