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.rs220
1 files changed, 16 insertions, 204 deletions
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index da9dd21183..09a256a86d 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/crates/hir-ty/src/lower/path.rs
@@ -3,15 +3,15 @@
use chalk_ir::{BoundVar, cast::Cast, fold::Shift};
use either::Either;
use hir_def::{
- GenericDefId, GenericParamId, Lookup, TraitId,
+ GenericDefId, GenericParamId, TraitId,
expr_store::{
- ExpressionStore, HygieneId,
+ ExpressionStore,
path::{GenericArg, GenericArgs, GenericArgsParentheses, Path, PathSegment, PathSegments},
},
hir::generics::{
GenericParamDataRef, TypeOrConstParamData, TypeParamData, TypeParamProvenance,
},
- resolver::{ResolveValueResult, TypeNs, ValueNs},
+ resolver::TypeNs,
signatures::TraitFlags,
type_ref::{TypeRef, TypeRefId},
};
@@ -21,36 +21,36 @@ 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,
- consteval::{unknown_const, unknown_const_as_generic},
+ QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyDefId, TyKind, WhereClause,
+ consteval_chalk::{unknown_const, unknown_const_as_generic},
db::HirDatabase,
error_lifetime,
generics::{Generics, generics},
- lower::{LifetimeElisionKind, named_associated_type_shorthand_candidates},
+ lower::{LifetimeElisionKind, TyLoweringContext, named_associated_type_shorthand_candidates},
next_solver::{
DbInterner,
mapping::{ChalkToNextSolver, NextSolverToChalk},
},
- static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
+ to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
utils::associated_type_by_name_including_super_traits,
};
-type CallbackData<'a> = Either<
+type CallbackData<'a, 'db> = Either<
super::PathDiagnosticCallbackData,
- crate::infer::diagnostics::PathDiagnosticCallbackData<'a>,
+ 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<'_>, PathLoweringDiagnostic),
}
pub(crate) struct PathLoweringContext<'a, 'b> {
ctx: &'a mut TyLoweringContext<'b>,
- on_diagnostic: PathDiagnosticCallback<'a>,
+ on_diagnostic: PathDiagnosticCallback<'a, 'b>,
path: &'a Path,
segments: PathSegments<'a>,
current_segment_idx: usize,
@@ -62,7 +62,7 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
#[inline]
pub(crate) fn new(
ctx: &'a mut TyLoweringContext<'b>,
- on_diagnostic: PathDiagnosticCallback<'a>,
+ on_diagnostic: PathDiagnosticCallback<'a, 'b>,
path: &'a Path,
) -> Self {
let segments = path.segments();
@@ -110,20 +110,6 @@ 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,
@@ -390,103 +376,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
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)
- }
-
fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty {
let Some(res) = res else {
return TyKind::Error.intern(Interner);
@@ -556,62 +445,6 @@ impl<'a, 'b> PathLoweringContext<'a, 'b> {
self.ctx.db.ty(typeable).instantiate(interner, args).to_chalk(interner)
}
- /// 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,
- ) -> Substitution {
- 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 Substitution::empty(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,
@@ -816,14 +649,6 @@ 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,
@@ -976,8 +801,6 @@ 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(
@@ -1050,13 +873,6 @@ 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);
}
@@ -1265,15 +1081,11 @@ 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::ElisionFailure
- | LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }
+ 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: _ } => {
- static_lifetime().cast(Interner)
- }
LifetimeElisionKind::Elided(lifetime) => lifetime.clone().cast(Interner),
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: false }
| LifetimeElisionKind::Infer => {