From 2aa897f694273d82ba6cc3316ad85fb93138f808 Mon Sep 17 00:00:00 2001 From: TheLazyDutchman Date: Sun, 5 Nov 2023 15:29:18 +0100 Subject: [PATCH 1/4] Added shadowed hint for overlapping associated types --- .../rustc_hir_analysis/src/astconv/errors.rs | 29 ++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 32be7e0837b6d..2e1b8cd8c4a11 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -4,6 +4,7 @@ use crate::errors::{ ParenthesizedFnTraitExpansion, }; use crate::traits::error_reporting::report_object_safety_error; +use hir::{TraitRef, TypeBinding}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; @@ -513,6 +514,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if associated_types.values().all(|v| v.is_empty()) { return; } + let tcx = self.tcx(); // FIXME: Marked `mut` so that we can replace the spans further below with a more // appropriate one, but this should be handled earlier in the span assignment. @@ -585,6 +587,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } + let bound_names = trait_bounds + .iter() + .flat_map(|poly_trait_ref| { + poly_trait_ref.trait_ref.path.segments.iter().flat_map(|x| { + x.args.iter().flat_map(|args| { + args.bindings.iter().map(|binding| { + (binding.ident.name, (binding, poly_trait_ref.trait_ref)) + }) + }) + }) + }) + .collect::, TraitRef<'_>)>>(); + let mut names = names .into_iter() .map(|(trait_, mut assocs)| { @@ -626,7 +641,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } let mut dupes = false; for item in assoc_items { - let prefix = if names[&item.name] > 1 { + let prefix = if names[&item.name] > 1 || bound_names.contains_key(&item.name) { let trait_def_id = item.container_id(tcx); dupes = true; format!("{}::", tcx.def_path_str(trait_def_id)) @@ -636,6 +651,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(sp) = tcx.hir().span_if_local(item.def_id) { err.span_label(sp, format!("`{}{}` defined here", prefix, item.name)); } + + if let Some((shadow, trait_ref)) = bound_names.get(&item.name) { + if let Some(def_id) = trait_ref.path.res.opt_def_id() { + let items = tcx.associated_items(def_id); + for assoc_item in items.filter_by_name_unhygienic(shadow.ident.name) { + err.span_label( + tcx.def_span(assoc_item.def_id), + format!("`{}{}` shadowed here", prefix, item.name), + ); + } + } + } } if potential_assoc_types.len() == assoc_items.len() { // When the amount of missing associated types equals the number of From a41cd836e59e096f222f7a67175914166199b80b Mon Sep 17 00:00:00 2001 From: TheLazyDutchman Date: Mon, 6 Nov 2023 11:45:45 +0100 Subject: [PATCH 2/4] Added help message to suggest renaming --- .../rustc_hir_analysis/src/astconv/errors.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 2e1b8cd8c4a11..9347d9b649a75 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -629,6 +629,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { pluralize!(names_len), names, ); + let mut rename_suggestions = vec![]; let mut suggestions = vec![]; let mut types_count = 0; let mut where_constraints = vec![]; @@ -640,11 +641,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { *names.entry(item.name).or_insert(0) += 1; } let mut dupes = false; + let mut shadows = false; for item in assoc_items { - let prefix = if names[&item.name] > 1 || bound_names.contains_key(&item.name) { + let prefix = if names[&item.name] > 1 { let trait_def_id = item.container_id(tcx); dupes = true; format!("{}::", tcx.def_path_str(trait_def_id)) + } else if bound_names.contains_key(&item.name) { + let trait_def_id = item.container_id(tcx); + shadows = true; + format!("{}::", tcx.def_path_str(trait_def_id)) } else { String::new() }; @@ -669,6 +675,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // extra type arguments present. A suggesting to replace the generic args with // associated types is already emitted. already_has_generics_args_suggestion = true; + } else if shadows { + for item in assoc_items { + if let Some(sp) = tcx.hir().span_if_local(item.def_id) { + rename_suggestions.push(sp); + } + } } else if let (Ok(snippet), false) = (tcx.sess.source_map().span_to_snippet(*span), dupes) { @@ -752,6 +764,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.span_help(where_constraints, where_msg); } } + + for span in rename_suggestions { + err.span_help(span, "consider renaming this associated type"); + } err.emit(); } } From 40064dbe0e9b1fbb5fd023a6559ef0564ed374d8 Mon Sep 17 00:00:00 2001 From: TheLazyDutchman Date: Mon, 6 Nov 2023 12:05:08 +0100 Subject: [PATCH 3/4] Added rename help message on subtrait --- .../rustc_hir_analysis/src/astconv/errors.rs | 33 +++++++++++-------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 9347d9b649a75..38ccb494ed854 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -4,13 +4,12 @@ use crate::errors::{ ParenthesizedFnTraitExpansion, }; use crate::traits::error_reporting::report_object_safety_error; -use hir::{TraitRef, TypeBinding}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::traits::FulfillmentError; -use rustc_middle::ty::{self, suggest_constraining_type_param, Ty, TyCtxt}; +use rustc_middle::ty::{self, suggest_constraining_type_param, AssocItem, Ty, TyCtxt}; use rustc_session::parse::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::symbol::{sym, Ident}; @@ -593,12 +592,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { poly_trait_ref.trait_ref.path.segments.iter().flat_map(|x| { x.args.iter().flat_map(|args| { args.bindings.iter().map(|binding| { - (binding.ident.name, (binding, poly_trait_ref.trait_ref)) + let name = binding.ident.name; + let trait_def = poly_trait_ref.trait_ref.path.res.opt_def_id(); + let assoc_item = trait_def.and_then(|did| { + tcx.associated_items(did).filter_by_name_unhygienic(name).next() + }); + (name, assoc_item) }) }) }) }) - .collect::, TraitRef<'_>)>>(); + .collect::>>(); let mut names = names .into_iter() @@ -658,16 +662,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { err.span_label(sp, format!("`{}{}` defined here", prefix, item.name)); } - if let Some((shadow, trait_ref)) = bound_names.get(&item.name) { - if let Some(def_id) = trait_ref.path.res.opt_def_id() { - let items = tcx.associated_items(def_id); - for assoc_item in items.filter_by_name_unhygienic(shadow.ident.name) { - err.span_label( - tcx.def_span(assoc_item.def_id), - format!("`{}{}` shadowed here", prefix, item.name), - ); - } - } + if let Some(Some(assoc_item)) = bound_names.get(&item.name) { + err.span_label( + tcx.def_span(assoc_item.def_id), + format!("`{}{}` shadowed here", prefix, item.name), + ); } } if potential_assoc_types.len() == assoc_items.len() { @@ -680,6 +679,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { if let Some(sp) = tcx.hir().span_if_local(item.def_id) { rename_suggestions.push(sp); } + + if let Some(Some(assoc_item)) = bound_names.get(&item.name) { + if let Some(sp) = tcx.hir().span_if_local(assoc_item.def_id) { + rename_suggestions.push(sp); + } + } } } else if let (Ok(snippet), false) = (tcx.sess.source_map().span_to_snippet(*span), dupes) From e9a900d6c816ebd1bf231ea6a28ad2b2dabdb26d Mon Sep 17 00:00:00 2001 From: TheLazyDutchman Date: Mon, 6 Nov 2023 21:28:34 +0100 Subject: [PATCH 4/4] Remove rename suggestions on unrelated associated types --- compiler/rustc_hir_analysis/src/astconv/errors.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs index 38ccb494ed854..cae3aae46a50a 100644 --- a/compiler/rustc_hir_analysis/src/astconv/errors.rs +++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs @@ -676,11 +676,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { already_has_generics_args_suggestion = true; } else if shadows { for item in assoc_items { - if let Some(sp) = tcx.hir().span_if_local(item.def_id) { - rename_suggestions.push(sp); - } - if let Some(Some(assoc_item)) = bound_names.get(&item.name) { + if let Some(sp) = tcx.hir().span_if_local(item.def_id) { + rename_suggestions.push(sp); + } + if let Some(sp) = tcx.hir().span_if_local(assoc_item.def_id) { rename_suggestions.push(sp); }