1 use super::IsMethodCall
;
3 AstConv
, CreateSubstsForGenericArgsCtxt
, ExplicitLateBound
, GenericArgCountMismatch
,
4 GenericArgCountResult
, GenericArgPosition
,
6 use crate::errors
::AssocTypeBindingNotAllowed
;
7 use crate::structured_errors
::{StructuredDiagnostic, WrongNumberOfGenericArgs}
;
8 use rustc_ast
::ast
::ParamKindOrd
;
9 use rustc_errors
::{struct_span_err, Applicability, DiagnosticBuilder, ErrorReported}
;
11 use rustc_hir
::def
::{DefKind, Res}
;
12 use rustc_hir
::def_id
::DefId
;
13 use rustc_hir
::GenericArg
;
14 use rustc_middle
::ty
::{
15 self, subst
, subst
::SubstsRef
, GenericParamDef
, GenericParamDefKind
, Ty
, TyCtxt
,
17 use rustc_session
::lint
::builtin
::LATE_BOUND_LIFETIME_ARGUMENTS
;
18 use rustc_span
::{symbol::kw, MultiSpan, Span}
;
19 use smallvec
::SmallVec
;
21 impl<'o
, 'tcx
> dyn AstConv
<'tcx
> + 'o
{
22 /// Report an error that a generic argument did not match the generic parameter that was
24 fn generic_arg_mismatch_err(
27 param
: &GenericParamDef
,
28 possible_ordering_error
: bool
,
32 let mut err
= struct_span_err
!(
36 "{} provided when a {} was expected",
41 if let GenericParamDefKind
::Const { .. }
= param
.kind
{
42 if let GenericArg
::Type(hir
::Ty { kind: hir::TyKind::Infer, .. }
) = arg
{
43 err
.help("const arguments cannot yet be inferred with `_`");
47 let add_braces_suggestion
= |arg
: &GenericArg
<'_
>, err
: &mut DiagnosticBuilder
<'_
>| {
48 let suggestions
= vec
![
49 (arg
.span().shrink_to_lo(), String
::from("{ ")),
50 (arg
.span().shrink_to_hi(), String
::from(" }")),
52 err
.multipart_suggestion(
53 "if this generic argument was intended as a const parameter, \
54 surround it with braces",
56 Applicability
::MaybeIncorrect
,
60 // Specific suggestion set for diagnostics
61 match (arg
, ¶m
.kind
) {
63 GenericArg
::Type(hir
::Ty
{
64 kind
: hir
::TyKind
::Path(rustc_hir
::QPath
::Resolved(_
, path
)),
67 GenericParamDefKind
::Const { .. }
,
70 add_braces_suggestion(arg
, &mut err
);
71 err
.set_primary_message(
72 "unresolved item provided when a constant was expected",
77 Res
::Def(DefKind
::TyParam
, src_def_id
) => {
78 if let Some(param_local_id
) = param
.def_id
.as_local() {
79 let param_hir_id
= tcx
.hir().local_def_id_to_hir_id(param_local_id
);
80 let param_name
= tcx
.hir().ty_param_name(param_hir_id
);
81 let param_type
= tcx
.type_of(param
.def_id
);
82 if param_type
.is_suggestable() {
84 tcx
.def_span(src_def_id
),
85 "consider changing this type parameter to be a `const` generic",
86 format
!("const {}: {}", param_name
, param_type
),
87 Applicability
::MaybeIncorrect
,
92 _
=> add_braces_suggestion(arg
, &mut err
),
95 GenericArg
::Type(hir
::Ty { kind: hir::TyKind::Path(_), .. }
),
96 GenericParamDefKind
::Const { .. }
,
97 ) => add_braces_suggestion(arg
, &mut err
),
99 GenericArg
::Type(hir
::Ty { kind: hir::TyKind::Array(_, len), .. }
),
100 GenericParamDefKind
::Const { .. }
,
101 ) if tcx
.type_of(param
.def_id
) == tcx
.types
.usize => {
102 let snippet
= sess
.source_map().span_to_snippet(tcx
.hir().span(len
.hir_id
));
103 if let Ok(snippet
) = snippet
{
106 "array type provided where a `usize` was expected, try",
107 format
!("{{ {} }}", snippet
),
108 Applicability
::MaybeIncorrect
,
112 (GenericArg
::Const(cnst
), GenericParamDefKind
::Type { .. }
) => {
113 let body
= tcx
.hir().body(cnst
.value
.body
);
114 if let rustc_hir
::ExprKind
::Path(rustc_hir
::QPath
::Resolved(_
, path
)) =
117 if let Res
::Def(DefKind
::Fn { .. }
, id
) = path
.res
{
119 "`{}` is a function item, not a type",
122 err
.help("function item types cannot be named directly");
129 let kind_ord
= param
.kind
.to_ord(tcx
);
130 let arg_ord
= arg
.to_ord(&tcx
.features());
132 // This note is only true when generic parameters are strictly ordered by their kind.
133 if possible_ordering_error
&& kind_ord
.cmp(&arg_ord
) != core
::cmp
::Ordering
::Equal
{
134 let (first
, last
) = if kind_ord
< arg_ord
{
135 (param
.kind
.descr(), arg
.descr())
137 (arg
.descr(), param
.kind
.descr())
139 err
.note(&format
!("{} arguments must be provided before {} arguments", first
, last
));
140 if let Some(help
) = help
{
148 /// Creates the relevant generic argument substitutions
149 /// corresponding to a set of generic parameters. This is a
150 /// rather complex function. Let us try to explain the role
151 /// of each of its parameters:
153 /// To start, we are given the `def_id` of the thing we are
154 /// creating the substitutions for, and a partial set of
155 /// substitutions `parent_substs`. In general, the substitutions
156 /// for an item begin with substitutions for all the "parents" of
157 /// that item -- e.g., for a method it might include the
158 /// parameters from the impl.
160 /// Therefore, the method begins by walking down these parents,
161 /// starting with the outermost parent and proceed inwards until
162 /// it reaches `def_id`. For each parent `P`, it will check `parent_substs`
163 /// first to see if the parent's substitutions are listed in there. If so,
164 /// we can append those and move on. Otherwise, it invokes the
165 /// three callback functions:
167 /// - `args_for_def_id`: given the `DefId` `P`, supplies back the
168 /// generic arguments that were given to that parent from within
169 /// the path; so e.g., if you have `<T as Foo>::Bar`, the `DefId`
170 /// might refer to the trait `Foo`, and the arguments might be
171 /// `[T]`. The boolean value indicates whether to infer values
172 /// for arguments whose values were not explicitly provided.
173 /// - `provided_kind`: given the generic parameter and the value from `args_for_def_id`,
174 /// instantiate a `GenericArg`.
175 /// - `inferred_kind`: if no parameter was provided, and inference is enabled, then
176 /// creates a suitable inference variable.
177 pub fn create_substs_for_generic_args
<'a
>(
180 parent_substs
: &[subst
::GenericArg
<'tcx
>],
182 self_ty
: Option
<Ty
<'tcx
>>,
183 arg_count
: &GenericArgCountResult
,
184 ctx
: &mut impl CreateSubstsForGenericArgsCtxt
<'a
, 'tcx
>,
185 ) -> SubstsRef
<'tcx
> {
186 // Collect the segments of the path; we need to substitute arguments
187 // for parameters throughout the entire path (wherever there are
188 // generic parameters).
189 let mut parent_defs
= tcx
.generics_of(def_id
);
190 let count
= parent_defs
.count();
191 let mut stack
= vec
![(def_id
, parent_defs
)];
192 while let Some(def_id
) = parent_defs
.parent
{
193 parent_defs
= tcx
.generics_of(def_id
);
194 stack
.push((def_id
, parent_defs
));
197 // We manually build up the substitution, rather than using convenience
198 // methods in `subst.rs`, so that we can iterate over the arguments and
199 // parameters in lock-step linearly, instead of trying to match each pair.
200 let mut substs
: SmallVec
<[subst
::GenericArg
<'tcx
>; 8]> = SmallVec
::with_capacity(count
);
201 // Iterate over each segment of the path.
202 while let Some((def_id
, defs
)) = stack
.pop() {
203 let mut params
= defs
.params
.iter().peekable();
205 // If we have already computed substitutions for parents, we can use those directly.
206 while let Some(¶m
) = params
.peek() {
207 if let Some(&kind
) = parent_substs
.get(param
.index
as usize) {
215 // `Self` is handled first, unless it's been handled in `parent_substs`.
217 if let Some(¶m
) = params
.peek() {
218 if param
.index
== 0 {
219 if let GenericParamDefKind
::Type { .. }
= param
.kind
{
223 .unwrap_or_else(|| ctx
.inferred_kind(None
, param
, true)),
231 // Check whether this segment takes generic arguments and the user has provided any.
232 let (generic_args
, infer_args
) = ctx
.args_for_def_id(def_id
);
234 let args_iter
= generic_args
.iter().flat_map(|generic_args
| generic_args
.args
.iter());
235 let mut args
= args_iter
.clone().peekable();
237 // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
238 // If we later encounter a lifetime, we know that the arguments were provided in the
239 // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
240 // inferred, so we can use it for diagnostics later.
241 let mut force_infer_lt
= None
;
244 // We're going to iterate through the generic arguments that the user
245 // provided, matching them with the generic parameters we expect.
246 // Mismatches can occur as a result of elided lifetimes, or for malformed
247 // input. We try to handle both sensibly.
248 match (args
.peek(), params
.peek()) {
249 (Some(&arg
), Some(¶m
)) => {
250 match (arg
, ¶m
.kind
, arg_count
.explicit_late_bound
) {
251 (GenericArg
::Lifetime(_
), GenericParamDefKind
::Lifetime
, _
)
252 | (GenericArg
::Type(_
), GenericParamDefKind
::Type { .. }
, _
)
253 | (GenericArg
::Const(_
), GenericParamDefKind
::Const { .. }
, _
) => {
254 substs
.push(ctx
.provided_kind(param
, arg
));
259 GenericArg
::Type(_
) | GenericArg
::Const(_
),
260 GenericParamDefKind
::Lifetime
,
263 // We expected a lifetime argument, but got a type or const
264 // argument. That means we're inferring the lifetimes.
265 substs
.push(ctx
.inferred_kind(None
, param
, infer_args
));
266 force_infer_lt
= Some((arg
, param
));
269 (GenericArg
::Lifetime(_
), _
, ExplicitLateBound
::Yes
) => {
270 // We've come across a lifetime when we expected something else in
271 // the presence of explicit late bounds. This is most likely
272 // due to the presence of the explicit bound so we're just going to
277 // We expected one kind of parameter, but the user provided
278 // another. This is an error. However, if we already know that
279 // the arguments don't match up with the parameters, we won't issue
280 // an additional error, as the user already knows what's wrong.
281 if arg_count
.correct
.is_ok()
282 && arg_count
.explicit_late_bound
== ExplicitLateBound
::No
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
293 GenericParamDefKind
::Lifetime
=> {
294 ParamKindOrd
::Lifetime
296 GenericParamDefKind
::Type { .. }
=> {
299 GenericParamDefKind
::Const { .. }
=> {
300 ParamKindOrd
::Const
{
303 .unordered_const_ty_params(),
310 .collect
::<Vec
<(ParamKindOrd
, GenericParamDef
)>>();
311 param_types_present
.sort_by_key(|(ord
, _
)| *ord
);
312 let (mut param_types_present
, ordered_params
): (
314 Vec
<GenericParamDef
>,
315 ) = param_types_present
.into_iter().unzip();
316 param_types_present
.dedup();
318 Self::generic_arg_mismatch_err(
322 !args_iter
.clone().is_sorted_by_key(|arg
| match arg
{
323 GenericArg
::Lifetime(_
) => ParamKindOrd
::Lifetime
,
324 GenericArg
::Type(_
) => ParamKindOrd
::Type
,
325 GenericArg
::Const(_
) => ParamKindOrd
::Const
{
328 .unordered_const_ty_params(),
332 "reorder the arguments: {}: `<{}>`",
335 .map(|ord
| format
!("{}s", ord
.to_string()))
336 .collect
::<Vec
<String
>>()
340 .filter_map(|param
| {
341 if param
.name
== kw
::SelfUpper
{
344 Some(param
.name
.to_string())
347 .collect
::<Vec
<String
>>()
353 // We've reported the error, but we want to make sure that this
354 // problem doesn't bubble down and create additional, irrelevant
355 // errors. In this case, we're simply going to ignore the argument
356 // and any following arguments. The rest of the parameters will be
358 while args
.next().is_some() {}
363 (Some(&arg
), None
) => {
364 // We should never be able to reach this point with well-formed input.
365 // There are three situations in which we can encounter this issue.
367 // 1. The number of arguments is incorrect. In this case, an error
368 // will already have been emitted, and we can ignore it.
369 // 2. There are late-bound lifetime parameters present, yet the
370 // lifetime arguments have also been explicitly specified by the
372 // 3. We've inferred some lifetimes, which have been provided later (i.e.
373 // after a type or const). We want to throw an error in this case.
375 if arg_count
.correct
.is_ok()
376 && arg_count
.explicit_late_bound
== ExplicitLateBound
::No
378 let kind
= arg
.descr();
379 assert_eq
!(kind
, "lifetime");
380 let (provided_arg
, param
) =
381 force_infer_lt
.expect("lifetimes ought to have been inferred");
382 Self::generic_arg_mismatch_err(tcx
, provided_arg
, param
, false, None
);
388 (None
, Some(¶m
)) => {
389 // If there are fewer arguments than parameters, it means
390 // we're inferring the remaining arguments.
391 substs
.push(ctx
.inferred_kind(Some(&substs
), param
, infer_args
));
395 (None
, None
) => break,
400 tcx
.intern_substs(&substs
)
403 /// Checks that the correct number of generic arguments have been provided.
404 /// Used specifically for function calls.
405 pub fn check_generic_arg_count_for_call(
409 generics
: &ty
::Generics
,
410 seg
: &hir
::PathSegment
<'_
>,
411 is_method_call
: IsMethodCall
,
412 ) -> GenericArgCountResult
{
413 let empty_args
= hir
::GenericArgs
::none();
414 let suppress_mismatch
= Self::check_impl_trait(tcx
, seg
, &generics
);
416 let gen_args
= seg
.args
.unwrap_or(&empty_args
);
417 let gen_pos
= if is_method_call
== IsMethodCall
::Yes
{
418 GenericArgPosition
::MethodCall
420 GenericArgPosition
::Value
422 let has_self
= generics
.parent
.is_none() && generics
.has_self
;
423 let infer_args
= seg
.infer_args
|| suppress_mismatch
;
425 Self::check_generic_arg_count(
426 tcx
, span
, def_id
, seg
, generics
, gen_args
, gen_pos
, has_self
, infer_args
,
430 /// Checks that the correct number of generic arguments have been provided.
431 /// This is used both for datatypes and function calls.
432 pub(crate) fn check_generic_arg_count(
436 seg
: &hir
::PathSegment
<'_
>,
437 gen_params
: &ty
::Generics
,
438 gen_args
: &hir
::GenericArgs
<'_
>,
439 gen_pos
: GenericArgPosition
,
442 ) -> GenericArgCountResult
{
443 let default_counts
= gen_params
.own_defaults();
444 let param_counts
= gen_params
.own_counts();
445 let named_type_param_count
= param_counts
.types
- has_self
as usize;
446 let arg_counts
= gen_args
.own_counts();
447 let infer_lifetimes
= gen_pos
!= GenericArgPosition
::Type
&& arg_counts
.lifetimes
== 0;
449 if gen_pos
!= GenericArgPosition
::Type
&& !gen_args
.bindings
.is_empty() {
450 Self::prohibit_assoc_ty_binding(tcx
, gen_args
.bindings
[0].span
);
453 let explicit_late_bound
=
454 Self::prohibit_explicit_late_bound_lifetimes(tcx
, gen_params
, gen_args
, gen_pos
);
456 let mut invalid_args
= vec
![];
458 let mut check_generics
=
459 |kind
, expected_min
, expected_max
, provided
, params_offset
, args_offset
, silent
| {
460 if (expected_min
..=expected_max
).contains(&provided
) {
468 if provided
> expected_max
{
470 gen_args
.args
[args_offset
+ expected_max
..args_offset
+ provided
]
472 .map(|arg
| arg
.span()),
476 WrongNumberOfGenericArgs
{
496 let lifetimes_correct
= check_generics(
498 if infer_lifetimes { 0 }
else { param_counts.lifetimes }
,
499 param_counts
.lifetimes
,
500 arg_counts
.lifetimes
,
503 explicit_late_bound
== ExplicitLateBound
::Yes
,
507 let kind
= if param_counts
.consts
+ arg_counts
.consts
== 0 {
509 } else if named_type_param_count
+ arg_counts
.types
== 0 {
515 let expected_min
= if infer_args
{
518 param_counts
.consts
+ named_type_param_count
519 - default_counts
.types
520 - default_counts
.consts
526 param_counts
.consts
+ named_type_param_count
,
527 arg_counts
.consts
+ arg_counts
.types
,
528 param_counts
.lifetimes
+ has_self
as usize,
529 arg_counts
.lifetimes
,
534 GenericArgCountResult
{
536 correct
: if lifetimes_correct
&& args_correct
{
539 Err(GenericArgCountMismatch { reported: Some(ErrorReported), invalid_args }
)
544 /// Report error if there is an explicit type parameter when using `impl Trait`.
545 pub(crate) fn check_impl_trait(
547 seg
: &hir
::PathSegment
<'_
>,
548 generics
: &ty
::Generics
,
550 let explicit
= !seg
.infer_args
;
551 let impl_trait
= generics
.params
.iter().any(|param
| {
554 ty
::GenericParamDefKind
::Type
{
556 hir
::SyntheticTyParamKind
::ImplTrait
| hir
::SyntheticTyParamKind
::FromAttr
,
563 if explicit
&& impl_trait
{
568 .filter_map(|arg
| match arg
{
569 GenericArg
::Type(_
) | GenericArg
::Const(_
) => Some(arg
.span()),
572 .collect
::<Vec
<_
>>();
574 let mut err
= struct_span_err
! {
578 "cannot provide explicit generic arguments when `impl Trait` is \
579 used in argument position"
583 err
.span_label(span
, "explicit generic argument not allowed");
592 /// Emits an error regarding forbidden type binding associations
593 pub fn prohibit_assoc_ty_binding(tcx
: TyCtxt
<'_
>, span
: Span
) {
594 tcx
.sess
.emit_err(AssocTypeBindingNotAllowed { span }
);
597 /// Prohibits explicit lifetime arguments if late-bound lifetime parameters
598 /// are present. This is used both for datatypes and function calls.
599 pub(crate) fn prohibit_explicit_late_bound_lifetimes(
602 args
: &hir
::GenericArgs
<'_
>,
603 position
: GenericArgPosition
,
604 ) -> ExplicitLateBound
{
605 let param_counts
= def
.own_counts();
606 let arg_counts
= args
.own_counts();
607 let infer_lifetimes
= position
!= GenericArgPosition
::Type
&& arg_counts
.lifetimes
== 0;
610 return ExplicitLateBound
::No
;
613 if let Some(span_late
) = def
.has_late_bound_regions
{
614 let msg
= "cannot specify lifetime arguments explicitly \
615 if late bound lifetime parameters are present";
616 let note
= "the late bound lifetime parameter is introduced here";
617 let span
= args
.args
[0].span();
619 if position
== GenericArgPosition
::Value
620 && arg_counts
.lifetimes
!= param_counts
.lifetimes
622 let mut err
= tcx
.sess
.struct_span_err(span
, msg
);
623 err
.span_note(span_late
, note
);
626 let mut multispan
= MultiSpan
::from_span(span
);
627 multispan
.push_span_label(span_late
, note
.to_string());
628 tcx
.struct_span_lint_hir(
629 LATE_BOUND_LIFETIME_ARGUMENTS
,
632 |lint
| lint
.build(msg
).emit(),
636 ExplicitLateBound
::Yes
638 ExplicitLateBound
::No