Skip to main content

hir_ty/lower/
path.rs

1//! A wrapper around [`TyLoweringContext`] specifically for lowering paths.
2
3use either::Either;
4use hir_def::{
5    GenericDefId, GenericParamId, Lookup, TraitId, TypeParamId,
6    expr_store::{
7        ExpressionStore, HygieneId,
8        path::{
9            GenericArg as HirGenericArg, GenericArgs as HirGenericArgs, GenericArgsParentheses,
10            Path, PathSegment, PathSegments,
11        },
12    },
13    hir::generics::{
14        GenericParamDataRef, TypeOrConstParamData, TypeParamData, TypeParamProvenance,
15    },
16    resolver::{ResolveValueResult, TypeNs, ValueNs},
17    signatures::{TraitFlags, TraitSignature},
18    type_ref::{TypeRef, TypeRefId},
19};
20use rustc_type_ir::{
21    AliasTerm, AliasTy, AliasTyKind,
22    inherent::{GenericArgs as _, Region as _, Ty as _},
23};
24use smallvec::SmallVec;
25
26use crate::{
27    GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource,
28    PathLoweringDiagnostic, Span, TyDefId, ValueTyDefId,
29    db::HirDatabase,
30    generics::{Generics, generics},
31    infer::unify::InferenceTable,
32    lower::{
33        AssocTypeShorthandResolution, ForbidParamsAfterReason, GenericPredicateSource,
34        LifetimeElisionKind, PathDiagnosticCallbackData, const_param_ty,
35    },
36    next_solver::{
37        AliasTermKind, Binder, Clause, Const, DbInterner, EarlyBinder, ErrorGuaranteed, GenericArg,
38        GenericArgs, Predicate, ProjectionPredicate, Region, TraitRef, Ty,
39    },
40};
41
42use super::{
43    ImplTraitLoweringMode, TyLoweringContext,
44    associated_type_by_name_including_super_traits_allow_ambiguity, ty_query,
45};
46
47type CallbackData<'a> =
48    Either<PathDiagnosticCallbackData, crate::infer::diagnostics::PathDiagnosticCallbackData<'a>>;
49
50// We cannot use `&mut dyn FnMut()` because of lifetime issues, and we don't want to use `Box<dyn FnMut()>`
51// because of the allocation, so we create a lifetime-less callback, tailored for our needs.
52pub(crate) struct PathDiagnosticCallback<'a, 'db> {
53    pub(crate) data: CallbackData<'a>,
54    pub(crate) callback:
55        fn(&CallbackData<'_>, &mut TyLoweringContext<'db, '_>, PathLoweringDiagnostic),
56}
57
58pub(crate) struct PathLoweringContext<'a, 'b, 'db> {
59    ctx: &'a mut TyLoweringContext<'db, 'b>,
60    on_diagnostic: PathDiagnosticCallback<'a, 'db>,
61    path: &'a Path,
62    segments: PathSegments<'a>,
63    current_segment_idx: usize,
64    /// Contains the previous segment if `current_segment_idx == segments.len()`
65    current_or_prev_segment: PathSegment<'a>,
66}
67
68impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
69    #[inline]
70    pub(crate) fn new(
71        ctx: &'a mut TyLoweringContext<'db, 'b>,
72        on_diagnostic: PathDiagnosticCallback<'a, 'db>,
73        path: &'a Path,
74    ) -> Self {
75        let segments = path.segments();
76        let first_segment = segments.first().unwrap_or(PathSegment::MISSING);
77        Self {
78            ctx,
79            on_diagnostic,
80            path,
81            segments,
82            current_segment_idx: 0,
83            current_or_prev_segment: first_segment,
84        }
85    }
86
87    #[track_caller]
88    pub(crate) fn expect_table(&mut self) -> &mut InferenceTable<'db> {
89        self.ctx.expect_table()
90    }
91
92    #[inline]
93    #[cold]
94    fn on_diagnostic(&mut self, diag: PathLoweringDiagnostic) {
95        (self.on_diagnostic.callback)(&self.on_diagnostic.data, self.ctx, diag);
96    }
97
98    #[inline]
99    pub(crate) fn ty_ctx(&mut self) -> &mut TyLoweringContext<'db, 'b> {
100        self.ctx
101    }
102
103    #[inline]
104    fn current_segment_u32(&self) -> u32 {
105        self.current_segment_idx as u32
106    }
107
108    #[inline]
109    fn skip_resolved_segment(&mut self) {
110        if !matches!(self.path, Path::LangItem(..)) {
111            // In lang items, the resolved "segment" is not one of the segments. Perhaps we should've put it
112            // point at -1, but I don't feel this is clearer.
113            self.current_segment_idx += 1;
114        }
115        self.update_current_segment();
116    }
117
118    #[inline]
119    fn update_current_segment(&mut self) {
120        self.current_or_prev_segment =
121            self.segments.get(self.current_segment_idx).unwrap_or(self.current_or_prev_segment);
122    }
123
124    #[inline]
125    pub(crate) fn ignore_last_segment(&mut self) {
126        self.segments = self.segments.strip_last();
127    }
128
129    #[inline]
130    pub(crate) fn set_current_segment(&mut self, segment: usize) {
131        self.current_segment_idx = segment;
132        self.current_or_prev_segment = self
133            .segments
134            .get(segment)
135            .expect("invalid segment passed to PathLoweringContext::set_current_segment()");
136    }
137
138    #[inline]
139    fn with_lifetime_elision<T>(
140        &mut self,
141        lifetime_elision: LifetimeElisionKind<'db>,
142        f: impl FnOnce(&mut PathLoweringContext<'_, '_, 'db>) -> T,
143    ) -> T {
144        let old_lifetime_elision =
145            std::mem::replace(&mut self.ctx.lifetime_elision, lifetime_elision);
146        let result = f(self);
147        self.ctx.lifetime_elision = old_lifetime_elision;
148        result
149    }
150
151    pub(crate) fn lower_ty_relative_path(
152        &mut self,
153        ty: Ty<'db>,
154        // We need the original resolution to lower `Self::AssocTy` correctly
155        res: Option<TypeNs>,
156        infer_args: bool,
157        span: Span,
158    ) -> (Ty<'db>, Option<TypeNs>) {
159        let remaining_segments = self.segments.len() - self.current_segment_idx;
160        match remaining_segments {
161            0 => (ty, res),
162            1 => {
163                // resolve unselected assoc types
164                (self.select_associated_type(res, infer_args, span), None)
165            }
166            _ => {
167                // FIXME report error (ambiguous associated type)
168                (self.ctx.types.types.error, None)
169            }
170        }
171    }
172
173    // When calling this, the current segment is the resolved segment (we don't advance it yet).
174    pub(crate) fn lower_partly_resolved_path(
175        &mut self,
176        resolution: TypeNs,
177        infer_args: bool,
178        span: Span,
179    ) -> (Ty<'db>, Option<TypeNs>) {
180        let remaining_segments = self.segments.skip(self.current_segment_idx + 1);
181        tracing::debug!(?remaining_segments);
182        let rem_seg_len = remaining_segments.len();
183        tracing::debug!(?rem_seg_len);
184
185        let ty = match resolution {
186            TypeNs::TraitId(trait_) => {
187                let ty = match remaining_segments.len() {
188                    1 => {
189                        let trait_ref = self.lower_trait_ref_from_resolved_path(
190                            trait_,
191                            self.ctx.types.types.error,
192                            infer_args,
193                            span,
194                        );
195                        tracing::debug!(?trait_ref);
196                        self.skip_resolved_segment();
197                        let segment = self.current_or_prev_segment;
198                        let trait_id = trait_ref.def_id.0;
199                        let found =
200                            trait_id.trait_items(self.ctx.db).associated_type_by_name(segment.name);
201
202                        tracing::debug!(?found);
203                        match found {
204                            Some(associated_ty) => {
205                                // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
206                                // generic params. It's inefficient to splice the `Substitution`s, so we may want
207                                // that method to optionally take parent `Substitution` as we already know them at
208                                // this point (`trait_ref.substitution`).
209                                let substitution = self.substs_from_path_segment(
210                                    associated_ty.into(),
211                                    infer_args,
212                                    None,
213                                    true,
214                                    span,
215                                );
216                                let args = GenericArgs::new_from_iter(
217                                    trait_ref
218                                        .args
219                                        .iter()
220                                        .chain(substitution.iter().skip(trait_ref.args.len())),
221                                );
222                                Ty::new_alias(
223                                    self.ctx.interner,
224                                    AliasTy::new_from_args(
225                                        self.ctx.interner,
226                                        AliasTyKind::Projection { def_id: associated_ty.into() },
227                                        args,
228                                    ),
229                                )
230                            }
231                            None => {
232                                // FIXME: report error (associated type not found)
233                                self.ctx.types.types.error
234                            }
235                        }
236                    }
237                    0 => {
238                        // Trait object type without dyn; this should be handled in upstream. See
239                        // `lower_path()`.
240                        stdx::never!("unexpected fully resolved trait path");
241                        self.ctx.types.types.error
242                    }
243                    _ => {
244                        // FIXME report error (ambiguous associated type)
245                        self.ctx.types.types.error
246                    }
247                };
248                return (ty, None);
249            }
250            TypeNs::GenericParam(param_id) => {
251                let generics = self.ctx.generics();
252                let idx = generics.type_or_const_param_idx(param_id.into());
253                self.ctx.type_param(param_id, idx)
254            }
255            TypeNs::SelfType(impl_id) => self.ctx.db.impl_self_ty(impl_id).skip_binder(),
256            TypeNs::AdtSelfType(adt) => {
257                let args = GenericArgs::identity_for_item(self.ctx.interner, adt.into());
258                Ty::new_adt(self.ctx.interner, adt, args)
259            }
260
261            TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args, span),
262            TypeNs::BuiltinType(it) => self.lower_path_inner(it.into(), infer_args, span),
263            TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args, span),
264            // FIXME: report error
265            TypeNs::EnumVariantId(_) | TypeNs::ModuleId(_) => {
266                return (self.ctx.types.types.error, None);
267            }
268        };
269
270        tracing::debug!(?ty);
271
272        self.skip_resolved_segment();
273        self.lower_ty_relative_path(ty, Some(resolution), infer_args, span)
274    }
275
276    /// This returns whether to keep the resolution (`true`) of throw it (`false`).
277    #[must_use]
278    fn handle_type_ns_resolution(&mut self, resolution: &TypeNs) -> bool {
279        let mut prohibit_generics_on_resolved = |reason| {
280            if self.current_or_prev_segment.args_and_bindings.is_some() {
281                let segment = self.current_segment_u32();
282                self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
283                    segment,
284                    reason,
285                });
286            }
287        };
288
289        match resolution {
290            TypeNs::SelfType(_) => {
291                prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy)
292            }
293            TypeNs::GenericParam(_) => {
294                prohibit_generics_on_resolved(GenericArgsProhibitedReason::TyParam)
295            }
296            TypeNs::AdtSelfType(_) => {
297                prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy);
298
299                if self.ctx.forbid_params_after.is_some()
300                    && self.ctx.forbid_params_after_reason
301                        == ForbidParamsAfterReason::LoweringParamDefault
302                {
303                    // FIXME: Handle other reasons.
304                    let segment = self.current_segment_u32();
305                    self.on_diagnostic(PathLoweringDiagnostic::GenericDefaultRefersToSelf {
306                        segment,
307                    });
308                    return false;
309                }
310            }
311            TypeNs::BuiltinType(_) => {
312                prohibit_generics_on_resolved(GenericArgsProhibitedReason::PrimitiveTy)
313            }
314            TypeNs::ModuleId(_) => {
315                prohibit_generics_on_resolved(GenericArgsProhibitedReason::Module)
316            }
317            TypeNs::AdtId(_)
318            | TypeNs::EnumVariantId(_)
319            | TypeNs::TypeAliasId(_)
320            | TypeNs::TraitId(_) => {}
321        }
322
323        true
324    }
325
326    pub(crate) fn resolve_path_in_type_ns_fully(&mut self) -> Option<TypeNs> {
327        let (res, unresolved) = self.resolve_path_in_type_ns()?;
328        if unresolved.is_some() {
329            return None;
330        }
331        Some(res)
332    }
333
334    #[tracing::instrument(skip(self), ret)]
335    pub(crate) fn resolve_path_in_type_ns(&mut self) -> Option<(TypeNs, Option<usize>)> {
336        let (resolution, remaining_index, _, prefix_info, _) =
337            self.ctx.resolver.resolve_path_in_type_ns_with_prefix_info(self.ctx.db, self.path)?;
338
339        let segments = self.segments;
340        if segments.is_empty() || matches!(self.path, Path::LangItem(..)) {
341            // `segments.is_empty()` can occur with `self`.
342            return Some((resolution, remaining_index));
343        }
344
345        let (module_segments, resolved_segment_idx, enum_segment) = match remaining_index {
346            None if prefix_info.enum_variant => {
347                (segments.strip_last_two(), segments.len() - 1, Some(segments.len() - 2))
348            }
349            None => (segments.strip_last(), segments.len() - 1, None),
350            Some(i) => (segments.take(i - 1), i - 1, None),
351        };
352
353        self.current_segment_idx = resolved_segment_idx;
354        self.current_or_prev_segment =
355            segments.get(resolved_segment_idx).expect("should have resolved segment");
356
357        for (i, mod_segment) in module_segments.iter().enumerate() {
358            if mod_segment.args_and_bindings.is_some() {
359                self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
360                    segment: i as u32,
361                    reason: GenericArgsProhibitedReason::Module,
362                });
363            }
364        }
365
366        if let Some(enum_segment) = enum_segment
367            && segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
368            && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
369        {
370            self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
371                segment: (enum_segment + 1) as u32,
372                reason: GenericArgsProhibitedReason::EnumVariant,
373            });
374        }
375
376        if !self.handle_type_ns_resolution(&resolution) {
377            return None;
378        }
379
380        Some((resolution, remaining_index))
381    }
382
383    pub(crate) fn resolve_path_in_value_ns(
384        &mut self,
385        hygiene_id: HygieneId,
386    ) -> Option<ResolveValueResult> {
387        let (res, prefix_info, _) = self.ctx.resolver.resolve_path_in_value_ns_with_prefix_info(
388            self.ctx.db,
389            self.path,
390            hygiene_id,
391        )?;
392
393        let segments = self.segments;
394        if segments.is_empty() || matches!(self.path, Path::LangItem(..)) {
395            // `segments.is_empty()` can occur with `self`.
396            return Some(res);
397        }
398
399        let (mod_segments, enum_segment, resolved_segment_idx) = match res {
400            ResolveValueResult::Partial(_, unresolved_segment) => {
401                (segments.take(unresolved_segment - 1), None, unresolved_segment - 1)
402            }
403            ResolveValueResult::ValueNs(ValueNs::EnumVariantId(_)) if prefix_info.enum_variant => {
404                (segments.strip_last_two(), segments.len().checked_sub(2), segments.len() - 1)
405            }
406            ResolveValueResult::ValueNs(..) => (segments.strip_last(), None, segments.len() - 1),
407        };
408
409        self.current_segment_idx = resolved_segment_idx;
410        self.current_or_prev_segment =
411            segments.get(resolved_segment_idx).expect("should have resolved segment");
412
413        for (i, mod_segment) in mod_segments.iter().enumerate() {
414            if mod_segment.args_and_bindings.is_some() {
415                self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
416                    segment: i as u32,
417                    reason: GenericArgsProhibitedReason::Module,
418                });
419            }
420        }
421
422        if let Some(enum_segment) = enum_segment
423            && segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
424            && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
425        {
426            self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
427                segment: (enum_segment + 1) as u32,
428                reason: GenericArgsProhibitedReason::EnumVariant,
429            });
430        }
431
432        match &res {
433            ResolveValueResult::ValueNs(resolution) => {
434                let resolved_segment_idx = self.current_segment_u32();
435                let resolved_segment = self.current_or_prev_segment;
436
437                let mut prohibit_generics_on_resolved = |reason| {
438                    if resolved_segment.args_and_bindings.is_some() {
439                        self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
440                            segment: resolved_segment_idx,
441                            reason,
442                        });
443                    }
444                };
445
446                match resolution {
447                    ValueNs::ImplSelf(_) => {
448                        prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy);
449                    }
450                    // FIXME: rustc generates E0107 (incorrect number of generic arguments) and not
451                    // E0109 (generic arguments provided for a type that doesn't accept them) for
452                    // consts and statics, presumably as a defense against future in which consts
453                    // and statics can be generic, or just because it was easier for rustc implementors.
454                    // That means we'll show the wrong error code. Because of us it's easier to do it
455                    // this way :)
456                    ValueNs::GenericParam(_) => {
457                        prohibit_generics_on_resolved(GenericArgsProhibitedReason::Const)
458                    }
459                    ValueNs::StaticId(_) => {
460                        prohibit_generics_on_resolved(GenericArgsProhibitedReason::Static)
461                    }
462                    ValueNs::LocalBinding(_) => {
463                        prohibit_generics_on_resolved(GenericArgsProhibitedReason::LocalVariable)
464                    }
465                    ValueNs::FunctionId(_)
466                    | ValueNs::StructId(_)
467                    | ValueNs::EnumVariantId(_)
468                    | ValueNs::ConstId(_) => {}
469                }
470            }
471            ResolveValueResult::Partial(resolution, _) => {
472                if !self.handle_type_ns_resolution(resolution) {
473                    return None;
474                }
475            }
476        };
477        Some(res)
478    }
479
480    #[tracing::instrument(skip(self), ret)]
481    fn select_associated_type(
482        &mut self,
483        res: Option<TypeNs>,
484        infer_args: bool,
485        span: Span,
486    ) -> Ty<'db> {
487        let interner = self.ctx.interner;
488        let db = self.ctx.db;
489        let def = self.ctx.generic_def;
490        let segment = self.current_or_prev_segment;
491        let assoc_name = segment.name;
492        let (assoc_type, trait_args) = match res {
493            Some(TypeNs::GenericParam(param)) => {
494                let AssocTypeShorthandResolution::Resolved(assoc_type) =
495                    super::resolve_type_param_assoc_type_shorthand(
496                        db,
497                        def,
498                        param,
499                        assoc_name.clone(),
500                    )
501                else {
502                    self.on_diagnostic(PathLoweringDiagnostic::UnresolvedAssociatedType {
503                        segment: self.current_segment_u32(),
504                    });
505                    return self.ctx.types.types.error;
506                };
507                assoc_type
508                    .get_with(|(assoc_type, trait_args)| (*assoc_type, trait_args.as_ref()))
509                    .skip_binder()
510            }
511            Some(TypeNs::SelfType(impl_)) => {
512                let Some(impl_trait) = db.impl_trait(impl_) else {
513                    return self.ctx.types.types.error;
514                };
515                let impl_trait = impl_trait.instantiate_identity().skip_norm_wip();
516                // Searching for `Self::Assoc` in `impl Trait for Type` is like searching for `Self::Assoc` in `Trait`.
517                let AssocTypeShorthandResolution::Resolved(assoc_type) =
518                    super::resolve_type_param_assoc_type_shorthand(
519                        db,
520                        impl_trait.def_id.0.into(),
521                        TypeParamId::trait_self(impl_trait.def_id.0),
522                        assoc_name.clone(),
523                    )
524                else {
525                    self.on_diagnostic(PathLoweringDiagnostic::UnresolvedAssociatedType {
526                        segment: self.current_segment_u32(),
527                    });
528                    return self.ctx.types.types.error;
529                };
530                let (assoc_type, trait_args) = assoc_type
531                    .get_with(|(assoc_type, trait_args)| (*assoc_type, trait_args.as_ref()))
532                    .skip_binder();
533                (
534                    assoc_type,
535                    EarlyBinder::bind(trait_args)
536                        .instantiate(interner, impl_trait.args)
537                        .skip_norm_wip(),
538                )
539            }
540            _ => return self.ctx.types.types.error,
541        };
542
543        // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
544        // generic params. It's inefficient to splice the `Substitution`s, so we may want
545        // that method to optionally take parent `Substitution` as we already know them at
546        // this point (`t.substitution`).
547        let substs = self.substs_from_path_segment(assoc_type.into(), infer_args, None, true, span);
548
549        let substs = GenericArgs::new_from_iter(
550            trait_args.iter().chain(substs.iter().skip(trait_args.len())),
551        );
552
553        Ty::new_projection_from_args(interner, assoc_type.into(), substs)
554    }
555
556    fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool, span: Span) -> Ty<'db> {
557        let generic_def = match typeable {
558            TyDefId::BuiltinType(builtinty) => {
559                return Ty::from_builtin_type(self.ctx.interner, builtinty);
560            }
561            TyDefId::AdtId(it) => it.into(),
562            TyDefId::TypeAliasId(it) => it.into(),
563        };
564        let args = self.substs_from_path_segment(generic_def, infer_args, None, false, span);
565        let ty = ty_query(self.ctx.db, typeable);
566        ty.instantiate(self.ctx.interner, args).skip_norm_wip()
567    }
568
569    /// Collect generic arguments from a path into a `Substs`. See also
570    /// `create_substs_for_ast_path` and `def_to_ty` in rustc.
571    pub(crate) fn substs_from_path(
572        &mut self,
573        // Note that we don't call `db.value_type(resolved)` here,
574        // `ValueTyDefId` is just a convenient way to pass generics and
575        // special-case enum variants
576        resolved: ValueTyDefId,
577        infer_args: bool,
578        lowering_assoc_type_generics: bool,
579        span: Span,
580    ) -> GenericArgs<'db> {
581        let prev_current_segment_idx = self.current_segment_idx;
582        let prev_current_segment = self.current_or_prev_segment;
583
584        let generic_def = match resolved {
585            ValueTyDefId::FunctionId(it) => it.into(),
586            ValueTyDefId::StructId(it) => it.into(),
587            ValueTyDefId::UnionId(it) => it.into(),
588            ValueTyDefId::ConstId(it) => it.into(),
589            ValueTyDefId::StaticId(_) => {
590                return GenericArgs::empty();
591            }
592            ValueTyDefId::EnumVariantId(var) => {
593                // the generic args for an enum variant may be either specified
594                // on the segment referring to the enum, or on the segment
595                // referring to the variant. So `Option::<T>::None` and
596                // `Option::None::<T>` are both allowed (though the former is
597                // FIXME: This isn't strictly correct, enum variants may be used not through the enum
598                // (via `use Enum::Variant`). The resolver returns whether they were, but we don't have its result
599                // available here. The worst that can happen is that we will show some confusing diagnostics to the user,
600                // if generics exist on the module and they don't match with the variant.
601                // preferred). See also `def_ids_for_path_segments` in rustc.
602                //
603                // `wrapping_sub(1)` will return a number which `get` will return None for if current_segment_idx<2.
604                // This simplifies the code a bit.
605                let penultimate_idx = self.current_segment_idx.wrapping_sub(1);
606                let penultimate = self.segments.get(penultimate_idx);
607                if let Some(penultimate) = penultimate
608                    && self.current_or_prev_segment.args_and_bindings.is_none()
609                    && penultimate.args_and_bindings.is_some()
610                {
611                    self.current_segment_idx = penultimate_idx;
612                    self.current_or_prev_segment = penultimate;
613                }
614                var.lookup(self.ctx.db).parent.into()
615            }
616        };
617        let result = self.substs_from_path_segment(
618            generic_def,
619            infer_args,
620            None,
621            lowering_assoc_type_generics,
622            span,
623        );
624        self.current_segment_idx = prev_current_segment_idx;
625        self.current_or_prev_segment = prev_current_segment;
626        result
627    }
628
629    pub(crate) fn substs_from_path_segment(
630        &mut self,
631        def: GenericDefId,
632        infer_args: bool,
633        explicit_self_ty: Option<Ty<'db>>,
634        lowering_assoc_type_generics: bool,
635        span: Span,
636    ) -> GenericArgs<'db> {
637        let old_lifetime_elision = self.ctx.lifetime_elision;
638
639        if let Some(args) = self.current_or_prev_segment.args_and_bindings
640            && args.parenthesized != GenericArgsParentheses::No
641        {
642            let prohibit_parens = match def {
643                GenericDefId::TraitId(trait_) => {
644                    // RTN is prohibited anyways if we got here.
645                    let is_rtn = args.parenthesized == GenericArgsParentheses::ReturnTypeNotation;
646                    let is_fn_trait = TraitSignature::of(self.ctx.db, trait_)
647                        .flags
648                        .contains(TraitFlags::RUSTC_PAREN_SUGAR);
649                    is_rtn || !is_fn_trait
650                }
651                _ => true,
652            };
653
654            if prohibit_parens {
655                let segment = self.current_segment_u32();
656                self.on_diagnostic(
657                    PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment },
658                );
659
660                return GenericArgs::error_for_item(self.ctx.interner, def.into());
661            }
662
663            // `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
664            self.ctx.lifetime_elision =
665                LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false };
666        }
667
668        let result = self.substs_from_args_and_bindings(
669            self.current_or_prev_segment.args_and_bindings,
670            def,
671            infer_args,
672            explicit_self_ty,
673            PathGenericsSource::Segment(self.current_segment_u32()),
674            lowering_assoc_type_generics,
675            self.ctx.lifetime_elision,
676            span,
677        );
678        self.ctx.lifetime_elision = old_lifetime_elision;
679        result
680    }
681
682    pub(super) fn substs_from_args_and_bindings(
683        &mut self,
684        args_and_bindings: Option<&HirGenericArgs>,
685        def: GenericDefId,
686        infer_args: bool,
687        explicit_self_ty: Option<Ty<'db>>,
688        generics_source: PathGenericsSource,
689        lowering_assoc_type_generics: bool,
690        lifetime_elision: LifetimeElisionKind<'db>,
691        span: Span,
692    ) -> GenericArgs<'db> {
693        struct LowererCtx<'a, 'b, 'c, 'db> {
694            ctx: &'a mut PathLoweringContext<'b, 'c, 'db>,
695            generics_source: PathGenericsSource,
696            span: Span,
697        }
698
699        impl<'db> GenericArgsLowerer<'db> for LowererCtx<'_, '_, '_, 'db> {
700            fn report_len_mismatch(
701                &mut self,
702                def: GenericDefId,
703                provided_count: u32,
704                expected_count: u32,
705                kind: IncorrectGenericsLenKind,
706            ) {
707                self.ctx.on_diagnostic(PathLoweringDiagnostic::IncorrectGenericsLen {
708                    generics_source: self.generics_source,
709                    provided_count,
710                    expected_count,
711                    kind,
712                    def,
713                });
714            }
715
716            fn report_arg_mismatch(
717                &mut self,
718                param_id: GenericParamId,
719                arg_idx: u32,
720                has_self_arg: bool,
721            ) {
722                self.ctx.on_diagnostic(PathLoweringDiagnostic::IncorrectGenericsOrder {
723                    generics_source: self.generics_source,
724                    param_id,
725                    arg_idx,
726                    has_self_arg,
727                });
728            }
729
730            fn provided_kind(
731                &mut self,
732                param_id: GenericParamId,
733                param: GenericParamDataRef<'_>,
734                arg: &HirGenericArg,
735            ) -> GenericArg<'db> {
736                match (param, *arg) {
737                    (
738                        GenericParamDataRef::LifetimeParamData(_),
739                        HirGenericArg::Lifetime(lifetime),
740                    ) => self.ctx.ctx.lower_lifetime(lifetime).into(),
741                    (GenericParamDataRef::TypeParamData(_), HirGenericArg::Type(type_ref)) => {
742                        self.ctx.ctx.lower_ty(type_ref).into()
743                    }
744                    (GenericParamDataRef::ConstParamData(_), HirGenericArg::Const(konst)) => {
745                        let GenericParamId::ConstParamId(const_id) = param_id else {
746                            unreachable!("non-const param ID for const param");
747                        };
748                        self.ctx
749                            .ctx
750                            .lower_const(konst, const_param_ty(self.ctx.ctx.db, const_id), false)
751                            .into()
752                    }
753                    _ => unreachable!("unmatching param kinds were passed to `provided_kind()`"),
754                }
755            }
756
757            fn provided_type_like_const(
758                &mut self,
759                type_ref: TypeRefId,
760                const_ty: Ty<'db>,
761                arg: TypeLikeConst<'_>,
762            ) -> Const<'db> {
763                match arg {
764                    TypeLikeConst::Path(path) => self.ctx.ctx.lower_path_as_const(path, const_ty),
765                    TypeLikeConst::Infer => self.ctx.ctx.next_const_var(type_ref.into()),
766                }
767            }
768
769            fn inferred_kind(
770                &mut self,
771                def: GenericDefId,
772                param_id: GenericParamId,
773                param: GenericParamDataRef<'_>,
774                infer_args: bool,
775                preceding_args: &[GenericArg<'db>],
776                had_count_error: bool,
777            ) -> GenericArg<'db> {
778                let default = || {
779                    self.ctx.ctx.db.generic_defaults(def).get(preceding_args.len()).map(|default| {
780                        default.instantiate(self.ctx.ctx.interner, preceding_args).skip_norm_wip()
781                    })
782                };
783                // If `!infer_args`, we've already emitted an error, so put a dummy span.
784                let span = if !infer_args || had_count_error { Span::Dummy } else { self.span };
785                match param {
786                    GenericParamDataRef::LifetimeParamData(_) => {
787                        self.ctx.ctx.next_region_var(span).into()
788                    }
789                    GenericParamDataRef::TypeParamData(param) => {
790                        if !infer_args
791                            && param.default.is_some()
792                            && let Some(default) = default()
793                        {
794                            return default;
795                        }
796                        self.ctx.ctx.next_ty_var(span).into()
797                    }
798                    GenericParamDataRef::ConstParamData(param) => {
799                        if !infer_args
800                            && param.default.is_some()
801                            && let Some(default) = default()
802                        {
803                            return default;
804                        }
805                        let GenericParamId::ConstParamId(_) = param_id else {
806                            unreachable!("non-const param ID for const param");
807                        };
808                        self.ctx.ctx.next_const_var(span).into()
809                    }
810                }
811            }
812
813            fn parent_arg(&mut self, _param_idx: u32, param_id: GenericParamId) -> GenericArg<'db> {
814                match param_id {
815                    GenericParamId::TypeParamId(_) => {
816                        Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into()
817                    }
818                    GenericParamId::ConstParamId(_) => self.ctx.ctx.types.consts.error.into(),
819                    GenericParamId::LifetimeParamId(_) => self.ctx.ctx.types.regions.error.into(),
820                }
821            }
822
823            fn report_elided_lifetimes_in_path(
824                &mut self,
825                def: GenericDefId,
826                expected_count: u32,
827                hard_error: bool,
828            ) {
829                self.ctx.on_diagnostic(PathLoweringDiagnostic::ElidedLifetimesInPath {
830                    generics_source: self.generics_source,
831                    def,
832                    expected_count,
833                    hard_error,
834                });
835            }
836
837            fn report_elision_failure(&mut self, def: GenericDefId, expected_count: u32) {
838                self.ctx.on_diagnostic(PathLoweringDiagnostic::ElisionFailure {
839                    generics_source: self.generics_source,
840                    def,
841                    expected_count,
842                });
843            }
844
845            fn report_missing_lifetime(&mut self, def: GenericDefId, expected_count: u32) {
846                self.ctx.on_diagnostic(PathLoweringDiagnostic::MissingLifetime {
847                    generics_source: self.generics_source,
848                    def,
849                    expected_count,
850                });
851            }
852        }
853
854        substs_from_args_and_bindings(
855            self.ctx.db,
856            self.ctx.store,
857            args_and_bindings,
858            def,
859            infer_args,
860            lifetime_elision,
861            lowering_assoc_type_generics,
862            explicit_self_ty,
863            &mut LowererCtx { ctx: self, generics_source, span },
864        )
865    }
866
867    pub(crate) fn lower_trait_ref_from_resolved_path(
868        &mut self,
869        resolved: TraitId,
870        explicit_self_ty: Ty<'db>,
871        infer_args: bool,
872        span: Span,
873    ) -> TraitRef<'db> {
874        let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args, span);
875        TraitRef::new_from_args(self.ctx.interner, resolved.into(), args)
876    }
877
878    fn trait_ref_substs_from_path(
879        &mut self,
880        resolved: TraitId,
881        explicit_self_ty: Ty<'db>,
882        infer_args: bool,
883        span: Span,
884    ) -> GenericArgs<'db> {
885        self.substs_from_path_segment(
886            resolved.into(),
887            infer_args,
888            Some(explicit_self_ty),
889            false,
890            span,
891        )
892    }
893
894    pub(super) fn assoc_type_bindings_from_type_bound(
895        mut self,
896        trait_ref: TraitRef<'db>,
897        span: Span,
898    ) -> Option<impl Iterator<Item = (Clause<'db>, GenericPredicateSource)> + use<'a, 'b, 'db>>
899    {
900        let interner = self.ctx.interner;
901        self.current_or_prev_segment.args_and_bindings.map(|args_and_bindings| {
902            args_and_bindings.bindings.iter().enumerate().flat_map(move |(binding_idx, binding)| {
903                let found = associated_type_by_name_including_super_traits_allow_ambiguity(
904                    self.ctx.db,
905                    trait_ref,
906                    binding.name.clone(),
907                );
908                let (associated_ty, super_trait_args) = match found {
909                    None => return SmallVec::new(),
910                    Some(t) => t,
911                };
912                let args =
913                    self.with_lifetime_elision(LifetimeElisionKind::AnonymousReportError, |this| {
914                        // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
915                        // generic params. It's inefficient to splice the `Substitution`s, so we may want
916                        // that method to optionally take parent `Substitution` as we already know them at
917                        // this point (`super_trait_ref.substitution`).
918                        this.substs_from_args_and_bindings(
919                            binding.args.as_ref(),
920                            associated_ty.into(),
921                            false, // this is not relevant
922                            Some(super_trait_args.type_at(0)),
923                            PathGenericsSource::AssocType {
924                                segment: this.current_segment_u32(),
925                                assoc_type: binding_idx as u32,
926                            },
927                            false,
928                            this.ctx.lifetime_elision,
929                            span,
930                        )
931                    });
932                let args = GenericArgs::new_from_iter(
933                    super_trait_args.iter().chain(args.iter().skip(super_trait_args.len())),
934                );
935                let projection_term = AliasTerm::new_from_args(
936                    interner,
937                    AliasTermKind::ProjectionTy { def_id: associated_ty.into() },
938                    args,
939                );
940                let mut predicates: SmallVec<[_; 1]> = SmallVec::with_capacity(
941                    binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
942                );
943                if let Some(type_ref) = binding.type_ref {
944                    let lifetime_elision =
945                        if args_and_bindings.parenthesized == GenericArgsParentheses::ParenSugar {
946                            // `Fn()`-style generics are elided like functions. This is `Output` (we lower to it in hir-def).
947                            LifetimeElisionKind::for_fn_ret(self.ctx.interner)
948                        } else {
949                            self.ctx.lifetime_elision
950                        };
951                    self.with_lifetime_elision(lifetime_elision, |this| {
952                        match (&this.ctx.store[type_ref], this.ctx.impl_trait_mode.mode) {
953                            (TypeRef::ImplTrait(_), ImplTraitLoweringMode::Disallowed) => (),
954                            (
955                                _,
956                                ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque,
957                            ) => {
958                                let ty = this.ctx.lower_ty(type_ref);
959                                let bound_vars = this.ctx.peek_bound_vars();
960                                let pred = Clause(Predicate::new(
961                                    interner,
962                                    Binder::bind_with_vars(
963                                        rustc_type_ir::PredicateKind::Clause(
964                                            rustc_type_ir::ClauseKind::Projection(
965                                                ProjectionPredicate {
966                                                    projection_term,
967                                                    term: ty.into(),
968                                                },
969                                            ),
970                                        ),
971                                        bound_vars,
972                                    ),
973                                ));
974                                predicates.push((pred, GenericPredicateSource::SelfOnly));
975                            }
976                        }
977                    })
978                }
979                for bound in binding.bounds.iter() {
980                    predicates.extend(
981                        self.ctx
982                            .lower_type_bound(
983                                bound,
984                                Ty::new_alias(
985                                    self.ctx.interner,
986                                    AliasTy::new_from_args(
987                                        self.ctx.interner,
988                                        AliasTyKind::Projection { def_id: associated_ty.into() },
989                                        args,
990                                    ),
991                                ),
992                                false,
993                            )
994                            .map(|(pred, _)| (pred, GenericPredicateSource::AssocTyBound)),
995                    );
996                }
997                predicates
998            })
999        })
1000    }
1001
1002    pub(crate) fn interner(&self) -> DbInterner<'db> {
1003        self.ctx.interner
1004    }
1005}
1006
1007/// A const that were parsed like a type.
1008pub(crate) enum TypeLikeConst<'a> {
1009    Infer,
1010    Path(&'a Path),
1011}
1012
1013pub(crate) trait GenericArgsLowerer<'db> {
1014    fn report_elided_lifetimes_in_path(
1015        &mut self,
1016        def: GenericDefId,
1017        expected_count: u32,
1018        hard_error: bool,
1019    );
1020
1021    fn report_elision_failure(&mut self, def: GenericDefId, expected_count: u32);
1022
1023    fn report_missing_lifetime(&mut self, def: GenericDefId, expected_count: u32);
1024
1025    fn report_len_mismatch(
1026        &mut self,
1027        def: GenericDefId,
1028        provided_count: u32,
1029        expected_count: u32,
1030        kind: IncorrectGenericsLenKind,
1031    );
1032
1033    fn report_arg_mismatch(&mut self, param_id: GenericParamId, arg_idx: u32, has_self_arg: bool);
1034
1035    fn provided_kind(
1036        &mut self,
1037        param_id: GenericParamId,
1038        param: GenericParamDataRef<'_>,
1039        arg: &HirGenericArg,
1040    ) -> GenericArg<'db>;
1041
1042    fn provided_type_like_const(
1043        &mut self,
1044        type_ref: TypeRefId,
1045        const_ty: Ty<'db>,
1046        arg: TypeLikeConst<'_>,
1047    ) -> Const<'db>;
1048
1049    fn inferred_kind(
1050        &mut self,
1051        def: GenericDefId,
1052        param_id: GenericParamId,
1053        param: GenericParamDataRef<'_>,
1054        infer_args: bool,
1055        preceding_args: &[GenericArg<'db>],
1056        had_count_error: bool,
1057    ) -> GenericArg<'db>;
1058
1059    fn parent_arg(&mut self, param_idx: u32, param_id: GenericParamId) -> GenericArg<'db>;
1060}
1061
1062/// Returns true if there was an error.
1063fn check_generic_args_len<'db>(
1064    args_and_bindings: Option<&HirGenericArgs>,
1065    def: GenericDefId,
1066    def_generics: &Generics<'db>,
1067    infer_args: bool,
1068    lifetime_elision: &LifetimeElisionKind<'db>,
1069    lowering_assoc_type_generics: bool,
1070    ctx: &mut impl GenericArgsLowerer<'db>,
1071) -> bool {
1072    let mut had_error = false;
1073
1074    let (mut provided_lifetimes_count, mut provided_types_and_consts_count) = (0usize, 0usize);
1075    if let Some(args_and_bindings) = args_and_bindings {
1076        let args_no_self = &args_and_bindings.args[usize::from(args_and_bindings.has_self_type)..];
1077        for arg in args_no_self {
1078            match arg {
1079                HirGenericArg::Lifetime(_) => provided_lifetimes_count += 1,
1080                HirGenericArg::Type(_) | HirGenericArg::Const(_) => {
1081                    provided_types_and_consts_count += 1
1082                }
1083            }
1084        }
1085    }
1086
1087    let lifetime_args_len = def_generics.len_lifetimes_self();
1088    if provided_lifetimes_count == 0
1089        && lifetime_args_len > 0
1090        && (!lowering_assoc_type_generics || infer_args)
1091    {
1092        // In generic associated types, we never allow inferring the lifetimes, but only in type context, that is
1093        // when `infer_args == false`. In expression/pattern context we always allow inferring them, even for GATs.
1094        match lifetime_elision {
1095            &LifetimeElisionKind::AnonymousCreateParameter { report_in_path } => {
1096                ctx.report_elided_lifetimes_in_path(def, lifetime_args_len as u32, report_in_path);
1097                had_error |= report_in_path;
1098            }
1099            LifetimeElisionKind::AnonymousReportError => {
1100                ctx.report_missing_lifetime(def, lifetime_args_len as u32);
1101                had_error = true
1102            }
1103            LifetimeElisionKind::ElisionFailure => {
1104                ctx.report_elision_failure(def, lifetime_args_len as u32);
1105                had_error = true;
1106            }
1107            LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => {
1108                // FIXME: Check there are other lifetimes in scope, and error/lint.
1109            }
1110            LifetimeElisionKind::Elided(_) => {
1111                ctx.report_elided_lifetimes_in_path(def, lifetime_args_len as u32, false);
1112            }
1113            LifetimeElisionKind::Infer => {
1114                // Allow eliding lifetimes.
1115            }
1116        }
1117    } else if lifetime_args_len != provided_lifetimes_count {
1118        ctx.report_len_mismatch(
1119            def,
1120            provided_lifetimes_count as u32,
1121            lifetime_args_len as u32,
1122            IncorrectGenericsLenKind::Lifetimes,
1123        );
1124        had_error = true;
1125    }
1126
1127    let defaults_count =
1128        def_generics.iter_self_type_or_consts().filter(|(_, param)| param.has_default()).count();
1129    let named_type_and_const_params_count = def_generics
1130        .iter_self_type_or_consts()
1131        .filter(|(_, param)| match param {
1132            TypeOrConstParamData::TypeParamData(param) => {
1133                param.provenance == TypeParamProvenance::TypeParamList
1134            }
1135            TypeOrConstParamData::ConstParamData(_) => true,
1136        })
1137        .count();
1138    let expected_max = named_type_and_const_params_count;
1139    let expected_min =
1140        if infer_args { 0 } else { named_type_and_const_params_count - defaults_count };
1141    if provided_types_and_consts_count < expected_min
1142        || expected_max < provided_types_and_consts_count
1143    {
1144        ctx.report_len_mismatch(
1145            def,
1146            provided_types_and_consts_count as u32,
1147            named_type_and_const_params_count as u32,
1148            IncorrectGenericsLenKind::TypesAndConsts,
1149        );
1150        had_error = true;
1151    }
1152
1153    had_error
1154}
1155
1156pub(crate) fn substs_from_args_and_bindings<'db>(
1157    db: &'db dyn HirDatabase,
1158    store: &ExpressionStore,
1159    args_and_bindings: Option<&HirGenericArgs>,
1160    def: GenericDefId,
1161    mut infer_args: bool,
1162    lifetime_elision: LifetimeElisionKind<'db>,
1163    lowering_assoc_type_generics: bool,
1164    explicit_self_ty: Option<Ty<'db>>,
1165    ctx: &mut impl GenericArgsLowerer<'db>,
1166) -> GenericArgs<'db> {
1167    let interner = DbInterner::new_no_crate(db);
1168
1169    tracing::debug!(?args_and_bindings);
1170
1171    // Order is
1172    // - Parent parameters
1173    // - Optional Self parameter
1174    // - Lifetime parameters
1175    // - Type or Const parameters
1176    let def_generics = generics(db, def);
1177    let args_slice = args_and_bindings.map(|it| &*it.args).unwrap_or_default();
1178
1179    // We do not allow inference if there are specified args, i.e. we do not allow partial inference.
1180    let has_non_lifetime_args =
1181        args_slice.iter().any(|arg| !matches!(arg, HirGenericArg::Lifetime(_)));
1182    infer_args &= !has_non_lifetime_args;
1183
1184    let had_count_error = check_generic_args_len(
1185        args_and_bindings,
1186        def,
1187        &def_generics,
1188        infer_args,
1189        &lifetime_elision,
1190        lowering_assoc_type_generics,
1191        ctx,
1192    );
1193
1194    let mut substs = Vec::with_capacity(def_generics.len(true));
1195
1196    substs.extend(
1197        def_generics.iter_parent_id().enumerate().map(|(idx, id)| ctx.parent_arg(idx as u32, id)),
1198    );
1199
1200    let mut args = args_slice.iter().enumerate().peekable();
1201    let mut params = def_generics.iter_self().peekable();
1202
1203    // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
1204    // If we later encounter a lifetime, we know that the arguments were provided in the
1205    // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
1206    // inferred, so we can use it for diagnostics later.
1207    let mut force_infer_lt = None;
1208
1209    let has_self_arg = args_and_bindings.is_some_and(|it| it.has_self_type);
1210    // First, handle `Self` parameter. Consume it from the args if provided, otherwise from `explicit_self_ty`,
1211    // and lastly infer it.
1212    if let Some(&(
1213        self_param_id,
1214        self_param @ GenericParamDataRef::TypeParamData(TypeParamData {
1215            provenance: TypeParamProvenance::TraitSelf,
1216            ..
1217        }),
1218    )) = params.peek()
1219    {
1220        let self_ty = if has_self_arg {
1221            let (_, self_ty) = args.next().expect("has_self_type=true, should have Self type");
1222            ctx.provided_kind(self_param_id, self_param, self_ty)
1223        } else {
1224            explicit_self_ty.map(|it| it.into()).unwrap_or_else(|| {
1225                ctx.inferred_kind(
1226                    def,
1227                    self_param_id,
1228                    self_param,
1229                    infer_args,
1230                    &substs,
1231                    had_count_error,
1232                )
1233            })
1234        };
1235        params.next();
1236        substs.push(self_ty);
1237    } else if has_self_arg {
1238        // A qualified path `<T as Trait>::Assoc` where `Trait` resolved to something without a
1239        // `Self` parameter, e.g. a struct. `check_generic_args_len()` skips the self type
1240        // unconditionally, so drop it here too instead of matching it against a real parameter.
1241        // FIXME: Report a diagnostic here, rustc emits `E0404: expected trait, found struct`.
1242        args.next();
1243    }
1244
1245    loop {
1246        // We're going to iterate through the generic arguments that the user
1247        // provided, matching them with the generic parameters we expect.
1248        // Mismatches can occur as a result of elided lifetimes, or for malformed
1249        // input. We try to handle both sensibly.
1250        match (args.peek(), params.peek()) {
1251            (Some(&(arg_idx, arg)), Some(&(param_id, param))) => match (arg, param) {
1252                (HirGenericArg::Type(_), GenericParamDataRef::TypeParamData(type_param))
1253                    if type_param.provenance == TypeParamProvenance::ArgumentImplTrait =>
1254                {
1255                    // Do not allow specifying `impl Trait` explicitly. We already err at that, but if we won't handle it here
1256                    // we will handle it as if it was specified, instead of inferring it.
1257                    substs.push(ctx.inferred_kind(
1258                        def,
1259                        param_id,
1260                        param,
1261                        infer_args,
1262                        &substs,
1263                        had_count_error,
1264                    ));
1265                    params.next();
1266                }
1267                (HirGenericArg::Lifetime(_), GenericParamDataRef::LifetimeParamData(_))
1268                | (HirGenericArg::Type(_), GenericParamDataRef::TypeParamData(_))
1269                | (HirGenericArg::Const(_), GenericParamDataRef::ConstParamData(_)) => {
1270                    substs.push(ctx.provided_kind(param_id, param, arg));
1271                    args.next();
1272                    params.next();
1273                }
1274                (
1275                    HirGenericArg::Type(_) | HirGenericArg::Const(_),
1276                    GenericParamDataRef::LifetimeParamData(_),
1277                ) => {
1278                    // We expected a lifetime argument, but got a type or const
1279                    // argument. That means we're inferring the lifetime.
1280                    substs.push(ctx.inferred_kind(
1281                        def,
1282                        param_id,
1283                        param,
1284                        infer_args,
1285                        &substs,
1286                        had_count_error,
1287                    ));
1288                    params.next();
1289                    force_infer_lt = Some((arg_idx as u32, param_id));
1290                }
1291                (HirGenericArg::Type(type_ref), GenericParamDataRef::ConstParamData(_)) => {
1292                    if let Some(konst) = type_looks_like_const(store, *type_ref) {
1293                        let GenericParamId::ConstParamId(param_id) = param_id else {
1294                            panic!("unmatching param kinds");
1295                        };
1296                        let const_ty = const_param_ty(db, param_id);
1297                        substs
1298                            .push(ctx.provided_type_like_const(*type_ref, const_ty, konst).into());
1299                        args.next();
1300                        params.next();
1301                    } else {
1302                        // See the `_ => { ... }` branch.
1303                        if !had_count_error {
1304                            ctx.report_arg_mismatch(param_id, arg_idx as u32, has_self_arg);
1305                        }
1306                        while args.next().is_some() {}
1307                    }
1308                }
1309                _ => {
1310                    // We expected one kind of parameter, but the user provided
1311                    // another. This is an error. However, if we already know that
1312                    // the arguments don't match up with the parameters, we won't issue
1313                    // an additional error, as the user already knows what's wrong.
1314                    if !had_count_error {
1315                        ctx.report_arg_mismatch(param_id, arg_idx as u32, has_self_arg);
1316                    }
1317
1318                    // We've reported the error, but we want to make sure that this
1319                    // problem doesn't bubble down and create additional, irrelevant
1320                    // errors. In this case, we're simply going to ignore the argument
1321                    // and any following arguments. The rest of the parameters will be
1322                    // inferred.
1323                    while args.next().is_some() {}
1324                }
1325            },
1326
1327            (Some(&(_, arg)), None) => {
1328                // We should never be able to reach this point with well-formed input.
1329                // There are two situations in which we can encounter this issue.
1330                //
1331                //  1. The number of arguments is incorrect. In this case, an error
1332                //     will already have been emitted, and we can ignore it.
1333                //  2. We've inferred some lifetimes, which have been provided later (i.e.
1334                //     after a type or const). We want to throw an error in this case.
1335                if !had_count_error {
1336                    assert!(
1337                        matches!(arg, HirGenericArg::Lifetime(_)),
1338                        "the only possible situation here is incorrect lifetime order"
1339                    );
1340                    let (provided_arg_idx, param_id) =
1341                        force_infer_lt.expect("lifetimes ought to have been inferred");
1342                    ctx.report_arg_mismatch(param_id, provided_arg_idx, has_self_arg);
1343                }
1344
1345                break;
1346            }
1347
1348            (None, Some(&(param_id, param))) => {
1349                // If there are fewer arguments than parameters, it means we're inferring the remaining arguments.
1350                let param = if let GenericParamId::LifetimeParamId(_) = param_id {
1351                    match &lifetime_elision {
1352                        LifetimeElisionKind::ElisionFailure
1353                        | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }
1354                        | LifetimeElisionKind::AnonymousReportError => {
1355                            assert!(had_count_error);
1356                            ctx.inferred_kind(
1357                                def,
1358                                param_id,
1359                                param,
1360                                infer_args,
1361                                &substs,
1362                                had_count_error,
1363                            )
1364                        }
1365                        LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => {
1366                            Region::new_static(interner).into()
1367                        }
1368                        LifetimeElisionKind::Elided(lifetime) => (*lifetime).into(),
1369                        LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false }
1370                        | LifetimeElisionKind::Infer => {
1371                            // FIXME: With `AnonymousCreateParameter`, we need to create a new lifetime parameter here
1372                            // (but this will probably be done in hir-def lowering instead).
1373                            ctx.inferred_kind(
1374                                def,
1375                                param_id,
1376                                param,
1377                                infer_args,
1378                                &substs,
1379                                had_count_error,
1380                            )
1381                        }
1382                    }
1383                } else {
1384                    ctx.inferred_kind(def, param_id, param, infer_args, &substs, had_count_error)
1385                };
1386                substs.push(param);
1387                params.next();
1388            }
1389
1390            (None, None) => break,
1391        }
1392    }
1393
1394    GenericArgs::new_from_slice(&substs)
1395}
1396
1397fn type_looks_like_const(
1398    store: &ExpressionStore,
1399    type_ref: TypeRefId,
1400) -> Option<TypeLikeConst<'_>> {
1401    // A path/`_` const will be parsed as a type, instead of a const, because when parsing/lowering
1402    // in hir-def we don't yet know the expected argument kind. rustc does this a bit differently,
1403    // when lowering to HIR it resolves the path, and if it doesn't resolve to the type namespace
1404    // it is lowered as a const. Our behavior could deviate from rustc when the value is resolvable
1405    // in both the type and value namespaces, but I believe we only allow more code.
1406    let type_ref = &store[type_ref];
1407    match type_ref {
1408        TypeRef::Path(path) => Some(TypeLikeConst::Path(path)),
1409        TypeRef::Placeholder => Some(TypeLikeConst::Infer),
1410        _ => None,
1411    }
1412}