Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/lower/path.rs')
-rw-r--r--crates/hir-ty/src/lower/path.rs717
1 files changed, 369 insertions, 348 deletions
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index 5c06234fa0..9ba0da6f49 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/crates/hir-ty/src/lower/path.rs
@@ -1,12 +1,14 @@
//! A wrapper around [`TyLoweringContext`] specifically for lowering paths.
-use chalk_ir::{BoundVar, cast::Cast, fold::Shift};
use either::Either;
use hir_def::{
- GenericDefId, GenericParamId, Lookup, TraitId,
+ GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId,
expr_store::{
ExpressionStore, HygieneId,
- path::{GenericArg, GenericArgs, GenericArgsParentheses, Path, PathSegment, PathSegments},
+ path::{
+ GenericArg as HirGenericArg, GenericArgs as HirGenericArgs, GenericArgsParentheses,
+ Path, PathSegment, PathSegments,
+ },
},
hir::generics::{
GenericParamDataRef, TypeOrConstParamData, TypeParamData, TypeParamProvenance,
@@ -15,38 +17,50 @@ use hir_def::{
signatures::TraitFlags,
type_ref::{TypeRef, TypeRefId},
};
+use hir_expand::name::Name;
+use rustc_type_ir::{
+ AliasTerm, AliasTy, AliasTyKind,
+ inherent::{GenericArgs as _, Region as _, SliceLike, Ty as _},
+};
use smallvec::SmallVec;
use stdx::never;
use crate::{
- AliasEq, AliasTy, GenericArgsProhibitedReason, ImplTraitLoweringMode, IncorrectGenericsLenKind,
- Interner, ParamLoweringMode, PathGenericsSource, PathLoweringDiagnostic, ProjectionTy,
- QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyDefId, TyKind,
- TyLoweringContext, ValueTyDefId, WhereClause,
+ GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource,
+ PathLoweringDiagnostic, TyDefId, ValueTyDefId,
consteval::{unknown_const, unknown_const_as_generic},
db::HirDatabase,
- error_lifetime,
generics::{Generics, generics},
- lower::{LifetimeElisionKind, named_associated_type_shorthand_candidates},
- static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
- utils::associated_type_by_name_including_super_traits,
+ lower::{
+ LifetimeElisionKind, PathDiagnosticCallbackData, named_associated_type_shorthand_candidates,
+ },
+ next_solver::{
+ Binder, Clause, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Predicate,
+ ProjectionPredicate, Region, TraitRef, Ty,
+ },
};
-type CallbackData<'a> = Either<
- super::PathDiagnosticCallbackData,
- crate::infer::diagnostics::PathDiagnosticCallbackData<'a>,
+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> {
- pub(crate) data: CallbackData<'a>,
- pub(crate) callback: fn(&CallbackData<'_>, &mut TyLoweringContext<'_>, PathLoweringDiagnostic),
+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> {
- ctx: &'a mut TyLoweringContext<'b>,
- on_diagnostic: PathDiagnosticCallback<'a>,
+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,
@@ -54,11 +68,11 @@ pub(crate) struct PathLoweringContext<'a, 'b> {
current_or_prev_segment: PathSegment<'a>,
}
-impl<'a, 'b> PathLoweringContext<'a, 'b> {
+impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
#[inline]
pub(crate) fn new(
- ctx: &'a mut TyLoweringContext<'b>,
- on_diagnostic: PathDiagnosticCallback<'a>,
+ ctx: &'a mut TyLoweringContext<'db, 'b>,
+ on_diagnostic: PathDiagnosticCallback<'a, 'db>,
path: &'a Path,
) -> Self {
let segments = path.segments();
@@ -80,7 +94,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
}
#[inline]
- pub(crate) fn ty_ctx(&mut self) -> &mut TyLoweringContext<'b> {
+ pub(crate) fn ty_ctx(&mut self) -> &mut TyLoweringContext<'db, 'b> {
self.ctx
}
@@ -122,8 +136,8 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
#[inline]
fn with_lifetime_elision<T>(
&mut self,
- lifetime_elision: LifetimeElisionKind,
- f: impl FnOnce(&mut PathLoweringContext<'_, '_>) -> T,
+ 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);
@@ -134,12 +148,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
pub(crate) fn lower_ty_relative_path(
&mut self,
- ty: Ty,
+ ty: Ty<'db>,
// We need the original resolution to lower `Self::AssocTy` correctly
res: Option<TypeNs>,
infer_args: bool,
- ) -> (Ty, Option<TypeNs>) {
- match self.segments.len() - self.current_segment_idx {
+ ) -> (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
@@ -147,7 +162,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
}
_ => {
// FIXME report error (ambiguous associated type)
- (TyKind::Error.intern(Interner), None)
+ (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None)
}
}
}
@@ -157,8 +172,11 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
&mut self,
resolution: TypeNs,
infer_args: bool,
- ) -> (Ty, Option<TypeNs>) {
+ ) -> (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_) => {
@@ -166,15 +184,17 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
1 => {
let trait_ref = self.lower_trait_ref_from_resolved_path(
trait_,
- TyKind::Error.intern(Interner),
- infer_args,
+ 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_.trait_items(self.ctx.db).associated_type_by_name(segment.name);
+ 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
@@ -183,27 +203,30 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
// this point (`trait_ref.substitution`).
let substitution = self.substs_from_path_segment(
associated_ty.into(),
- infer_args,
+ false,
None,
true,
);
- let substitution = Substitution::from_iter(
- Interner,
- trait_ref.substitution.iter(Interner).chain(
- substitution
- .iter(Interner)
- .skip(trait_ref.substitution.len(Interner)),
- ),
+ let args = GenericArgs::new_from_iter(
+ self.ctx.interner,
+ trait_ref
+ .args
+ .iter()
+ .chain(substitution.iter().skip(trait_ref.args.len())),
);
- TyKind::Alias(AliasTy::Projection(ProjectionTy {
- associated_ty_id: to_assoc_type_id(associated_ty),
- substitution,
- }))
- .intern(Interner)
+ 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)
- TyKind::Error.intern(Interner)
+ Ty::new_error(self.ctx.interner, ErrorGuaranteed)
}
}
}
@@ -211,61 +234,34 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
// Trait object type without dyn; this should be handled in upstream. See
// `lower_path()`.
stdx::never!("unexpected fully resolved trait path");
- TyKind::Error.intern(Interner)
+ Ty::new_error(self.ctx.interner, ErrorGuaranteed)
}
_ => {
// FIXME report error (ambiguous associated type)
- TyKind::Error.intern(Interner)
+ Ty::new_error(self.ctx.interner, ErrorGuaranteed)
}
};
return (ty, None);
}
- TypeNs::TraitAliasId(_) => {
- // FIXME(trait_alias): Implement trait alias.
- return (TyKind::Error.intern(Interner), None);
- }
- TypeNs::GenericParam(param_id) => match self.ctx.type_param_mode {
- ParamLoweringMode::Placeholder => {
- TyKind::Placeholder(to_placeholder_idx(self.ctx.db, param_id.into()))
- }
- ParamLoweringMode::Variable => {
- let idx = match self.ctx.generics().type_or_const_param_idx(param_id.into()) {
- None => {
- never!("no matching generics");
- return (TyKind::Error.intern(Interner), None);
- }
- Some(idx) => idx,
- };
-
- TyKind::BoundVar(BoundVar::new(self.ctx.in_binders, idx))
- }
- }
- .intern(Interner),
- TypeNs::SelfType(impl_id) => {
+ TypeNs::GenericParam(param_id) => {
let generics = self.ctx.generics();
-
- match self.ctx.type_param_mode {
- ParamLoweringMode::Placeholder => {
- // `def` can be either impl itself or item within, and we need impl itself
- // now.
- let generics = generics.parent_or_self();
- let subst = generics.placeholder_subst(self.ctx.db);
- self.ctx.db.impl_self_ty(impl_id).substitute(Interner, &subst)
+ 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());
+ self.ctx.type_param(param_id, idx as u32)
}
- ParamLoweringMode::Variable => TyBuilder::impl_self_ty(self.ctx.db, impl_id)
- .fill_with_bound_vars(self.ctx.in_binders, 0)
- .build(),
}
}
+ TypeNs::SelfType(impl_id) => self.ctx.db.impl_self_ty(impl_id).skip_binder(),
TypeNs::AdtSelfType(adt) => {
- let generics = generics(self.ctx.db, adt.into());
- let substs = match self.ctx.type_param_mode {
- ParamLoweringMode::Placeholder => generics.placeholder_subst(self.ctx.db),
- ParamLoweringMode::Variable => {
- generics.bound_vars_subst(self.ctx.db, self.ctx.in_binders)
- }
- };
- self.ctx.db.ty(adt.into()).substitute(Interner, &substs)
+ let args = 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),
@@ -273,15 +269,19 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args),
// FIXME: report error
TypeNs::EnumVariantId(_) | TypeNs::ModuleId(_) => {
- return (TyKind::Error.intern(Interner), None);
+ 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) {
+ /// This returns whether to keep the resolution (`true`) of throw it (`false`).
+ #[must_use]
+ fn handle_type_ns_resolution(&mut self, resolution: &TypeNs) -> bool {
let mut prohibit_generics_on_resolved = |reason| {
if self.current_or_prev_segment.args_and_bindings.is_some() {
let segment = self.current_segment_u32();
@@ -300,7 +300,13 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
prohibit_generics_on_resolved(GenericArgsProhibitedReason::TyParam)
}
TypeNs::AdtSelfType(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy)
+ prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy);
+
+ if self.ctx.lowering_param_default.is_some() {
+ // Generic defaults are not allowed to refer to `Self`.
+ // FIXME: Emit an error.
+ return false;
+ }
}
TypeNs::BuiltinType(_) => {
prohibit_generics_on_resolved(GenericArgsProhibitedReason::PrimitiveTy)
@@ -311,9 +317,10 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
TypeNs::AdtId(_)
| TypeNs::EnumVariantId(_)
| TypeNs::TypeAliasId(_)
- | TypeNs::TraitId(_)
- | TypeNs::TraitAliasId(_) => {}
+ | TypeNs::TraitId(_) => {}
}
+
+ true
}
pub(crate) fn resolve_path_in_type_ns_fully(&mut self) -> Option<TypeNs> {
@@ -324,6 +331,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
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)?;
@@ -346,11 +354,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
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 {
@@ -360,18 +363,19 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
}
}
- if let Some(enum_segment) = enum_segment {
- if 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,
- });
- }
+ 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);
+ if !self.handle_type_ns_resolution(&resolution) {
+ return None;
+ }
Some((resolution, remaining_index))
}
@@ -417,15 +421,14 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
}
}
- if let Some(enum_segment) = enum_segment {
- if 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,
- });
- }
+ 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 {
@@ -444,7 +447,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
match resolution {
ValueNs::ImplSelf(_) => {
- prohibit_generics_on_resolved(GenericArgsProhibitedReason::SelfTy)
+ 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
@@ -468,77 +471,67 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
}
}
ResolveValueResult::Partial(resolution, _, _) => {
- self.handle_type_ns_resolution(resolution);
+ if !self.handle_type_ns_resolution(resolution) {
+ return None;
+ }
}
};
Some(res)
}
- fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty {
+ #[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 TyKind::Error.intern(Interner);
+ return Ty::new_error(self.ctx.interner, ErrorGuaranteed);
};
+ let def = self.ctx.def;
let segment = self.current_or_prev_segment;
- let ty = named_associated_type_shorthand_candidates(
- self.ctx.db,
- self.ctx.def,
- res,
- Some(segment.name.clone()),
- move |name, t, associated_ty| {
- if name != segment.name {
- return None;
- }
- let generics = self.ctx.generics();
-
- let parent_subst = t.substitution.clone();
- let parent_subst = match self.ctx.type_param_mode {
- ParamLoweringMode::Placeholder => {
- // if we're lowering to placeholders, we have to put them in now.
- let s = generics.placeholder_subst(self.ctx.db);
- s.apply(parent_subst, Interner)
- }
- ParamLoweringMode::Variable => {
- // We need to shift in the bound vars, since
- // `named_associated_type_shorthand_candidates` does not do that.
- parent_subst.shifted_in_from(Interner, self.ctx.in_binders)
- }
- };
-
- // 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 = Substitution::from_iter(
- Interner,
- parent_subst
- .iter(Interner)
- .chain(substs.iter(Interner).skip(parent_subst.len(Interner))),
- );
-
- Some(
- TyKind::Alias(AliasTy::Projection(ProjectionTy {
- associated_ty_id: to_assoc_type_id(associated_ty),
- substitution: substs,
- }))
- .intern(Interner),
- )
- },
- );
+ let assoc_name = segment.name;
+ let check_alias = |name: &Name, t: TraitRef<'db>, associated_ty: TypeAliasId| {
+ if name != assoc_name {
+ return None;
+ }
- ty.unwrap_or_else(|| TyKind::Error.intern(Interner))
+ // 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 = 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 {
+ fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> {
let generic_def = match typeable {
- TyDefId::BuiltinType(builtin) => return TyBuilder::builtin(builtin),
+ TyDefId::BuiltinType(builtinty) => {
+ return Ty::from_builtin_type(self.ctx.interner, builtinty);
+ }
TyDefId::AdtId(it) => it.into(),
TyDefId::TypeAliasId(it) => it.into(),
};
- let substs = self.substs_from_path_segment(generic_def, infer_args, None, false);
- self.ctx.db.ty(typeable).substitute(Interner, &substs)
+ 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
@@ -551,7 +544,8 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
resolved: ValueTyDefId,
infer_args: bool,
lowering_assoc_type_generics: bool,
- ) -> Substitution {
+ ) -> 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;
@@ -560,7 +554,9 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
ValueTyDefId::StructId(it) => it.into(),
ValueTyDefId::UnionId(it) => it.into(),
ValueTyDefId::ConstId(it) => it.into(),
- ValueTyDefId::StaticId(_) => return Substitution::empty(Interner),
+ ValueTyDefId::StaticId(_) => {
+ return 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
@@ -576,13 +572,12 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
// 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 {
- if 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;
- }
+ 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()
}
@@ -602,71 +597,72 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
&mut self,
def: GenericDefId,
infer_args: bool,
- explicit_self_ty: Option<Ty>,
+ explicit_self_ty: Option<Ty<'db>>,
lowering_assoc_type_generics: bool,
- ) -> Substitution {
- let mut lifetime_elision = self.ctx.lifetime_elision.clone();
-
- if let Some(args) = self.current_or_prev_segment.args_and_bindings {
- if 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 TyBuilder::unknown_subst(self.ctx.db, def);
+ ) -> 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,
+ };
- // `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
- lifetime_elision =
- LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false };
+ 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 };
}
- self.substs_from_args_and_bindings(
+ 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,
- lifetime_elision,
- )
+ 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>,
+ args_and_bindings: Option<&HirGenericArgs>,
def: GenericDefId,
infer_args: bool,
- explicit_self_ty: Option<Ty>,
+ explicit_self_ty: Option<Ty<'db>>,
generics_source: PathGenericsSource,
lowering_assoc_type_generics: bool,
- lifetime_elision: LifetimeElisionKind,
- ) -> Substitution {
- struct LowererCtx<'a, 'b, 'c> {
- ctx: &'a mut PathLoweringContext<'b, 'c>,
+ lifetime_elision: LifetimeElisionKind<'db>,
+ ) -> GenericArgs<'db> {
+ struct LowererCtx<'a, 'b, 'c, 'db> {
+ ctx: &'a mut PathLoweringContext<'b, 'c, 'db>,
generics_source: PathGenericsSource,
}
- impl GenericArgsLowerer for LowererCtx<'_, '_, '_> {
+ impl<'db> GenericArgsLowerer<'db> for LowererCtx<'_, '_, '_, 'db> {
fn report_len_mismatch(
&mut self,
def: GenericDefId,
@@ -701,23 +697,24 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
&mut self,
param_id: GenericParamId,
param: GenericParamDataRef<'_>,
- arg: &GenericArg,
- ) -> crate::GenericArg {
- match (param, arg) {
- (GenericParamDataRef::LifetimeParamData(_), GenericArg::Lifetime(lifetime)) => {
- self.ctx.ctx.lower_lifetime(*lifetime).cast(Interner)
- }
- (GenericParamDataRef::TypeParamData(_), GenericArg::Type(type_ref)) => {
- self.ctx.ctx.lower_ty(*type_ref).cast(Interner)
+ arg: &HirGenericArg,
+ ) -> GenericArg<'db> {
+ match (param, *arg) {
+ (
+ GenericParamDataRef::LifetimeParamData(_),
+ HirGenericArg::Lifetime(lifetime),
+ ) => self.ctx.ctx.lower_lifetime(lifetime).into(),
+ (GenericParamDataRef::TypeParamData(_), HirGenericArg::Type(type_ref)) => {
+ self.ctx.ctx.lower_ty(type_ref).into()
}
- (GenericParamDataRef::ConstParamData(_), GenericArg::Const(konst)) => {
+ (GenericParamDataRef::ConstParamData(_), HirGenericArg::Const(konst)) => {
let GenericParamId::ConstParamId(const_id) = param_id else {
unreachable!("non-const param ID for const param");
};
self.ctx
.ctx
- .lower_const(konst, self.ctx.ctx.db.const_param_ty(const_id))
- .cast(Interner)
+ .lower_const(konst, const_param_ty_query(self.ctx.ctx.db, const_id))
+ .into()
}
_ => unreachable!("unmatching param kinds were passed to `provided_kind()`"),
}
@@ -725,9 +722,9 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
fn provided_type_like_const(
&mut self,
- const_ty: Ty,
+ const_ty: Ty<'db>,
arg: TypeLikeConst<'_>,
- ) -> crate::Const {
+ ) -> Const<'db> {
match arg {
TypeLikeConst::Path(path) => self.ctx.ctx.lower_path_as_const(path, const_ty),
TypeLikeConst::Infer => unknown_const(const_ty),
@@ -740,48 +737,55 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
param_id: GenericParamId,
param: GenericParamDataRef<'_>,
infer_args: bool,
- preceding_args: &[crate::GenericArg],
- ) -> crate::GenericArg {
- let default = || {
- self.ctx
- .ctx
- .db
- .generic_defaults(def)
- .get(preceding_args.len())
- .map(|default| default.clone().substitute(Interner, preceding_args))
- };
+ preceding_args: &[GenericArg<'db>],
+ ) -> GenericArg<'db> {
+ let default =
+ || {
+ self.ctx.ctx.db.generic_defaults(def).get(preceding_args.len()).map(
+ |default| default.instantiate(self.ctx.ctx.interner, preceding_args),
+ )
+ };
match param {
- GenericParamDataRef::LifetimeParamData(_) => error_lifetime().cast(Interner),
+ GenericParamDataRef::LifetimeParamData(_) => {
+ Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed))
+ .into()
+ }
GenericParamDataRef::TypeParamData(param) => {
- if !infer_args && param.default.is_some() {
- if let Some(default) = default() {
- return default;
- }
+ if !infer_args
+ && param.default.is_some()
+ && let Some(default) = default()
+ {
+ return default;
}
- TyKind::Error.intern(Interner).cast(Interner)
+ Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into()
}
GenericParamDataRef::ConstParamData(param) => {
- if !infer_args && param.default.is_some() {
- if let Some(default) = default() {
- return default;
- }
+ 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(self.ctx.ctx.db.const_param_ty(const_id))
- .cast(Interner)
+ unknown_const_as_generic(const_param_ty_query(self.ctx.ctx.db, const_id))
}
}
}
- fn parent_arg(&mut self, param_id: GenericParamId) -> crate::GenericArg {
+ fn parent_arg(&mut self, param_id: GenericParamId) -> GenericArg<'db> {
match param_id {
- GenericParamId::TypeParamId(_) => TyKind::Error.intern(Interner).cast(Interner),
+ GenericParamId::TypeParamId(_) => {
+ Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into()
+ }
GenericParamId::ConstParamId(const_id) => {
- unknown_const_as_generic(self.ctx.ctx.db.const_param_ty(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()
}
- GenericParamId::LifetimeParamId(_) => error_lifetime().cast(Interner),
}
}
@@ -832,38 +836,39 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
pub(crate) fn lower_trait_ref_from_resolved_path(
&mut self,
resolved: TraitId,
- explicit_self_ty: Ty,
+ explicit_self_ty: Ty<'db>,
infer_args: bool,
- ) -> TraitRef {
- let substs = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args);
- TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs }
+ ) -> 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,
+ explicit_self_ty: Ty<'db>,
infer_args: bool,
- ) -> Substitution {
+ ) -> 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,
- ) -> Option<impl Iterator<Item = QuantifiedWhereClause> + use<'a, 'b, 'c>> {
+ 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.clone(),
+ trait_ref,
&binding.name,
);
let (super_trait_ref, associated_ty) = match found {
None => return SmallVec::new(),
Some(t) => t,
};
- let substitution =
+ 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
@@ -873,7 +878,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
binding.args.as_ref(),
associated_ty.into(),
false, // this is not relevant
- Some(super_trait_ref.self_type_parameter(Interner)),
+ Some(super_trait_ref.self_ty()),
PathGenericsSource::AssocType {
segment: this.current_segment_u32(),
assoc_type: binding_idx as u32,
@@ -882,27 +887,20 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
this.ctx.lifetime_elision.clone(),
)
});
- let substitution = Substitution::from_iter(
- Interner,
- super_trait_ref.substitution.iter(Interner).chain(
- substitution
- .iter(Interner)
- .skip(super_trait_ref.substitution.len(Interner)),
- ),
+ let args = GenericArgs::new_from_iter(
+ interner,
+ super_trait_ref.args.iter().chain(args.iter().skip(super_trait_ref.args.len())),
);
- let projection_ty = ProjectionTy {
- associated_ty_id: to_assoc_type_id(associated_ty),
- substitution,
- };
+ 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()
+ LifetimeElisionKind::for_fn_ret(self.ctx.interner)
} else {
self.ctx.lifetime_elision.clone()
};
@@ -914,31 +912,33 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
ImplTraitLoweringMode::Disallowed | ImplTraitLoweringMode::Opaque,
) => {
let ty = this.ctx.lower_ty(type_ref);
- let alias_eq = AliasEq {
- alias: AliasTy::Projection(projection_ty.clone()),
- ty,
- };
- predicates.push(crate::wrap_empty_binders(WhereClause::AliasEq(
- alias_eq,
- )));
+ 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,
+ ));
}
-
- self.with_lifetime_elision(LifetimeElisionKind::AnonymousReportError, |this| {
- for bound in binding.bounds.iter() {
- predicates.extend(
- this.ctx.lower_type_bound(
- bound,
- TyKind::Alias(AliasTy::Projection(projection_ty.clone()))
- .intern(Interner),
- false,
- ),
- );
- }
- });
-
predicates
})
})
@@ -951,7 +951,7 @@ pub(crate) enum TypeLikeConst<'a> {
Path(&'a Path),
}
-pub(crate) trait GenericArgsLowerer {
+pub(crate) trait GenericArgsLowerer<'db> {
fn report_elided_lifetimes_in_path(
&mut self,
def: GenericDefId,
@@ -977,10 +977,11 @@ pub(crate) trait GenericArgsLowerer {
&mut self,
param_id: GenericParamId,
param: GenericParamDataRef<'_>,
- arg: &GenericArg,
- ) -> crate::GenericArg;
+ arg: &HirGenericArg,
+ ) -> GenericArg<'db>;
- fn provided_type_like_const(&mut self, const_ty: Ty, arg: TypeLikeConst<'_>) -> crate::Const;
+ fn provided_type_like_const(&mut self, const_ty: Ty<'db>, arg: TypeLikeConst<'_>)
+ -> Const<'db>;
fn inferred_kind(
&mut self,
@@ -988,21 +989,21 @@ pub(crate) trait GenericArgsLowerer {
param_id: GenericParamId,
param: GenericParamDataRef<'_>,
infer_args: bool,
- preceding_args: &[crate::GenericArg],
- ) -> crate::GenericArg;
+ preceding_args: &[GenericArg<'db>],
+ ) -> GenericArg<'db>;
- fn parent_arg(&mut self, param_id: GenericParamId) -> crate::GenericArg;
+ fn parent_arg(&mut self, param_id: GenericParamId) -> GenericArg<'db>;
}
/// Returns true if there was an error.
-fn check_generic_args_len(
- args_and_bindings: Option<&GenericArgs>,
+fn check_generic_args_len<'db>(
+ args_and_bindings: Option<&HirGenericArgs>,
def: GenericDefId,
def_generics: &Generics,
infer_args: bool,
- lifetime_elision: &LifetimeElisionKind,
+ lifetime_elision: &LifetimeElisionKind<'db>,
lowering_assoc_type_generics: bool,
- ctx: &mut impl GenericArgsLowerer,
+ ctx: &mut impl GenericArgsLowerer<'db>,
) -> bool {
let mut had_error = false;
@@ -1011,8 +1012,10 @@ fn check_generic_args_len(
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,
+ HirGenericArg::Lifetime(_) => provided_lifetimes_count += 1,
+ HirGenericArg::Type(_) | HirGenericArg::Const(_) => {
+ provided_types_and_consts_count += 1
+ }
}
}
}
@@ -1086,17 +1089,21 @@ fn check_generic_args_len(
had_error
}
-pub(crate) fn substs_from_args_and_bindings(
- db: &dyn HirDatabase,
+pub(crate) fn substs_from_args_and_bindings<'db>(
+ db: &'db dyn HirDatabase,
store: &ExpressionStore,
- args_and_bindings: Option<&GenericArgs>,
+ args_and_bindings: Option<&HirGenericArgs>,
def: GenericDefId,
mut infer_args: bool,
- lifetime_elision: LifetimeElisionKind,
+ lifetime_elision: LifetimeElisionKind<'db>,
lowering_assoc_type_generics: bool,
- explicit_self_ty: Option<Ty>,
- ctx: &mut impl GenericArgsLowerer,
-) -> Substitution {
+ explicit_self_ty: Option<Ty<'db>>,
+ ctx: &mut impl GenericArgsLowerer<'db>,
+) -> GenericArgs<'db> {
+ let interner = DbInterner::new_with(db, None, None);
+
+ tracing::debug!(?args_and_bindings);
+
// Order is
// - Parent parameters
// - Optional Self parameter
@@ -1107,7 +1114,7 @@ pub(crate) fn substs_from_args_and_bindings(
// 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(_)));
+ args_slice.iter().any(|arg| !matches!(arg, HirGenericArg::Lifetime(_)));
infer_args &= !has_non_lifetime_args;
let had_count_error = check_generic_args_len(
@@ -1148,7 +1155,7 @@ pub(crate) fn substs_from_args_and_bindings(
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.cast(Interner)).unwrap_or_else(|| {
+ explicit_self_ty.map(|it| it.into()).unwrap_or_else(|| {
ctx.inferred_kind(def, self_param_id, self_param, infer_args, &substs)
})
};
@@ -1163,7 +1170,7 @@ pub(crate) fn substs_from_args_and_bindings(
// 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))
+ (HirGenericArg::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
@@ -1171,15 +1178,15 @@ pub(crate) fn substs_from_args_and_bindings(
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(_)) => {
+ (HirGenericArg::Lifetime(_), GenericParamDataRef::LifetimeParamData(_))
+ | (HirGenericArg::Type(_), GenericParamDataRef::TypeParamData(_))
+ | (HirGenericArg::Const(_), GenericParamDataRef::ConstParamData(_)) => {
substs.push(ctx.provided_kind(param_id, param, arg));
args.next();
params.next();
}
(
- GenericArg::Type(_) | GenericArg::Const(_),
+ HirGenericArg::Type(_) | HirGenericArg::Const(_),
GenericParamDataRef::LifetimeParamData(_),
) => {
// We expected a lifetime argument, but got a type or const
@@ -1188,13 +1195,13 @@ pub(crate) fn substs_from_args_and_bindings(
params.next();
force_infer_lt = Some((arg_idx as u32, param_id));
}
- (GenericArg::Type(type_ref), GenericParamDataRef::ConstParamData(_)) => {
+ (HirGenericArg::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 = db.const_param_ty(param_id);
- substs.push(ctx.provided_type_like_const(const_ty, konst).cast(Interner));
+ 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 {
@@ -1233,7 +1240,7 @@ pub(crate) fn substs_from_args_and_bindings(
// after a type or const). We want to throw an error in this case.
if !had_count_error {
assert!(
- matches!(arg, GenericArg::Lifetime(_)),
+ matches!(arg, HirGenericArg::Lifetime(_)),
"the only possible situation here is incorrect lifetime order"
);
let (provided_arg_idx, param_id) =
@@ -1255,9 +1262,9 @@ pub(crate) fn substs_from_args_and_bindings(
ctx.inferred_kind(def, param_id, param, infer_args, &substs)
}
LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => {
- static_lifetime().cast(Interner)
+ Region::new_static(interner).into()
}
- LifetimeElisionKind::Elided(lifetime) => lifetime.clone().cast(Interner),
+ 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
@@ -1276,7 +1283,7 @@ pub(crate) fn substs_from_args_and_bindings(
}
}
- Substitution::from_iter(Interner, substs)
+ GenericArgs::new_from_iter(interner, substs)
}
fn type_looks_like_const(
@@ -1295,3 +1302,17 @@ fn type_looks_like_const(
_ => None,
}
}
+
+fn unknown_subst<'db>(interner: DbInterner<'db>, def: impl Into<GenericDefId>) -> GenericArgs<'db> {
+ let params = generics(interner.db(), def.into());
+ 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(_) => Region::error(interner).into(),
+ }),
+ )
+}