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