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.rs768
1 files changed, 480 insertions, 288 deletions
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index 09a256a86d..9ba0da6f49 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/crates/hir-ty/src/lower/path.rs
@@ -1,42 +1,52 @@
//! A wrapper around [`TyLoweringContext`] specifically for lowering paths.
-use chalk_ir::{BoundVar, cast::Cast, fold::Shift};
use either::Either;
use hir_def::{
- GenericDefId, GenericParamId, TraitId,
+ GenericDefId, GenericParamId, Lookup, TraitId, TypeAliasId,
expr_store::{
- ExpressionStore,
- path::{GenericArg, GenericArgs, GenericArgsParentheses, Path, PathSegment, PathSegments},
+ ExpressionStore, HygieneId,
+ path::{
+ GenericArg as HirGenericArg, GenericArgs as HirGenericArgs, GenericArgsParentheses,
+ Path, PathSegment, PathSegments,
+ },
},
hir::generics::{
GenericParamDataRef, TypeOrConstParamData, TypeParamData, TypeParamProvenance,
},
- resolver::TypeNs,
+ resolver::{ResolveValueResult, TypeNs, ValueNs},
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, WhereClause,
- consteval_chalk::{unknown_const, unknown_const_as_generic},
+ GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource,
+ PathLoweringDiagnostic, TyDefId, ValueTyDefId,
+ consteval::{unknown_const, unknown_const_as_generic},
db::HirDatabase,
- error_lifetime,
generics::{Generics, generics},
- lower::{LifetimeElisionKind, TyLoweringContext, named_associated_type_shorthand_candidates},
+ lower::{
+ LifetimeElisionKind, PathDiagnosticCallbackData, named_associated_type_shorthand_candidates,
+ },
next_solver::{
- DbInterner,
- mapping::{ChalkToNextSolver, NextSolverToChalk},
+ Binder, Clause, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Predicate,
+ ProjectionPredicate, Region, TraitRef, Ty,
},
- to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
- utils::associated_type_by_name_including_super_traits,
+};
+
+use super::{
+ ImplTraitLoweringMode, TyLoweringContext, associated_type_by_name_including_super_traits,
+ const_param_ty_query, ty_query,
};
type CallbackData<'a, 'db> = Either<
- super::PathDiagnosticCallbackData,
+ PathDiagnosticCallbackData,
crate::infer::diagnostics::PathDiagnosticCallbackData<'a, 'db>,
>;
@@ -45,12 +55,12 @@ type CallbackData<'a, 'db> = Either<
pub(crate) struct PathDiagnosticCallback<'a, 'db> {
pub(crate) data: CallbackData<'a, 'db>,
pub(crate) callback:
- fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'_>, PathLoweringDiagnostic),
+ fn(&CallbackData<'_, 'db>, &mut TyLoweringContext<'db, '_>, PathLoweringDiagnostic),
}
-pub(crate) struct PathLoweringContext<'a, 'b> {
- ctx: &'a mut TyLoweringContext<'b>,
- on_diagnostic: PathDiagnosticCallback<'a, 'b>,
+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,
@@ -58,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, 'b>,
+ ctx: &'a mut TyLoweringContext<'db, 'b>,
+ on_diagnostic: PathDiagnosticCallback<'a, 'db>,
path: &'a Path,
) -> Self {
let segments = path.segments();
@@ -84,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
}
@@ -110,10 +120,24 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
}
#[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,
- 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);
@@ -124,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
@@ -137,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)
}
}
}
@@ -147,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_) => {
@@ -156,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
@@ -173,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)
}
}
}
@@ -201,73 +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::GenericParam(param_id) => match self.ctx.type_param_mode {
- ParamLoweringMode::Placeholder => {
- let generics = self.ctx.generics();
- let idx = generics.type_or_const_param_idx(param_id.into()).unwrap();
- TyKind::Placeholder(to_placeholder_idx(
- self.ctx.db,
- param_id.into(),
- idx as u32,
- ))
- }
- 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 interner = DbInterner::new_with(self.ctx.db, None, None);
- let subst = generics.placeholder_subst(self.ctx.db);
- let args: crate::next_solver::GenericArgs<'_> =
- subst.to_nextsolver(interner);
- self.ctx
- .db
- .impl_self_ty(impl_id)
- .instantiate(interner, args)
- .to_chalk(interner)
+ 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(DbInterner::conjure())
- .to_chalk(DbInterner::conjure()),
}
}
+ 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)
- }
- };
- let interner = DbInterner::conjure();
- let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
- self.ctx.db.ty(adt.into()).instantiate(interner, args).to_chalk(interner)
+ 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),
@@ -275,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();
@@ -302,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)
@@ -315,6 +319,8 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
| TypeNs::TypeAliasId(_)
| TypeNs::TraitId(_) => {}
}
+
+ true
}
pub(crate) fn resolve_path_in_type_ns_fully(&mut self) -> Option<TypeNs> {
@@ -325,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)?;
@@ -347,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 {
@@ -371,87 +373,233 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
});
}
- self.handle_type_ns_resolution(&resolution);
+ if !self.handle_type_ns_resolution(&resolution) {
+ return None;
+ }
Some((resolution, remaining_index))
}
- fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty {
- let Some(res) = res else {
- return TyKind::Error.intern(Interner);
- };
- let segment = self.current_or_prev_segment;
- let ty = named_associated_type_shorthand_candidates(
+ 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.ctx.def,
- res,
- Some(segment.name.clone()),
- move |name, t, associated_ty| {
- if name != segment.name {
- return None;
- }
- let generics = self.ctx.generics();
+ self.path,
+ hygiene_id,
+ )?;
- 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)
+ 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,
+ });
}
};
- // 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))),
- );
+ 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, _, _) => {
+ if !self.handle_type_ns_resolution(resolution) {
+ return None;
+ }
+ }
+ };
+ Some(res)
+ }
- Some(
- TyKind::Alias(AliasTy::Projection(ProjectionTy {
- associated_ty_id: to_assoc_type_id(associated_ty),
- substitution: substs,
- }))
- .intern(Interner),
- )
- },
- );
+ #[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 def = self.ctx.def;
+ let segment = self.current_or_prev_segment;
+ 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);
- let interner = DbInterner::conjure();
- let args: crate::next_solver::GenericArgs<'_> = substs.to_nextsolver(interner);
- self.ctx.db.ty(typeable).instantiate(interner, args).to_chalk(interner)
+ 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,
+ ) -> 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 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>,
+ explicit_self_ty: Option<Ty<'db>>,
lowering_assoc_type_generics: bool,
- ) -> Substitution {
+ ) -> GenericArgs<'db> {
let old_lifetime_elision = self.ctx.lifetime_elision.clone();
if let Some(args) = self.current_or_prev_segment.args_and_bindings
@@ -478,7 +626,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
PathLoweringDiagnostic::ParenthesizedGenericArgsWithoutFnTrait { segment },
);
- return TyBuilder::unknown_subst(self.ctx.db, def);
+ return unknown_subst(self.ctx.interner, def);
}
// `Fn()`-style generics are treated like functions for the purpose of lifetime elision.
@@ -501,20 +649,20 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
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,
@@ -549,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()`"),
}
@@ -573,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),
@@ -588,18 +737,19 @@ 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()
@@ -607,7 +757,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
{
return default;
}
- TyKind::Error.intern(Interner).cast(Interner)
+ Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into()
}
GenericParamDataRef::ConstParamData(param) => {
if !infer_args
@@ -619,19 +769,23 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
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),
}
}
@@ -649,6 +803,14 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
});
}
+ 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,
@@ -674,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
@@ -715,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,
@@ -724,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()
};
@@ -756,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
})
})
@@ -793,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,
@@ -801,6 +959,8 @@ pub(crate) trait GenericArgsLowerer {
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(
@@ -817,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,
@@ -828,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;
@@ -851,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
+ }
}
}
}
@@ -873,6 +1036,13 @@ fn check_generic_args_len(
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);
}
@@ -919,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
@@ -940,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(
@@ -981,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)
})
};
@@ -996,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
@@ -1004,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
@@ -1021,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 {
@@ -1066,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) =
@@ -1081,12 +1255,16 @@ pub(crate) fn substs_from_args_and_bindings(
// 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::AnonymousCreateParameter { report_in_path: true }
+ 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::Elided(lifetime) => lifetime.clone().cast(Interner),
+ 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
@@ -1105,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(
@@ -1124,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(),
+ }),
+ )
+}