Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #22237 from ChayimFriedman2/infcx-ty-lowering
fix: Provide an InferCtxt to TyLoweringContext
Chayim Refael Friedman 7 days ago
parent ecc571a · parent 9fc3180 · commit eefa158
-rw-r--r--crates/hir-ty/src/consteval.rs14
-rw-r--r--crates/hir-ty/src/generics.rs2
-rw-r--r--crates/hir-ty/src/infer.rs154
-rw-r--r--crates/hir-ty/src/infer/closure.rs8
-rw-r--r--crates/hir-ty/src/infer/diagnostics.rs19
-rw-r--r--crates/hir-ty/src/infer/path.rs31
-rw-r--r--crates/hir-ty/src/infer/unify.rs11
-rw-r--r--crates/hir-ty/src/lib.rs29
-rw-r--r--crates/hir-ty/src/lower.rs205
-rw-r--r--crates/hir-ty/src/lower/path.rs152
-rw-r--r--crates/hir-ty/src/method_resolution/confirm.rs7
-rw-r--r--crates/hir-ty/src/next_solver.rs3
-rw-r--r--crates/hir-ty/src/next_solver/infer/mod.rs11
-rw-r--r--crates/hir-ty/src/opaques.rs4
-rw-r--r--crates/hir-ty/src/tests/simple.rs3
-rw-r--r--crates/hir/src/source_analyzer.rs11
-rw-r--r--crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs12
17 files changed, 413 insertions, 263 deletions
diff --git a/crates/hir-ty/src/consteval.rs b/crates/hir-ty/src/consteval.rs
index 67e40fa811..21e368c88f 100644
--- a/crates/hir-ty/src/consteval.rs
+++ b/crates/hir-ty/src/consteval.rs
@@ -25,23 +25,15 @@ use crate::{
generics::Generics,
mir::{MirEvalError, MirLowerError, pad16},
next_solver::{
- Allocation, Const, ConstKind, Consts, DbInterner, DefaultAny, ErrorGuaranteed, GenericArg,
- GenericArgs, ParamConst, ScalarInt, StoredAllocation, StoredEarlyBinder, StoredGenericArgs,
- Ty, TyKind, UnevaluatedConst, ValTreeKind, default_types, infer::InferCtxt,
+ Allocation, Const, ConstKind, Consts, DbInterner, DefaultAny, GenericArgs, ParamConst,
+ ScalarInt, StoredAllocation, StoredEarlyBinder, StoredGenericArgs, Ty, TyKind,
+ UnevaluatedConst, ValTreeKind, default_types, infer::InferCtxt,
},
traits::StoredParamEnvAndCrate,
};
use super::mir::interpret_mir;
-pub fn unknown_const<'db>(_ty: Ty<'db>) -> Const<'db> {
- Const::new(DbInterner::conjure(), rustc_type_ir::ConstKind::Error(ErrorGuaranteed))
-}
-
-pub fn unknown_const_as_generic<'db>(ty: Ty<'db>) -> GenericArg<'db> {
- unknown_const(ty).into()
-}
-
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ConstEvalError {
MirLowerError(MirLowerError),
diff --git a/crates/hir-ty/src/generics.rs b/crates/hir-ty/src/generics.rs
index 25a31e2f58..c4321e8a61 100644
--- a/crates/hir-ty/src/generics.rs
+++ b/crates/hir-ty/src/generics.rs
@@ -39,7 +39,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics<'_>
}
#[derive(Debug)]
-pub(crate) struct Generics<'db> {
+pub struct Generics<'db> {
chain: ArrayVec<SingleGenerics<'db>, 2>,
}
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index b399a7e0ed..8aadab6cdb 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -50,7 +50,7 @@ use hir_def::{
layout::Integer,
resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
signatures::{ConstSignature, EnumSignature, FunctionSignature, StaticSignature},
- type_ref::{LifetimeRefId, TypeRef, TypeRefId},
+ type_ref::{LifetimeRefId, TypeRefId},
unstable_features::UnstableFeatures,
};
use hir_expand::{mod_path::ModPath, name::Name};
@@ -61,7 +61,7 @@ use rustc_ast_ir::Mutability;
use rustc_hash::{FxHashMap, FxHashSet};
use rustc_type_ir::{
AliasTyKind, TypeFoldable, TypeVisitableExt,
- inherent::{IntoKind, Ty as _},
+ inherent::{GenericArgs as _, IntoKind, Ty as _},
};
use smallvec::SmallVec;
use span::Edition;
@@ -72,7 +72,6 @@ use crate::{
ImplTraitId, IncorrectGenericsLenKind, InferBodyId, PathLoweringDiagnostic, Span,
TargetFeatures,
closure_analysis::PlaceBase,
- collect_type_inference_vars,
consteval::{create_anon_const, path_to_const},
db::{AnonConstId, GeneralConstId, HirDatabase, InternedOpaqueTyId},
generics::Generics,
@@ -89,7 +88,8 @@ use crate::{
unify::resolve_completely::WriteBackCtxt,
},
lower::{
- ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic,
+ ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind, TyLoweringInferVarsCtx,
+ diagnostics::TyLoweringDiagnostic,
},
method_resolution::CandidateId,
next_solver::{
@@ -1189,6 +1189,7 @@ pub(crate) struct InferenceContext<'body, 'db> {
pub(crate) edition: Edition,
allow_using_generic_params: bool,
generics: OnceCell<Generics<'db>>,
+ identity_args: OnceCell<GenericArgs<'db>>,
pub(crate) table: unify::InferenceTable<'db>,
pub(crate) lang_items: &'db LangItems,
pub(crate) features: &'db UnstableFeatures,
@@ -1302,6 +1303,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
generic_def,
allow_using_generic_params,
generics: OnceCell::new(),
+ identity_args: OnceCell::new(),
store,
traits_in_scope: resolver.traits_in_scope(db),
resolver,
@@ -1611,7 +1613,6 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
InferenceTyDiagnosticSource::Signature,
ExpressionStoreOwnerId::Signature(id.into()),
LifetimeElisionKind::for_const(self.interner(), id.loc(self.db).container),
- Span::Dummy,
);
self.return_ty = return_ty;
@@ -1624,7 +1625,6 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
InferenceTyDiagnosticSource::Signature,
ExpressionStoreOwnerId::Signature(id.into()),
LifetimeElisionKind::Elided(self.types.regions.statik),
- Span::Dummy,
);
self.return_ty = return_ty;
@@ -1662,12 +1662,12 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
if let Some(self_param) = self_param
&& let Some(ty) = param_tys.next()
{
- let ty = self.process_user_written_ty(Span::Dummy, ty);
+ let ty = self.process_user_written_ty(ty);
self.write_binding_ty(self_param, ty);
}
for pat in params {
let ty = param_tys.next().unwrap_or_else(|| self.table.next_ty_var(Span::Dummy));
- let ty = self.process_user_written_ty(Span::Dummy, ty);
+ let ty = self.process_user_written_ty(ty);
self.infer_top_pat(*pat, ty, PatOrigin::Param);
}
@@ -1683,7 +1683,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
ctx.lower_ty(return_ty)
},
);
- self.process_user_written_ty(Span::Dummy, return_ty)
+ self.process_user_written_ty(return_ty)
}
None => self.types.types.unit,
};
@@ -1797,10 +1797,6 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
self.result.type_of_pat.insert(pat, ty.store());
}
- fn write_type_placeholder_ty(&mut self, type_ref: TypeRefId, ty: Ty<'db>) {
- self.result.type_of_type_placeholder.insert(type_ref, ty.store());
- }
-
fn write_binding_ty(&mut self, id: BindingId, ty: Ty<'db>) {
self.result.type_of_binding.insert(id, ty.store());
}
@@ -1832,6 +1828,13 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
lifetime_elision: LifetimeElisionKind<'db>,
f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R,
) -> R {
+ let infer_vars = match types_source {
+ InferenceTyDiagnosticSource::Body => Some(TyLoweringInferVarsCtx {
+ table: &mut self.table,
+ type_of_placeholder: &mut self.result.type_of_type_placeholder,
+ }),
+ InferenceTyDiagnosticSource::Signature => None,
+ };
let mut ctx = TyLoweringContext::new(
self.db,
&self.resolver,
@@ -1840,8 +1843,10 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
types_source,
store_owner,
self.generic_def,
+ &self.generics,
lifetime_elision,
self.allow_using_generic_params,
+ infer_vars,
&self.defined_anon_consts,
);
f(&mut ctx)
@@ -1867,30 +1872,11 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
type_source: InferenceTyDiagnosticSource,
store_owner: ExpressionStoreOwnerId,
lifetime_elision: LifetimeElisionKind<'db>,
- span: Span,
) -> Ty<'db> {
let ty = self.with_ty_lowering(store, type_source, store_owner, lifetime_elision, |ctx| {
ctx.lower_ty(type_ref)
});
- let ty = self.process_user_written_ty(span, ty);
-
- // Record the association from placeholders' TypeRefId to type variables.
- // We only record them if their number matches. This assumes TypeRef::walk and TypeVisitable process the items in the same order.
- let type_variables = collect_type_inference_vars(&ty);
- let mut placeholder_ids = vec![];
- TypeRef::walk(type_ref, store, &mut |type_ref_id, type_ref| {
- if matches!(type_ref, TypeRef::Placeholder) {
- placeholder_ids.push(type_ref_id);
- }
- });
-
- if placeholder_ids.len() == type_variables.len() {
- for (placeholder_id, type_variable) in placeholder_ids.into_iter().zip(type_variables) {
- self.write_type_placeholder_ty(placeholder_id, type_variable);
- }
- }
-
- ty
+ self.process_user_written_ty(ty)
}
pub(crate) fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> {
@@ -1900,13 +1886,16 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
InferenceTyDiagnosticSource::Body,
self.store_owner,
LifetimeElisionKind::Infer,
- type_ref.into(),
)
}
fn generics(&self) -> &Generics<'db> {
- self.generics.get_or_init(|| {
- crate::generics::generics(self.db, self.store_owner.generic_def(self.db))
+ self.generics.get_or_init(|| crate::generics::generics(self.db, self.generic_def))
+ }
+
+ fn identity_args(&self) -> GenericArgs<'db> {
+ *self.identity_args.get_or_init(|| {
+ GenericArgs::identity_for_item(self.interner(), self.store_owner.into())
})
}
@@ -1960,14 +1949,14 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
LifetimeElisionKind::Infer,
|ctx| ctx.lower_lifetime(lifetime_ref),
);
- self.insert_type_vars(lt, Span::Dummy)
+ self.insert_type_vars(lt)
}
- fn insert_type_vars<T>(&mut self, ty: T, span: Span) -> T
+ fn insert_type_vars<T>(&mut self, ty: T) -> T
where
T: TypeFoldable<DbInterner<'db>>,
{
- self.table.insert_type_vars(ty, span)
+ self.table.insert_type_vars(ty)
}
/// Attempts to returns the deeply last field of nested structures, but
@@ -2032,8 +2021,8 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
/// Whenever you lower a user-written type, you should call this.
- fn process_user_written_ty(&mut self, span: Span, ty: Ty<'db>) -> Ty<'db> {
- self.table.process_user_written_ty(span, ty)
+ fn process_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
+ self.table.process_user_written_ty(ty)
}
/// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation,
@@ -2174,6 +2163,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
path: &Path,
value_ns: bool,
) -> (Ty<'db>, Option<VariantId>) {
+ let interner = self.interner();
let mut ctx = TyLoweringContext::new(
self.db,
&self.resolver,
@@ -2182,18 +2172,23 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
InferenceTyDiagnosticSource::Body,
self.store_owner,
self.generic_def,
+ &self.generics,
LifetimeElisionKind::Infer,
self.allow_using_generic_params,
+ Some(TyLoweringInferVarsCtx {
+ table: &mut self.table,
+ type_of_placeholder: &mut self.result.type_of_type_placeholder,
+ }),
&self.defined_anon_consts,
);
if let Some(type_anchor) = path.type_anchor() {
let mut segments = path.segments();
if segments.is_empty() {
- return (self.err_ty(), None);
+ return (self.types.types.error, None);
}
let (mut ty, type_ns) = ctx.lower_ty_ext(type_anchor);
- ty = self.table.process_user_written_ty(type_anchor.into(), ty);
+ ty = ctx.expect_table().process_user_written_ty(ty);
if let Some(TypeNs::SelfType(impl_)) = type_ns
&& let Some(trait_ref) = self.db.impl_trait(impl_)
@@ -2205,20 +2200,20 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
.associated_type_by_name(segments.first().unwrap().name)
{
// `<Self>::AssocType`
- let args = self.infcx().fill_rest_fresh_args(
+ let args = ctx.expect_table().infer_ctxt.fill_rest_fresh_args(
node.into(),
assoc_type.into(),
trait_ref.args,
);
let alias = Ty::new_alias(
- self.interner(),
+ interner,
AliasTy::new_from_args(
- self.interner(),
+ interner,
AliasTyKind::Projection { def_id: assoc_type.into() },
args,
),
);
- ty = self.table.try_structurally_resolve_type(node.into(), alias);
+ ty = ctx.expect_table().try_structurally_resolve_type(node.into(), alias);
segments = segments.skip(1);
}
@@ -2234,15 +2229,15 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
segments = segments.skip(1);
variant.into()
} else {
- return (self.err_ty(), None);
+ return (self.types.types.error, None);
}
}
- None => return (self.err_ty(), None),
+ None => return (self.types.types.error, None),
};
if !segments.is_empty() {
// FIXME: Report an error.
- return (self.err_ty(), None);
+ return (self.types.types.error, None);
} else {
return (ty, Some(variant));
}
@@ -2252,33 +2247,34 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
let interner = DbInterner::conjure();
let (resolution, unresolved) = if value_ns {
let Some(res) = path_ctx.resolve_path_in_value_ns(HygieneId::ROOT) else {
- return (self.err_ty(), None);
+ return (self.types.types.error, None);
};
match res {
ResolveValueResult::ValueNs(value) => match value {
ValueNs::EnumVariantId(var) => {
- let args = path_ctx.substs_from_path(var.into(), true, false);
+ let args = path_ctx.substs_from_path(var.into(), true, false, node.into());
drop(ctx);
let ty = self
.db
.ty(var.lookup(self.db).parent.into())
.instantiate(interner, args)
.skip_norm_wip();
- let ty = self.insert_type_vars(ty, Span::Dummy);
+ let ty = self.insert_type_vars(ty);
return (ty, Some(var.into()));
}
ValueNs::StructId(strukt) => {
- let args = path_ctx.substs_from_path(strukt.into(), true, false);
+ let args =
+ path_ctx.substs_from_path(strukt.into(), true, false, node.into());
drop(ctx);
let ty =
self.db.ty(strukt.into()).instantiate(interner, args).skip_norm_wip();
- let ty = self.insert_type_vars(ty, Span::Dummy);
+ let ty = self.insert_type_vars(ty);
return (ty, Some(strukt.into()));
}
ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None),
_ => {
drop(ctx);
- return (self.err_ty(), None);
+ return (self.types.types.error, None);
}
},
ResolveValueResult::Partial(typens, unresolved) => (typens, Some(unresolved)),
@@ -2286,33 +2282,33 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
} else {
match path_ctx.resolve_path_in_type_ns() {
Some((it, idx)) => (it, idx),
- None => return (self.err_ty(), None),
+ None => return (self.types.types.error, None),
}
};
return match resolution {
TypeNs::AdtId(AdtId::StructId(strukt)) => {
- let args = path_ctx.substs_from_path(strukt.into(), true, false);
+ let args = path_ctx.substs_from_path(strukt.into(), true, false, node.into());
drop(ctx);
let ty = self.db.ty(strukt.into()).instantiate(interner, args).skip_norm_wip();
- let ty = self.insert_type_vars(ty, Span::Dummy);
+ let ty = self.insert_type_vars(ty);
forbid_unresolved_segments(self, (ty, Some(strukt.into())), unresolved)
}
TypeNs::AdtId(AdtId::UnionId(u)) => {
- let args = path_ctx.substs_from_path(u.into(), true, false);
+ let args = path_ctx.substs_from_path(u.into(), true, false, node.into());
drop(ctx);
let ty = self.db.ty(u.into()).instantiate(interner, args).skip_norm_wip();
- let ty = self.insert_type_vars(ty, Span::Dummy);
+ let ty = self.insert_type_vars(ty);
forbid_unresolved_segments(self, (ty, Some(u.into())), unresolved)
}
TypeNs::EnumVariantId(var) => {
- let args = path_ctx.substs_from_path(var.into(), true, false);
+ let args = path_ctx.substs_from_path(var.into(), true, false, node.into());
drop(ctx);
let ty = self
.db
.ty(var.lookup(self.db).parent.into())
.instantiate(interner, args)
.skip_norm_wip();
- let ty = self.insert_type_vars(ty, Span::Dummy);
+ let ty = self.insert_type_vars(ty);
forbid_unresolved_segments(self, (ty, Some(var.into())), unresolved)
}
TypeNs::SelfType(impl_id) => {
@@ -2322,7 +2318,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
drop(ctx);
let Some(mod_path) = path.mod_path() else {
never!("resolver should always resolve lang item paths");
- return (self.err_ty(), None);
+ return (self.types.types.error, None);
};
return self.resolve_variant_on_alias(node, ty, None, mod_path);
};
@@ -2350,7 +2346,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
// We still have unresolved paths, but enum variants never have
// associated types!
// FIXME: Report an error.
- (self.err_ty(), None)
+ (self.types.types.error, None)
};
}
}
@@ -2364,12 +2360,12 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
// `lower_partly_resolved_path()` returns `None` as type namespace unless
// `remaining_segments` is empty, which is never the case here. We don't know
// which namespace the new `ty` is in until normalized anyway.
- (ty, _) = path_ctx.lower_partly_resolved_path(resolution, true);
+ (ty, _) = path_ctx.lower_partly_resolved_path(resolution, true, node.into());
tried_resolving_once = true;
- ty = self.table.process_user_written_ty(node.into(), ty);
+ ty = path_ctx.expect_table().process_user_written_ty(ty);
if ty.is_ty_error() {
- return (self.err_ty(), None);
+ return (self.types.types.error, None);
}
remaining_segments = remaining_segments.skip(1);
@@ -2388,7 +2384,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
TypeNs::TraitId(_) => {
let Some(remaining_idx) = unresolved else {
- return (self.err_ty(), None);
+ return (self.types.types.error, None);
};
let remaining_segments = path.segments().skip(remaining_idx);
@@ -2397,8 +2393,9 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
path_ctx.ignore_last_segment();
}
- let (mut ty, _) = path_ctx.lower_partly_resolved_path(resolution, true);
- ty = self.table.process_user_written_ty(node.into(), ty);
+ let (mut ty, _) =
+ path_ctx.lower_partly_resolved_path(resolution, true, node.into());
+ ty = ctx.expect_table().process_user_written_ty(ty);
if let Some(segment) = remaining_segments.get(1)
&& let Some((AdtId::EnumId(id), _)) = ty.as_adt()
@@ -2411,7 +2408,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
// We still have unresolved paths, but enum variants never have
// associated types!
// FIXME: Report an error.
- (self.err_ty(), None)
+ (self.types.types.error, None)
};
}
}
@@ -2429,27 +2426,28 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
TypeNs::TypeAliasId(it) => {
let Some(mod_path) = path.mod_path() else {
never!("resolver should always resolve lang item paths");
- return (self.err_ty(), None);
+ return (self.types.types.error, None);
};
- let args = path_ctx.substs_from_path_segment(it.into(), true, None, false);
+ let args =
+ path_ctx.substs_from_path_segment(it.into(), true, None, false, node.into());
drop(ctx);
let interner = DbInterner::conjure();
let ty = self.db.ty(it.into()).instantiate(interner, args).skip_norm_wip();
- let ty = self.insert_type_vars(ty, Span::Dummy);
+ let ty = self.insert_type_vars(ty);
self.resolve_variant_on_alias(node, ty, unresolved, mod_path)
}
TypeNs::AdtSelfType(_) => {
// FIXME this could happen in array size expressions, once we're checking them
- (self.err_ty(), None)
+ (self.types.types.error, None)
}
TypeNs::GenericParam(_) => {
// FIXME potentially resolve assoc type
- (self.err_ty(), None)
+ (self.types.types.error, None)
}
TypeNs::AdtId(AdtId::EnumId(_)) | TypeNs::BuiltinType(_) | TypeNs::ModuleId(_) => {
// FIXME diagnostic
- (self.err_ty(), None)
+ (self.types.types.error, None)
}
};
diff --git a/crates/hir-ty/src/infer/closure.rs b/crates/hir-ty/src/infer/closure.rs
index 90578e30c2..ab111736d5 100644
--- a/crates/hir-ty/src/infer/closure.rs
+++ b/crates/hir-ty/src/infer/closure.rs
@@ -23,9 +23,9 @@ use crate::{
db::{InternedClosure, InternedClosureId, InternedCoroutineClosureId, InternedCoroutineId},
infer::{BreakableKind, Diverges, coerce::CoerceMany, pat::PatOrigin},
next_solver::{
- AliasTy, Binder, ClauseKind, DbInterner, ErrorGuaranteed, FnSig, GenericArg, GenericArgs,
- PolyFnSig, PolyProjectionPredicate, Predicate, PredicateKind, SolverDefId, TermId, Ty,
- TyKind, Unnormalized,
+ AliasTy, Binder, ClauseKind, DbInterner, ErrorGuaranteed, FnSig, GenericArg, PolyFnSig,
+ PolyProjectionPredicate, Predicate, PredicateKind, SolverDefId, TermId, Ty, TyKind,
+ Unnormalized,
abi::Safety,
infer::{
BoundRegionConversionTime, InferOk, InferResult,
@@ -99,7 +99,7 @@ impl<'db> InferenceContext<'_, 'db> {
debug!(?bound_sig, ?liberated_sig);
- let parent_args = GenericArgs::identity_for_item(interner, self.store_owner.into());
+ let parent_args = self.identity_args();
let tupled_upvars_ty = self.table.next_ty_var(closure_expr.into());
diff --git a/crates/hir-ty/src/infer/diagnostics.rs b/crates/hir-ty/src/infer/diagnostics.rs
index 71aa35e634..50feab8dd4 100644
--- a/crates/hir-ty/src/infer/diagnostics.rs
+++ b/crates/hir-ty/src/infer/diagnostics.rs
@@ -2,7 +2,7 @@
//! and a wrapper around [`TyLoweringContext`] ([`InferenceTyLoweringContext`]) that replaces
//! it and takes care of diagnostics in inference.
-use std::cell::RefCell;
+use std::cell::{OnceCell, RefCell};
use std::ops::{Deref, DerefMut};
use either::Either;
@@ -16,8 +16,9 @@ use thin_vec::ThinVec;
use crate::{
InferenceDiagnostic, InferenceTyDiagnosticSource, TyLoweringDiagnostic,
db::{AnonConstId, HirDatabase},
+ generics::Generics,
lower::{
- ForbidParamsAfterReason, LifetimeElisionKind, TyLoweringContext,
+ ForbidParamsAfterReason, LifetimeElisionKind, TyLoweringContext, TyLoweringInferVarsCtx,
path::{PathDiagnosticCallback, PathLoweringContext},
},
};
@@ -71,12 +72,22 @@ impl<'db, 'a> InferenceTyLoweringContext<'db, 'a> {
source: InferenceTyDiagnosticSource,
def: ExpressionStoreOwnerId,
generic_def: GenericDefId,
+ generics: &'a OnceCell<Generics<'db>>,
lifetime_elision: LifetimeElisionKind<'db>,
allow_using_generic_params: bool,
+ infer_vars: Option<TyLoweringInferVarsCtx<'a, 'db>>,
defined_anon_consts: &'a RefCell<ThinVec<AnonConstId>>,
) -> Self {
- let mut ctx =
- TyLoweringContext::new(db, resolver, store, def, generic_def, lifetime_elision);
+ let mut ctx = TyLoweringContext::new(
+ db,
+ resolver,
+ store,
+ def,
+ generic_def,
+ generics,
+ lifetime_elision,
+ )
+ .with_infer_vars_behavior(infer_vars);
if !allow_using_generic_params {
ctx.forbid_params_after(0, ForbidParamsAfterReason::AnonConst);
}
diff --git a/crates/hir-ty/src/infer/path.rs b/crates/hir-ty/src/infer/path.rs
index a2bcf02589..c5b3d184b1 100644
--- a/crates/hir-ty/src/infer/path.rs
+++ b/crates/hir-ty/src/infer/path.rs
@@ -13,7 +13,7 @@ use stdx::never;
use crate::{
InferenceDiagnostic, Span, ValueTyDefId,
infer::diagnostics::InferenceTyLoweringContext as TyLoweringContext,
- lower::{GenericPredicates, LifetimeElisionKind},
+ lower::{GenericPredicates, LifetimeElisionKind, TyLoweringInferVarsCtx},
method_resolution::{self, CandidateId, MethodError},
next_solver::{
GenericArg, GenericArgs, TraitRef, Ty, Unnormalized, infer::traits::ObligationCause,
@@ -38,7 +38,7 @@ impl<'db> InferenceContext<'_, 'db> {
}
ValuePathResolution::NonGeneric(ty) => return Some((value, ty)),
};
- let args = self.insert_type_vars(substs, id.into());
+ let args = self.insert_type_vars(substs);
self.add_required_obligations_for_value_path(id, generic_def, args);
@@ -117,7 +117,7 @@ impl<'db> InferenceContext<'_, 'db> {
if let Some(last_segment) = last_segment {
path_ctx.set_current_segment(last_segment)
}
- path_ctx.substs_from_path(value_def, true, false)
+ path_ctx.substs_from_path(value_def, true, false, id.into())
})
};
@@ -147,8 +147,13 @@ impl<'db> InferenceContext<'_, 'db> {
InferenceTyDiagnosticSource::Body,
self.store_owner,
self.generic_def,
+ &self.generics,
LifetimeElisionKind::Infer,
self.allow_using_generic_params,
+ Some(TyLoweringInferVarsCtx {
+ table: &mut self.table,
+ type_of_placeholder: &mut self.result.type_of_type_placeholder,
+ }),
&self.defined_anon_consts,
);
let mut path_ctx = if no_diagnostics {
@@ -160,12 +165,12 @@ impl<'db> InferenceContext<'_, 'db> {
let last = path.segments().last()?;
let (ty, orig_ns) = path_ctx.ty_ctx().lower_ty_ext(type_ref);
- let ty = self.table.process_user_written_ty(type_ref.into(), ty);
+ let ty = path_ctx.expect_table().process_user_written_ty(ty);
path_ctx.ignore_last_segment();
- let (ty, _) = path_ctx.lower_ty_relative_path(ty, orig_ns, true);
+ let (ty, _) = path_ctx.lower_ty_relative_path(ty, orig_ns, true, id.into());
drop_ctx(ctx, no_diagnostics);
- let ty = self.table.process_user_written_ty(id.into(), ty);
+ let ty = self.table.process_user_written_ty(ty);
self.resolve_ty_assoc_item(ty, last.name, id).map(|(it, substs)| (it, Some(substs)))?
} else {
let hygiene = self.store.expr_or_pat_path_hygiene(id);
@@ -190,9 +195,13 @@ impl<'db> InferenceContext<'_, 'db> {
let (resolution, substs) = match (def, is_before_last) {
(TypeNs::TraitId(trait_), true) => {
- let self_ty = self.table.next_ty_var(id.into());
- let trait_ref =
- path_ctx.lower_trait_ref_from_resolved_path(trait_, self_ty, true);
+ let self_ty = path_ctx.expect_table().next_ty_var(id.into());
+ let trait_ref = path_ctx.lower_trait_ref_from_resolved_path(
+ trait_,
+ self_ty,
+ true,
+ id.into(),
+ );
drop_ctx(ctx, no_diagnostics);
self.resolve_trait_assoc_item(trait_ref, last_segment, id)
}
@@ -202,13 +211,13 @@ impl<'db> InferenceContext<'_, 'db> {
// should resolve to an associated type of that trait (e.g. `<T
// as Iterator>::Item::default`)
path_ctx.ignore_last_segment();
- let (ty, _) = path_ctx.lower_partly_resolved_path(def, true);
+ let (ty, _) = path_ctx.lower_partly_resolved_path(def, true, id.into());
drop_ctx(ctx, no_diagnostics);
if ty.is_ty_error() {
return None;
}
- let ty = self.process_user_written_ty(id.into(), ty);
+ let ty = self.process_user_written_ty(ty);
self.resolve_ty_assoc_item(ty, last_segment.name, id)
}
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index 8527b42d78..168da95600 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -442,23 +442,22 @@ impl<'db> InferenceTable<'db> {
}
}
- pub(super) fn insert_type_vars<T>(&mut self, ty: T, span: Span) -> T
+ pub(super) fn insert_type_vars<T>(&mut self, ty: T) -> T
where
T: TypeFoldable<DbInterner<'db>>,
{
- self.infer_ctxt.insert_type_vars(ty, span)
+ self.infer_ctxt.insert_type_vars(ty)
}
/// Whenever you lower a user-written type, you should call this.
- pub(crate) fn process_user_written_ty(&mut self, span: Span, ty: Ty<'db>) -> Ty<'db> {
- let ty = self.insert_type_vars(ty, span);
- self.try_structurally_resolve_type(span, ty)
+ pub(crate) fn process_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
+ self.process_remote_user_written_ty(ty)
}
/// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation,
/// while `process_user_written_ty()` should (but doesn't currently).
pub(crate) fn process_remote_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {
- let ty = self.insert_type_vars(ty, Span::Dummy);
+ let ty = self.insert_type_vars(ty);
// See https://github.com/rust-lang/rust/blob/cdb45c87e2cd43495379f7e867e3cc15dcee9f93/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs#L487-L495:
// Even though the new solver only lazily normalizes usually, here we eagerly normalize so that not everything needs
// to normalize before inspecting the `TyKind`.
diff --git a/crates/hir-ty/src/lib.rs b/crates/hir-ty/src/lib.rs
index dc8b8d6c99..4c80921423 100644
--- a/crates/hir-ty/src/lib.rs
+++ b/crates/hir-ty/src/lib.rs
@@ -502,35 +502,6 @@ where
Vec::from_iter(collector.params)
}
-struct TypeInferenceVarCollector<'db> {
- type_inference_vars: Vec<Ty<'db>>,
-}
-
-impl<'db> rustc_type_ir::TypeVisitor<DbInterner<'db>> for TypeInferenceVarCollector<'db> {
- type Result = ();
-
- fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
- use crate::rustc_type_ir::Flags;
- if ty.is_ty_var() {
- self.type_inference_vars.push(ty);
- } else if ty.flags().intersects(rustc_type_ir::TypeFlags::HAS_TY_INFER) {
- ty.super_visit_with(self);
- } else {
- // Fast path: don't visit inner types (e.g. generic arguments) when `flags` indicate
- // that there are no placeholders.
- }
- }
-}
-
-pub fn collect_type_inference_vars<'db, T>(value: &T) -> Vec<Ty<'db>>
-where
- T: ?Sized + rustc_type_ir::TypeVisitable<DbInterner<'db>>,
-{
- let mut collector = TypeInferenceVarCollector { type_inference_vars: vec![] };
- value.visit_with(&mut collector);
- collector.type_inference_vars
-}
-
pub fn known_const_to_ast<'db>(
konst: Const<'db>,
db: &'db dyn HirDatabase,
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index f79bcddef0..61329f6c88 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -39,7 +39,7 @@ use la_arena::{Arena, ArenaMap, Idx};
use path::{PathDiagnosticCallback, PathLoweringContext};
use rustc_abi::ExternAbi;
use rustc_ast_ir::Mutability;
-use rustc_hash::FxHashSet;
+use rustc_hash::{FxHashMap, FxHashSet};
use rustc_type_ir::{
AliasTyKind, BoundVarIndexKind, DebruijnIndex, ExistentialPredicate, ExistentialProjection,
ExistentialTraitRef, FnSig, Interner, OutlivesPredicate, TermKind, TyKind, TypeFoldable,
@@ -52,16 +52,17 @@ use thin_vec::ThinVec;
use tracing::debug;
use crate::{
- ImplTraitId, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
+ ImplTraitId, Span, TyLoweringDiagnostic, TyLoweringDiagnosticKind,
consteval::{create_anon_const, path_to_const},
db::{AnonConstId, GeneralConstId, HirDatabase, InternedOpaqueTyId},
generics::{Generics, SingleGenerics, generics},
+ infer::unify::InferenceTable,
next_solver::{
AliasTy, Binder, BoundExistentialPredicates, Clause, ClauseKind, Clauses, Const, ConstKind,
- DbInterner, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, FnSigKind, FxIndexMap,
- GenericArg, GenericArgs, ParamConst, ParamEnv, PolyFnSig, Predicate, Region, StoredClauses,
- StoredEarlyBinder, StoredGenericArg, StoredGenericArgs, StoredPolyFnSig, StoredTraitRef,
- StoredTy, TraitPredicate, TraitRef, Ty, Tys, Unnormalized, abi::Safety,
+ DbInterner, DefaultAny, EarlyBinder, EarlyParamRegion, ErrorGuaranteed, FnSigKind,
+ FxIndexMap, GenericArg, GenericArgs, ParamConst, ParamEnv, PolyFnSig, Predicate, Region,
+ StoredClauses, StoredEarlyBinder, StoredGenericArg, StoredGenericArgs, StoredPolyFnSig,
+ StoredTraitRef, StoredTy, TraitPredicate, TraitRef, Ty, Tys, Unnormalized, abi::Safety,
util::BottomUpFolder,
},
};
@@ -184,7 +185,12 @@ pub(crate) enum ForbidParamsAfterReason {
ConstParamTy,
}
-#[derive(Debug)]
+pub(crate) struct TyLoweringInferVarsCtx<'a, 'db> {
+ // Technically we can just put an `&InferCtxt` here, but borrowck constraints requires us to put this:
+ pub(crate) table: &'a mut InferenceTable<'db>,
+ pub(crate) type_of_placeholder: &'a mut FxHashMap<TypeRefId, StoredTy>,
+}
+
pub struct TyLoweringContext<'db, 'a> {
pub db: &'db dyn HirDatabase,
interner: DbInterner<'db>,
@@ -194,7 +200,7 @@ pub struct TyLoweringContext<'db, 'a> {
store: &'a ExpressionStore,
def: ExpressionStoreOwnerId,
generic_def: GenericDefId,
- generics: OnceCell<Generics<'db>>,
+ generics: &'a OnceCell<Generics<'db>>,
in_binders: DebruijnIndex,
impl_trait_mode: ImplTraitLoweringState,
/// Tracks types with explicit `?Sized` bounds.
@@ -204,6 +210,7 @@ pub struct TyLoweringContext<'db, 'a> {
forbid_params_after: Option<u32>,
forbid_params_after_reason: ForbidParamsAfterReason,
pub(crate) defined_anon_consts: ThinVec<AnonConstId>,
+ infer_vars: Option<TyLoweringInferVarsCtx<'a, 'db>>,
}
impl<'db, 'a> TyLoweringContext<'db, 'a> {
@@ -213,6 +220,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
store: &'a ExpressionStore,
def: ExpressionStoreOwnerId,
generic_def: GenericDefId,
+ generics: &'a OnceCell<Generics<'db>>,
lifetime_elision: LifetimeElisionKind<'db>,
) -> Self {
let impl_trait_mode = ImplTraitLoweringState::new(ImplTraitLoweringMode::Disallowed);
@@ -227,7 +235,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
resolver,
def,
generic_def,
- generics: Default::default(),
+ generics,
store,
in_binders,
impl_trait_mode,
@@ -237,6 +245,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
forbid_params_after: None,
forbid_params_after_reason: ForbidParamsAfterReason::AnonConst,
defined_anon_consts: ThinVec::new(),
+ infer_vars: None,
}
}
@@ -277,9 +286,66 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
self.forbid_params_after_reason = reason;
}
+ pub(crate) fn with_infer_vars_behavior(
+ mut self,
+ behavior: Option<TyLoweringInferVarsCtx<'a, 'db>>,
+ ) -> Self {
+ self.infer_vars = behavior;
+ self
+ }
+
pub(crate) fn push_diagnostic(&mut self, type_ref: TypeRefId, kind: TyLoweringDiagnosticKind) {
self.diagnostics.push(TyLoweringDiagnostic { source: type_ref, kind });
}
+
+ #[track_caller]
+ pub(crate) fn expect_table(&mut self) -> &mut InferenceTable<'db> {
+ self.infer_vars.as_mut().unwrap().table
+ }
+
+ fn next_ty_var(&mut self, type_ref: TypeRefId) -> Ty<'db> {
+ match &mut self.infer_vars {
+ Some(infer_vars) => {
+ let var = infer_vars.table.next_ty_var(type_ref.into());
+ infer_vars.type_of_placeholder.insert(type_ref, var.store());
+ var
+ }
+ None => {
+ // FIXME: Emit an error: no infer vars allowed here.
+ self.types.types.error
+ }
+ }
+ }
+
+ fn next_ty_var_no_placeholder(&mut self, span: Span) -> Ty<'db> {
+ match &mut self.infer_vars {
+ Some(infer_vars) => infer_vars.table.next_ty_var(span),
+ None => {
+ // FIXME: Emit an error: no infer vars allowed here.
+ self.types.types.error
+ }
+ }
+ }
+
+ fn next_const_var(&mut self, span: Span) -> Const<'db> {
+ match &mut self.infer_vars {
+ Some(infer_vars) => infer_vars.table.next_const_var(span),
+ None => {
+ // FIXME: Emit an error: no infer vars allowed here.
+ self.types.consts.error
+ }
+ }
+ }
+
+ fn next_region_var(&mut self, span: Span) -> Region<'db> {
+ match &mut self.infer_vars {
+ Some(infer_vars) => infer_vars.table.next_region_var(span),
+ None => {
+ // FIXME: Emit an error: no infer vars allowed here.
+ self.types.regions.error
+ }
+ }
+ }
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Default)]
@@ -308,7 +374,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
self.resolver,
const_type,
&|| self.generics(),
- None,
+ self.infer_vars.as_ref().map(|vars_ctx| &vars_ctx.table.infer_ctxt),
self.forbid_params_after,
);
@@ -344,7 +410,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
fn type_param(&mut self, id: TypeParamId, index: u32) -> Ty<'db> {
if self.param_index_is_disallowed(index) {
// FIXME: Report an error.
- Ty::new_error(self.interner, ErrorGuaranteed)
+ self.types.types.error
} else {
Ty::new_param(self.interner, id, index)
}
@@ -353,7 +419,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
fn region_param(&mut self, id: LifetimeParamId, index: u32) -> Region<'db> {
if self.param_index_is_disallowed(index) {
// FIXME: Report an error.
- Region::error(self.interner)
+ self.types.regions.error
} else {
Region::new_early_param(self.interner, EarlyParamRegion { id, index })
}
@@ -390,7 +456,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
TypeRef::Array(array) => {
let inner_ty = self.lower_ty(array.ty);
- let const_len = self.lower_const(array.len, Ty::new_usize(interner));
+ let const_len = self.lower_const(array.len, self.types.types.usize);
Ty::new_array_with_const_len(interner, inner_ty, const_len)
}
&TypeRef::Slice(inner) => {
@@ -400,12 +466,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
TypeRef::Reference(ref_) => {
let inner_ty = self.lower_ty(ref_.ty);
// FIXME: It should infer the eldided lifetimes instead of stubbing with error
- let lifetime = ref_
- .lifetime
- .map_or_else(|| Region::error(interner), |lr| self.lower_lifetime(lr));
+ let lifetime =
+ ref_.lifetime.map_or(self.types.regions.error, |lr| self.lower_lifetime(lr));
Ty::new_ref(interner, lifetime, inner_ty, lower_mutability(ref_.mutability))
}
- TypeRef::Placeholder => Ty::new_error(interner, ErrorGuaranteed),
+ TypeRef::Placeholder => self.next_ty_var(type_ref_id),
TypeRef::Fn(fn_) => self.lower_fn_ptr(fn_),
TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
TypeRef::ImplTrait(bounds) => {
@@ -461,11 +526,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
}
ImplTraitLoweringMode::Disallowed => {
// FIXME: report error
- Ty::new_error(self.interner, ErrorGuaranteed)
+ self.types.types.error
}
}
}
- TypeRef::Error => Ty::new_error(self.interner, ErrorGuaranteed),
+ TypeRef::Error => self.types.types.error,
};
(ty, res)
}
@@ -547,13 +612,13 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
if let Some(type_ref) = path.type_anchor() {
let (ty, res) = self.lower_ty_ext(type_ref);
let mut ctx = self.at_path(path_id);
- return ctx.lower_ty_relative_path(ty, res, false);
+ return ctx.lower_ty_relative_path(ty, res, false, path_id.type_ref().into());
}
let mut ctx = self.at_path(path_id);
let (resolution, remaining_index) = match ctx.resolve_path_in_type_ns() {
Some(it) => it,
- None => return (Ty::new_error(self.interner, ErrorGuaranteed), None),
+ None => return (self.types.types.error, None),
};
if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
@@ -563,7 +628,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
return (ty, None);
}
- ctx.lower_partly_resolved_path(resolution, false)
+ ctx.lower_partly_resolved_path(resolution, false, path_id.type_ref().into())
}
fn lower_trait_ref_from_path(
@@ -577,7 +642,15 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
TypeNs::TraitId(tr) => tr,
_ => return None,
};
- Some((ctx.lower_trait_ref_from_resolved_path(resolved, explicit_self_ty, false), ctx))
+ Some((
+ ctx.lower_trait_ref_from_resolved_path(
+ resolved,
+ explicit_self_ty,
+ false,
+ path_id.type_ref().into(),
+ ),
+ ctx,
+ ))
}
fn lower_trait_ref(
@@ -639,7 +712,10 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
ctx.ty_ctx().unsized_types.insert(self_ty);
} else {
if !ignore_bindings {
- assoc_bounds = ctx.assoc_type_bindings_from_type_bound(trait_ref);
+ assoc_bounds = ctx.assoc_type_bindings_from_type_bound(
+ trait_ref,
+ path.type_ref().into(),
+ );
}
clause = Some(Clause(Predicate::new(
interner,
@@ -686,7 +762,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
fn lower_dyn_trait(&mut self, bounds: &[TypeBound]) -> Ty<'db> {
let interner = self.interner;
- let dummy_self_ty = dyn_trait_dummy_self(interner);
+ let dummy_self_ty = self.types.types.dyn_trait_dummy_self;
let mut region = None;
// INVARIANT: The principal trait bound, if present, must come first. Others may be in any
// order but should be in the same order for the same set but possibly different order of
@@ -884,7 +960,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
.map(|arg| {
if arg.walk().any(|arg| arg == dummy_self_ty.into()) {
// FIXME: Report an error.
- Ty::new_error(interner, ErrorGuaranteed).into()
+ self.types.types.error.into()
} else {
arg
}
@@ -910,8 +986,11 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
false
});
if references_self {
- proj.projection_term =
- replace_dummy_self_with_error(interner, proj.projection_term);
+ proj.projection_term = replace_dummy_self_with_error(
+ interner,
+ self.types,
+ proj.projection_term,
+ );
}
ExistentialPredicate::Projection(ExistentialProjection::erase_self_ty(
@@ -949,7 +1028,7 @@ impl<'db, 'a> TyLoweringContext<'db, 'a> {
} else {
// FIXME: report error
// (additional non-auto traits, associated type rebound, or no resolved trait)
- Ty::new_error(self.interner, ErrorGuaranteed)
+ self.types.types.error
}
}
@@ -1083,20 +1162,15 @@ impl<T> TyLoweringResult<T> {
}
}
-fn dyn_trait_dummy_self(interner: DbInterner<'_>) -> Ty<'_> {
- // This type must not appear anywhere except here.
- Ty::new_fresh(interner, 0)
-}
-
fn replace_dummy_self_with_error<'db, T: TypeFoldable<DbInterner<'db>>>(
interner: DbInterner<'db>,
+ types: &DefaultAny<'db>,
t: T,
) -> T {
- let dyn_trait_dummy_self = dyn_trait_dummy_self(interner);
t.fold_with(&mut BottomUpFolder {
interner,
ty_op: |ty| {
- if ty == dyn_trait_dummy_self { Ty::new_error(interner, ErrorGuaranteed) } else { ty }
+ if ty == types.types.dyn_trait_dummy_self { types.types.error } else { ty }
},
lt_op: |lt| lt,
ct_op: |ct| ct,
@@ -1126,12 +1200,14 @@ pub(crate) fn impl_trait_with_diagnostics(
) -> Option<TyLoweringResult<StoredEarlyBinder<StoredTraitRef>>> {
let impl_data = ImplSignature::of(db, impl_id);
let resolver = impl_id.resolver(db);
+ let generics = OnceCell::new();
let mut ctx = TyLoweringContext::new(
db,
&resolver,
&impl_data.store,
ExpressionStoreOwnerId::Signature(impl_id.into()),
impl_id.into(),
+ &generics,
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
);
let self_ty = db.impl_self_ty(impl_id).skip_binder();
@@ -1208,12 +1284,14 @@ impl ImplTraits {
// FIXME unify with fn_sig_for_fn instead of doing lowering twice, maybe
let data = FunctionSignature::of(db, def);
let resolver = def.resolver(db);
+ let generics = OnceCell::new();
let mut ctx_ret = TyLoweringContext::new(
db,
&resolver,
&data.store,
ExpressionStoreOwnerId::Signature(def.into()),
def.into(),
+ &generics,
LifetimeElisionKind::Infer,
)
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
@@ -1237,12 +1315,14 @@ impl ImplTraits {
) -> Option<Box<StoredEarlyBinder<ImplTraits>>> {
let data = TypeAliasSignature::of(db, def);
let resolver = def.resolver(db);
+ let generics = OnceCell::new();
let mut ctx = TyLoweringContext::new(
db,
&resolver,
&data.store,
ExpressionStoreOwnerId::Signature(def.into()),
def.into(),
+ &generics,
LifetimeElisionKind::AnonymousReportError,
)
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
@@ -1336,12 +1416,14 @@ pub(crate) fn type_for_const_with_diagnostics(
let resolver = def.resolver(db);
let data = ConstSignature::of(db, def);
let parent = def.loc(db).container;
+ let generics = OnceCell::new();
let mut ctx = TyLoweringContext::new(
db,
&resolver,
&data.store,
ExpressionStoreOwnerId::Signature(def.into()),
def.into(),
+ &generics,
LifetimeElisionKind::AnonymousReportError,
);
ctx.set_lifetime_elision(LifetimeElisionKind::for_const(ctx.interner, parent));
@@ -1364,12 +1446,14 @@ pub(crate) fn type_for_static_with_diagnostics(
) -> TyLoweringResult<StoredEarlyBinder<StoredTy>> {
let resolver = def.resolver(db);
let data = StaticSignature::of(db, def);
+ let generics = OnceCell::new();
let mut ctx = TyLoweringContext::new(
db,
&resolver,
&data.store,
ExpressionStoreOwnerId::Signature(def.into()),
def.into(),
+ &generics,
LifetimeElisionKind::AnonymousReportError,
);
ctx.set_lifetime_elision(LifetimeElisionKind::Elided(Region::new_static(ctx.interner)));
@@ -1437,19 +1521,21 @@ pub(crate) fn type_for_type_alias_with_diagnostics(
t: TypeAliasId,
) -> TyLoweringResult<StoredEarlyBinder<StoredTy>> {
let type_alias_data = TypeAliasSignature::of(db, t);
- let resolver = t.resolver(db);
let interner = DbInterner::new_no_crate(db);
if type_alias_data.flags.contains(TypeAliasFlags::IS_EXTERN) {
TyLoweringResult::empty(StoredEarlyBinder::bind(
Ty::new_foreign(interner, t.into()).store(),
))
} else {
+ let resolver = t.resolver(db);
+ let generics = OnceCell::new();
let mut ctx = TyLoweringContext::new(
db,
&resolver,
&type_alias_data.store,
ExpressionStoreOwnerId::Signature(t.into()),
t.into(),
+ &generics,
LifetimeElisionKind::AnonymousReportError,
)
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
@@ -1487,7 +1573,7 @@ pub(crate) fn impl_self_ty_with_diagnostics(
impl_id: ImplId,
) -> TyLoweringResult<StoredEarlyBinder<StoredTy>> {
let resolver = impl_id.resolver(db);
-
+ let generics = OnceCell::new();
let impl_data = ImplSignature::of(db, impl_id);
let mut ctx = TyLoweringContext::new(
db,
@@ -1495,6 +1581,7 @@ pub(crate) fn impl_self_ty_with_diagnostics(
&impl_data.store,
ExpressionStoreOwnerId::Signature(impl_id.into()),
impl_id.into(),
+ &generics,
LifetimeElisionKind::AnonymousCreateParameter { report_in_path: true },
);
let ty = ctx.lower_ty(impl_data.self_ty);
@@ -1535,12 +1622,14 @@ pub(crate) fn const_param_types_with_diagnostics(
let mut result = ArenaMap::new();
let (data, store) = GenericParams::with_store(db, def);
let resolver = def.resolver(db);
+ let generics = OnceCell::new();
let mut ctx = TyLoweringContext::new(
db,
&resolver,
store,
ExpressionStoreOwnerId::Signature(def),
def,
+ &generics,
LifetimeElisionKind::AnonymousReportError,
);
ctx.forbid_params_after(0, ForbidParamsAfterReason::ConstParamTy);
@@ -1585,6 +1674,7 @@ pub(crate) fn field_types_with_diagnostics(
VariantId::UnionId(it) => (it.resolver(db), it.into()),
VariantId::EnumVariantId(it) => (it.resolver(db), it.lookup(db).parent.into()),
};
+ let generics = OnceCell::new();
let mut res = ArenaMap::default();
let mut ctx = TyLoweringContext::new(
db,
@@ -1592,6 +1682,7 @@ pub(crate) fn field_types_with_diagnostics(
&var_data.store,
ExpressionStoreOwnerId::VariantFields(variant_id),
generic_def,
+ &generics,
LifetimeElisionKind::AnonymousReportError,
);
for (field_id, field_data) in var_data.fields().iter() {
@@ -1714,16 +1805,20 @@ fn resolve_type_param_assoc_type_shorthand(
assoc_name: Name,
) -> AssocTypeShorthandResolution {
let generics = generics(db, def);
+ let store = generics.store();
+ let generics = &OnceCell::from(generics);
let resolver = def.resolver(db);
let mut ctx = TyLoweringContext::new(
db,
&resolver,
- generics.store(),
+ store,
ExpressionStoreOwnerId::Signature(def),
def,
+ generics,
LifetimeElisionKind::AnonymousReportError,
);
let interner = ctx.interner;
+ let generics = generics.get().unwrap();
let param_ty = Ty::new_param(interner, param, generics.type_or_const_param_idx(param.into()));
let mut this_trait_resolution = None;
@@ -1891,13 +1986,15 @@ pub(crate) fn type_alias_bounds_with_diagnostics(
type_alias: TypeAliasId,
) -> TyLoweringResult<TypeAliasBounds<StoredEarlyBinder<StoredClauses>>> {
let type_alias_data = TypeAliasSignature::of(db, type_alias);
- let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
+ let resolver = type_alias.resolver(db);
+ let generics = OnceCell::new();
let mut ctx = TyLoweringContext::new(
db,
&resolver,
&type_alias_data.store,
ExpressionStoreOwnerId::Signature(type_alias.into()),
type_alias.into(),
+ &generics,
LifetimeElisionKind::AnonymousReportError,
);
let interner = ctx.interner;
@@ -2130,16 +2227,20 @@ fn generic_predicates(
def: GenericDefId,
) -> TyLoweringResult<GenericPredicates> {
let generics = generics(db, def);
+ let store = generics.store();
+ let generics = &OnceCell::from(generics);
let resolver = def.resolver(db);
let interner = DbInterner::new_no_crate(db);
let mut ctx = TyLoweringContext::new(
db,
&resolver,
- generics.store(),
+ store,
ExpressionStoreOwnerId::Signature(def),
def,
+ generics,
LifetimeElisionKind::AnonymousReportError,
);
+ let generics = generics.get().unwrap();
let sized_trait = ctx.lang_items.Sized;
// We need to lower parents and self separately - see the comment below lowering of implicit
@@ -2339,24 +2440,27 @@ pub(crate) fn generic_defaults_with_diagnostics(
db: &dyn HirDatabase,
def: GenericDefId,
) -> TyLoweringResult<GenericDefaults> {
- let generic_params = generics(db, def);
- if generic_params.has_no_params() {
+ let generics = generics(db, def);
+ if generics.has_no_params() {
return TyLoweringResult::empty(GenericDefaults(ThinVec::new()));
}
let resolver = def.resolver(db);
- let store_for_self = generic_params.store();
+ let store_for_self = generics.store();
+ let generics = &OnceCell::from(generics);
let mut ctx = TyLoweringContext::new(
db,
&resolver,
store_for_self,
ExpressionStoreOwnerId::Signature(def),
def,
+ generics,
LifetimeElisionKind::AnonymousReportError,
)
.with_impl_trait_mode(ImplTraitLoweringMode::Disallowed);
+ let generics = generics.get().unwrap();
let mut defaults = ThinVec::new();
- if let Some(parent) = generic_params.parent() {
+ if let Some(parent) = generics.parent() {
ctx.store = parent.store();
defaults.extend(
parent.iter_with_idx().map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)),
@@ -2366,9 +2470,7 @@ pub(crate) fn generic_defaults_with_diagnostics(
ctx.defined_anon_consts.clear();
ctx.store = store_for_self;
defaults.extend(
- generic_params
- .iter_self_with_idx()
- .map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)),
+ generics.iter_self_with_idx().map(|(idx, _id, p)| handle_generic_param(&mut ctx, idx, p)),
);
defaults.shrink_to_fit();
return TyLoweringResult::from_ctx(GenericDefaults(defaults), ctx);
@@ -2434,12 +2536,14 @@ fn fn_sig_for_fn(
let data = FunctionSignature::of(db, def);
let resolver = def.resolver(db);
let interner = DbInterner::new_no_crate(db);
+ let generics = OnceCell::new();
let mut ctx_params = TyLoweringContext::new(
db,
&resolver,
&data.store,
ExpressionStoreOwnerId::Signature(def.into()),
def.into(),
+ &generics,
LifetimeElisionKind::for_fn_params(data),
);
let params = data.params.iter().map(|&tr| ctx_params.lower_ty(tr));
@@ -2450,6 +2554,7 @@ fn fn_sig_for_fn(
&data.store,
ExpressionStoreOwnerId::Signature(def.into()),
def.into(),
+ &generics,
LifetimeElisionKind::for_fn_ret(interner),
)
.with_impl_trait_mode(ImplTraitLoweringMode::Opaque);
@@ -2521,14 +2626,16 @@ pub(crate) fn associated_ty_item_bounds<'db>(
type_alias: TypeAliasId,
) -> EarlyBinder<'db, BoundExistentialPredicates<'db>> {
let type_alias_data = TypeAliasSignature::of(db, type_alias);
- let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db);
+ let resolver = type_alias.resolver(db);
let interner = DbInterner::new_no_crate(db);
+ let generics = OnceCell::new();
let mut ctx = TyLoweringContext::new(
db,
&resolver,
&type_alias_data.store,
ExpressionStoreOwnerId::Signature(type_alias.into()),
type_alias.into(),
+ &generics,
LifetimeElisionKind::AnonymousReportError,
);
// FIXME: we should never create non-existential predicates in the first place
diff --git a/crates/hir-ty/src/lower/path.rs b/crates/hir-ty/src/lower/path.rs
index dfa8873b86..0757d57500 100644
--- a/crates/hir-ty/src/lower/path.rs
+++ b/crates/hir-ty/src/lower/path.rs
@@ -25,10 +25,10 @@ use smallvec::SmallVec;
use crate::{
GenericArgsProhibitedReason, IncorrectGenericsLenKind, PathGenericsSource,
- PathLoweringDiagnostic, TyDefId, ValueTyDefId,
- consteval::{unknown_const, unknown_const_as_generic},
+ PathLoweringDiagnostic, Span, TyDefId, ValueTyDefId,
db::HirDatabase,
generics::{Generics, generics},
+ infer::unify::InferenceTable,
lower::{
AssocTypeShorthandResolution, ForbidParamsAfterReason, GenericPredicateSource,
LifetimeElisionKind, PathDiagnosticCallbackData, const_param_ty,
@@ -84,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) {
@@ -149,17 +154,18 @@ 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)
- (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None)
+ (self.ctx.types.types.error, None)
}
}
}
@@ -169,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);
@@ -181,8 +188,9 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
1 => {
let trait_ref = self.lower_trait_ref_from_resolved_path(
trait_,
- Ty::new_error(self.ctx.interner, ErrorGuaranteed),
+ self.ctx.types.types.error,
infer_args,
+ span,
);
tracing::debug!(?trait_ref);
self.skip_resolved_segment();
@@ -203,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,
@@ -222,7 +231,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
}
None => {
// FIXME: report error (associated type not found)
- Ty::new_error(self.ctx.interner, ErrorGuaranteed)
+ self.ctx.types.types.error
}
}
}
@@ -230,11 +239,11 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
// Trait object type without dyn; this should be handled in upstream. See
// `lower_path()`.
stdx::never!("unexpected fully resolved trait path");
- Ty::new_error(self.ctx.interner, ErrorGuaranteed)
+ self.ctx.types.types.error
}
_ => {
// FIXME report error (ambiguous associated type)
- Ty::new_error(self.ctx.interner, ErrorGuaranteed)
+ self.ctx.types.types.error
}
};
return (ty, None);
@@ -250,19 +259,19 @@ 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 (Ty::new_error(self.ctx.interner, ErrorGuaranteed), None);
+ return (self.ctx.types.types.error, None);
}
};
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`).
@@ -470,13 +479,17 @@ 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;
let segment = self.current_or_prev_segment;
let assoc_name = segment.name;
- let error_ty = || Ty::new_error(self.ctx.interner, ErrorGuaranteed);
let (assoc_type, trait_args) = match res {
Some(TypeNs::GenericParam(param)) => {
let AssocTypeShorthandResolution::Resolved(assoc_type) =
@@ -488,7 +501,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
)
else {
// FIXME: Emit an error.
- return error_ty();
+ return self.ctx.types.types.error;
};
assoc_type
.get_with(|(assoc_type, trait_args)| (*assoc_type, trait_args.as_ref()))
@@ -496,7 +509,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
}
Some(TypeNs::SelfType(impl_)) => {
let Some(impl_trait) = db.impl_trait(impl_) else {
- return error_ty();
+ return self.ctx.types.types.error;
};
let impl_trait = impl_trait.instantiate_identity().skip_norm_wip();
// Searching for `Self::Assoc` in `impl Trait for Type` is like searching for `Self::Assoc` in `Trait`.
@@ -509,7 +522,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
)
else {
// FIXME: Emit an error.
- return error_ty();
+ return self.ctx.types.types.error;
};
let (assoc_type, trait_args) = assoc_type
.get_with(|(assoc_type, trait_args)| (*assoc_type, trait_args.as_ref()))
@@ -521,14 +534,14 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
.skip_norm_wip(),
)
}
- _ => return error_ty(),
+ _ => return self.ctx.types.types.error,
};
// 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(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,
@@ -538,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);
@@ -546,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()
}
@@ -561,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;
@@ -604,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;
@@ -616,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;
@@ -656,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
@@ -670,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> {
@@ -736,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 => unknown_const(const_ty),
+ TypeLikeConst::Infer => self.ctx.ctx.next_const_var(type_ref.into()),
}
}
@@ -753,16 +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(_) => {
- Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed))
- .into()
+ self.ctx.ctx.next_region_var(span).into()
}
GenericParamDataRef::TypeParamData(param) => {
if !infer_args
@@ -771,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,10 +801,10 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
{
return default;
}
- let GenericParamId::ConstParamId(const_id) = param_id else {
+ let GenericParamId::ConstParamId(_) = param_id else {
unreachable!("non-const param ID for const param");
};
- unknown_const_as_generic(const_param_ty(self.ctx.ctx.db, const_id))
+ self.ctx.ctx.next_const_var(span).into()
}
}
}
@@ -793,13 +814,8 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
GenericParamId::TypeParamId(_) => {
Ty::new_error(self.ctx.ctx.interner, ErrorGuaranteed).into()
}
- GenericParamId::ConstParamId(const_id) => {
- unknown_const_as_generic(const_param_ty(self.ctx.ctx.db, const_id))
- }
- GenericParamId::LifetimeParamId(_) => {
- Region::new(self.ctx.ctx.interner, rustc_type_ir::ReError(ErrorGuaranteed))
- .into()
- }
+ GenericParamId::ConstParamId(_) => self.ctx.ctx.types.consts.error.into(),
+ GenericParamId::LifetimeParamId(_) => self.ctx.ctx.types.regions.error.into(),
}
}
@@ -843,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 },
)
}
@@ -852,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)
}
@@ -862,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;
@@ -900,6 +925,7 @@ impl<'a, 'b, 'db> PathLoweringContext<'a, 'b, 'db> {
},
false,
this.ctx.lifetime_elision,
+ span,
)
});
let args = GenericArgs::new_from_iter(
@@ -1019,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>;
@@ -1187,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();
@@ -1206,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(_))
@@ -1222,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));
}
@@ -1291,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()
@@ -1301,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();
diff --git a/crates/hir-ty/src/method_resolution/confirm.rs b/crates/hir-ty/src/method_resolution/confirm.rs
index a3a5a9ca54..c425e69dc5 100644
--- a/crates/hir-ty/src/method_resolution/confirm.rs
+++ b/crates/hir-ty/src/method_resolution/confirm.rs
@@ -427,12 +427,15 @@ impl<'a, 'b, 'db> ConfirmContext<'a, 'b, 'db> {
_def: GenericDefId,
param_id: GenericParamId,
_param: GenericParamDataRef<'_>,
- _infer_args: bool,
+ infer_args: bool,
_preceding_args: &[GenericArg<'db>],
+ had_count_error: bool,
) -> GenericArg<'db> {
// Always create an inference var, even when `infer_args == false`. This helps with diagnostics,
// and I think it's also required in the presence of `impl Trait` (that must be inferred).
- self.ctx.table.var_for_def(param_id, Span::Dummy)
+ let span =
+ if !infer_args || had_count_error { Span::Dummy } else { self.expr.into() };
+ self.ctx.table.var_for_def(param_id, span)
}
fn parent_arg(&mut self, param_idx: u32, _param_id: GenericParamId) -> GenericArg<'db> {
diff --git a/crates/hir-ty/src/next_solver.rs b/crates/hir-ty/src/next_solver.rs
index 78fdb1548c..47b4b1dc4a 100644
--- a/crates/hir-ty/src/next_solver.rs
+++ b/crates/hir-ty/src/next_solver.rs
@@ -93,6 +93,7 @@ pub struct DefaultTypes<'db> {
pub static_u8_slice: Ty<'db>,
/// `*mut ()`
pub mut_unit_ptr: Ty<'db>,
+ pub dyn_trait_dummy_self: Ty<'db>,
}
pub struct DefaultConsts<'db> {
@@ -272,6 +273,8 @@ pub fn default_types<'a, 'db>(db: &'db dyn HirDatabase) -> &'a DefaultAny<'db> {
u8_slice,
static_u8_slice,
mut_unit_ptr: create_ty(TyKind::RawPtr(unit, rustc_ast_ir::Mutability::Mut)),
+ // This type must not appear anywhere except here.
+ dyn_trait_dummy_self: create_ty(TyKind::Infer(rustc_type_ir::InferTy::FreshTy(0))),
},
consts: DefaultConsts {
error: create_const(ConstKind::Error(ErrorGuaranteed)),
diff --git a/crates/hir-ty/src/next_solver/infer/mod.rs b/crates/hir-ty/src/next_solver/infer/mod.rs
index d51a4c1312..839bdf17e7 100644
--- a/crates/hir-ty/src/next_solver/infer/mod.rs
+++ b/crates/hir-ty/src/next_solver/infer/mod.rs
@@ -430,13 +430,12 @@ impl<'db> InferCtxt<'db> {
))
}
- pub(crate) fn insert_type_vars<T>(&self, ty: T, span: Span) -> T
+ pub(crate) fn insert_type_vars<T>(&self, ty: T) -> T
where
T: TypeFoldable<DbInterner<'db>>,
{
struct Folder<'a, 'db> {
infcx: &'a InferCtxt<'db>,
- span: Span,
}
impl<'db> TypeFolder<DbInterner<'db>> for Folder<'_, 'db> {
fn cx(&self) -> DbInterner<'db> {
@@ -449,7 +448,7 @@ impl<'db> InferCtxt<'db> {
}
if ty.is_ty_error() {
- self.infcx.next_ty_var(self.span)
+ self.infcx.next_ty_var(Span::Dummy)
} else {
ty.super_fold_with(self)
}
@@ -461,18 +460,18 @@ impl<'db> InferCtxt<'db> {
}
if ct.is_ct_error() {
- self.infcx.next_const_var(self.span)
+ self.infcx.next_const_var(Span::Dummy)
} else {
ct.super_fold_with(self)
}
}
fn fold_region(&mut self, r: Region<'db>) -> Region<'db> {
- if r.is_error() { self.infcx.next_region_var(self.span) } else { r }
+ if r.is_error() { self.infcx.next_region_var(Span::Dummy) } else { r }
}
}
- ty.fold_with(&mut Folder { infcx: self, span })
+ ty.fold_with(&mut Folder { infcx: self })
}
/// Evaluates whether the predicate can be satisfied in the given
diff --git a/crates/hir-ty/src/opaques.rs b/crates/hir-ty/src/opaques.rs
index d39e74b9af..4244b1bac4 100644
--- a/crates/hir-ty/src/opaques.rs
+++ b/crates/hir-ty/src/opaques.rs
@@ -10,7 +10,7 @@ use rustc_type_ir::inherent::Ty as _;
use syntax::ast;
use crate::{
- ImplTraitId, InferBodyId, InferenceResult, Span,
+ ImplTraitId, InferBodyId, InferenceResult,
db::{HirDatabase, InternedOpaqueTyId},
lower::{ImplTraitIdx, ImplTraits},
next_solver::{
@@ -146,7 +146,7 @@ pub(crate) fn tait_hidden_types(
}
// In the presence of errors, we attempt to create a unified type from all
// types. rustc doesn't do that, but this should improve the experience.
- let hidden_type = infcx.insert_type_vars(hidden_type.as_ref(), Span::Dummy);
+ let hidden_type = infcx.insert_type_vars(hidden_type.as_ref());
match result.entry(opaque_idx) {
la_arena::Entry::Vacant(entry) => {
entry.insert(StoredEarlyBinder::bind(hidden_type.store()));
diff --git a/crates/hir-ty/src/tests/simple.rs b/crates/hir-ty/src/tests/simple.rs
index 76da816055..c0b8d93b47 100644
--- a/crates/hir-ty/src/tests/simple.rs
+++ b/crates/hir-ty/src/tests/simple.rs
@@ -2697,7 +2697,6 @@ fn generic_default_in_struct_literal() {
#[test]
fn generic_default_depending_on_other_type_arg() {
- // FIXME: the {unknown} is a bug
check_infer(
r#"
struct Thing<T = u128, F = fn() -> T> { t: T }
@@ -2714,7 +2713,7 @@ fn generic_default_depending_on_other_type_arg() {
83..130 '{ ...2 }; }': ()
89..91 't1': Thing<u32, fn() -> u32>
97..99 't2': Thing<u128, fn() -> u128>
- 105..127 'Thing:...1u32 }': Thing<u32, fn() -> {unknown}>
+ 105..127 'Thing:...1u32 }': Thing<u32, fn() -> u32>
121..125 '1u32': u32
"#]],
);
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 4029b004a7..0fc439b3cc 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -5,7 +5,10 @@
//!
//! So, this modules should not be used during hir construction, it exists
//! purely for "IDE needs".
-use std::iter::{self, once};
+use std::{
+ cell::OnceCell,
+ iter::{self, once},
+};
use either::Either;
use hir_def::{
@@ -374,12 +377,14 @@ impl<'db> SourceAnalyzer<'db> {
let type_ref = self.type_id(ty)?;
let generic_def = self.resolver.generic_def()?;
+ let generics = OnceCell::new();
let mut ty = TyLoweringContext::new(
db,
&self.resolver,
self.store()?,
generic_def.into(),
generic_def,
+ &generics,
// FIXME: Is this correct here? Anyway that should impact mostly diagnostics, which we don't emit here
// (this can impact the lifetimes generated, e.g. in `const` they won't be `'static`, but this seems like a
// small problem).
@@ -1753,12 +1758,14 @@ fn resolve_hir_path_(
let types = || {
let (ty, unresolved) = match path.type_anchor() {
Some(type_ref) => resolver.generic_def().and_then(|def| {
+ let generics = OnceCell::new();
let (_, res) = TyLoweringContext::new(
db,
resolver,
store?,
def.into(),
def,
+ &generics,
LifetimeElisionKind::Infer,
)
.lower_ty_ext(type_ref);
@@ -1909,12 +1916,14 @@ fn resolve_hir_path_qualifier(
(|| {
let (ty, unresolved) = match path.type_anchor() {
Some(type_ref) => resolver.generic_def().and_then(|def| {
+ let generics = OnceCell::new();
let (_, res) = TyLoweringContext::new(
db,
resolver,
store,
def.into(),
def,
+ &generics,
LifetimeElisionKind::Infer,
)
.lower_ty_ext(type_ref);
diff --git a/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs b/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs
index 9c04d2be8a..5ee02279a2 100644
--- a/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs
+++ b/crates/ide-diagnostics/src/handlers/incorrect_generics_len.rs
@@ -43,8 +43,6 @@ struct Bar<T, U>(T, U);
fn foo() {
let _ = Bar::<()>;
// ^^^^^^ error: this struct takes 2 generic arguments but 1 generic argument was supplied
- // ^^^^^^^^^ error: type annotations needed
- // | full type: `fn Bar<(), {unknown}>((), {unknown}) -> Bar<(), {unknown}>`
}
"#,
@@ -53,10 +51,6 @@ fn foo() {
#[test]
fn enum_variant() {
- // FIXME: We should not have a "type annotations needed" error here, but to do that
- // we'll need to have access to the `InferenceContext` in `TyLoweringContext`, to
- // generate the infer var with a dummy span (instead of inserting it after the fact
- // with a non-dummy span).
check_diagnostics(
r#"
enum Enum<T, U> {
@@ -66,12 +60,8 @@ enum Enum<T, U> {
fn foo() {
let _ = Enum::<()>::Variant;
// ^^^^^^ error: this enum takes 2 generic arguments but 1 generic argument was supplied
- // ^^^^^^^^^^^^^^^^^^^ error: type annotations needed
- // | full type: `fn Variant<(), {unknown}>((), {unknown}) -> Enum<(), {unknown}>`
let _ = Enum::Variant::<()>;
// ^^^^^^ error: this enum takes 2 generic arguments but 1 generic argument was supplied
- // ^^^^^^^^^^^^^^^^^^^ error: type annotations needed
- // | full type: `fn Variant<(), {unknown}>((), {unknown}) -> Enum<(), {unknown}>`
}
"#,
@@ -137,8 +127,6 @@ struct Bar<T, const N: usize>(T);
fn bar() {
let _ = Bar::<()>;
// ^^^^^^ error: this struct takes 2 generic arguments but 1 generic argument was supplied
- // ^^^^^^^^^ error: type annotations needed
- // | full type: `fn Bar<(), _>(()) -> Bar<(), _>`
}
"#,
);