summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/structured_errors
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-07 05:48:48 +0000
commitef24de24a82fe681581cc130f342363c47c0969a (patch)
tree0d494f7e1a38b95c92426f58fe6eaa877303a86c /compiler/rustc_hir_analysis/src/structured_errors
parentReleasing progress-linux version 1.74.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-ef24de24a82fe681581cc130f342363c47c0969a.tar.xz
rustc-ef24de24a82fe681581cc130f342363c47c0969a.zip
Merging upstream version 1.75.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_hir_analysis/src/structured_errors')
-rw-r--r--compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs129
1 files changed, 90 insertions, 39 deletions
diff --git a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
index 61b182b1b..76bd370a6 100644
--- a/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
+++ b/compiler/rustc_hir_analysis/src/structured_errors/wrong_number_of_generic_args.rs
@@ -129,6 +129,44 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
if self.missing_lifetimes() { "lifetime" } else { "generic" }
}
+ /// Returns true if the generic type is a trait
+ /// and is being referred to from one of its trait impls
+ fn is_in_trait_impl(&self) -> bool {
+ if self.tcx.is_trait(self.def_id) {
+ // Here we check if the reference to the generic type
+ // is from the 'of_trait' field of the enclosing impl
+
+ let parent = self.tcx.hir().get_parent(self.path_segment.hir_id);
+ let parent_item = self
+ .tcx
+ .hir()
+ .get_by_def_id(self.tcx.hir().get_parent_item(self.path_segment.hir_id).def_id);
+
+ // Get the HIR id of the trait ref
+ let hir::Node::TraitRef(hir::TraitRef { hir_ref_id: trait_ref_id, .. }) = parent else {
+ return false;
+ };
+
+ // Get the HIR id of the 'of_trait' field of the impl
+ let hir::Node::Item(hir::Item {
+ kind:
+ hir::ItemKind::Impl(hir::Impl {
+ of_trait: Some(hir::TraitRef { hir_ref_id: id_in_of_trait, .. }),
+ ..
+ }),
+ ..
+ }) = parent_item
+ else {
+ return false;
+ };
+
+ // Check that trait is referred to from the of_trait field of impl
+ trait_ref_id == id_in_of_trait
+ } else {
+ false
+ }
+ }
+
fn num_provided_args(&self) -> usize {
if self.missing_lifetimes() {
self.num_provided_lifetime_args()
@@ -316,12 +354,18 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
}
// Suggest `'_` when in function parameter or elided function return.
- if let Some(fn_decl) = node.fn_decl() && let Some(ty_id) = ty_id {
+ if let Some(fn_decl) = node.fn_decl()
+ && let Some(ty_id) = ty_id
+ {
let in_arg = fn_decl.inputs.iter().any(|t| t.hir_id == ty_id);
- let in_ret = matches!(fn_decl.output, hir::FnRetTy::Return(ty) if ty.hir_id == ty_id);
+ let in_ret =
+ matches!(fn_decl.output, hir::FnRetTy::Return(ty) if ty.hir_id == ty_id);
if in_arg || (in_ret && fn_decl.lifetime_elision_allowed) {
- return std::iter::repeat("'_".to_owned()).take(num_params_to_take).collect::<Vec<_>>().join(", ");
+ return std::iter::repeat("'_".to_owned())
+ .take(num_params_to_take)
+ .collect::<Vec<_>>()
+ .join(", ");
}
}
@@ -730,28 +774,27 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
);
if let Some(parent_node) = self.tcx.hir().opt_parent_id(self.path_segment.hir_id)
- && let Some(parent_node) = self.tcx.hir().find(parent_node)
- && let hir::Node::Expr(expr) = parent_node {
+ && let Some(parent_node) = self.tcx.hir().find(parent_node)
+ && let hir::Node::Expr(expr) = parent_node
+ {
match &expr.kind {
- hir::ExprKind::Path(qpath) => {
- self.suggest_moving_args_from_assoc_fn_to_trait_for_qualified_path(
+ hir::ExprKind::Path(qpath) => self
+ .suggest_moving_args_from_assoc_fn_to_trait_for_qualified_path(
err,
qpath,
msg,
num_assoc_fn_excess_args,
- num_trait_generics_except_self
- )
- },
- hir::ExprKind::MethodCall(..) => {
- self.suggest_moving_args_from_assoc_fn_to_trait_for_method_call(
+ num_trait_generics_except_self,
+ ),
+ hir::ExprKind::MethodCall(..) => self
+ .suggest_moving_args_from_assoc_fn_to_trait_for_method_call(
err,
trait_,
expr,
msg,
num_assoc_fn_excess_args,
- num_trait_generics_except_self
- )
- },
+ num_trait_generics_except_self,
+ ),
_ => return,
}
}
@@ -766,23 +809,25 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
num_trait_generics_except_self: usize,
) {
if let hir::QPath::Resolved(_, path) = qpath
- && let Some(trait_path_segment) = path.segments.get(0) {
+ && let Some(trait_path_segment) = path.segments.get(0)
+ {
let num_generic_args_supplied_to_trait = trait_path_segment.args().num_generic_params();
- if num_generic_args_supplied_to_trait + num_assoc_fn_excess_args == num_trait_generics_except_self
+ if num_generic_args_supplied_to_trait + num_assoc_fn_excess_args
+ == num_trait_generics_except_self
{
if let Some(span) = self.gen_args.span_ext()
- && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+ && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
+ {
let sugg = vec![
- (self.path_segment.ident.span, format!("{}::{}", snippet, self.path_segment.ident)),
- (span.with_lo(self.path_segment.ident.span.hi()), "".to_owned())
+ (
+ self.path_segment.ident.span,
+ format!("{}::{}", snippet, self.path_segment.ident),
+ ),
+ (span.with_lo(self.path_segment.ident.span.hi()), "".to_owned()),
];
- err.multipart_suggestion(
- msg,
- sugg,
- Applicability::MaybeIncorrect
- );
+ err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
}
}
}
@@ -948,20 +993,26 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
// If there is a single unbound associated type and a single excess generic param
// suggest replacing the generic param with the associated type bound
if provided_args_matches_unbound_traits && !unbound_types.is_empty() {
- let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..];
- let suggestions = iter::zip(unused_generics, &unbound_types)
- .map(|(potential, name)| (potential.span().shrink_to_lo(), format!("{name} = ")))
- .collect::<Vec<_>>();
-
- if !suggestions.is_empty() {
- err.multipart_suggestion_verbose(
- format!(
- "replace the generic bound{s} with the associated type{s}",
- s = pluralize!(unbound_types.len())
- ),
- suggestions,
- Applicability::MaybeIncorrect,
- );
+ // Don't suggest if we're in a trait impl as
+ // that would result in invalid syntax (fixes #116464)
+ if !self.is_in_trait_impl() {
+ let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..];
+ let suggestions = iter::zip(unused_generics, &unbound_types)
+ .map(|(potential, name)| {
+ (potential.span().shrink_to_lo(), format!("{name} = "))
+ })
+ .collect::<Vec<_>>();
+
+ if !suggestions.is_empty() {
+ err.multipart_suggestion_verbose(
+ format!(
+ "replace the generic bound{s} with the associated type{s}",
+ s = pluralize!(unbound_types.len())
+ ),
+ suggestions,
+ Applicability::MaybeIncorrect,
+ );
+ }
}
} else if remove_entire_generics {
let span = self