Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lower_nextsolver/path.rs')
-rw-r--r--crates/hir-ty/src/lower_nextsolver/path.rs1354
1 files changed, 0 insertions, 1354 deletions
diff --git a/crates/hir-ty/src/lower_nextsolver/path.rs b/crates/hir-ty/src/lower_nextsolver/path.rs
deleted file mode 100644
index ef2c392f08..0000000000
--- a/crates/hir-ty/src/lower_nextsolver/path.rs
+++ /dev/null
@@ -1,1354 +0,0 @@
-//! A wrapper around [`TyLoweringContext`] specifically for lowering paths.
-
-use std::ops::Deref;
-
-use either::Either;
-use hir_def::{
- AssocItemId, GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId,
- builtin_type::BuiltinType,
- expr_store::{
- ExpressionStore, HygieneId,
- path::{GenericArg, GenericArgs, GenericArgsParentheses, Path, PathSegment, PathSegments},
- },
- hir::generics::{
- GenericParamDataRef, TypeOrConstParamData, TypeParamData, TypeParamProvenance,
- },
- resolver::{ResolveValueResult, TypeNs, ValueNs},
- signatures::TraitFlags,
- type_ref::{TypeRef, TypeRefId},
-};
-use hir_expand::name::Name;
-use intern::sym;
-use rustc_hash::FxHashSet;
-use rustc_type_ir::{
- AliasTerm, AliasTy, AliasTyKind, TypeVisitableExt,
- inherent::{GenericArgs as _, IntoKind, Region as _, SliceLike, Ty as _},
-};
-use smallvec::{SmallVec, smallvec};
-use stdx::never;
-
-use crate::{
- GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource,
- PathLoweringDiagnostic, TyDefId, ValueTyDefId,
- consteval::{unknown_const, unknown_const_as_generic},
- db::HirDatabase,
- generics::{Generics, generics},
- lower::PathDiagnosticCallbackData,
- lower_nextsolver::{
- LifetimeElisionKind, PredicateFilter, generic_predicates_filtered_by,
- named_associated_type_shorthand_candidates,
- },
- next_solver::{
- AdtDef, Binder, Clause, Const, DbInterner, ErrorGuaranteed, Predicate, ProjectionPredicate,
- Region, SolverDefId, TraitRef, Ty,
- mapping::{ChalkToNextSolver, convert_binder_to_early_binder},
- },
- primitive,
-};
-
-use super::{
- ImplTraitLoweringMode, TyLoweringContext, associated_type_by_name_including_super_traits,
- const_param_ty_query, ty_query,
-};
-
-type CallbackData<'a, 'db> = Either<
- PathDiagnosticCallbackData,
- crate::infer::diagnostics::PathDiagnosticCallbackData<'a, 'db>,
->;
-
-// We cannot use `&mut dyn FnMut()` because of lifetime issues, and we don't want to use `Box<dyn FnMut()>`
-// because of the allocation, so we create a lifetime-less callback, tailored for our needs.
-pub(crate) struct PathDiagnosticCallback<'a, 'db> {
- pub(crate) data: CallbackData<'a, 'db>,
- pub(crate) callback:
- fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'db, '_>, PathLoweringDiagnostic),
-}
-
-pub(crate) struct PathLoweringContext<'a, 'b, 'db> {
- ctx: &'a mut TyLoweringContext<'db, 'b>,
- on_diagnostic: PathDiagnosticCallback<'a, 'db>,
- path: &'a Path,
- segments: PathSegments<'a>,
- current_segment_idx: usize,
- /// Contains the previous segment if `current_segment_idx == segments.len()`
- current_or_prev_segment: PathSegment<'a>,
-}
-
-impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
- #[inline]
- pub(crate) fn new(
- ctx: &'a mut TyLoweringContext<'db, 'b>,
- on_diagnostic: PathDiagnosticCallback<'a, 'db>,
- path: &'a Path,
- ) -> Self {
- let segments = path.segments();
- let first_segment = segments.first().unwrap_or(PathSegment::MISSING);
- Self {
- ctx,
- on_diagnostic,
- path,
- segments,
- current_segment_idx: 0,
- current_or_prev_segment: first_segment,
- }
- }
-
- #[inline]
- #[cold]
- fn on_diagnostic(&mut self, diag: PathLoweringDiagnostic) {
- (self.on_diagnostic.callback)(&self.on_diagnostic.data, self.ctx, diag);
- }
-
- #[inline]
- pub(crate) fn ty_ctx(&mut self) -> &mut TyLoweringContext<'db, 'b> {
- self.ctx
- }
-
- #[inline]
- fn current_segment_u32(&self) -> u32 {
- self.current_segment_idx as u32
- }
-
- #[inline]
- fn skip_resolved_segment(&mut self) {
- if !matches!(self.path, Path::LangItem(..)) {
- // In lang items, the resolved "segment" is not one of the segments. Perhaps we should've put it
- // point at -1, but I don't feel this is clearer.
- self.current_segment_idx += 1;
- }
- self.update_current_segment();
- }
-
- #[inline]
- fn update_current_segment(&mut self) {
- self.current_or_prev_segment =
- self.segments.get(self.current_segment_idx).unwrap_or(self.current_or_prev_segment);
- }
-
- #[inline]
- pub(crate) fn ignore_last_segment(&mut self) {
- self.segments = self.segments.strip_last();
- }
-
- #[inline]
- pub(crate) fn set_current_segment(&mut self, segment: usize) {
- self.current_segment_idx = segment;
- self.current_or_prev_segment = self
- .segments
- .get(segment)
- .expect("invalid segment passed to PathLoweringContext::set_current_segment()");
- }
-
- #[inline]
- fn with_lifetime_elision<T>(
- &mut self,
- lifetime_elision: LifetimeElisionKind<'db>,
- f: impl FnOnce(&mut PathLoweringContext<'_, '_, 'db>) -> T,
- ) -> T {
- let old_lifetime_elision =
- std::mem::replace(&mut self.ctx.lifetime_elision, lifetime_elision);
- let result = f(self);
- self.ctx.lifetime_elision = old_lifetime_elision;
- result
- }
-
- pub(crate) fn lower_ty_relative_path(
- &mut self,
- ty: Ty<'db>,
- // We need the original resolution to lower `Self::AssocTy` correctly
- res: Option<TypeNs>,
- infer_args: bool,
- ) -> (Ty<'db>, Option<TypeNs>) {
- let remaining_segments = self.segments.len() - self.current_segment_idx;
- match remaining_segments {
- 0 => (ty, res),
- 1 => {
- // resolve unselected assoc types
- (self.select_associated_type(res, infer_args), None)
- }
- _ => {
- // FIXME report error (ambiguous associated type)
- (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None)
- }
- }
- }
-
- fn prohibit_parenthesized_generic_args(&mut self) -> bool {
- if let Some(generic_args) = self.current_or_prev_segment.args_and_bindings {
- match generic_args.parenthesized {
- GenericArgsParentheses::No => {}
- GenericArgsParentheses::ReturnTypeNotation | GenericArgsParentheses::ParenSugar => {
- let segment = self.current_segment_u32();
- self.on_diagnostic(
- PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment },
- );
- return true;
- }
- }
- }
- false
- }
-
- // When calling this, the current segment is the resolved segment (we don't advance it yet).
- pub(crate) fn lower_partly_resolved_path(
- &mut self,
- resolution: TypeNs,
- infer_args: bool,
- ) -> (Ty<'db>, Option<TypeNs>) {
- let remaining_segments = self.segments.skip(self.current_segment_idx + 1);
- tracing::debug!(?remaining_segments);
- let rem_seg_len = remaining_segments.len();
- tracing::debug!(?rem_seg_len);
-
- let ty = match resolution {
- TypeNs::TraitId(trait_) => {
- let ty = match remaining_segments.len() {
- 1 => {
- let trait_ref = self.lower_trait_ref_from_resolved_path(
- trait_,
- Ty::new_error(self.ctx.interner, ErrorGuaranteed),
- false,
- );
- tracing::debug!(?trait_ref);
- self.skip_resolved_segment();
- let segment = self.current_or_prev_segment;
- let trait_id = trait_ref.def_id.0;
- let found =
- trait_id.trait_items(self.ctx.db).associated_type_by_name(segment.name);
-
- tracing::debug!(?found);
- match found {
- Some(associated_ty) => {
- // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
- // generic params. It's inefficient to splice the `Substitution`s, so we may want
- // that method to optionally take parent `Substitution` as we already know them at
- // this point (`trait_ref.substitution`).
- let substitution = self.substs_from_path_segment(
- associated_ty.into(),
- false,
- None,
- true,
- );
- let args = crate::next_solver::GenericArgs::new_from_iter(
- self.ctx.interner,
- trait_ref
- .args
- .iter()
- .chain(substitution.iter().skip(trait_ref.args.len())),
- );
- Ty::new_alias(
- self.ctx.interner,
- AliasTyKind::Projection,
- AliasTy::new_from_args(
- self.ctx.interner,
- associated_ty.into(),
- args,
- ),
- )
- }
- None => {
- // FIXME: report error (associated type not found)
- Ty::new_error(self.ctx.interner, ErrorGuaranteed)
- }
- }
- }
- 0 => {
- // Trait object type without dyn; this should be handled in upstream. See
- // `lower_path()`.
- stdx::never!("unexpected fully resolved trait path");
- Ty::new_error(self.ctx.interner, ErrorGuaranteed)
- }
- _ => {
- // FIXME report error (ambiguous associated type)
- Ty::new_error(self.ctx.interner, ErrorGuaranteed)
- }
- };
- return (ty, None);
- }
- TypeNs::GenericParam(param_id) => {
- let generics = self.ctx.generics();
- let idx = generics.type_or_const_param_idx(param_id.into());
- match idx {
- None => {
- never!("no matching generics");
- Ty::new_error(self.ctx.interner, ErrorGuaranteed)
- }
- Some(idx) => {
- let (pidx, param) = generics.iter().nth(idx).unwrap();
- assert_eq!(pidx, param_id.into());
- let p = match param {
- GenericParamDataRef::TypeParamData(p) => p,
- _ => unreachable!(),
- };
- self.ctx.type_param(
- param_id,
- idx as u32,
- p.name
- .as_ref()
- .map_or_else(|| sym::MISSING_NAME.clone(), |p| p.symbol().clone()),
- )
- }
- }
- }
- TypeNs::SelfType(impl_id) => self.ctx.db.impl_self_ty(impl_id).skip_binder(),
- TypeNs::AdtSelfType(adt) => {
- let args = crate::next_solver::GenericArgs::identity_for_item(
- self.ctx.interner,
- adt.into(),
- );
- Ty::new_adt(self.ctx.interner, adt, args)
- }
-
- TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args),
- TypeNs::BuiltinType(it) => self.lower_path_inner(it.into(), infer_args),
- TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args),
- // FIXME: report error
- TypeNs::EnumVariantId(_) | TypeNs::ModuleId(_) => {
- return (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None);
- }
- };
-
- tracing::debug!(?ty);
-
- self.skip_resolved_segment();
- self.lower_ty_relative_path(ty, Some(resolution), infer_args)
- }
-
- fn handle_type_ns_resolution(&mut self, resolution: &TypeNs) {
- let mut prohibit_generics_on_resolved = |reason| {
- if self.current_or_prev_segment.args_and_bindings.is_some() {
- let segment = self.current_segment_u32();
- self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
- segment,
- reason,
- });
- }
- };
-
- match resolution {
- TypeNs::SelfType(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy)
- }
- TypeNs::GenericParam(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::TyParam)
- }
- TypeNs::AdtSelfType(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy)
- }
- TypeNs::BuiltinType(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::PrimitiveTy)
- }
- TypeNs::ModuleId(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::Module)
- }
- TypeNs::AdtId(_)
- | TypeNs::EnumVariantId(_)
- | TypeNs::TypeAliasId(_)
- | TypeNs::TraitId(_) => {}
- }
- }
-
- pub(crate) fn resolve_path_in_type_ns_fully(&mut self) -> Option<TypeNs> {
- let (res, unresolved) = self.resolve_path_in_type_ns()?;
- if unresolved.is_some() {
- return None;
- }
- Some(res)
- }
-
- #[tracing::instrument(skip(self), ret)]
- pub(crate) fn resolve_path_in_type_ns(&mut self) -> Option<(TypeNs, Option<usize>)> {
- let (resolution, remaining_index, _, prefix_info) =
- self.ctx.resolver.resolve_path_in_type_ns_with_prefix_info(self.ctx.db, self.path)?;
-
- let segments = self.segments;
- if segments.is_empty() || matches!(self.path, Path::LangItem(..)) {
- // `segments.is_empty()` can occur with `self`.
- return Some((resolution, remaining_index));
- }
-
- let (module_segments, resolved_segment_idx, enum_segment) = match remaining_index {
- None if prefix_info.enum_variant => {
- (segments.strip_last_two(), segments.len() - 1, Some(segments.len() - 2))
- }
- None => (segments.strip_last(), segments.len() - 1, None),
- Some(i) => (segments.take(i - 1), i - 1, None),
- };
-
- self.current_segment_idx = resolved_segment_idx;
- self.current_or_prev_segment =
- segments.get(resolved_segment_idx).expect("should have resolved segment");
-
- if matches!(self.path, Path::BarePath(..)) {
- // Bare paths cannot have generics, so skip them as an optimization.
- return Some((resolution, remaining_index));
- }
-
- for (i, mod_segment) in module_segments.iter().enumerate() {
- if mod_segment.args_and_bindings.is_some() {
- self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
- segment: i as u32,
- reason: GenericArgsProhibitedReason::Module,
- });
- }
- }
-
- if let Some(enum_segment) = enum_segment
- && segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
- && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
- {
- self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
- segment: (enum_segment + 1) as u32,
- reason: GenericArgsProhibitedReason::EnumVariant,
- });
- }
-
- self.handle_type_ns_resolution(&resolution);
-
- Some((resolution, remaining_index))
- }
-
- pub(crate) fn resolve_path_in_value_ns(
- &mut self,
- hygiene_id: HygieneId,
- ) -> Option<ResolveValueResult> {
- let (res, prefix_info) = self.ctx.resolver.resolve_path_in_value_ns_with_prefix_info(
- self.ctx.db,
- self.path,
- hygiene_id,
- )?;
-
- let segments = self.segments;
- if segments.is_empty() || matches!(self.path, Path::LangItem(..)) {
- // `segments.is_empty()` can occur with `self`.
- return Some(res);
- }
-
- let (mod_segments, enum_segment, resolved_segment_idx) = match res {
- ResolveValueResult::Partial(_, unresolved_segment, _) => {
- (segments.take(unresolved_segment - 1), None, unresolved_segment - 1)
- }
- ResolveValueResult::ValueNs(ValueNs::EnumVariantId(_), _)
- if prefix_info.enum_variant =>
- {
- (segments.strip_last_two(), segments.len().checked_sub(2), segments.len() - 1)
- }
- ResolveValueResult::ValueNs(..) => (segments.strip_last(), None, segments.len() - 1),
- };
-
- self.current_segment_idx = resolved_segment_idx;
- self.current_or_prev_segment =
- segments.get(resolved_segment_idx).expect("should have resolved segment");
-
- for (i, mod_segment) in mod_segments.iter().enumerate() {
- if mod_segment.args_and_bindings.is_some() {
- self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
- segment: i as u32,
- reason: GenericArgsProhibitedReason::Module,
- });
- }
- }
-
- if let Some(enum_segment) = enum_segment
- && segments.get(enum_segment).is_some_and(|it| it.args_and_bindings.is_some())
- && segments.get(enum_segment + 1).is_some_and(|it| it.args_and_bindings.is_some())
- {
- self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
- segment: (enum_segment + 1) as u32,
- reason: GenericArgsProhibitedReason::EnumVariant,
- });
- }
-
- match &res {
- ResolveValueResult::ValueNs(resolution, _) => {
- let resolved_segment_idx = self.current_segment_u32();
- let resolved_segment = self.current_or_prev_segment;
-
- let mut prohibit_generics_on_resolved = |reason| {
- if resolved_segment.args_and_bindings.is_some() {
- self.on_diagnostic(PathLoweringDiagnostic::GenericArgsProhibited {
- segment: resolved_segment_idx,
- reason,
- });
- }
- };
-
- match resolution {
- ValueNs::ImplSelf(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy)
- }
- // FIXME: rustc generates E0107 (incorrect number of generic arguments) and not
- // E0109 (generic arguments provided for a type that doesn't accept them) for
- // consts and statics, presumably as a defense against future in which consts
- // and statics can be generic, or just because it was easier for rustc implementors.
- // That means we'll show the wrong error code. Because of us it's easier to do it
- // this way :)
- ValueNs::GenericParam(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::Const)
- }
- ValueNs::StaticId(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::Static)
- }
- ValueNs::LocalBinding(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::LocalVariable)
- }
- ValueNs::FunctionId(_)
- | ValueNs::StructId(_)
- | ValueNs::EnumVariantId(_)
- | ValueNs::ConstId(_) => {}
- }
- }
- ResolveValueResult::Partial(resolution, _, _) => {
- self.handle_type_ns_resolution(resolution);
- }
- };
- Some(res)
- }
-
- #[tracing::instrument(skip(self), ret)]
- fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty<'db> {
- let interner = self.ctx.interner;
- let Some(res) = res else {
- return Ty::new_error(self.ctx.interner, ErrorGuaranteed);
- };
- let db = self.ctx.db;
- let def = self.ctx.def;
- let segment = self.current_or_prev_segment;
- let assoc_name = segment.name;
- let mut check_alias = |name: &Name, t: TraitRef<'db>, associated_ty: TypeAliasId| {
- if name != assoc_name {
- return None;
- }
-
- // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
- // generic params. It's inefficient to splice the `Substitution`s, so we may want
- // that method to optionally take parent `Substitution` as we already know them at
- // this point (`t.substitution`).
- let substs =
- self.substs_from_path_segment(associated_ty.into(), infer_args, None, true);
-
- let substs = crate::next_solver::GenericArgs::new_from_iter(
- interner,
- t.args.iter().chain(substs.iter().skip(t.args.len())),
- );
-
- Some(Ty::new_alias(
- interner,
- AliasTyKind::Projection,
- AliasTy::new(interner, associated_ty.into(), substs),
- ))
- };
- named_associated_type_shorthand_candidates(
- interner,
- def,
- res,
- Some(assoc_name.clone()),
- check_alias,
- )
- .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed))
- }
-
- fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> {
- let generic_def = match typeable {
- TyDefId::BuiltinType(builtinty) => {
- return Ty::from_builtin_type(self.ctx.interner, builtinty);
- }
- TyDefId::AdtId(it) => it.into(),
- TyDefId::TypeAliasId(it) => it.into(),
- };
- let args = self.substs_from_path_segment(generic_def, infer_args, None, false);
- let ty = ty_query(self.ctx.db, typeable);
- ty.instantiate(self.ctx.interner, args)
- }
-
- /// Collect generic arguments from a path into a `Substs`. See also
- /// `create_substs_for_ast_path` and `def_to_ty` in rustc.
- pub(crate) fn substs_from_path(
- &mut self,
- // Note that we don't call `db.value_type(resolved)` here,
- // `ValueTyDefId` is just a convenient way to pass generics and
- // special-case enum variants
- resolved: ValueTyDefId,
- infer_args: bool,
- lowering_assoc_type_generics: bool,
- ) -> crate::next_solver::GenericArgs<'db> {
- let interner = self.ctx.interner;
- let prev_current_segment_idx = self.current_segment_idx;
- let prev_current_segment = self.current_or_prev_segment;
-
- let generic_def = match resolved {
- ValueTyDefId::FunctionId(it) => it.into(),
- ValueTyDefId::StructId(it) => it.into(),
- ValueTyDefId::UnionId(it) => it.into(),
- ValueTyDefId::ConstId(it) => it.into(),
- ValueTyDefId::StaticId(_) => {
- return crate::next_solver::GenericArgs::new_from_iter(interner, []);
- }
- ValueTyDefId::EnumVariantId(var) => {
- // the generic args for an enum variant may be either specified
- // on the segment referring to the enum, or on the segment
- // referring to the variant. So `Option::<T>::None` and
- // `Option::None::<T>` are both allowed (though the former is
- // FIXME: This isn't strictly correct, enum variants may be used not through the enum
- // (via `use Enum::Variant`). The resolver returns whether they were, but we don't have its result
- // available here. The worst that can happen is that we will show some confusing diagnostics to the user,
- // if generics exist on the module and they don't match with the variant.
- // preferred). See also `def_ids_for_path_segments` in rustc.
- //
- // `wrapping_sub(1)` will return a number which `get` will return None for if current_segment_idx<2.
- // This simplifies the code a bit.
- let penultimate_idx = self.current_segment_idx.wrapping_sub(1);
- let penultimate = self.segments.get(penultimate_idx);
- if let Some(penultimate) = penultimate
- && self.current_or_prev_segment.args_and_bindings.is_none()
- && penultimate.args_and_bindings.is_some()
- {
- self.current_segment_idx = penultimate_idx;
- self.current_or_prev_segment = penultimate;
- }
- var.lookup(self.ctx.db).parent.into()
- }
- };
- let result = self.substs_from_path_segment(
- generic_def,
- infer_args,
- None,
- lowering_assoc_type_generics,
- );
- self.current_segment_idx = prev_current_segment_idx;
- self.current_or_prev_segment = prev_current_segment;
- result
- }
-
- pub(crate) fn substs_from_path_segment(
- &mut self,
- def: GenericDefId,
- infer_args: bool,
- explicit_self_ty: Option<Ty<'db>>,
- lowering_assoc_type_generics: bool,
- ) -> crate::next_solver::GenericArgs<'db> {
- let old_lifetime_elision = self.ctx.lifetime_elision.clone();
-
- if let Some(args) = self.current_or_prev_segment.args_and_bindings
- && args.parenthesized != GenericArgsParentheses::No
- {
- let prohibit_parens = match def {
- GenericDefId::TraitId(trait_) => {
- // RTN is prohibited anyways if we got here.
- let is_rtn = args.parenthesized == GenericArgsParentheses::ReturnTypeNotation;
- let is_fn_trait = self
- .ctx
- .db
- .trait_signature(trait_)
- .flags
- .contains(TraitFlags::RUSTC_PAREN_SUGAR);
- is_rtn || !is_fn_trait
- }
- _ => true,
- };
-
- if prohibit_parens {
- let segment = self.current_segment_u32();
- self.on_diagnostic(
- PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment },
- );
-
- return unknown_subst(self.ctx.interner, def);
- }
-
- // `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
- self.ctx.lifetime_elision =
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false };
- }
-
- let result = self.substs_from_args_and_bindings(
- self.current_or_prev_segment.args_and_bindings,
- def,
- infer_args,
- explicit_self_ty,
- PathGenericsSource::Segment(self.current_segment_u32()),
- lowering_assoc_type_generics,
- self.ctx.lifetime_elision.clone(),
- );
- self.ctx.lifetime_elision = old_lifetime_elision;
- result
- }
-
- pub(super) fn substs_from_args_and_bindings(
- &mut self,
- args_and_bindings: Option<&GenericArgs>,
- def: GenericDefId,
- infer_args: bool,
- explicit_self_ty: Option<Ty<'db>>,
- generics_source: PathGenericsSource,
- lowering_assoc_type_generics: bool,
- lifetime_elision: LifetimeElisionKind<'db>,
- ) -> crate::next_solver::GenericArgs<'db> {
- struct LowererCtx<'a, 'b, 'c, 'db> {
- ctx: &'a mut PathLoweringContext<'b, 'c, 'db>,
- generics_source: PathGenericsSource,
- }
-
- impl<'db> GenericArgsLowerer<'db> for LowererCtx<'_, '_, '_, 'db> {
- fn report_len_mismatch(
- &mut self,
- def: GenericDefId,
- provided_count: u32,
- expected_count: u32,
- kind: IncorrectGenericsLenKind,
- ) {
- self.ctx.on_diagnostic(PathLoweringDiagnostic::IncorrectGenericsLen {
- generics_source: self.generics_source,
- provided_count,
- expected_count,
- kind,
- def,
- });
- }
-
- fn report_arg_mismatch(
- &mut self,
- param_id: GenericParamId,
- arg_idx: u32,
- has_self_arg: bool,
- ) {
- self.ctx.on_diagnostic(PathLoweringDiagnostic::IncorrectGenericsOrder {
- generics_source: self.generics_source,
- param_id,
- arg_idx,
- has_self_arg,
- });
- }
-
- fn provided_kind(
- &mut self,
- param_id: GenericParamId,
- param: GenericParamDataRef<'_>,
- arg: &GenericArg,
- ) -> crate::next_solver::GenericArg<'db> {
- match (param, *arg) {
- (GenericParamDataRef::LifetimeParamData(_), GenericArg::Lifetime(lifetime)) => {
- self.ctx.ctx.lower_lifetime(lifetime).into()
- }
- (GenericParamDataRef::TypeParamData(_), GenericArg::Type(type_ref)) => {
- self.ctx.ctx.lower_ty(type_ref).into()
- }
- (GenericParamDataRef::ConstParamData(_), GenericArg::Const(konst)) => {
- let GenericParamId::ConstParamId(const_id) = param_id else {
- unreachable!("non-const param ID for const param");
- };
- self.ctx
- .ctx
- .lower_const(konst, const_param_ty_query(self.ctx.ctx.db, const_id))
- .into()
- }
- _ => unreachable!("unmatching param kinds were passed to `provided_kind()`"),
- }
- }
-
- fn provided_type_like_const(
- &mut self,
- const_ty: Ty<'db>,
- arg: TypeLikeConst<'_>,
- ) -> crate::next_solver::Const<'db> {
- match arg {
- TypeLikeConst::Path(path) => self.ctx.ctx.lower_path_as_const(path, const_ty),
- TypeLikeConst::Infer => unknown_const(const_ty),
- }
- }
-
- fn inferred_kind(
- &mut self,
- def: GenericDefId,
- param_id: GenericParamId,
- param: GenericParamDataRef<'_>,
- infer_args: bool,
- preceding_args: &[crate::next_solver::GenericArg<'db>],
- ) -> crate::next_solver::GenericArg<'db> {
- let default = || {
- self.ctx.ctx.db.generic_defaults(def).get(preceding_args.len()).map(|default| {
- convert_binder_to_early_binder(
- self.ctx.ctx.interner,
- def,
- default.to_nextsolver(self.ctx.ctx.interner),
- )
- .instantiate(self.ctx.ctx.interner, preceding_args)
- })
- };
- match param {
- GenericParamDataRef::LifetimeParamData(_) => {
- Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed))
- .into()
- }
- GenericParamDataRef::TypeParamData(param) => {
- if !infer_args
- && param.default.is_some()
- && let Some(default) = default()
- {
- return default;
- }
- Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into()
- }
- GenericParamDataRef::ConstParamData(param) => {
- if !infer_args
- && param.default.is_some()
- && let Some(default) = default()
- {
- return default;
- }
- let GenericParamId::ConstParamId(const_id) = param_id else {
- unreachable!("non-const param ID for const param");
- };
- unknown_const_as_generic(const_param_ty_query(self.ctx.ctx.db, const_id))
- }
- }
- }
-
- fn parent_arg(
- &mut self,
- param_id: GenericParamId,
- ) -> crate::next_solver::GenericArg<'db> {
- match param_id {
- GenericParamId::TypeParamId(_) => {
- Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into()
- }
- GenericParamId::ConstParamId(const_id) => {
- unknown_const_as_generic(const_param_ty_query(self.ctx.ctx.db, const_id))
- }
- GenericParamId::LifetimeParamId(_) => {
- Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed))
- .into()
- }
- }
- }
-
- fn report_elided_lifetimes_in_path(
- &mut self,
- def: GenericDefId,
- expected_count: u32,
- hard_error: bool,
- ) {
- self.ctx.on_diagnostic(PathLoweringDiagnostic::ElidedLifetimesInPath {
- generics_source: self.generics_source,
- def,
- expected_count,
- hard_error,
- });
- }
-
- fn report_elision_failure(&mut self, def: GenericDefId, expected_count: u32) {
- self.ctx.on_diagnostic(PathLoweringDiagnostic::ElisionFailure {
- generics_source: self.generics_source,
- def,
- expected_count,
- });
- }
-
- fn report_missing_lifetime(&mut self, def: GenericDefId, expected_count: u32) {
- self.ctx.on_diagnostic(PathLoweringDiagnostic::MissingLifetime {
- generics_source: self.generics_source,
- def,
- expected_count,
- });
- }
- }
-
- substs_from_args_and_bindings(
- self.ctx.db,
- self.ctx.store,
- args_and_bindings,
- def,
- infer_args,
- lifetime_elision,
- lowering_assoc_type_generics,
- explicit_self_ty,
- &mut LowererCtx { ctx: self, generics_source },
- )
- }
-
- pub(crate) fn lower_trait_ref_from_resolved_path(
- &mut self,
- resolved: TraitId,
- explicit_self_ty: Ty<'db>,
- infer_args: bool,
- ) -> TraitRef<'db> {
- let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args);
- TraitRef::new_from_args(self.ctx.interner, resolved.into(), args)
- }
-
- fn trait_ref_substs_from_path(
- &mut self,
- resolved: TraitId,
- explicit_self_ty: Ty<'db>,
- infer_args: bool,
- ) -> crate::next_solver::GenericArgs<'db> {
- self.substs_from_path_segment(resolved.into(), infer_args, Some(explicit_self_ty), false)
- }
-
- pub(super) fn assoc_type_bindings_from_type_bound<'c>(
- mut self,
- trait_ref: TraitRef<'db>,
- ) -> Option<impl Iterator<Item = Clause<'db>> + use<'a, 'b, 'c, 'db>> {
- let interner = self.ctx.interner;
- self.current_or_prev_segment.args_and_bindings.map(|args_and_bindings| {
- args_and_bindings.bindings.iter().enumerate().flat_map(move |(binding_idx, binding)| {
- let found = associated_type_by_name_including_super_traits(
- self.ctx.db,
- trait_ref,
- &binding.name,
- );
- let (super_trait_ref, associated_ty) = match found {
- None => return SmallVec::new(),
- Some(t) => t,
- };
- let args =
- self.with_lifetime_elision(LifetimeElisionKind::AnonymousReportError, |this| {
- // FIXME: `substs_from_path_segment()` pushes `TyKind::Error` for every parent
- // generic params. It's inefficient to splice the `Substitution`s, so we may want
- // that method to optionally take parent `Substitution` as we already know them at
- // this point (`super_trait_ref.substitution`).
- this.substs_from_args_and_bindings(
- binding.args.as_ref(),
- associated_ty.into(),
- false, // this is not relevant
- Some(super_trait_ref.self_ty()),
- PathGenericsSource::AssocType {
- segment: this.current_segment_u32(),
- assoc_type: binding_idx as u32,
- },
- false,
- this.ctx.lifetime_elision.clone(),
- )
- });
- let args = crate::next_solver::GenericArgs::new_from_iter(
- interner,
- super_trait_ref.args.iter().chain(args.iter().skip(super_trait_ref.args.len())),
- );
- let projection_term =
- AliasTerm::new_from_args(interner, associated_ty.into(), args);
- let mut predicates: SmallVec<[_; 1]> = SmallVec::with_capacity(
- binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(),
- );
- if let Some(type_ref) = binding.type_ref {
- let lifetime_elision =
- if args_and_bindings.parenthesized == GenericArgsParentheses::ParenSugar {
- // `Fn()`-style generics are elided like functions. This is `Output` (we lower to it in hir-def).
- LifetimeElisionKind::for_fn_ret(self.ctx.interner)
- } else {
- self.ctx.lifetime_elision.clone()
- };
- self.with_lifetime_elision(lifetime_elision, |this| {
- match (&this.ctx.store[type_ref], this.ctx.impl_trait_mode.mode) {
- (TypeRef::ImplTrait(_), ImplTraitLoweringMode::Disallowed) => (),
- (
- _,
- ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque,
- ) => {
- let ty = this.ctx.lower_ty(type_ref);
- let pred = Clause(Predicate::new(
- interner,
- Binder::dummy(rustc_type_ir::PredicateKind::Clause(
- rustc_type_ir::ClauseKind::Projection(
- ProjectionPredicate {
- projection_term,
- term: ty.into(),
- },
- ),
- )),
- ));
- predicates.push(pred);
- }
- }
- })
- }
- for bound in binding.bounds.iter() {
- predicates.extend(self.ctx.lower_type_bound(
- bound,
- Ty::new_alias(
- self.ctx.interner,
- AliasTyKind::Projection,
- AliasTy::new_from_args(self.ctx.interner, associated_ty.into(), args),
- ),
- false,
- ));
- }
- predicates
- })
- })
- }
-}
-
-/// A const that were parsed like a type.
-pub(crate) enum TypeLikeConst<'a> {
- Infer,
- Path(&'a Path),
-}
-
-pub(crate) trait GenericArgsLowerer<'db> {
- fn report_elided_lifetimes_in_path(
- &mut self,
- def: GenericDefId,
- expected_count: u32,
- hard_error: bool,
- );
-
- fn report_elision_failure(&mut self, def: GenericDefId, expected_count: u32);
-
- fn report_missing_lifetime(&mut self, def: GenericDefId, expected_count: u32);
-
- fn report_len_mismatch(
- &mut self,
- def: GenericDefId,
- provided_count: u32,
- expected_count: u32,
- kind: IncorrectGenericsLenKind,
- );
-
- fn report_arg_mismatch(&mut self, param_id: GenericParamId, arg_idx: u32, has_self_arg: bool);
-
- fn provided_kind(
- &mut self,
- param_id: GenericParamId,
- param: GenericParamDataRef<'_>,
- arg: &GenericArg,
- ) -> crate::next_solver::GenericArg<'db>;
-
- fn provided_type_like_const(&mut self, const_ty: Ty<'db>, arg: TypeLikeConst<'_>)
- -> Const<'db>;
-
- fn inferred_kind(
- &mut self,
- def: GenericDefId,
- param_id: GenericParamId,
- param: GenericParamDataRef<'_>,
- infer_args: bool,
- preceding_args: &[crate::next_solver::GenericArg<'db>],
- ) -> crate::next_solver::GenericArg<'db>;
-
- fn parent_arg(&mut self, param_id: GenericParamId) -> crate::next_solver::GenericArg<'db>;
-}
-
-/// Returns true if there was an error.
-fn check_generic_args_len<'db>(
- args_and_bindings: Option<&GenericArgs>,
- def: GenericDefId,
- def_generics: &Generics,
- infer_args: bool,
- lifetime_elision: &LifetimeElisionKind<'db>,
- lowering_assoc_type_generics: bool,
- ctx: &mut impl GenericArgsLowerer<'db>,
-) -> bool {
- let mut had_error = false;
-
- let (mut provided_lifetimes_count, mut provided_types_and_consts_count) = (0usize, 0usize);
- if let Some(args_and_bindings) = args_and_bindings {
- let args_no_self = &args_and_bindings.args[usize::from(args_and_bindings.has_self_type)..];
- for arg in args_no_self {
- match arg {
- GenericArg::Lifetime(_) => provided_lifetimes_count += 1,
- GenericArg::Type(_) | GenericArg::Const(_) => provided_types_and_consts_count += 1,
- }
- }
- }
-
- let lifetime_args_len = def_generics.len_lifetimes_self();
- if provided_lifetimes_count == 0
- && lifetime_args_len > 0
- && (!lowering_assoc_type_generics || infer_args)
- {
- // In generic associated types, we never allow inferring the lifetimes, but only in type context, that is
- // when `infer_args == false`. In expression/pattern context we always allow inferring them, even for GATs.
- match lifetime_elision {
- &LifetimeElisionKind::AnonymousCreateParameter { report_in_path } => {
- ctx.report_elided_lifetimes_in_path(def, lifetime_args_len as u32, report_in_path);
- had_error |= report_in_path;
- }
- LifetimeElisionKind::AnonymousReportError => {
- ctx.report_missing_lifetime(def, lifetime_args_len as u32);
- had_error = true
- }
- LifetimeElisionKind::ElisionFailure => {
- ctx.report_elision_failure(def, lifetime_args_len as u32);
- had_error = true;
- }
- LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => {
- // FIXME: Check there are other lifetimes in scope, and error/lint.
- }
- LifetimeElisionKind::Elided(_) => {
- ctx.report_elided_lifetimes_in_path(def, lifetime_args_len as u32, false);
- }
- LifetimeElisionKind::Infer => {
- // Allow eliding lifetimes.
- }
- }
- } else if lifetime_args_len != provided_lifetimes_count {
- ctx.report_len_mismatch(
- def,
- provided_lifetimes_count as u32,
- lifetime_args_len as u32,
- IncorrectGenericsLenKind::Lifetimes,
- );
- had_error = true;
- }
-
- let defaults_count =
- def_generics.iter_self_type_or_consts().filter(|(_, param)| param.has_default()).count();
- let named_type_and_const_params_count = def_generics
- .iter_self_type_or_consts()
- .filter(|(_, param)| match param {
- TypeOrConstParamData::TypeParamData(param) => {
- param.provenance == TypeParamProvenance::TypeParamList
- }
- TypeOrConstParamData::ConstParamData(_) => true,
- })
- .count();
- let expected_max = named_type_and_const_params_count;
- let expected_min =
- if infer_args { 0 } else { named_type_and_const_params_count - defaults_count };
- if provided_types_and_consts_count < expected_min
- || expected_max < provided_types_and_consts_count
- {
- ctx.report_len_mismatch(
- def,
- provided_types_and_consts_count as u32,
- named_type_and_const_params_count as u32,
- IncorrectGenericsLenKind::TypesAndConsts,
- );
- had_error = true;
- }
-
- had_error
-}
-
-pub(crate) fn substs_from_args_and_bindings<'db>(
- db: &'db dyn HirDatabase,
- store: &ExpressionStore,
- args_and_bindings: Option<&GenericArgs>,
- def: GenericDefId,
- mut infer_args: bool,
- lifetime_elision: LifetimeElisionKind<'db>,
- lowering_assoc_type_generics: bool,
- explicit_self_ty: Option<Ty<'db>>,
- ctx: &mut impl GenericArgsLowerer<'db>,
-) -> crate::next_solver::GenericArgs<'db> {
- let interner = DbInterner::new_with(db, None, None);
-
- tracing::debug!(?args_and_bindings);
-
- // Order is
- // - Parent parameters
- // - Optional Self parameter
- // - Lifetime parameters
- // - Type or Const parameters
- let def_generics = generics(db, def);
- let args_slice = args_and_bindings.map(|it| &*it.args).unwrap_or_default();
-
- // We do not allow inference if there are specified args, i.e. we do not allow partial inference.
- let has_non_lifetime_args =
- args_slice.iter().any(|arg| !matches!(arg, GenericArg::Lifetime(_)));
- infer_args &= !has_non_lifetime_args;
-
- let had_count_error = check_generic_args_len(
- args_and_bindings,
- def,
- &def_generics,
- infer_args,
- &lifetime_elision,
- lowering_assoc_type_generics,
- ctx,
- );
-
- let mut substs = Vec::with_capacity(def_generics.len());
-
- substs.extend(def_generics.iter_parent_id().map(|id| ctx.parent_arg(id)));
-
- let mut args = args_slice.iter().enumerate().peekable();
- let mut params = def_generics.iter_self().peekable();
-
- // If we encounter a type or const when we expect a lifetime, we infer the lifetimes.
- // If we later encounter a lifetime, we know that the arguments were provided in the
- // wrong order. `force_infer_lt` records the type or const that forced lifetimes to be
- // inferred, so we can use it for diagnostics later.
- let mut force_infer_lt = None;
-
- let has_self_arg = args_and_bindings.is_some_and(|it| it.has_self_type);
- // First, handle `Self` parameter. Consume it from the args if provided, otherwise from `explicit_self_ty`,
- // and lastly infer it.
- if let Some(&(
- self_param_id,
- self_param @ GenericParamDataRef::TypeParamData(TypeParamData {
- provenance: TypeParamProvenance::TraitSelf,
- ..
- }),
- )) = params.peek()
- {
- let self_ty = if has_self_arg {
- let (_, self_ty) = args.next().expect("has_self_type=true, should have Self type");
- ctx.provided_kind(self_param_id, self_param, self_ty)
- } else {
- explicit_self_ty.map(|it| it.into()).unwrap_or_else(|| {
- ctx.inferred_kind(def, self_param_id, self_param, infer_args, &substs)
- })
- };
- params.next();
- substs.push(self_ty);
- }
-
- loop {
- // We're going to iterate through the generic arguments that the user
- // provided, matching them with the generic parameters we expect.
- // Mismatches can occur as a result of elided lifetimes, or for malformed
- // input. We try to handle both sensibly.
- match (args.peek(), params.peek()) {
- (Some(&(arg_idx, arg)), Some(&(param_id, param))) => match (arg, param) {
- (GenericArg::Type(_), GenericParamDataRef::TypeParamData(type_param))
- if type_param.provenance == TypeParamProvenance::ArgumentImplTrait =>
- {
- // Do not allow specifying `impl Trait` explicitly. We already err at that, but if we won't handle it here
- // we will handle it as if it was specified, instead of inferring it.
- substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs));
- params.next();
- }
- (GenericArg::Lifetime(_), GenericParamDataRef::LifetimeParamData(_))
- | (GenericArg::Type(_), GenericParamDataRef::TypeParamData(_))
- | (GenericArg::Const(_), GenericParamDataRef::ConstParamData(_)) => {
- substs.push(ctx.provided_kind(param_id, param, arg));
- args.next();
- params.next();
- }
- (
- GenericArg::Type(_) | GenericArg::Const(_),
- GenericParamDataRef::LifetimeParamData(_),
- ) => {
- // We expected a lifetime argument, but got a type or const
- // argument. That means we're inferring the lifetime.
- substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs));
- params.next();
- force_infer_lt = Some((arg_idx as u32, param_id));
- }
- (GenericArg::Type(type_ref), GenericParamDataRef::ConstParamData(_)) => {
- if let Some(konst) = type_looks_like_const(store, *type_ref) {
- let GenericParamId::ConstParamId(param_id) = param_id else {
- panic!("unmatching param kinds");
- };
- let const_ty = const_param_ty_query(db, param_id);
- substs.push(ctx.provided_type_like_const(const_ty, konst).into());
- args.next();
- params.next();
- } else {
- // See the `_ => { ... }` branch.
- if !had_count_error {
- ctx.report_arg_mismatch(param_id, arg_idx as u32, has_self_arg);
- }
- while args.next().is_some() {}
- }
- }
- _ => {
- // We expected one kind of parameter, but the user provided
- // another. This is an error. However, if we already know that
- // the arguments don't match up with the parameters, we won't issue
- // an additional error, as the user already knows what's wrong.
- if !had_count_error {
- ctx.report_arg_mismatch(param_id, arg_idx as u32, has_self_arg);
- }
-
- // We've reported the error, but we want to make sure that this
- // problem doesn't bubble down and create additional, irrelevant
- // errors. In this case, we're simply going to ignore the argument
- // and any following arguments. The rest of the parameters will be
- // inferred.
- while args.next().is_some() {}
- }
- },
-
- (Some(&(_, arg)), None) => {
- // We should never be able to reach this point with well-formed input.
- // There are two situations in which we can encounter this issue.
- //
- // 1. The number of arguments is incorrect. In this case, an error
- // will already have been emitted, and we can ignore it.
- // 2. We've inferred some lifetimes, which have been provided later (i.e.
- // after a type or const). We want to throw an error in this case.
- if !had_count_error {
- assert!(
- matches!(arg, GenericArg::Lifetime(_)),
- "the only possible situation here is incorrect lifetime order"
- );
- let (provided_arg_idx, param_id) =
- force_infer_lt.expect("lifetimes ought to have been inferred");
- ctx.report_arg_mismatch(param_id, provided_arg_idx, has_self_arg);
- }
-
- break;
- }
-
- (None, Some(&(param_id, param))) => {
- // If there are fewer arguments than parameters, it means we're inferring the remaining arguments.
- let param = if let GenericParamId::LifetimeParamId(_) = param_id {
- match &lifetime_elision {
- LifetimeElisionKind::ElisionFailure
- | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }
- | LifetimeElisionKind::AnonymousReportError => {
- assert!(had_count_error);
- ctx.inferred_kind(def, param_id, param, infer_args, &substs)
- }
- LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => {
- Region::new_static(interner).into()
- }
- LifetimeElisionKind::Elided(lifetime) => (*lifetime).into(),
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false }
- | LifetimeElisionKind::Infer => {
- // FIXME: With `AnonymousCreateParameter`, we need to create a new lifetime parameter here
- // (but this will probably be done in hir-def lowering instead).
- ctx.inferred_kind(def, param_id, param, infer_args, &substs)
- }
- }
- } else {
- ctx.inferred_kind(def, param_id, param, infer_args, &substs)
- };
- substs.push(param);
- params.next();
- }
-
- (None, None) => break,
- }
- }
-
- crate::next_solver::GenericArgs::new_from_iter(interner, substs)
-}
-
-fn type_looks_like_const(
- store: &ExpressionStore,
- type_ref: TypeRefId,
-) -> Option<TypeLikeConst<'_>> {
- // A path/`_` const will be parsed as a type, instead of a const, because when parsing/lowering
- // in hir-def we don't yet know the expected argument kind. rustc does this a bit differently,
- // when lowering to HIR it resolves the path, and if it doesn't resolve to the type namespace
- // it is lowered as a const. Our behavior could deviate from rustc when the value is resolvable
- // in both the type and value namespaces, but I believe we only allow more code.
- let type_ref = &store[type_ref];
- match type_ref {
- TypeRef::Path(path) => Some(TypeLikeConst::Path(path)),
- TypeRef::Placeholder => Some(TypeLikeConst::Infer),
- _ => None,
- }
-}
-
-fn unknown_subst<'db>(
- interner: DbInterner<'db>,
- def: impl Into<GenericDefId>,
-) -> crate::next_solver::GenericArgs<'db> {
- let params = generics(interner.db(), def.into());
- crate::next_solver::GenericArgs::new_from_iter(
- interner,
- params.iter_id().map(|id| match id {
- GenericParamId::TypeParamId(_) => Ty::new_error(interner, ErrorGuaranteed).into(),
- GenericParamId::ConstParamId(id) => {
- unknown_const_as_generic(const_param_ty_query(interner.db(), id))
- }
- GenericParamId::LifetimeParamId(_) => {
- crate::next_solver::Region::error(interner).into()
- }
- }),
- )
-}