Skip to main content

rustc_hir_analysis/hir_ty_lowering/
generics.rs

1use rustc_ast::ast::ParamKindOrd;
2use rustc_errors::codes::*;
3use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, struct_span_code_err};
4use rustc_hir::def::{DefKind, Res};
5use rustc_hir::def_id::DefId;
6use rustc_hir::{self as hir, GenericArg};
7use rustc_middle::ty::{
8    self, GenericArgsRef, GenericParamDef, GenericParamDefKind, IsSuggestable, Ty,
9};
10use rustc_session::lint::builtin::LATE_BOUND_LIFETIME_ARGUMENTS;
11use rustc_span::kw;
12use rustc_trait_selection::traits;
13use smallvec::SmallVec;
14use tracing::{debug, instrument};
15
16use super::{HirTyLowerer, IsMethodCall};
17use crate::errors::wrong_number_of_generic_args::{GenericArgsInfo, WrongNumberOfGenericArgs};
18use crate::hir_ty_lowering::errors::prohibit_assoc_item_constraint;
19use crate::hir_ty_lowering::{
20    ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, GenericArgPosition,
21    GenericArgsLowerer,
22};
23
24/// Report an error that a generic argument did not match the generic parameter that was
25/// expected.
26fn generic_arg_mismatch_err(
27    cx: &dyn HirTyLowerer<'_>,
28    arg: &GenericArg<'_>,
29    param: &GenericParamDef,
30    possible_ordering_error: bool,
31    help: Option<String>,
32) -> ErrorGuaranteed {
33    let tcx = cx.tcx();
34    let sess = tcx.sess;
35    let mut err = {
    cx.dcx().struct_span_err(arg.span(),
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("{0} provided when a {1} was expected",
                            arg.descr(), param.kind.descr()))
                })).with_code(E0747)
}struct_span_code_err!(
36        cx.dcx(),
37        arg.span(),
38        E0747,
39        "{} provided when a {} was expected",
40        arg.descr(),
41        param.kind.descr(),
42    );
43
44    let add_braces_suggestion = |arg: &GenericArg<'_>, err: &mut Diag<'_>| {
45        let suggestions = <[_]>::into_vec(::alloc::boxed::box_new([(arg.span().shrink_to_lo(),
                    String::from("{ ")),
                (arg.span().shrink_to_hi(), String::from(" }"))]))vec![
46            (arg.span().shrink_to_lo(), String::from("{ ")),
47            (arg.span().shrink_to_hi(), String::from(" }")),
48        ];
49        err.multipart_suggestion(
50            "if this generic argument was intended as a const parameter, \
51                 surround it with braces",
52            suggestions,
53            Applicability::MaybeIncorrect,
54        );
55    };
56
57    // Specific suggestion set for diagnostics
58    match (arg, &param.kind) {
59        (
60            GenericArg::Type(hir::Ty {
61                kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)),
62                ..
63            }),
64            GenericParamDefKind::Const { .. },
65        ) => match path.res {
66            Res::Err => {
67                add_braces_suggestion(arg, &mut err);
68                return err
69                    .with_primary_message("unresolved item provided when a constant was expected")
70                    .emit();
71            }
72            Res::Def(DefKind::TyParam, src_def_id) => {
73                if let Some(param_local_id) = param.def_id.as_local() {
74                    let param_name = tcx.hir_ty_param_name(param_local_id);
75                    let param_type = tcx.type_of(param.def_id).instantiate_identity();
76                    if param_type.is_suggestable(tcx, false) {
77                        err.span_suggestion_verbose(
78                            tcx.def_span(src_def_id),
79                            "consider changing this type parameter to a const parameter",
80                            ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("const {0}: {1}", param_name,
                param_type))
    })format!("const {param_name}: {param_type}"),
81                            Applicability::MaybeIncorrect,
82                        );
83                    };
84                }
85            }
86            _ => add_braces_suggestion(arg, &mut err),
87        },
88        (
89            GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }),
90            GenericParamDefKind::Const { .. },
91        ) => add_braces_suggestion(arg, &mut err),
92        (
93            GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }),
94            GenericParamDefKind::Const { .. },
95        ) if tcx.type_of(param.def_id).skip_binder() == tcx.types.usize => {
96            let snippet = sess.source_map().span_to_snippet(tcx.hir_span(len.hir_id));
97            if let Ok(snippet) = snippet {
98                err.span_suggestion(
99                    arg.span(),
100                    "array type provided where a `usize` was expected, try",
101                    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{{ {0} }}", snippet))
    })format!("{{ {snippet} }}"),
102                    Applicability::MaybeIncorrect,
103                );
104            }
105        }
106        (GenericArg::Const(cnst), GenericParamDefKind::Type { .. }) => {
107            if let hir::ConstArgKind::Path(qpath) = cnst.kind
108                && let rustc_hir::QPath::Resolved(_, path) = qpath
109                && let Res::Def(DefKind::Fn { .. }, id) = path.res
110            {
111                err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is a function item, not a type",
                tcx.item_name(id)))
    })format!("`{}` is a function item, not a type", tcx.item_name(id)));
112                err.help("function item types cannot be named directly");
113            } else if let hir::ConstArgKind::Anon(anon) = cnst.kind
114                && let body = tcx.hir_body(anon.body)
115                && let rustc_hir::ExprKind::Path(rustc_hir::QPath::Resolved(_, path)) =
116                    body.value.kind
117                && let Res::Def(DefKind::Fn { .. }, id) = path.res
118            {
119                // FIXME(mgca): this branch is dead once new const path lowering
120                // (for single-segment paths) is no longer gated
121                err.help(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("`{0}` is a function item, not a type",
                tcx.item_name(id)))
    })format!("`{}` is a function item, not a type", tcx.item_name(id)));
122                err.help("function item types cannot be named directly");
123            }
124        }
125        _ => {}
126    }
127
128    let kind_ord = param.kind.to_ord();
129    let arg_ord = arg.to_ord();
130
131    // This note is only true when generic parameters are strictly ordered by their kind.
132    if possible_ordering_error && kind_ord.cmp(&arg_ord) != core::cmp::Ordering::Equal {
133        let (first, last) = if kind_ord < arg_ord {
134            (param.kind.descr(), arg.descr())
135        } else {
136            (arg.descr(), param.kind.descr())
137        };
138        err.note(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("{0} arguments must be provided before {1} arguments",
                first, last))
    })format!("{first} arguments must be provided before {last} arguments"));
139        if let Some(help) = help {
140            err.help(help);
141        }
142    }
143
144    err.emit()
145}
146
147/// Lower generic arguments from the HIR to the [`rustc_middle::ty`] representation.
148///
149/// This is a rather complex function. Let us try to explain the role
150/// of each of its parameters:
151///
152/// To start, we are given the `def_id` of the thing whose generic parameters we
153/// are creating, and a partial set of arguments `parent_args`. In general,
154/// the generic arguments for an item begin with arguments for all the "parents"
155/// of that item -- e.g., for a method it might include the parameters from the impl.
156///
157/// Therefore, the method begins by walking down these parents,
158/// starting with the outermost parent and proceed inwards until
159/// it reaches `def_id`. For each parent `P`, it will check `parent_args`
160/// first to see if the parent's arguments are listed in there. If so,
161/// we can append those and move on. Otherwise, it uses the provided
162/// [`GenericArgsLowerer`] `ctx` which has the following methods:
163///
164/// - `args_for_def_id`: given the `DefId` `P`, supplies back the
165///   generic arguments that were given to that parent from within
166///   the path; so e.g., if you have `<T as Foo>::Bar`, the `DefId`
167///   might refer to the trait `Foo`, and the arguments might be
168///   `[T]`. The boolean value indicates whether to infer values
169///   for arguments whose values were not explicitly provided.
170/// - `provided_kind`: given the generic parameter and the value
171///   from `args_for_def_id`, creating a `GenericArg`.
172/// - `inferred_kind`: if no parameter was provided, and inference
173///   is enabled, then creates a suitable inference variable.
174pub fn lower_generic_args<'tcx: 'a, 'a>(
175    cx: &dyn HirTyLowerer<'tcx>,
176    def_id: DefId,
177    parent_args: &[ty::GenericArg<'tcx>],
178    has_self: bool,
179    self_ty: Option<Ty<'tcx>>,
180    arg_count: &GenericArgCountResult,
181    ctx: &mut impl GenericArgsLowerer<'a, 'tcx>,
182) -> GenericArgsRef<'tcx> {
183    let tcx = cx.tcx();
184    // Collect the segments of the path; we need to instantiate arguments
185    // for parameters throughout the entire path (wherever there are
186    // generic parameters).
187    let mut parent_defs = tcx.generics_of(def_id);
188    let count = parent_defs.count();
189    let mut stack = <[_]>::into_vec(::alloc::boxed::box_new([(def_id, parent_defs)]))vec![(def_id, parent_defs)];
190    while let Some(def_id) = parent_defs.parent {
191        parent_defs = tcx.generics_of(def_id);
192        stack.push((def_id, parent_defs));
193    }
194
195    // We manually build up the generic arguments, rather than using convenience
196    // methods in `rustc_middle/src/ty/generic_args.rs`, so that we can iterate over the arguments and
197    // parameters in lock-step linearly, instead of trying to match each pair.
198    let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count);
199    // Iterate over each segment of the path.
200    while let Some((def_id, defs)) = stack.pop() {
201        let mut params = defs.own_params.iter().peekable();
202
203        // If we have already computed the generic arguments for parents,
204        // we can use those directly.
205        while let Some(&param) = params.peek() {
206            if let Some(&kind) = parent_args.get(param.index as usize) {
207                args.push(kind);
208                params.next();
209            } else {
210                break;
211            }
212        }
213
214        // `Self` is handled first, unless it's been handled in `parent_args`.
215        if has_self {
216            if let Some(&param) = params.peek() {
217                if param.index == 0 {
218                    if let GenericParamDefKind::Type { .. } = param.kind {
219                        match (&&args[..], &&[]) {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(&args[..], &[]);
220                        args.push(
221                            self_ty
222                                .map(|ty| ty.into())
223                                .unwrap_or_else(|| ctx.inferred_kind(&args, param, true)),
224                        );
225                        params.next();
226                    }
227                }
228            }
229        }
230
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);
233
234        let mut args_iter =
235            generic_args.iter().flat_map(|generic_args| generic_args.args.iter()).peekable();
236
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;
242
243        loop {
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_iter.peek(), params.peek()) {
249                (Some(&arg), Some(&param)) => {
250                    match (arg, &param.kind, arg_count.explicit_late_bound) {
251                        (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
252                        | (
253                            GenericArg::Type(_) | GenericArg::Infer(_),
254                            GenericParamDefKind::Type { .. },
255                            _,
256                        )
257                        | (
258                            GenericArg::Const(_) | GenericArg::Infer(_),
259                            GenericParamDefKind::Const { .. },
260                            _,
261                        ) => {
262                            // We lower to an infer even when the feature gate is not enabled
263                            // as it is useful for diagnostics to be able to see a `ConstKind::Infer`
264                            args.push(ctx.provided_kind(&args, param, arg));
265                            args_iter.next();
266                            params.next();
267                        }
268                        (
269                            GenericArg::Infer(_) | GenericArg::Type(_) | GenericArg::Const(_),
270                            GenericParamDefKind::Lifetime,
271                            _,
272                        ) => {
273                            // We expected a lifetime argument, but got a type or const
274                            // argument. That means we're inferring the lifetimes.
275                            args.push(ctx.inferred_kind(&args, param, infer_args));
276                            force_infer_lt = Some((arg, param));
277                            params.next();
278                        }
279                        (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => {
280                            // We've come across a lifetime when we expected something else in
281                            // the presence of explicit late bounds. This is most likely
282                            // due to the presence of the explicit bound so we're just going to
283                            // ignore it.
284                            args_iter.next();
285                        }
286                        (_, _, _) => {
287                            // We expected one kind of parameter, but the user provided
288                            // another. This is an error. However, if we already know that
289                            // the arguments don't match up with the parameters, we won't issue
290                            // an additional error, as the user already knows what's wrong.
291                            if arg_count.correct.is_ok() {
292                                // We're going to iterate over the parameters to sort them out, and
293                                // show that order to the user as a possible order for the parameters
294                                let mut param_types_present = defs
295                                    .own_params
296                                    .iter()
297                                    .map(|param| (param.kind.to_ord(), param.clone()))
298                                    .collect::<Vec<(ParamKindOrd, GenericParamDef)>>();
299                                param_types_present.sort_by_key(|(ord, _)| *ord);
300                                let (mut param_types_present, ordered_params): (
301                                    Vec<ParamKindOrd>,
302                                    Vec<GenericParamDef>,
303                                ) = param_types_present.into_iter().unzip();
304                                param_types_present.dedup();
305
306                                generic_arg_mismatch_err(
307                                    cx,
308                                    arg,
309                                    param,
310                                    !args_iter.clone().is_sorted_by_key(|arg| arg.to_ord()),
311                                    Some(::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("reorder the arguments: {0}: `<{1}>`",
                param_types_present.into_iter().map(|ord|
                                ::alloc::__export::must_use({
                                        ::alloc::fmt::format(format_args!("{0}s", ord))
                                    })).collect::<Vec<String>>().join(", then "),
                ordered_params.into_iter().filter_map(|param|
                                {
                                    if param.name == kw::SelfUpper {
                                        None
                                    } else { Some(param.name.to_string()) }
                                }).collect::<Vec<String>>().join(", ")))
    })format!(
312                                        "reorder the arguments: {}: `<{}>`",
313                                        param_types_present
314                                            .into_iter()
315                                            .map(|ord| format!("{ord}s"))
316                                            .collect::<Vec<String>>()
317                                            .join(", then "),
318                                        ordered_params
319                                            .into_iter()
320                                            .filter_map(|param| {
321                                                if param.name == kw::SelfUpper {
322                                                    None
323                                                } else {
324                                                    Some(param.name.to_string())
325                                                }
326                                            })
327                                            .collect::<Vec<String>>()
328                                            .join(", ")
329                                    )),
330                                );
331                            }
332
333                            // We've reported the error, but we want to make sure that this
334                            // problem doesn't bubble down and create additional, irrelevant
335                            // errors. In this case, we're simply going to ignore the argument
336                            // and any following arguments. The rest of the parameters will be
337                            // inferred.
338                            while args_iter.next().is_some() {}
339                        }
340                    }
341                }
342
343                (Some(&arg), None) => {
344                    // We should never be able to reach this point with well-formed input.
345                    // There are three situations in which we can encounter this issue.
346                    //
347                    //  1. The number of arguments is incorrect. In this case, an error
348                    //     will already have been emitted, and we can ignore it.
349                    //  2. There are late-bound lifetime parameters present, yet the
350                    //     lifetime arguments have also been explicitly specified by the
351                    //     user.
352                    //  3. We've inferred some lifetimes, which have been provided later (i.e.
353                    //     after a type or const). We want to throw an error in this case.
354
355                    if arg_count.correct.is_ok()
356                        && arg_count.explicit_late_bound == ExplicitLateBound::No
357                    {
358                        let kind = arg.descr();
359                        match (&kind, &"lifetime") {
    (left_val, right_val) => {
        if !(*left_val == *right_val) {
            let kind = ::core::panicking::AssertKind::Eq;
            ::core::panicking::assert_failed(kind, &*left_val, &*right_val,
                ::core::option::Option::None);
        }
    }
};assert_eq!(kind, "lifetime");
360                        let (provided_arg, param) =
361                            force_infer_lt.expect("lifetimes ought to have been inferred");
362                        generic_arg_mismatch_err(cx, provided_arg, param, false, None);
363                    }
364
365                    break;
366                }
367
368                (None, Some(&param)) => {
369                    // If there are fewer arguments than parameters, it means
370                    // we're inferring the remaining arguments.
371                    args.push(ctx.inferred_kind(&args, param, infer_args));
372                    params.next();
373                }
374
375                (None, None) => break,
376            }
377        }
378    }
379
380    tcx.mk_args(&args)
381}
382
383/// Checks that the correct number of generic arguments have been provided.
384/// Used specifically for function calls.
385pub fn check_generic_arg_count_for_call(
386    cx: &dyn HirTyLowerer<'_>,
387    def_id: DefId,
388    generics: &ty::Generics,
389    seg: &hir::PathSegment<'_>,
390    is_method_call: IsMethodCall,
391) -> GenericArgCountResult {
392    let gen_pos = match is_method_call {
393        IsMethodCall::Yes => GenericArgPosition::MethodCall,
394        IsMethodCall::No => GenericArgPosition::Value,
395    };
396    let has_self = generics.parent.is_none() && generics.has_self;
397    check_generic_arg_count(cx, def_id, seg, generics, gen_pos, has_self)
398}
399
400/// Checks that the correct number of generic arguments have been provided.
401/// This is used both for datatypes and function calls.
402#[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("check_generic_arg_count",
                                    "rustc_hir_analysis::hir_ty_lowering::generics",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs"),
                                    ::tracing_core::__macro_support::Option::Some(402u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::generics"),
                                    ::tracing_core::field::FieldSet::new(&["def_id", "seg",
                                                    "gen_params", "has_self"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&seg)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&gen_params)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&has_self as
                                                            &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

        #[allow(unknown_lints, unreachable_code, clippy ::
        diverging_sub_expression, clippy :: empty_loop, clippy ::
        let_unit_value, clippy :: let_with_type_underscore, clippy ::
        needless_return, clippy :: unreachable)]
        if false {
            let __tracing_attr_fake_return: GenericArgCountResult = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let gen_args = seg.args();
            let default_counts = gen_params.own_defaults();
            let param_counts = gen_params.own_counts();
            let synth_type_param_count =
                gen_params.own_params.iter().filter(|param|
                            #[allow(non_exhaustive_omitted_patterns)] match param.kind {
                                ty::GenericParamDefKind::Type { synthetic: true, .. } =>
                                    true,
                                _ => false,
                            }).count();
            let named_type_param_count =
                param_counts.types - has_self as usize -
                    synth_type_param_count;
            let named_const_param_count = param_counts.consts;
            let infer_lifetimes =
                (gen_pos != GenericArgPosition::Type || seg.infer_args) &&
                    !gen_args.has_lifetime_params();
            if gen_pos != GenericArgPosition::Type &&
                    let Some(c) = gen_args.constraints.first() {
                prohibit_assoc_item_constraint(cx, c, None);
            }
            let explicit_late_bound =
                prohibit_explicit_late_bound_lifetimes(cx, gen_params,
                    gen_args, gen_pos);
            let mut invalid_args = ::alloc::vec::Vec::new();
            let mut check_lifetime_args =
                |min_expected_args: usize, max_expected_args: usize,
                    provided_args: usize, late_bounds_ignore: bool|
                    {
                        if (min_expected_args..=max_expected_args).contains(&provided_args)
                            {
                            return Ok(());
                        }
                        if late_bounds_ignore { return Ok(()); }
                        invalid_args.extend(min_expected_args..provided_args);
                        let gen_args_info =
                            if provided_args > min_expected_args {
                                let num_redundant_args = provided_args - min_expected_args;
                                GenericArgsInfo::ExcessLifetimes { num_redundant_args }
                            } else {
                                let num_missing_args = min_expected_args - provided_args;
                                GenericArgsInfo::MissingLifetimes { num_missing_args }
                            };
                        let reported =
                            cx.dcx().emit_err(WrongNumberOfGenericArgs::new(cx.tcx(),
                                    gen_args_info, seg, gen_params, has_self as usize, gen_args,
                                    def_id));
                        Err(reported)
                    };
            let min_expected_lifetime_args =
                if infer_lifetimes { 0 } else { param_counts.lifetimes };
            let max_expected_lifetime_args = param_counts.lifetimes;
            let num_provided_lifetime_args = gen_args.num_lifetime_params();
            let lifetimes_correct =
                check_lifetime_args(min_expected_lifetime_args,
                    max_expected_lifetime_args, num_provided_lifetime_args,
                    explicit_late_bound == ExplicitLateBound::Yes);
            let mut check_types_and_consts =
                |expected_min, expected_max, expected_max_with_synth,
                    provided, params_offset, args_offset|
                    {
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs:490",
                                                "rustc_hir_analysis::hir_ty_lowering::generics",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs"),
                                                ::tracing_core::__macro_support::Option::Some(490u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::generics"),
                                                ::tracing_core::field::FieldSet::new(&["message",
                                                                "expected_min", "expected_max", "provided", "params_offset",
                                                                "args_offset"],
                                                    ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                ::tracing::metadata::Kind::EVENT)
                                        };
                                    ::tracing::callsite::DefaultCallsite::new(&META)
                                };
                            let enabled =
                                ::tracing::Level::DEBUG <=
                                            ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                        ::tracing::Level::DEBUG <=
                                            ::tracing::level_filters::LevelFilter::current() &&
                                    {
                                        let interest = __CALLSITE.interest();
                                        !interest.is_never() &&
                                            ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                interest)
                                    };
                            if enabled {
                                (|value_set: ::tracing::field::ValueSet|
                                            {
                                                let meta = __CALLSITE.metadata();
                                                ::tracing::Event::dispatch(meta, &value_set);
                                                ;
                                            })({
                                        #[allow(unused_imports)]
                                        use ::tracing::field::{debug, display, Value};
                                        let mut iter = __CALLSITE.metadata().fields().iter();
                                        __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&format_args!("check_types_and_consts")
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&expected_min)
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&expected_max)
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&provided)
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&params_offset)
                                                                    as &dyn Value)),
                                                        (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&args_offset)
                                                                    as &dyn Value))])
                                    });
                            } else { ; }
                        };
                        if (expected_min..=expected_max).contains(&provided) {
                            return Ok(());
                        }
                        let num_default_params = expected_max - expected_min;
                        let mut all_params_are_binded = false;
                        let gen_args_info =
                            if provided > expected_max {
                                invalid_args.extend((expected_max..provided).map(|i|
                                            i + args_offset));
                                let num_redundant_args = provided - expected_max;
                                let synth_provided = provided <= expected_max_with_synth;
                                GenericArgsInfo::ExcessTypesOrConsts {
                                    num_redundant_args,
                                    num_default_params,
                                    args_offset,
                                    synth_provided,
                                }
                            } else {
                                let parent_is_impl_block =
                                    cx.tcx().hir_parent_owner_iter(seg.hir_id).next().is_some_and(|(_,
                                                owner_node)| owner_node.is_impl_block());
                                if parent_is_impl_block {
                                    let constraint_names: Vec<_> =
                                        gen_args.constraints.iter().map(|b| b.ident.name).collect();
                                    let param_names: Vec<_> =
                                        gen_params.own_params.iter().filter(|param|
                                                        !has_self ||
                                                            param.index != 0).map(|param| param.name).collect();
                                    if constraint_names == param_names {
                                        let has_assoc_ty_with_same_name =
                                            if let DefKind::Trait = cx.tcx().def_kind(def_id) {
                                                gen_args.constraints.iter().any(|constraint|
                                                        {
                                                            traits::supertrait_def_ids(cx.tcx(),
                                                                    def_id).any(|trait_did|
                                                                    {
                                                                        cx.probe_trait_that_defines_assoc_item(trait_did,
                                                                            ty::AssocTag::Type, constraint.ident)
                                                                    })
                                                        })
                                            } else { false };
                                        all_params_are_binded = !has_assoc_ty_with_same_name;
                                    };
                                }
                                let num_missing_args = expected_max - provided;
                                GenericArgsInfo::MissingTypesOrConsts {
                                    num_missing_args,
                                    num_default_params,
                                    args_offset,
                                }
                            };
                        {
                            use ::tracing::__macro_support::Callsite as _;
                            static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                                {
                                    static META: ::tracing::Metadata<'static> =
                                        {
                                            ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs:571",
                                                "rustc_hir_analysis::hir_ty_lowering::generics",
                                                ::tracing::Level::DEBUG,
                                                ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs"),
                                                ::tracing_core::__macro_support::Option::Some(571u32),
                                                ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::generics"),
                                                ::tracing_core::field::FieldSet::new(&["gen_args_info"],
                                                    ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                                ::tracing::metadata::Kind::EVENT)
                                        };
                                    ::tracing::callsite::DefaultCallsite::new(&META)
                                };
                            let enabled =
                                ::tracing::Level::DEBUG <=
                                            ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                        ::tracing::Level::DEBUG <=
                                            ::tracing::level_filters::LevelFilter::current() &&
                                    {
                                        let interest = __CALLSITE.interest();
                                        !interest.is_never() &&
                                            ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                                interest)
                                    };
                            if enabled {
                                (|value_set: ::tracing::field::ValueSet|
                                            {
                                                let meta = __CALLSITE.metadata();
                                                ::tracing::Event::dispatch(meta, &value_set);
                                                ;
                                            })({
                                        #[allow(unused_imports)]
                                        use ::tracing::field::{debug, display, Value};
                                        let mut iter = __CALLSITE.metadata().fields().iter();
                                        __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                            ::tracing::__macro_support::Option::Some(&debug(&gen_args_info)
                                                                    as &dyn Value))])
                                    });
                            } else { ; }
                        };
                        let reported =
                            gen_args.has_err().unwrap_or_else(||
                                    {
                                        cx.dcx().create_err(WrongNumberOfGenericArgs::new(cx.tcx(),
                                                    gen_args_info, seg, gen_params, params_offset, gen_args,
                                                    def_id)).emit_unless_delay(all_params_are_binded)
                                    });
                        Err(reported)
                    };
            let args_correct =
                {
                    let expected_min =
                        if seg.infer_args {
                            0
                        } else {
                            param_counts.consts + named_type_param_count -
                                    default_counts.types - default_counts.consts
                        };
                    {
                        use ::tracing::__macro_support::Callsite as _;
                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                            {
                                static META: ::tracing::Metadata<'static> =
                                    {
                                        ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs:598",
                                            "rustc_hir_analysis::hir_ty_lowering::generics",
                                            ::tracing::Level::DEBUG,
                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs"),
                                            ::tracing_core::__macro_support::Option::Some(598u32),
                                            ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::generics"),
                                            ::tracing_core::field::FieldSet::new(&["expected_min"],
                                                ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                            ::tracing::metadata::Kind::EVENT)
                                    };
                                ::tracing::callsite::DefaultCallsite::new(&META)
                            };
                        let enabled =
                            ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                    ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::LevelFilter::current() &&
                                {
                                    let interest = __CALLSITE.interest();
                                    !interest.is_never() &&
                                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                            interest)
                                };
                        if enabled {
                            (|value_set: ::tracing::field::ValueSet|
                                        {
                                            let meta = __CALLSITE.metadata();
                                            ::tracing::Event::dispatch(meta, &value_set);
                                            ;
                                        })({
                                    #[allow(unused_imports)]
                                    use ::tracing::field::{debug, display, Value};
                                    let mut iter = __CALLSITE.metadata().fields().iter();
                                    __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                        ::tracing::__macro_support::Option::Some(&debug(&expected_min)
                                                                as &dyn Value))])
                                });
                        } else { ; }
                    };
                    {
                        use ::tracing::__macro_support::Callsite as _;
                        static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                            {
                                static META: ::tracing::Metadata<'static> =
                                    {
                                        ::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs:599",
                                            "rustc_hir_analysis::hir_ty_lowering::generics",
                                            ::tracing::Level::DEBUG,
                                            ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs"),
                                            ::tracing_core::__macro_support::Option::Some(599u32),
                                            ::tracing_core::__macro_support::Option::Some("rustc_hir_analysis::hir_ty_lowering::generics"),
                                            ::tracing_core::field::FieldSet::new(&["arg_counts.lifetimes"],
                                                ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                            ::tracing::metadata::Kind::EVENT)
                                    };
                                ::tracing::callsite::DefaultCallsite::new(&META)
                            };
                        let enabled =
                            ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                    ::tracing::Level::DEBUG <=
                                        ::tracing::level_filters::LevelFilter::current() &&
                                {
                                    let interest = __CALLSITE.interest();
                                    !interest.is_never() &&
                                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                                            interest)
                                };
                        if enabled {
                            (|value_set: ::tracing::field::ValueSet|
                                        {
                                            let meta = __CALLSITE.metadata();
                                            ::tracing::Event::dispatch(meta, &value_set);
                                            ;
                                        })({
                                    #[allow(unused_imports)]
                                    use ::tracing::field::{debug, display, Value};
                                    let mut iter = __CALLSITE.metadata().fields().iter();
                                    __CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                        ::tracing::__macro_support::Option::Some(&debug(&gen_args.num_lifetime_params())
                                                                as &dyn Value))])
                                });
                        } else { ; }
                    };
                    let provided = gen_args.num_generic_params();
                    check_types_and_consts(expected_min,
                        named_const_param_count + named_type_param_count,
                        named_const_param_count + named_type_param_count +
                            synth_type_param_count, provided,
                        param_counts.lifetimes + has_self as usize,
                        gen_args.num_lifetime_params())
                };
            GenericArgCountResult {
                explicit_late_bound,
                correct: lifetimes_correct.and(args_correct).map_err(|reported|
                        GenericArgCountMismatch { reported, invalid_args }),
            }
        }
    }
}#[instrument(skip(cx, gen_pos), level = "debug")]
403pub(crate) fn check_generic_arg_count(
404    cx: &dyn HirTyLowerer<'_>,
405    def_id: DefId,
406    seg: &hir::PathSegment<'_>,
407    gen_params: &ty::Generics,
408    gen_pos: GenericArgPosition,
409    has_self: bool,
410) -> GenericArgCountResult {
411    let gen_args = seg.args();
412    let default_counts = gen_params.own_defaults();
413    let param_counts = gen_params.own_counts();
414
415    // Subtracting from param count to ensure type params synthesized from `impl Trait`
416    // cannot be explicitly specified.
417    let synth_type_param_count = gen_params
418        .own_params
419        .iter()
420        .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }))
421        .count();
422    let named_type_param_count = param_counts.types - has_self as usize - synth_type_param_count;
423    let named_const_param_count = param_counts.consts;
424    let infer_lifetimes =
425        (gen_pos != GenericArgPosition::Type || seg.infer_args) && !gen_args.has_lifetime_params();
426
427    if gen_pos != GenericArgPosition::Type
428        && let Some(c) = gen_args.constraints.first()
429    {
430        prohibit_assoc_item_constraint(cx, c, None);
431    }
432
433    let explicit_late_bound =
434        prohibit_explicit_late_bound_lifetimes(cx, gen_params, gen_args, gen_pos);
435
436    let mut invalid_args = vec![];
437
438    let mut check_lifetime_args = |min_expected_args: usize,
439                                   max_expected_args: usize,
440                                   provided_args: usize,
441                                   late_bounds_ignore: bool| {
442        if (min_expected_args..=max_expected_args).contains(&provided_args) {
443            return Ok(());
444        }
445
446        if late_bounds_ignore {
447            return Ok(());
448        }
449
450        invalid_args.extend(min_expected_args..provided_args);
451
452        let gen_args_info = if provided_args > min_expected_args {
453            let num_redundant_args = provided_args - min_expected_args;
454            GenericArgsInfo::ExcessLifetimes { num_redundant_args }
455        } else {
456            let num_missing_args = min_expected_args - provided_args;
457            GenericArgsInfo::MissingLifetimes { num_missing_args }
458        };
459
460        let reported = cx.dcx().emit_err(WrongNumberOfGenericArgs::new(
461            cx.tcx(),
462            gen_args_info,
463            seg,
464            gen_params,
465            has_self as usize,
466            gen_args,
467            def_id,
468        ));
469
470        Err(reported)
471    };
472
473    let min_expected_lifetime_args = if infer_lifetimes { 0 } else { param_counts.lifetimes };
474    let max_expected_lifetime_args = param_counts.lifetimes;
475    let num_provided_lifetime_args = gen_args.num_lifetime_params();
476
477    let lifetimes_correct = check_lifetime_args(
478        min_expected_lifetime_args,
479        max_expected_lifetime_args,
480        num_provided_lifetime_args,
481        explicit_late_bound == ExplicitLateBound::Yes,
482    );
483
484    let mut check_types_and_consts = |expected_min,
485                                      expected_max,
486                                      expected_max_with_synth,
487                                      provided,
488                                      params_offset,
489                                      args_offset| {
490        debug!(
491            ?expected_min,
492            ?expected_max,
493            ?provided,
494            ?params_offset,
495            ?args_offset,
496            "check_types_and_consts"
497        );
498        if (expected_min..=expected_max).contains(&provided) {
499            return Ok(());
500        }
501
502        let num_default_params = expected_max - expected_min;
503
504        let mut all_params_are_binded = false;
505        let gen_args_info = if provided > expected_max {
506            invalid_args.extend((expected_max..provided).map(|i| i + args_offset));
507            let num_redundant_args = provided - expected_max;
508
509            // Provide extra note if synthetic arguments like `impl Trait` are specified.
510            let synth_provided = provided <= expected_max_with_synth;
511
512            GenericArgsInfo::ExcessTypesOrConsts {
513                num_redundant_args,
514                num_default_params,
515                args_offset,
516                synth_provided,
517            }
518        } else {
519            // Check if associated type bounds are incorrectly written in impl block header like:
520            // ```
521            // trait Foo<T> {}
522            // impl Foo<T: Default> for u8 {}
523            // ```
524            let parent_is_impl_block = cx
525                .tcx()
526                .hir_parent_owner_iter(seg.hir_id)
527                .next()
528                .is_some_and(|(_, owner_node)| owner_node.is_impl_block());
529            if parent_is_impl_block {
530                let constraint_names: Vec<_> =
531                    gen_args.constraints.iter().map(|b| b.ident.name).collect();
532                let param_names: Vec<_> = gen_params
533                    .own_params
534                    .iter()
535                    .filter(|param| !has_self || param.index != 0) // Assumes `Self` will always be the first parameter
536                    .map(|param| param.name)
537                    .collect();
538                if constraint_names == param_names {
539                    let has_assoc_ty_with_same_name =
540                        if let DefKind::Trait = cx.tcx().def_kind(def_id) {
541                            gen_args.constraints.iter().any(|constraint| {
542                                traits::supertrait_def_ids(cx.tcx(), def_id).any(|trait_did| {
543                                    cx.probe_trait_that_defines_assoc_item(
544                                        trait_did,
545                                        ty::AssocTag::Type,
546                                        constraint.ident,
547                                    )
548                                })
549                            })
550                        } else {
551                            false
552                        };
553                    // We set this to true and delay emitting `WrongNumberOfGenericArgs`
554                    // to provide a succinct error for cases like issue #113073,
555                    // but only if when we don't have any assoc type with the same name with a
556                    // generic arg. Otherwise it will cause an ICE due to a delayed error because we
557                    // don't have any error other than `WrongNumberOfGenericArgs`.
558                    all_params_are_binded = !has_assoc_ty_with_same_name;
559                };
560            }
561
562            let num_missing_args = expected_max - provided;
563
564            GenericArgsInfo::MissingTypesOrConsts {
565                num_missing_args,
566                num_default_params,
567                args_offset,
568            }
569        };
570
571        debug!(?gen_args_info);
572
573        let reported = gen_args.has_err().unwrap_or_else(|| {
574            cx.dcx()
575                .create_err(WrongNumberOfGenericArgs::new(
576                    cx.tcx(),
577                    gen_args_info,
578                    seg,
579                    gen_params,
580                    params_offset,
581                    gen_args,
582                    def_id,
583                ))
584                .emit_unless_delay(all_params_are_binded)
585        });
586
587        Err(reported)
588    };
589
590    let args_correct = {
591        let expected_min = if seg.infer_args {
592            0
593        } else {
594            param_counts.consts + named_type_param_count
595                - default_counts.types
596                - default_counts.consts
597        };
598        debug!(?expected_min);
599        debug!(arg_counts.lifetimes=?gen_args.num_lifetime_params());
600
601        let provided = gen_args.num_generic_params();
602
603        check_types_and_consts(
604            expected_min,
605            named_const_param_count + named_type_param_count,
606            named_const_param_count + named_type_param_count + synth_type_param_count,
607            provided,
608            param_counts.lifetimes + has_self as usize,
609            gen_args.num_lifetime_params(),
610        )
611    };
612
613    GenericArgCountResult {
614        explicit_late_bound,
615        correct: lifetimes_correct
616            .and(args_correct)
617            .map_err(|reported| GenericArgCountMismatch { reported, invalid_args }),
618    }
619}
620
621/// Prohibits explicit lifetime arguments if late-bound lifetime parameters
622/// are present. This is used both for datatypes and function calls.
623pub(crate) fn prohibit_explicit_late_bound_lifetimes(
624    cx: &dyn HirTyLowerer<'_>,
625    def: &ty::Generics,
626    args: &hir::GenericArgs<'_>,
627    position: GenericArgPosition,
628) -> ExplicitLateBound {
629    let param_counts = def.own_counts();
630
631    if let Some(span_late) = def.has_late_bound_regions
632        && args.has_lifetime_params()
633    {
634        let msg = "cannot specify lifetime arguments explicitly \
635                       if late bound lifetime parameters are present";
636        let note = "the late bound lifetime parameter is introduced here";
637        let span = args.args[0].span();
638
639        if position == GenericArgPosition::Value
640            && args.num_lifetime_params() != param_counts.lifetimes
641        {
642            {
    cx.dcx().struct_span_err(span,
            ::alloc::__export::must_use({
                    ::alloc::fmt::format(format_args!("{0}", msg))
                })).with_code(E0794)
}struct_span_code_err!(cx.dcx(), span, E0794, "{}", msg)
643                .with_span_note(span_late, note)
644                .emit();
645        } else {
646            let mut multispan = MultiSpan::from_span(span);
647            multispan.push_span_label(span_late, note);
648            cx.tcx().node_span_lint(
649                LATE_BOUND_LIFETIME_ARGUMENTS,
650                args.args[0].hir_id(),
651                multispan,
652                |lint| {
653                    lint.primary_message(msg);
654                },
655            );
656        }
657
658        ExplicitLateBound::Yes
659    } else {
660        ExplicitLateBound::No
661    }
662}