1 use crate::structured_errors
::StructuredDiagnostic
;
3 pluralize
, Applicability
, Diagnostic
, DiagnosticBuilder
, DiagnosticId
, ErrorGuaranteed
,
7 use rustc_middle
::hir
::map
::fn_sig
;
8 use rustc_middle
::ty
::{self as ty, AssocItems, AssocKind, TyCtxt}
;
9 use rustc_session
::Session
;
10 use rustc_span
::def_id
::DefId
;
13 use GenericArgsInfo
::*;
15 /// Handles the `wrong number of type / lifetime / ... arguments` family of error messages.
16 pub struct WrongNumberOfGenericArgs
<'a
, 'tcx
> {
17 pub(crate) tcx
: TyCtxt
<'tcx
>,
19 pub(crate) angle_brackets
: AngleBrackets
,
21 pub(crate) gen_args_info
: GenericArgsInfo
,
23 /// Offending path segment
24 pub(crate) path_segment
: &'a hir
::PathSegment
<'a
>,
26 /// Generic parameters as expected by type or trait
27 pub(crate) gen_params
: &'a ty
::Generics
,
29 /// Index offset into parameters. Depends on whether `Self` is included and on
30 /// number of lifetime parameters in case we're processing missing or redundant
31 /// type or constant arguments.
32 pub(crate) params_offset
: usize,
34 /// Generic arguments as provided by user
35 pub(crate) gen_args
: &'a hir
::GenericArgs
<'a
>,
37 /// DefId of the generic type
38 pub(crate) def_id
: DefId
,
41 // Provides information about the kind of arguments that were provided for
42 // the PathSegment, for which missing generic arguments were detected
44 pub(crate) enum AngleBrackets
{
45 // No angle brackets were provided, but generic arguments exist in elided form
48 // No angle brackets were provided
51 // Angle brackets are available, but missing some generic arguments
55 // Information about the kind of arguments that are either missing or are unexpected
57 pub enum GenericArgsInfo
{
59 num_missing_args
: usize,
62 num_redundant_args
: usize,
64 MissingTypesOrConsts
{
65 num_missing_args
: usize,
67 // type or const generic arguments can have default values
68 num_default_params
: usize,
70 // lifetime arguments precede type and const parameters, this
71 // field gives the number of generic lifetime arguments to let
72 // us infer the position of type and const generic arguments
73 // in the angle brackets
78 num_redundant_args
: usize,
80 // type or const generic arguments can have default values
81 num_default_params
: usize,
83 // lifetime arguments precede type and const parameters, this
84 // field gives the number of generic lifetime arguments to let
85 // us infer the position of type and const generic arguments
86 // in the angle brackets
89 // if synthetic type arguments (e.g. `impl Trait`) are specified
94 impl<'a
, 'tcx
> WrongNumberOfGenericArgs
<'a
, 'tcx
> {
97 gen_args_info
: GenericArgsInfo
,
98 path_segment
: &'a hir
::PathSegment
<'_
>,
99 gen_params
: &'a ty
::Generics
,
100 params_offset
: usize,
101 gen_args
: &'a hir
::GenericArgs
<'a
>,
104 let angle_brackets
= if gen_args
.span_ext().is_none() {
105 if gen_args
.is_empty() { AngleBrackets::Missing }
else { AngleBrackets::Implied }
107 AngleBrackets
::Available
122 fn missing_lifetimes(&self) -> bool
{
123 match self.gen_args_info
{
124 MissingLifetimes { .. }
| ExcessLifetimes { .. }
=> true,
125 MissingTypesOrConsts { .. }
| ExcessTypesOrConsts { .. }
=> false,
129 fn kind(&self) -> String
{
130 if self.missing_lifetimes() { "lifetime".to_string() }
else { "generic".to_string() }
133 fn num_provided_args(&self) -> usize {
134 if self.missing_lifetimes() {
135 self.num_provided_lifetime_args()
137 self.num_provided_type_or_const_args()
141 fn num_provided_lifetime_args(&self) -> usize {
142 match self.angle_brackets
{
143 AngleBrackets
::Missing
=> 0,
144 // Only lifetime arguments can be implied
145 AngleBrackets
::Implied
=> self.gen_args
.args
.len(),
146 AngleBrackets
::Available
=> self.gen_args
.num_lifetime_params(),
150 fn num_provided_type_or_const_args(&self) -> usize {
151 match self.angle_brackets
{
152 AngleBrackets
::Missing
=> 0,
153 // Only lifetime arguments can be implied
154 AngleBrackets
::Implied
=> 0,
155 AngleBrackets
::Available
=> self.gen_args
.num_generic_params(),
159 fn num_expected_lifetime_args(&self) -> usize {
160 let num_provided_args
= self.num_provided_lifetime_args();
161 match self.gen_args_info
{
162 MissingLifetimes { num_missing_args }
=> num_provided_args
+ num_missing_args
,
163 ExcessLifetimes { num_redundant_args }
=> num_provided_args
- num_redundant_args
,
168 fn num_expected_type_or_const_args(&self) -> usize {
169 let num_provided_args
= self.num_provided_type_or_const_args();
170 match self.gen_args_info
{
171 MissingTypesOrConsts { num_missing_args, .. }
=> num_provided_args
+ num_missing_args
,
172 ExcessTypesOrConsts { num_redundant_args, .. }
=> {
173 num_provided_args
- num_redundant_args
179 // Gives the number of expected arguments taking into account default arguments
180 fn num_expected_type_or_const_args_including_defaults(&self) -> usize {
181 let provided_args
= self.num_provided_type_or_const_args();
182 match self.gen_args_info
{
183 MissingTypesOrConsts { num_missing_args, num_default_params, .. }
=> {
184 provided_args
+ num_missing_args
- num_default_params
186 ExcessTypesOrConsts { num_redundant_args, num_default_params, .. }
=> {
187 provided_args
- num_redundant_args
- num_default_params
193 fn num_missing_lifetime_args(&self) -> usize {
194 let missing_args
= self.num_expected_lifetime_args() - self.num_provided_lifetime_args();
195 assert
!(missing_args
> 0);
199 fn num_missing_type_or_const_args(&self) -> usize {
200 let missing_args
= self.num_expected_type_or_const_args_including_defaults()
201 - self.num_provided_type_or_const_args();
202 assert
!(missing_args
> 0);
206 fn num_excess_lifetime_args(&self) -> usize {
207 match self.gen_args_info
{
208 ExcessLifetimes { num_redundant_args }
=> num_redundant_args
,
213 fn num_excess_type_or_const_args(&self) -> usize {
214 match self.gen_args_info
{
215 ExcessTypesOrConsts { num_redundant_args, .. }
=> num_redundant_args
,
220 fn too_many_args_provided(&self) -> bool
{
221 match self.gen_args_info
{
222 MissingLifetimes { .. }
| MissingTypesOrConsts { .. }
=> false,
223 ExcessLifetimes { num_redundant_args }
224 | ExcessTypesOrConsts { num_redundant_args, .. }
=> {
225 assert
!(num_redundant_args
> 0);
231 fn not_enough_args_provided(&self) -> bool
{
232 match self.gen_args_info
{
233 MissingLifetimes { num_missing_args }
234 | MissingTypesOrConsts { num_missing_args, .. }
=> {
235 assert
!(num_missing_args
> 0);
238 ExcessLifetimes { .. }
| ExcessTypesOrConsts { .. }
=> false,
242 // Helper method to get the index offset in angle brackets, at which type or const arguments
244 fn get_lifetime_args_offset(&self) -> usize {
245 match self.gen_args_info
{
246 MissingLifetimes { .. }
| ExcessLifetimes { .. }
=> 0,
247 MissingTypesOrConsts { args_offset, .. }
| ExcessTypesOrConsts { args_offset, .. }
=> {
253 fn get_num_default_params(&self) -> usize {
254 match self.gen_args_info
{
255 MissingTypesOrConsts { num_default_params, .. }
256 | ExcessTypesOrConsts { num_default_params, .. }
=> num_default_params
,
261 fn is_synth_provided(&self) -> bool
{
262 match self.gen_args_info
{
263 ExcessTypesOrConsts { synth_provided, .. }
=> synth_provided
,
268 // Helper function to choose a quantifier word for the number of expected arguments
269 // and to give a bound for the number of expected arguments
270 fn get_quantifier_and_bound(&self) -> (&'
static str, usize) {
271 if self.get_num_default_params() == 0 {
272 match self.gen_args_info
{
273 MissingLifetimes { .. }
| ExcessLifetimes { .. }
=> {
274 ("", self.num_expected_lifetime_args())
276 MissingTypesOrConsts { .. }
| ExcessTypesOrConsts { .. }
=> {
277 ("", self.num_expected_type_or_const_args())
281 match self.gen_args_info
{
282 MissingLifetimes { .. }
=> ("at least ", self.num_expected_lifetime_args()),
283 MissingTypesOrConsts { .. }
=> {
284 ("at least ", self.num_expected_type_or_const_args_including_defaults())
286 ExcessLifetimes { .. }
=> ("at most ", self.num_expected_lifetime_args()),
287 ExcessTypesOrConsts { .. }
=> ("at most ", self.num_expected_type_or_const_args()),
292 // Creates lifetime name suggestions from the lifetime parameter names
293 fn get_lifetime_args_suggestions_from_param_names(
295 path_hir_id
: Option
<hir
::HirId
>,
296 num_params_to_take
: usize,
298 debug
!(?path_hir_id
);
300 if let Some(path_hir_id
) = path_hir_id
{
301 let mut ret
= Vec
::new();
302 for (id
, node
) in self.tcx
.hir().parent_iter(path_hir_id
) {
304 let params
= if let Some(generics
) = node
.generics() {
306 } else if let hir
::Node
::Ty(ty
) = node
307 && let hir
::TyKind
::BareFn(bare_fn
) = ty
.kind
309 bare_fn
.generic_params
313 ret
.extend(params
.iter().filter_map(|p
| {
314 let hir
::GenericParamKind
::Lifetime { kind: hir::LifetimeParamKind::Explicit }
316 else { return None }
;
317 let hir
::ParamName
::Plain(name
) = p
.name
else { return None }
;
318 Some(name
.to_string())
320 // Suggest `'static` when in const/static item-like.
321 if let hir
::Node
::Item(hir
::Item
{
322 kind
: hir
::ItemKind
::Static { .. }
| hir
::ItemKind
::Const { .. }
,
325 | hir
::Node
::TraitItem(hir
::TraitItem
{
326 kind
: hir
::TraitItemKind
::Const { .. }
,
329 | hir
::Node
::ImplItem(hir
::ImplItem
{
330 kind
: hir
::ImplItemKind
::Const { .. }
,
333 | hir
::Node
::ForeignItem(hir
::ForeignItem
{
334 kind
: hir
::ForeignItemKind
::Static { .. }
,
337 | hir
::Node
::AnonConst(..) = node
340 std
::iter
::repeat("'static".to_owned())
341 .take(num_params_to_take
.saturating_sub(ret
.len())),
344 if ret
.len() >= num_params_to_take
{
345 return ret
[..num_params_to_take
].join(", ");
347 // We cannot refer to lifetimes defined in an outer function.
348 if let hir
::Node
::Item(_
) = node
{
354 // We could not gather enough lifetime parameters in the scope.
355 // We use the parameter names from the target type's definition instead.
359 .skip(self.params_offset
+ self.num_provided_lifetime_args())
360 .take(num_params_to_take
)
361 .map(|param
| param
.name
.to_string())
366 // Creates type or constant name suggestions from the provided parameter names
367 fn get_type_or_const_args_suggestions_from_param_names(
369 num_params_to_take
: usize,
371 let fn_sig
= self.tcx
.hir().get_if_local(self.def_id
).and_then(fn_sig
);
372 let is_used_in_input
= |def_id
| {
373 fn_sig
.map_or(false, |fn_sig
| {
374 fn_sig
.decl
.inputs
.iter().any(|ty
| match ty
.kind
{
375 hir
::TyKind
::Path(hir
::QPath
::Resolved(
377 hir
::Path { res: hir::def::Res::Def(_, id), .. }
,
386 .skip(self.params_offset
+ self.num_provided_type_or_const_args())
387 .take(num_params_to_take
)
388 .map(|param
| match param
.kind
{
389 // This is being inferred from the item's inputs, no need to set it.
390 ty
::GenericParamDefKind
::Type { .. }
if is_used_in_input(param
.def_id
) => {
393 _
=> param
.name
.to_string(),
399 fn get_unbound_associated_types(&self) -> Vec
<String
> {
400 if self.tcx
.is_trait(self.def_id
) {
401 let items
: &AssocItems
<'_
> = self.tcx
.associated_items(self.def_id
);
403 .in_definition_order()
404 .filter(|item
| item
.kind
== AssocKind
::Type
)
406 !self.gen_args
.bindings
.iter().any(|binding
| binding
.ident
.name
== item
.name
)
408 .map(|item
| item
.name
.to_ident_string())
415 fn create_error_message(&self) -> String
{
416 let def_path
= self.tcx
.def_path_str(self.def_id
);
417 let def_kind
= self.tcx
.def_kind(self.def_id
).descr(self.def_id
);
418 let (quantifier
, bound
) = self.get_quantifier_and_bound();
419 let kind
= self.kind();
420 let provided_lt_args
= self.num_provided_lifetime_args();
421 let provided_type_or_const_args
= self.num_provided_type_or_const_args();
423 let get_verb
= |num_args
| if num_args
== 1 { "was" }
else { "were" }
;
425 let (provided_args_str
, verb
) = match self.gen_args_info
{
426 MissingLifetimes { .. }
| ExcessLifetimes { .. }
=> (
427 format
!("{} lifetime argument{}", provided_lt_args
, pluralize
!(provided_lt_args
)),
428 get_verb(provided_lt_args
),
430 MissingTypesOrConsts { .. }
| ExcessTypesOrConsts { .. }
=> (
432 "{} generic argument{}",
433 provided_type_or_const_args
,
434 pluralize
!(provided_type_or_const_args
)
436 get_verb(provided_type_or_const_args
),
440 if self.gen_args
.span_ext().is_some() {
442 "this {} takes {}{} {} argument{} but {} {} supplied",
448 provided_args_str
.as_str(),
452 format
!("missing generics for {} `{}`", def_kind
, def_path
)
456 fn start_diagnostics(&self) -> DiagnosticBuilder
<'tcx
, ErrorGuaranteed
> {
457 let span
= self.path_segment
.ident
.span
;
458 let msg
= self.create_error_message();
460 self.tcx
.sess
.struct_span_err_with_code(span
, &msg
, self.code())
463 /// Builds the `expected 1 type argument / supplied 2 type arguments` message.
464 fn notify(&self, err
: &mut Diagnostic
) {
465 let (quantifier
, bound
) = self.get_quantifier_and_bound();
466 let provided_args
= self.num_provided_args();
469 self.path_segment
.ident
.span
,
471 "expected {}{} {} argument{}",
479 // When too many arguments were provided, we don't highlight each of them, because it
480 // would overlap with the suggestion to remove them:
483 // type Foo = Bar<usize, usize>;
484 // ----- ----- supplied 2 type arguments
485 // ^^^^^^^ remove this type argument
487 if self.too_many_args_provided() {
495 .skip(self.get_lifetime_args_offset())
499 for (i
, arg
) in args
{
502 if i
+ 1 == provided_args
{
504 "supplied {} {} argument{}",
507 pluralize
!(provided_args
)
516 fn suggest(&self, err
: &mut Diagnostic
) {
518 "suggest(self.provided {:?}, self.gen_args.span(): {:?})",
519 self.num_provided_args(),
520 self.gen_args
.span(),
523 match self.angle_brackets
{
524 AngleBrackets
::Missing
| AngleBrackets
::Implied
=> self.suggest_adding_args(err
),
525 AngleBrackets
::Available
=> {
526 if self.not_enough_args_provided() {
527 self.suggest_adding_args(err
);
528 } else if self.too_many_args_provided() {
529 self.suggest_removing_args_or_generics(err
);
537 /// Suggests to add missing argument(s) when current invocation site already contains some
541 /// type Map = HashMap<String>;
543 fn suggest_adding_args(&self, err
: &mut Diagnostic
) {
544 if self.gen_args
.parenthesized
{
548 match self.gen_args_info
{
549 MissingLifetimes { .. }
=> {
550 self.suggest_adding_lifetime_args(err
);
552 MissingTypesOrConsts { .. }
=> {
553 self.suggest_adding_type_and_const_args(err
);
559 fn suggest_adding_lifetime_args(&self, err
: &mut Diagnostic
) {
560 debug
!("suggest_adding_lifetime_args(path_segment: {:?})", self.path_segment
);
561 let num_missing_args
= self.num_missing_lifetime_args();
562 let num_params_to_take
= num_missing_args
;
563 let msg
= format
!("add missing {} argument{}", self.kind(), pluralize
!(num_missing_args
));
565 let suggested_args
= self.get_lifetime_args_suggestions_from_param_names(
566 self.path_segment
.hir_id
,
569 debug
!("suggested_args: {:?}", &suggested_args
);
571 match self.angle_brackets
{
572 AngleBrackets
::Missing
=> {
573 let span
= self.path_segment
.ident
.span
;
575 // insert a suggestion of the form "Y<'a, 'b>"
576 let ident
= self.path_segment
.ident
.name
.to_ident_string();
577 let sugg
= format
!("{}<{}>", ident
, suggested_args
);
578 debug
!("sugg: {:?}", sugg
);
580 err
.span_suggestion_verbose(span
, &msg
, sugg
, Applicability
::HasPlaceholders
);
583 AngleBrackets
::Available
=> {
584 let (sugg_span
, is_first
) = if self.num_provided_lifetime_args() == 0 {
585 (self.gen_args
.span().unwrap().shrink_to_lo(), true)
587 let last_lt
= &self.gen_args
.args
[self.num_provided_lifetime_args() - 1];
588 (last_lt
.span().shrink_to_hi(), false)
590 let has_non_lt_args
= self.num_provided_type_or_const_args() != 0;
591 let has_bindings
= !self.gen_args
.bindings
.is_empty();
593 let sugg_prefix
= if is_first { "" }
else { ", " }
;
595 if is_first
&& (has_non_lt_args
|| has_bindings
) { ", " }
else { "" }
;
597 let sugg
= format
!("{}{}{}", sugg_prefix
, suggested_args
, sugg_suffix
);
598 debug
!("sugg: {:?}", sugg
);
600 err
.span_suggestion_verbose(sugg_span
, &msg
, sugg
, Applicability
::HasPlaceholders
);
602 AngleBrackets
::Implied
=> {
603 // We never encounter missing lifetimes in situations in which lifetimes are elided
609 fn suggest_adding_type_and_const_args(&self, err
: &mut Diagnostic
) {
610 let num_missing_args
= self.num_missing_type_or_const_args();
611 let msg
= format
!("add missing {} argument{}", self.kind(), pluralize
!(num_missing_args
));
614 self.get_type_or_const_args_suggestions_from_param_names(num_missing_args
);
615 debug
!("suggested_args: {:?}", suggested_args
);
617 match self.angle_brackets
{
618 AngleBrackets
::Missing
| AngleBrackets
::Implied
=> {
619 let span
= self.path_segment
.ident
.span
;
621 // insert a suggestion of the form "Y<T, U>"
622 let ident
= self.path_segment
.ident
.name
.to_ident_string();
623 let sugg
= format
!("{}<{}>", ident
, suggested_args
);
624 debug
!("sugg: {:?}", sugg
);
626 err
.span_suggestion_verbose(span
, &msg
, sugg
, Applicability
::HasPlaceholders
);
628 AngleBrackets
::Available
=> {
629 let gen_args_span
= self.gen_args
.span().unwrap();
631 self.get_lifetime_args_offset() + self.num_provided_type_or_const_args();
633 let (sugg_span
, is_first
) = if sugg_offset
== 0 {
634 (gen_args_span
.shrink_to_lo(), true)
636 let arg_span
= self.gen_args
.args
[sugg_offset
- 1].span();
637 // If we came here then inferred lifetime's spans can only point
638 // to either the opening bracket or to the space right after.
639 // Both of these spans have an `hi` lower than or equal to the span
640 // of the generics excluding the brackets.
641 // This allows us to check if `arg_span` is the artificial span of
642 // an inferred lifetime, in which case the generic we're suggesting to
643 // add will be the first visible, even if it isn't the actual first generic.
644 (arg_span
.shrink_to_hi(), arg_span
.hi() <= gen_args_span
.lo())
647 let sugg_prefix
= if is_first { "" }
else { ", " }
;
649 if is_first
&& !self.gen_args
.bindings
.is_empty() { ", " }
else { "" }
;
651 let sugg
= format
!("{}{}{}", sugg_prefix
, suggested_args
, sugg_suffix
);
652 debug
!("sugg: {:?}", sugg
);
654 err
.span_suggestion_verbose(sugg_span
, &msg
, sugg
, Applicability
::HasPlaceholders
);
659 /// Suggests to remove redundant argument(s):
662 /// type Map = HashMap<String, String, String, String>;
664 fn suggest_removing_args_or_generics(&self, err
: &mut Diagnostic
) {
665 let num_provided_lt_args
= self.num_provided_lifetime_args();
666 let num_provided_type_const_args
= self.num_provided_type_or_const_args();
667 let unbound_types
= self.get_unbound_associated_types();
668 let num_provided_args
= num_provided_lt_args
+ num_provided_type_const_args
;
669 assert
!(num_provided_args
> 0);
671 let num_redundant_lt_args
= self.num_excess_lifetime_args();
672 let num_redundant_type_or_const_args
= self.num_excess_type_or_const_args();
673 let num_redundant_args
= num_redundant_lt_args
+ num_redundant_type_or_const_args
;
675 let redundant_lifetime_args
= num_redundant_lt_args
> 0;
676 let redundant_type_or_const_args
= num_redundant_type_or_const_args
> 0;
678 let remove_entire_generics
= num_redundant_args
>= self.gen_args
.args
.len();
679 let provided_args_matches_unbound_traits
=
680 unbound_types
.len() == num_redundant_type_or_const_args
;
682 let remove_lifetime_args
= |err
: &mut Diagnostic
| {
683 let mut lt_arg_spans
= Vec
::new();
684 let mut found_redundant
= false;
685 for arg
in self.gen_args
.args
{
686 if let hir
::GenericArg
::Lifetime(_
) = arg
{
687 lt_arg_spans
.push(arg
.span());
688 if lt_arg_spans
.len() > self.num_expected_lifetime_args() {
689 found_redundant
= true;
691 } else if found_redundant
{
692 // Argument which is redundant and separated like this `'c`
693 // is not included to avoid including `Bar` in span.
695 // type Foo<'a, T> = &'a T;
696 // let _: Foo<'a, 'b, Bar, 'c>;
702 let span_lo_redundant_lt_args
= lt_arg_spans
[self.num_expected_lifetime_args()];
703 let span_hi_redundant_lt_args
= lt_arg_spans
[lt_arg_spans
.len() - 1];
705 let span_redundant_lt_args
= span_lo_redundant_lt_args
.to(span_hi_redundant_lt_args
);
706 debug
!("span_redundant_lt_args: {:?}", span_redundant_lt_args
);
708 let num_redundant_lt_args
= lt_arg_spans
.len() - self.num_expected_lifetime_args();
709 let msg_lifetimes
= format
!(
710 "remove {these} lifetime argument{s}",
711 these
= pluralize
!("this", num_redundant_lt_args
),
712 s
= pluralize
!(num_redundant_lt_args
),
716 span_redundant_lt_args
,
719 Applicability
::MaybeIncorrect
,
723 let remove_type_or_const_args
= |err
: &mut Diagnostic
| {
724 let mut gen_arg_spans
= Vec
::new();
725 let mut found_redundant
= false;
726 for arg
in self.gen_args
.args
{
728 hir
::GenericArg
::Type(_
)
729 | hir
::GenericArg
::Const(_
)
730 | hir
::GenericArg
::Infer(_
) => {
731 gen_arg_spans
.push(arg
.span());
732 if gen_arg_spans
.len() > self.num_expected_type_or_const_args() {
733 found_redundant
= true;
736 _
if found_redundant
=> break,
741 let span_lo_redundant_type_or_const_args
=
742 gen_arg_spans
[self.num_expected_type_or_const_args()];
743 let span_hi_redundant_type_or_const_args
= gen_arg_spans
[gen_arg_spans
.len() - 1];
745 let span_redundant_type_or_const_args
=
746 span_lo_redundant_type_or_const_args
.to(span_hi_redundant_type_or_const_args
);
747 debug
!("span_redundant_type_or_const_args: {:?}", span_redundant_type_or_const_args
);
749 let num_redundant_gen_args
=
750 gen_arg_spans
.len() - self.num_expected_type_or_const_args();
751 let msg_types_or_consts
= format
!(
752 "remove {these} generic argument{s}",
753 these
= pluralize
!("this", num_redundant_gen_args
),
754 s
= pluralize
!(num_redundant_gen_args
),
758 span_redundant_type_or_const_args
,
759 &msg_types_or_consts
,
761 Applicability
::MaybeIncorrect
,
765 // If there is a single unbound associated type and a single excess generic param
766 // suggest replacing the generic param with the associated type bound
767 if provided_args_matches_unbound_traits
&& !unbound_types
.is_empty() {
768 let mut suggestions
= vec
![];
769 let unused_generics
= &self.gen_args
.args
[self.num_expected_type_or_const_args()..];
770 for (potential
, name
) in iter
::zip(unused_generics
, &unbound_types
) {
771 if let Ok(snippet
) = self.tcx
.sess
.source_map().span_to_snippet(potential
.span()) {
772 suggestions
.push((potential
.span(), format
!("{} = {}", name
, snippet
)));
776 if !suggestions
.is_empty() {
777 err
.multipart_suggestion(
779 "replace the generic bound{s} with the associated type{s}",
780 s
= pluralize
!(unbound_types
.len())
783 Applicability
::MaybeIncorrect
,
786 } else if remove_entire_generics
{
793 .with_lo(self.path_segment
.ident
.span
.hi());
796 "remove these {}generics",
797 if self.gen_args
.parenthesized { "parenthetical " }
else { "" }
,
800 err
.span_suggestion(span
, &msg
, "", Applicability
::MaybeIncorrect
);
801 } else if redundant_lifetime_args
&& redundant_type_or_const_args
{
802 remove_lifetime_args(err
);
803 remove_type_or_const_args(err
);
804 } else if redundant_lifetime_args
{
805 remove_lifetime_args(err
);
807 assert
!(redundant_type_or_const_args
);
808 remove_type_or_const_args(err
);
812 /// Builds the `type defined here` message.
813 fn show_definition(&self, err
: &mut Diagnostic
) {
814 let mut spans
: MultiSpan
= if let Some(def_span
) = self.tcx
.def_ident_span(self.def_id
) {
815 if self.tcx
.sess
.source_map().span_to_snippet(def_span
).is_ok() {
825 let def_kind
= self.tcx
.def_kind(self.def_id
).descr(self.def_id
);
826 let (quantifier
, bound
) = self.get_quantifier_and_bound();
828 let params
= if bound
== 0 {
835 .skip(self.params_offset
)
838 let span
= self.tcx
.def_span(param
.def_id
);
839 spans
.push_span_label(span
, String
::new());
842 .map(|param
| format
!("`{}`", param
.name
))
846 format
!(": {}", params
)
850 "{} defined here, with {}{} {} parameter{}{}",
860 err
.span_note(spans
, &msg
);
863 /// Add note if `impl Trait` is explicitly specified.
864 fn note_synth_provided(&self, err
: &mut Diagnostic
) {
865 if !self.is_synth_provided() {
869 err
.note("`impl Trait` cannot be explicitly specified as a generic argument");
873 impl<'tcx
> StructuredDiagnostic
<'tcx
> for WrongNumberOfGenericArgs
<'_
, 'tcx
> {
874 fn session(&self) -> &Session
{
878 fn code(&self) -> DiagnosticId
{
879 rustc_errors
::error_code
!(E0107
)
882 fn diagnostic_common(&self) -> DiagnosticBuilder
<'tcx
, ErrorGuaranteed
> {
883 let mut err
= self.start_diagnostics();
885 self.notify(&mut err
);
886 self.suggest(&mut err
);
887 self.show_definition(&mut err
);
888 self.note_synth_provided(&mut err
);