1 use super::IsMethodCall
;
3 errors
::prohibit_assoc_ty_binding
, CreateSubstsForGenericArgsCtxt
, ExplicitLateBound
,
4 GenericArgCountMismatch
, GenericArgCountResult
, GenericArgPosition
,
6 use crate::structured_errors
::{GenericArgsInfo, StructuredDiagnostic, WrongNumberOfGenericArgs}
;
7 use rustc_ast
::ast
::ParamKindOrd
;
8 use rustc_errors
::{struct_span_err, Applicability, Diagnostic, ErrorGuaranteed, MultiSpan}
;
10 use rustc_hir
::def
::{DefKind, Res}
;
11 use rustc_hir
::def_id
::DefId
;
12 use rustc_hir
::GenericArg
;
13 use rustc_middle
::ty
::{
14 self, subst
, subst
::SubstsRef
, GenericParamDef
, GenericParamDefKind
, IsSuggestable
, Ty
, TyCtxt
,
16 use rustc_session
::lint
::builtin
::LATE_BOUND_LIFETIME_ARGUMENTS
;
17 use rustc_span
::{symbol::kw, Span}
;
18 use smallvec
::SmallVec
;
20 /// Report an error that a generic argument did not match the generic parameter that was
22 fn generic_arg_mismatch_err(
25 param
: &GenericParamDef
,
26 possible_ordering_error
: bool
,
28 ) -> ErrorGuaranteed
{
30 let mut err
= struct_span_err
!(
34 "{} provided when a {} was expected",
39 if let GenericParamDefKind
::Const { .. }
= param
.kind
{
40 if matches
!(arg
, GenericArg
::Type(hir
::Ty { kind: hir::TyKind::Infer, .. }
)) {
41 err
.help("const arguments cannot yet be inferred with `_`");
42 if sess
.is_nightly_build() {
43 err
.help("add `#![feature(generic_arg_infer)]` to the crate attributes to enable");
48 let add_braces_suggestion
= |arg
: &GenericArg
<'_
>, err
: &mut Diagnostic
| {
49 let suggestions
= vec
![
50 (arg
.span().shrink_to_lo(), String
::from("{ ")),
51 (arg
.span().shrink_to_hi(), String
::from(" }")),
53 err
.multipart_suggestion(
54 "if this generic argument was intended as a const parameter, \
55 surround it with braces",
57 Applicability
::MaybeIncorrect
,
61 // Specific suggestion set for diagnostics
62 match (arg
, ¶m
.kind
) {
64 GenericArg
::Type(hir
::Ty
{
65 kind
: hir
::TyKind
::Path(rustc_hir
::QPath
::Resolved(_
, path
)),
68 GenericParamDefKind
::Const { .. }
,
71 add_braces_suggestion(arg
, &mut err
);
73 .set_primary_message("unresolved item provided when a constant was expected")
76 Res
::Def(DefKind
::TyParam
, src_def_id
) => {
77 if let Some(param_local_id
) = param
.def_id
.as_local() {
78 let param_name
= tcx
.hir().ty_param_name(param_local_id
);
79 let param_type
= tcx
.type_of(param
.def_id
).subst_identity();
80 if param_type
.is_suggestable(tcx
, false) {
82 tcx
.def_span(src_def_id
),
83 "consider changing this type parameter to a const parameter",
84 format
!("const {}: {}", param_name
, param_type
),
85 Applicability
::MaybeIncorrect
,
90 _
=> add_braces_suggestion(arg
, &mut err
),
93 GenericArg
::Type(hir
::Ty { kind: hir::TyKind::Path(_), .. }
),
94 GenericParamDefKind
::Const { .. }
,
95 ) => add_braces_suggestion(arg
, &mut err
),
97 GenericArg
::Type(hir
::Ty { kind: hir::TyKind::Array(_, len), .. }
),
98 GenericParamDefKind
::Const { .. }
,
99 ) if tcx
.type_of(param
.def_id
).skip_binder() == tcx
.types
.usize => {
100 let snippet
= sess
.source_map().span_to_snippet(tcx
.hir().span(len
.hir_id()));
101 if let Ok(snippet
) = snippet
{
104 "array type provided where a `usize` was expected, try",
105 format
!("{{ {} }}", snippet
),
106 Applicability
::MaybeIncorrect
,
110 (GenericArg
::Const(cnst
), GenericParamDefKind
::Type { .. }
) => {
111 let body
= tcx
.hir().body(cnst
.value
.body
);
112 if let rustc_hir
::ExprKind
::Path(rustc_hir
::QPath
::Resolved(_
, path
)) = body
.value
.kind
114 if let Res
::Def(DefKind
::Fn { .. }
, id
) = path
.res
{
115 err
.help(&format
!("`{}` is a function item, not a type", tcx
.item_name(id
)));
116 err
.help("function item types cannot be named directly");
123 let kind_ord
= param
.kind
.to_ord();
124 let arg_ord
= arg
.to_ord();
126 // This note is only true when generic parameters are strictly ordered by their kind.
127 if possible_ordering_error
&& kind_ord
.cmp(&arg_ord
) != core
::cmp
::Ordering
::Equal
{
128 let (first
, last
) = if kind_ord
< arg_ord
{
129 (param
.kind
.descr(), arg
.descr())
131 (arg
.descr(), param
.kind
.descr())
133 err
.note(&format
!("{} arguments must be provided before {} arguments", first
, last
));
134 if let Some(help
) = help
{
142 /// Creates the relevant generic argument substitutions
143 /// corresponding to a set of generic parameters. This is a
144 /// rather complex function. Let us try to explain the role
145 /// of each of its parameters:
147 /// To start, we are given the `def_id` of the thing we are
148 /// creating the substitutions for, and a partial set of
149 /// substitutions `parent_substs`. In general, the substitutions
150 /// for an item begin with substitutions for all the "parents" of
151 /// that item -- e.g., for a method it might include the
152 /// parameters from the impl.
154 /// Therefore, the method begins by walking down these parents,
155 /// starting with the outermost parent and proceed inwards until
156 /// it reaches `def_id`. For each parent `P`, it will check `parent_substs`
157 /// first to see if the parent's substitutions are listed in there. If so,
158 /// we can append those and move on. Otherwise, it invokes the
159 /// three callback functions:
161 /// - `args_for_def_id`: given the `DefId` `P`, supplies back the
162 /// generic arguments that were given to that parent from within
163 /// the path; so e.g., if you have `<T as Foo>::Bar`, the `DefId`
164 /// might refer to the trait `Foo`, and the arguments might be
165 /// `[T]`. The boolean value indicates whether to infer values
166 /// for arguments whose values were not explicitly provided.
167 /// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`,
168 /// instantiate a `GenericArg`.
169 /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
170 /// creates a suitable inference variable.
171 pub fn create_substs_for_generic_args
<'tcx
, 'a
>(
174 parent_substs
: &[subst
::GenericArg
<'tcx
>],
176 self_ty
: Option
<Ty
<'tcx
>>,
177 arg_count
: &GenericArgCountResult
,
178 ctx
: &mut impl CreateSubstsForGenericArgsCtxt
<'a
, 'tcx
>,
179 ) -> SubstsRef
<'tcx
> {
180 // Collect the segments of the path; we need to substitute arguments
181 // for parameters throughout the entire path (wherever there are
182 // generic parameters).
183 let mut parent_defs
= tcx
.generics_of(def_id
);
184 let count
= parent_defs
.count();
185 let mut stack
= vec
![(def_id
, parent_defs
)];
186 while let Some(def_id
) = parent_defs
.parent
{
187 parent_defs
= tcx
.generics_of(def_id
);
188 stack
.push((def_id
, parent_defs
));
191 // We manually build up the substitution, rather than using convenience
192 // methods in `subst.rs`, so that we can iterate over the arguments and
193 // parameters in lock-step linearly, instead of trying to match each pair.
194 let mut substs
: SmallVec
<[subst
::GenericArg
<'tcx
>; 8]> = SmallVec
::with_capacity(count
);
195 // Iterate over each segment of the path.
196 while let Some((def_id
, defs
)) = stack
.pop() {
197 let mut params
= defs
.params
.iter().peekable();
199 // If we have already computed substitutions for parents, we can use those directly.
200 while let Some(¶m
) = params
.peek() {
201 if let Some(&kind
) = parent_substs
.get(param
.index
as usize) {
209 // `Self` is handled first, unless it's been handled in `parent_substs`.
211 if let Some(¶m
) = params
.peek() {
212 if param
.index
== 0 {
213 if let GenericParamDefKind
::Type { .. }
= param
.kind
{
217 .unwrap_or_else(|| ctx
.inferred_kind(None
, param
, true)),
225 // Check whether this segment takes generic arguments and the user has provided any.
226 let (generic_args
, infer_args
) = ctx
.args_for_def_id(def_id
);
228 let args_iter
= generic_args
.iter().flat_map(|generic_args
| generic_args
.args
.iter());
229 let mut args
= args_iter
.clone().peekable();
231 // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
232 // If we later encounter a lifetime, we know that the arguments were provided in the
233 // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
234 // inferred, so we can use it for diagnostics later.
235 let mut force_infer_lt
= None
;
238 // We're going to iterate through the generic arguments that the user
239 // provided, matching them with the generic parameters we expect.
240 // Mismatches can occur as a result of elided lifetimes, or for malformed
241 // input. We try to handle both sensibly.
242 match (args
.peek(), params
.peek()) {
243 (Some(&arg
), Some(¶m
)) => {
244 match (arg
, ¶m
.kind
, arg_count
.explicit_late_bound
) {
245 (GenericArg
::Lifetime(_
), GenericParamDefKind
::Lifetime
, _
)
247 GenericArg
::Type(_
) | GenericArg
::Infer(_
),
248 GenericParamDefKind
::Type { .. }
,
252 GenericArg
::Const(_
) | GenericArg
::Infer(_
),
253 GenericParamDefKind
::Const { .. }
,
256 substs
.push(ctx
.provided_kind(param
, arg
));
261 GenericArg
::Infer(_
) | GenericArg
::Type(_
) | GenericArg
::Const(_
),
262 GenericParamDefKind
::Lifetime
,
265 // We expected a lifetime argument, but got a type or const
266 // argument. That means we're inferring the lifetimes.
267 substs
.push(ctx
.inferred_kind(None
, param
, infer_args
));
268 force_infer_lt
= Some((arg
, param
));
271 (GenericArg
::Lifetime(_
), _
, ExplicitLateBound
::Yes
) => {
272 // We've come across a lifetime when we expected something else in
273 // the presence of explicit late bounds. This is most likely
274 // due to the presence of the explicit bound so we're just going to
279 // We expected one kind of parameter, but the user provided
280 // another. This is an error. However, if we already know that
281 // the arguments don't match up with the parameters, we won't issue
282 // an additional error, as the user already knows what's wrong.
283 if arg_count
.correct
.is_ok() {
284 // We're going to iterate over the parameters to sort them out, and
285 // show that order to the user as a possible order for the parameters
286 let mut param_types_present
= defs
289 .map(|param
| (param
.kind
.to_ord(), param
.clone()))
290 .collect
::<Vec
<(ParamKindOrd
, GenericParamDef
)>>();
291 param_types_present
.sort_by_key(|(ord
, _
)| *ord
);
292 let (mut param_types_present
, ordered_params
): (
294 Vec
<GenericParamDef
>,
295 ) = param_types_present
.into_iter().unzip();
296 param_types_present
.dedup();
298 generic_arg_mismatch_err(
302 !args_iter
.clone().is_sorted_by_key(|arg
| arg
.to_ord()),
304 "reorder the arguments: {}: `<{}>`",
307 .map(|ord
| format
!("{}s", ord
))
308 .collect
::<Vec
<String
>>()
312 .filter_map(|param
| {
313 if param
.name
== kw
::SelfUpper
{
316 Some(param
.name
.to_string())
319 .collect
::<Vec
<String
>>()
325 // We've reported the error, but we want to make sure that this
326 // problem doesn't bubble down and create additional, irrelevant
327 // errors. In this case, we're simply going to ignore the argument
328 // and any following arguments. The rest of the parameters will be
330 while args
.next().is_some() {}
335 (Some(&arg
), None
) => {
336 // We should never be able to reach this point with well-formed input.
337 // There are three situations in which we can encounter this issue.
339 // 1. The number of arguments is incorrect. In this case, an error
340 // will already have been emitted, and we can ignore it.
341 // 2. There are late-bound lifetime parameters present, yet the
342 // lifetime arguments have also been explicitly specified by the
344 // 3. We've inferred some lifetimes, which have been provided later (i.e.
345 // after a type or const). We want to throw an error in this case.
347 if arg_count
.correct
.is_ok()
348 && arg_count
.explicit_late_bound
== ExplicitLateBound
::No
350 let kind
= arg
.descr();
351 assert_eq
!(kind
, "lifetime");
352 let (provided_arg
, param
) =
353 force_infer_lt
.expect("lifetimes ought to have been inferred");
354 generic_arg_mismatch_err(tcx
, provided_arg
, param
, false, None
);
360 (None
, Some(¶m
)) => {
361 // If there are fewer arguments than parameters, it means
362 // we're inferring the remaining arguments.
363 substs
.push(ctx
.inferred_kind(Some(&substs
), param
, infer_args
));
367 (None
, None
) => break,
372 tcx
.mk_substs(&substs
)
375 /// Checks that the correct number of generic arguments have been provided.
376 /// Used specifically for function calls.
377 pub fn check_generic_arg_count_for_call(
381 generics
: &ty
::Generics
,
382 seg
: &hir
::PathSegment
<'_
>,
383 is_method_call
: IsMethodCall
,
384 ) -> GenericArgCountResult
{
385 let empty_args
= hir
::GenericArgs
::none();
386 let gen_args
= seg
.args
.unwrap_or(&empty_args
);
387 let gen_pos
= match is_method_call
{
388 IsMethodCall
::Yes
=> GenericArgPosition
::MethodCall
,
389 IsMethodCall
::No
=> GenericArgPosition
::Value
,
391 let has_self
= generics
.parent
.is_none() && generics
.has_self
;
393 check_generic_arg_count(
406 /// Checks that the correct number of generic arguments have been provided.
407 /// This is used both for datatypes and function calls.
408 #[instrument(skip(tcx, gen_pos), level = "debug")]
409 pub(crate) fn check_generic_arg_count(
413 seg
: &hir
::PathSegment
<'_
>,
414 gen_params
: &ty
::Generics
,
415 gen_args
: &hir
::GenericArgs
<'_
>,
416 gen_pos
: GenericArgPosition
,
419 ) -> GenericArgCountResult
{
420 let default_counts
= gen_params
.own_defaults();
421 let param_counts
= gen_params
.own_counts();
423 // Subtracting from param count to ensure type params synthesized from `impl Trait`
424 // cannot be explicitly specified.
425 let synth_type_param_count
= gen_params
428 .filter(|param
| matches
!(param
.kind
, ty
::GenericParamDefKind
::Type { synthetic: true, .. }
))
430 let named_type_param_count
= param_counts
.types
- has_self
as usize - synth_type_param_count
;
431 let infer_lifetimes
=
432 (gen_pos
!= GenericArgPosition
::Type
|| infer_args
) && !gen_args
.has_lifetime_params();
434 if gen_pos
!= GenericArgPosition
::Type
&& let Some(b
) = gen_args
.bindings
.first() {
435 prohibit_assoc_ty_binding(tcx
, b
.span
, None
);
438 let explicit_late_bound
=
439 prohibit_explicit_late_bound_lifetimes(tcx
, gen_params
, gen_args
, gen_pos
);
441 let mut invalid_args
= vec
![];
443 let mut check_lifetime_args
= |min_expected_args
: usize,
444 max_expected_args
: usize,
445 provided_args
: usize,
446 late_bounds_ignore
: bool
| {
447 if (min_expected_args
..=max_expected_args
).contains(&provided_args
) {
451 if late_bounds_ignore
{
455 if provided_args
> max_expected_args
{
457 gen_args
.args
[max_expected_args
..provided_args
].iter().map(|arg
| arg
.span()),
461 let gen_args_info
= if provided_args
> min_expected_args
{
463 gen_args
.args
[min_expected_args
..provided_args
].iter().map(|arg
| arg
.span()),
465 let num_redundant_args
= provided_args
- min_expected_args
;
466 GenericArgsInfo
::ExcessLifetimes { num_redundant_args }
468 let num_missing_args
= min_expected_args
- provided_args
;
469 GenericArgsInfo
::MissingLifetimes { num_missing_args }
472 let reported
= WrongNumberOfGenericArgs
::new(
487 let min_expected_lifetime_args
= if infer_lifetimes { 0 }
else { param_counts.lifetimes }
;
488 let max_expected_lifetime_args
= param_counts
.lifetimes
;
489 let num_provided_lifetime_args
= gen_args
.num_lifetime_params();
491 let lifetimes_correct
= check_lifetime_args(
492 min_expected_lifetime_args
,
493 max_expected_lifetime_args
,
494 num_provided_lifetime_args
,
495 explicit_late_bound
== ExplicitLateBound
::Yes
,
498 let mut check_types_and_consts
= |expected_min
,
500 expected_max_with_synth
,
510 "check_types_and_consts"
512 if (expected_min
..=expected_max
).contains(&provided
) {
516 let num_default_params
= expected_max
- expected_min
;
518 let gen_args_info
= if provided
> expected_max
{
520 gen_args
.args
[args_offset
+ expected_max
..args_offset
+ provided
]
522 .map(|arg
| arg
.span()),
524 let num_redundant_args
= provided
- expected_max
;
526 // Provide extra note if synthetic arguments like `impl Trait` are specified.
527 let synth_provided
= provided
<= expected_max_with_synth
;
529 GenericArgsInfo
::ExcessTypesOrConsts
{
536 let num_missing_args
= expected_max
- provided
;
538 GenericArgsInfo
::MissingTypesOrConsts
{
545 debug
!(?gen_args_info
);
547 let reported
= WrongNumberOfGenericArgs
::new(
557 .emit_unless(gen_args
.has_err());
563 let expected_min
= if infer_args
{
566 param_counts
.consts
+ named_type_param_count
567 - default_counts
.types
568 - default_counts
.consts
570 debug
!(?expected_min
);
571 debug
!(arg_counts
.lifetimes
=?gen_args
.num_lifetime_params());
573 check_types_and_consts(
575 param_counts
.consts
+ named_type_param_count
,
576 param_counts
.consts
+ named_type_param_count
+ synth_type_param_count
,
577 gen_args
.num_generic_params(),
578 param_counts
.lifetimes
+ has_self
as usize,
579 gen_args
.num_lifetime_params(),
583 GenericArgCountResult
{
585 correct
: lifetimes_correct
587 .map_err(|reported
| GenericArgCountMismatch { reported: Some(reported), invalid_args }
),
591 /// Prohibits explicit lifetime arguments if late-bound lifetime parameters
592 /// are present. This is used both for datatypes and function calls.
593 pub(crate) fn prohibit_explicit_late_bound_lifetimes(
596 args
: &hir
::GenericArgs
<'_
>,
597 position
: GenericArgPosition
,
598 ) -> ExplicitLateBound
{
599 let param_counts
= def
.own_counts();
600 let infer_lifetimes
= position
!= GenericArgPosition
::Type
&& !args
.has_lifetime_params();
603 return ExplicitLateBound
::No
;
606 if let Some(span_late
) = def
.has_late_bound_regions
{
607 let msg
= "cannot specify lifetime arguments explicitly \
608 if late bound lifetime parameters are present";
609 let note
= "the late bound lifetime parameter is introduced here";
610 let span
= args
.args
[0].span();
612 if position
== GenericArgPosition
::Value
613 && args
.num_lifetime_params() != param_counts
.lifetimes
615 let mut err
= struct_span_err
!(tcx
.sess
, span
, E0794
, "{}", msg
);
616 err
.span_note(span_late
, note
);
619 let mut multispan
= MultiSpan
::from_span(span
);
620 multispan
.push_span_label(span_late
, note
);
621 tcx
.struct_span_lint_hir(
622 LATE_BOUND_LIFETIME_ARGUMENTS
,
623 args
.args
[0].hir_id(),
630 ExplicitLateBound
::Yes
632 ExplicitLateBound
::No