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.rs118
1 files changed, 94 insertions, 24 deletions
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index 1e7e56ab88..0757d57500 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/crates/hir-ty/src/lower/path.rs
@@ -25,9 +25,10 @@ use smallvec::SmallVec;
use crate::{
GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource,
- PathLoweringDiagnostic, TyDefId, ValueTyDefId,
+ PathLoweringDiagnostic, Span, TyDefId, ValueTyDefId,
db::HirDatabase,
generics::{Generics, generics},
+ infer::unify::InferenceTable,
lower::{
AssocTypeShorthandResolution, ForbidParamsAfterReason, GenericPredicateSource,
LifetimeElisionKind, PathDiagnosticCallbackData, const_param_ty,
@@ -83,6 +84,11 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
}
}
+ #[track_caller]
+ pub(crate) fn expect_table(&mut self) -> &mut InferenceTable<'db> {
+ self.ctx.expect_table()
+ }
+
#[inline]
#[cold]
fn on_diagnostic(&mut self, diag: PathLoweringDiagnostic) {
@@ -148,13 +154,14 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
// We need the original resolution to lower `Self::AssocTy` correctly
res: Option<TypeNs>,
infer_args: bool,
+ span: Span,
) -> (Ty<'db>, Option<TypeNs>) {
let remaining_segments = self.segments.len() - self.current_segment_idx;
match remaining_segments {
0 => (ty, res),
1 => {
// resolve unselected assoc types
- (self.select_associated_type(res, infer_args), None)
+ (self.select_associated_type(res, infer_args, span), None)
}
_ => {
// FIXME report error (ambiguous associated type)
@@ -168,6 +175,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
&mut self,
resolution: TypeNs,
infer_args: bool,
+ span: Span,
) -> (Ty<'db>, Option<TypeNs>) {
let remaining_segments = self.segments.skip(self.current_segment_idx + 1);
tracing::debug!(?remaining_segments);
@@ -182,6 +190,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
trait_,
self.ctx.types.types.error,
infer_args,
+ span,
);
tracing::debug!(?trait_ref);
self.skip_resolved_segment();
@@ -202,6 +211,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
infer_args,
None,
true,
+ span,
);
let args = GenericArgs::new_from_iter(
self.ctx.interner,
@@ -249,9 +259,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
Ty::new_adt(self.ctx.interner, adt, args)
}
- TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args),
- TypeNs::BuiltinType(it) => self.lower_path_inner(it.into(), infer_args),
- TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args),
+ TypeNs::AdtId(it) => self.lower_path_inner(it.into(), infer_args, span),
+ TypeNs::BuiltinType(it) => self.lower_path_inner(it.into(), infer_args, span),
+ TypeNs::TypeAliasId(it) => self.lower_path_inner(it.into(), infer_args, span),
// FIXME: report error
TypeNs::EnumVariantId(_) | TypeNs::ModuleId(_) => {
return (self.ctx.types.types.error, None);
@@ -261,7 +271,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
tracing::debug!(?ty);
self.skip_resolved_segment();
- self.lower_ty_relative_path(ty, Some(resolution), infer_args)
+ self.lower_ty_relative_path(ty, Some(resolution), infer_args, span)
}
/// This returns whether to keep the resolution (`true`) of throw it (`false`).
@@ -469,7 +479,12 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
}
#[tracing::instrument(skip(self), ret)]
- fn select_associated_type(&mut self, res: Option<TypeNs>, infer_args: bool) -> Ty<'db> {
+ fn select_associated_type(
+ &mut self,
+ res: Option<TypeNs>,
+ infer_args: bool,
+ span: Span,
+ ) -> Ty<'db> {
let interner = self.ctx.interner;
let db = self.ctx.db;
let def = self.ctx.generic_def;
@@ -526,7 +541,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
// 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(assoc_type.into(), infer_args, None, true);
+ let substs = self.substs_from_path_segment(assoc_type.into(), infer_args, None, true, span);
let substs = GenericArgs::new_from_iter(
interner,
@@ -536,7 +551,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
Ty::new_projection_from_args(interner, assoc_type.into(), substs)
}
- fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool) -> Ty<'db> {
+ fn lower_path_inner(&mut self, typeable: TyDefId, infer_args: bool, span: Span) -> Ty<'db> {
let generic_def = match typeable {
TyDefId::BuiltinType(builtinty) => {
return Ty::from_builtin_type(self.ctx.interner, builtinty);
@@ -544,7 +559,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
TyDefId::AdtId(it) => it.into(),
TyDefId::TypeAliasId(it) => it.into(),
};
- let args = self.substs_from_path_segment(generic_def, infer_args, None, false);
+ let args = self.substs_from_path_segment(generic_def, infer_args, None, false, span);
let ty = ty_query(self.ctx.db, typeable);
ty.instantiate(self.ctx.interner, args).skip_norm_wip()
}
@@ -559,6 +574,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
resolved: ValueTyDefId,
infer_args: bool,
lowering_assoc_type_generics: bool,
+ span: Span,
) -> GenericArgs<'db> {
let interner = self.ctx.interner;
let prev_current_segment_idx = self.current_segment_idx;
@@ -602,6 +618,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
infer_args,
None,
lowering_assoc_type_generics,
+ span,
);
self.current_segment_idx = prev_current_segment_idx;
self.current_or_prev_segment = prev_current_segment;
@@ -614,6 +631,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
infer_args: bool,
explicit_self_ty: Option<Ty<'db>>,
lowering_assoc_type_generics: bool,
+ span: Span,
) -> GenericArgs<'db> {
let old_lifetime_elision = self.ctx.lifetime_elision;
@@ -654,6 +672,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
PathGenericsSource::Segment(self.current_segment_u32()),
lowering_assoc_type_generics,
self.ctx.lifetime_elision,
+ span,
);
self.ctx.lifetime_elision = old_lifetime_elision;
result
@@ -668,10 +687,12 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
generics_source: PathGenericsSource,
lowering_assoc_type_generics: bool,
lifetime_elision: LifetimeElisionKind<'db>,
+ span: Span,
) -> GenericArgs<'db> {
struct LowererCtx<'a, 'b, 'c, 'db> {
ctx: &'a mut PathLoweringContext<'b, 'c, 'db>,
generics_source: PathGenericsSource,
+ span: Span,
}
impl<'db> GenericArgsLowerer<'db> for LowererCtx<'_, '_, '_, 'db> {
@@ -734,13 +755,13 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
fn provided_type_like_const(
&mut self,
- _type_ref: TypeRefId,
+ type_ref: TypeRefId,
const_ty: Ty<'db>,
arg: TypeLikeConst<'_>,
) -> Const<'db> {
match arg {
TypeLikeConst::Path(path) => self.ctx.ctx.lower_path_as_const(path, const_ty),
- TypeLikeConst::Infer => self.ctx.ctx.types.consts.error,
+ TypeLikeConst::Infer => self.ctx.ctx.next_const_var(type_ref.into()),
}
}
@@ -751,15 +772,18 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
param: GenericParamDataRef<'_>,
infer_args: bool,
preceding_args: &[GenericArg<'db>],
+ had_count_error: bool,
) -> 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).skip_norm_wip()
})
};
+ // If `!infer_args`, we've already emitted an error, so put a dummy span.
+ let span = if !infer_args || had_count_error { Span::Dummy } else { self.span };
match param {
GenericParamDataRef::LifetimeParamData(_) => {
- self.ctx.ctx.types.regions.error.into()
+ self.ctx.ctx.next_region_var(span).into()
}
GenericParamDataRef::TypeParamData(param) => {
if !infer_args
@@ -768,7 +792,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
{
return default;
}
- Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into()
+ self.ctx.ctx.next_ty_var_no_placeholder(span).into()
}
GenericParamDataRef::ConstParamData(param) => {
if !infer_args
@@ -780,7 +804,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
let GenericParamId::ConstParamId(_) = param_id else {
unreachable!("non-const param ID for const param");
};
- self.ctx.ctx.types.consts.error.into()
+ self.ctx.ctx.next_const_var(span).into()
}
}
}
@@ -835,7 +859,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
lifetime_elision,
lowering_assoc_type_generics,
explicit_self_ty,
- &mut LowererCtx { ctx: self, generics_source },
+ &mut LowererCtx { ctx: self, generics_source, span },
)
}
@@ -844,8 +868,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
resolved: TraitId,
explicit_self_ty: Ty<'db>,
infer_args: bool,
+ span: Span,
) -> TraitRef<'db> {
- let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args);
+ let args = self.trait_ref_substs_from_path(resolved, explicit_self_ty, infer_args, span);
TraitRef::new_from_args(self.ctx.interner, resolved.into(), args)
}
@@ -854,13 +879,21 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
resolved: TraitId,
explicit_self_ty: Ty<'db>,
infer_args: bool,
+ span: Span,
) -> GenericArgs<'db> {
- self.substs_from_path_segment(resolved.into(), infer_args, Some(explicit_self_ty), false)
+ self.substs_from_path_segment(
+ resolved.into(),
+ infer_args,
+ Some(explicit_self_ty),
+ false,
+ span,
+ )
}
pub(super) fn assoc_type_bindings_from_type_bound<'c>(
mut self,
trait_ref: TraitRef<'db>,
+ span: Span,
) -> Option<impl Iterator<Item = (Clause<'db>, GenericPredicateSource)> + use<'a, 'b, 'c, 'db>>
{
let interner = self.ctx.interner;
@@ -892,6 +925,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
},
false,
this.ctx.lifetime_elision,
+ span,
)
});
let args = GenericArgs::new_from_iter(
@@ -1011,6 +1045,7 @@ pub(crate) trait GenericArgsLowerer<'db> {
param: GenericParamDataRef<'_>,
infer_args: bool,
preceding_args: &[GenericArg<'db>],
+ had_count_error: bool,
) -> GenericArg<'db>;
fn parent_arg(&mut self, param_idx: u32, param_id: GenericParamId) -> GenericArg<'db>;
@@ -1179,7 +1214,14 @@ pub(crate) fn substs_from_args_and_bindings<'db>(
ctx.provided_kind(self_param_id, self_param, self_ty)
} else {
explicit_self_ty.map(|it| it.into()).unwrap_or_else(|| {
- ctx.inferred_kind(def, self_param_id, self_param, infer_args, &substs)
+ ctx.inferred_kind(
+ def,
+ self_param_id,
+ self_param,
+ infer_args,
+ &substs,
+ had_count_error,
+ )
})
};
params.next();
@@ -1198,7 +1240,14 @@ pub(crate) fn substs_from_args_and_bindings<'db>(
{
// Do not allow specifying `impl Trait` explicitly. We already err at that, but if we won't handle it here
// we will handle it as if it was specified, instead of inferring it.
- substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs));
+ substs.push(ctx.inferred_kind(
+ def,
+ param_id,
+ param,
+ infer_args,
+ &substs,
+ had_count_error,
+ ));
params.next();
}
(HirGenericArg::Lifetime(_), GenericParamDataRef::LifetimeParamData(_))
@@ -1214,7 +1263,14 @@ pub(crate) fn substs_from_args_and_bindings<'db>(
) => {
// We expected a lifetime argument, but got a type or const
// argument. That means we're inferring the lifetime.
- substs.push(ctx.inferred_kind(def, param_id, param, infer_args, &substs));
+ substs.push(ctx.inferred_kind(
+ def,
+ param_id,
+ param,
+ infer_args,
+ &substs,
+ had_count_error,
+ ));
params.next();
force_infer_lt = Some((arg_idx as u32, param_id));
}
@@ -1283,7 +1339,14 @@ pub(crate) fn substs_from_args_and_bindings<'db>(
| LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true }
| LifetimeElisionKind::AnonymousReportError => {
assert!(had_count_error);
- ctx.inferred_kind(def, param_id, param, infer_args, &substs)
+ ctx.inferred_kind(
+ def,
+ param_id,
+ param,
+ infer_args,
+ &substs,
+ had_count_error,
+ )
}
LifetimeElisionKind::StaticIfNoLifetimeInScope { only_lint: _ } => {
Region::new_static(interner).into()
@@ -1293,11 +1356,18 @@ pub(crate) fn substs_from_args_and_bindings<'db>(
| LifetimeElisionKind::Infer => {
// FIXME: With `AnonymousCreateParameter`, we need to create a new lifetime parameter here
// (but this will probably be done in hir-def lowering instead).
- ctx.inferred_kind(def, param_id, param, infer_args, &substs)
+ ctx.inferred_kind(
+ def,
+ param_id,
+ param,
+ infer_args,
+ &substs,
+ had_count_error,
+ )
}
}
} else {
- ctx.inferred_kind(def, param_id, param, infer_args, &substs)
+ ctx.inferred_kind(def, param_id, param, infer_args, &substs, had_count_error)
};
substs.push(param);
params.next();