Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/infer.rs')
-rw-r--r--crates/hir-ty/src/infer.rs138
1 files changed, 77 insertions, 61 deletions
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 3b9e168d54..462f81a304 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -65,6 +65,7 @@ use rustc_type_ir::{
AliasTyKind, TypeFoldable, TypeVisitableExt,
inherent::{GenericArgs as _, IntoKind, Ty as _},
};
+use salsa::Update;
use smallvec::SmallVec;
use span::Edition;
use stdx::never;
@@ -118,7 +119,7 @@ pub use unify::{could_unify, could_unify_deeply};
use cast::{CastCheck, CastError};
/// The entry point of type inference.
-fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult {
+fn infer_query<'db>(db: &'db dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'db> {
infer_query_with_inspect(db, def, None, LoweringMode::Analysis)
}
@@ -127,7 +128,7 @@ pub fn infer_query_with_inspect<'db>(
def: DefWithBodyId,
inspect: Option<ObligationInspector<'db>>,
lowering_mode: LoweringMode,
-) -> InferenceResult {
+) -> InferenceResult<'db> {
let _p = tracing::info_span!("infer_query").entered();
let resolver = def.resolver(db);
let body = Body::of(db, def);
@@ -185,7 +186,11 @@ pub fn infer_query_with_inspect<'db>(
infer_finalize(ctx)
}
-fn infer_cycle_result(db: &dyn HirDatabase, _: salsa::Id, _: DefWithBodyId) -> InferenceResult {
+fn infer_cycle_result<'db>(
+ db: &'db dyn HirDatabase,
+ _: salsa::Id,
+ _: DefWithBodyId,
+) -> InferenceResult<'db> {
InferenceResult {
has_errors: true,
..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))
@@ -193,7 +198,10 @@ fn infer_cycle_result(db: &dyn HirDatabase, _: salsa::Id, _: DefWithBodyId) -> I
}
/// Infer types for an anonymous const expression.
-fn infer_anon_const_query(db: &dyn HirDatabase, def: AnonConstId) -> InferenceResult {
+fn infer_anon_const_query<'db>(
+ db: &'db dyn HirDatabase,
+ def: AnonConstId<'db>,
+) -> InferenceResult<'db> {
let _p = tracing::info_span!("infer_anon_const_query").entered();
let loc = def.loc(db);
let store_owner = loc.owner;
@@ -221,18 +229,18 @@ fn infer_anon_const_query(db: &dyn HirDatabase, def: AnonConstId) -> InferenceRe
infer_finalize(ctx)
}
-fn infer_anon_const_cycle_result(
- db: &dyn HirDatabase,
+fn infer_anon_const_cycle_result<'db>(
+ db: &'db dyn HirDatabase,
_: salsa::Id,
- _: AnonConstId,
-) -> InferenceResult {
+ _: AnonConstId<'db>,
+) -> InferenceResult<'db> {
InferenceResult {
has_errors: true,
..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))
}
}
-fn infer_finalize(mut ctx: InferenceContext<'_, '_>) -> InferenceResult {
+fn infer_finalize<'db>(mut ctx: InferenceContext<'db>) -> InferenceResult<'db> {
ctx.handle_opaque_type_uses();
ctx.type_inference_fallback();
@@ -736,8 +744,8 @@ pub enum PatAdjust {
/// When you add a field that stores types (including `Substitution` and the like), don't forget
/// `resolve_completely()`'ing them in `InferenceContext::resolve_all()`. Inference variables must
/// not appear in the final inference result.
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct InferenceResult {
+#[derive(Clone, PartialEq, Eq, Debug, Update)]
+pub struct InferenceResult<'db> {
/// For each method call expr, records the function it resolves to.
method_resolutions: FxHashMap<ExprId, (FunctionId, StoredGenericArgs)>,
/// For each field access expr, records the field it resolves to.
@@ -801,7 +809,7 @@ pub struct InferenceResult {
pub closures_data: FxHashMap<ExprId, ClosureData>,
- defined_anon_consts: ThinVec<AnonConstId>,
+ defined_anon_consts: ThinVec<AnonConstId<'db>>,
}
#[derive(Clone, PartialEq, Eq, Debug, Default)]
@@ -1023,24 +1031,32 @@ pub enum UpvarCapture {
}
#[salsa::tracked]
-impl InferenceResult {
+impl<'db> InferenceResult<'db> {
#[salsa::tracked(returns(ref), cycle_result = infer_cycle_result)]
- fn for_body(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult {
+ fn for_body(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'_> {
infer_query(db, def)
}
+}
+#[salsa::tracked]
+impl<'db> InferenceResult<'db> {
/// Infer types for all const expressions in an item's signature.
///
/// Returns an `InferenceResult` containing type information for array lengths,
/// const generic arguments, and other const expressions appearing in type
/// positions within the item's signature.
#[salsa::tracked(returns(ref), cycle_result = infer_anon_const_cycle_result)]
- fn for_anon_const(db: &dyn HirDatabase, def: AnonConstId) -> InferenceResult {
+ fn for_anon_const(db: &'db dyn HirDatabase, def: AnonConstId<'db>) -> InferenceResult<'db> {
infer_anon_const_query(db, def)
}
+}
+impl<'db> InferenceResult<'db> {
#[inline]
- pub fn of(db: &dyn HirDatabase, def: impl Into<InferBodyId>) -> &InferenceResult {
+ pub fn of(
+ db: &'db dyn HirDatabase,
+ def: impl Into<InferBodyId<'db>>,
+ ) -> &'db InferenceResult<'db> {
match def.into() {
InferBodyId::DefWithBodyId(it) => InferenceResult::for_body(db, it),
InferBodyId::AnonConstId(it) => InferenceResult::for_anon_const(db, it),
@@ -1048,7 +1064,7 @@ impl InferenceResult {
}
}
-impl InferenceResult {
+impl<'db> InferenceResult<'db> {
fn new(error_ty: Ty<'_>) -> Self {
Self {
method_resolutions: Default::default(),
@@ -1075,7 +1091,7 @@ impl InferenceResult {
}
}
- pub fn method_resolution<'db>(&self, expr: ExprId) -> Option<(FunctionId, GenericArgs<'db>)> {
+ pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, GenericArgs<'db>)> {
self.method_resolutions.get(&expr).map(|(func, args)| (*func, args.as_ref()))
}
pub fn field_resolution(&self, expr: ExprId) -> Option<Either<FieldId, TupleFieldId>> {
@@ -1093,22 +1109,22 @@ impl InferenceResult {
ExprOrPatId::PatId(id) => self.variant_resolution_for_pat(id),
}
}
- pub fn assoc_resolutions_for_expr<'db>(
+ pub fn assoc_resolutions_for_expr<'a>(
&self,
id: ExprId,
- ) -> Option<(CandidateId, GenericArgs<'db>)> {
+ ) -> Option<(CandidateId, GenericArgs<'a>)> {
self.assoc_resolutions.get(&id.into()).map(|(assoc, args)| (*assoc, args.as_ref()))
}
- pub fn assoc_resolutions_for_pat<'db>(
+ pub fn assoc_resolutions_for_pat<'a>(
&self,
id: PatId,
- ) -> Option<(CandidateId, GenericArgs<'db>)> {
+ ) -> Option<(CandidateId, GenericArgs<'a>)> {
self.assoc_resolutions.get(&id.into()).map(|(assoc, args)| (*assoc, args.as_ref()))
}
- pub fn assoc_resolutions_for_expr_or_pat<'db>(
+ pub fn assoc_resolutions_for_expr_or_pat<'a>(
&self,
id: ExprOrPatId,
- ) -> Option<(CandidateId, GenericArgs<'db>)> {
+ ) -> Option<(CandidateId, GenericArgs<'a>)> {
match id {
ExprOrPatId::ExprId(id) => self.assoc_resolutions_for_expr(id),
ExprOrPatId::PatId(id) => self.assoc_resolutions_for_pat(id),
@@ -1131,19 +1147,19 @@ impl InferenceResult {
pub fn has_type_mismatches(&self) -> bool {
self.nodes_with_type_mismatches.is_some()
}
- pub fn placeholder_types<'db>(&self) -> impl Iterator<Item = (TypeRefId, Ty<'db>)> {
+ pub fn placeholder_types<'a>(&self) -> impl Iterator<Item = (TypeRefId, Ty<'a>)> {
self.type_of_type_placeholder.iter().map(|(&type_ref, ty)| (type_ref, ty.as_ref()))
}
- pub fn type_of_type_placeholder<'db>(&self, type_ref: TypeRefId) -> Option<Ty<'db>> {
+ pub fn type_of_type_placeholder<'a>(&self, type_ref: TypeRefId) -> Option<Ty<'a>> {
self.type_of_type_placeholder.get(&type_ref).map(|ty| ty.as_ref())
}
- pub fn type_of_expr_or_pat<'db>(&self, id: ExprOrPatId) -> Option<Ty<'db>> {
+ pub fn type_of_expr_or_pat<'a>(&self, id: ExprOrPatId) -> Option<Ty<'a>> {
match id {
ExprOrPatId::ExprId(id) => self.type_of_expr.get(id).map(|it| it.as_ref()),
ExprOrPatId::PatId(id) => self.type_of_pat.get(id).map(|it| it.as_ref()),
}
}
- pub fn type_of_expr_with_adjust<'db>(&self, id: ExprId) -> Option<Ty<'db>> {
+ pub fn type_of_expr_with_adjust<'a>(&self, id: ExprId) -> Option<Ty<'a>> {
match self.expr_adjustments.get(&id).and_then(|adjustments| {
adjustments.iter().rfind(|adj| {
// https://github.com/rust-lang/rust/blob/67819923ac8ea353aaa775303f4c3aacbf41d010/compiler/rustc_mir_build/src/thir/cx/expr.rs#L140
@@ -1160,7 +1176,7 @@ impl InferenceResult {
None => self.type_of_expr.get(id).map(|it| it.as_ref()),
}
}
- pub fn type_of_pat_with_adjust<'db>(&self, id: PatId) -> Ty<'db> {
+ pub fn type_of_pat_with_adjust<'a>(&self, id: PatId) -> Ty<'a> {
match self.pat_adjustments.get(&id).and_then(|adjustments| adjustments.last()) {
Some(adjusted) => adjusted.source.as_ref(),
None => self.pat_ty(id),
@@ -1174,7 +1190,7 @@ impl InferenceResult {
&self.diagnostics
}
- pub fn tuple_field_access_type<'db>(&self, id: TupleId) -> Tys<'db> {
+ pub fn tuple_field_access_type<'a>(&self, id: TupleId) -> Tys<'a> {
self.tuple_field_access_types[id.0 as usize].as_ref()
}
@@ -1191,25 +1207,25 @@ impl InferenceResult {
}
// This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.
- pub fn expression_types<'db>(&self) -> impl Iterator<Item = (ExprId, Ty<'db>)> {
+ pub fn expression_types<'a>(&self) -> impl Iterator<Item = (ExprId, Ty<'a>)> {
self.type_of_expr.iter().map(|(k, v)| (k, v.as_ref()))
}
// This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.
- pub fn pattern_types<'db>(&self) -> impl Iterator<Item = (PatId, Ty<'db>)> {
+ pub fn pattern_types<'a>(&self) -> impl Iterator<Item = (PatId, Ty<'a>)> {
self.type_of_pat.iter().map(|(k, v)| (k, v.as_ref()))
}
// This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.
- pub fn binding_types<'db>(&self) -> impl Iterator<Item = (BindingId, Ty<'db>)> {
+ pub fn binding_types<'a>(&self) -> impl Iterator<Item = (BindingId, Ty<'a>)> {
self.type_of_binding.iter().map(|(k, v)| (k, v.as_ref()))
}
// This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.
- pub fn return_position_impl_trait_types<'db>(
- &'db self,
- db: &'db dyn HirDatabase,
- ) -> impl Iterator<Item = (ImplTraitIdx, Ty<'db>)> {
+ pub fn return_position_impl_trait_types<'a>(
+ &'a self,
+ db: &'a dyn HirDatabase,
+ ) -> impl Iterator<Item = (ImplTraitIdx, Ty<'a>)> {
self.type_of_opaque.iter().filter_map(move |(&id, ty)| {
let ImplTraitId::ReturnTypeImplTrait(_, rpit_idx) = id.loc(db) else {
return None;
@@ -1218,24 +1234,24 @@ impl InferenceResult {
})
}
- pub fn expr_ty<'db>(&self, id: ExprId) -> Ty<'db> {
+ pub fn expr_ty<'a>(&self, id: ExprId) -> Ty<'a> {
self.type_of_expr.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())
}
- pub fn pat_ty<'db>(&self, id: PatId) -> Ty<'db> {
+ pub fn pat_ty<'a>(&self, id: PatId) -> Ty<'a> {
self.type_of_pat.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())
}
- pub fn expr_or_pat_ty<'db>(&self, id: ExprOrPatId) -> Ty<'db> {
+ pub fn expr_or_pat_ty<'a>(&self, id: ExprOrPatId) -> Ty<'a> {
self.type_of_expr_or_pat(id).unwrap_or(self.error_ty.as_ref())
}
- pub fn binding_ty<'db>(&self, id: BindingId) -> Ty<'db> {
+ pub fn binding_ty<'a>(&self, id: BindingId) -> Ty<'a> {
self.type_of_binding.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())
}
/// This does not deduplicate, which means you'll get the types once per capture.
- pub fn closure_captures_tys<'db>(&self, closure: ExprId) -> impl Iterator<Item = Ty<'db>> {
+ pub fn closure_captures_tys<'a>(&self, closure: ExprId) -> impl Iterator<Item = Ty<'a>> {
self.closures_data[&closure]
.min_captures
.values()
@@ -1243,11 +1259,11 @@ impl InferenceResult {
}
/// Like [`Self::closure_captures_tys()`], but using [`CapturedPlace::captured_ty()`].
- pub fn closure_captures_captured_tys<'db>(
+ pub fn closure_captures_captured_tys<'a>(
&self,
- db: &'db dyn HirDatabase,
+ db: &'a dyn HirDatabase,
closure: ExprId,
- ) -> impl Iterator<Item = Ty<'db>> {
+ ) -> impl Iterator<Item = Ty<'a>> {
self.closures_data[&closure]
.min_captures
.values()
@@ -1267,12 +1283,12 @@ enum DerefPatBorrowMode {
/// The inference context contains all information needed during type inference.
#[derive(Debug)]
-pub(crate) struct InferenceContext<'body, 'db> {
+pub(crate) struct InferenceContext<'db> {
pub(crate) db: &'db dyn HirDatabase,
- pub(crate) owner: InferBodyId,
+ pub(crate) owner: InferBodyId<'db>,
pub(crate) store_owner: ExpressionStoreOwnerId,
pub(crate) generic_def: GenericDefId,
- pub(crate) store: &'body ExpressionStore,
+ pub(crate) store: &'db ExpressionStore,
pub(crate) lowering_mode: LoweringMode,
/// Generally you should not resolve things via this resolver. Instead create a TyLoweringContext
/// and resolve the path via its methods. This will ensure proper error reporting.
@@ -1287,7 +1303,7 @@ pub(crate) struct InferenceContext<'body, 'db> {
pub(crate) features: &'db UnstableFeatures,
/// The traits in scope, disregarding block modules. This is used for caching purposes.
traits_in_scope: FxHashSet<TraitId>,
- pub(crate) result: InferenceResult,
+ pub(crate) result: InferenceResult<'db>,
tuple_field_accesses_rev:
IndexSet<Tys<'db>, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>,
/// The return type of the function being inferred, the closure or async block if we're
@@ -1317,7 +1333,7 @@ pub(crate) struct InferenceContext<'body, 'db> {
diagnostics: Diagnostics,
vars_emitted_type_must_be_known_for: FxHashSet<Term<'db>>,
- defined_anon_consts: RefCell<ThinVec<AnonConstId>>,
+ defined_anon_consts: RefCell<ThinVec<AnonConstId<'db>>>,
}
#[derive(Clone, Debug)]
@@ -1364,13 +1380,13 @@ fn find_continuable<'a, 'db>(
}
}
-impl<'body, 'db> InferenceContext<'body, 'db> {
+impl<'db> InferenceContext<'db> {
fn new(
db: &'db dyn HirDatabase,
- owner: InferBodyId,
+ owner: InferBodyId<'db>,
store_owner: ExpressionStoreOwnerId,
generic_def: GenericDefId,
- store: &'body ExpressionStore,
+ store: &'db ExpressionStore,
resolver: Resolver<'db>,
allow_using_generic_params: bool,
lowering_mode: LoweringMode,
@@ -1412,7 +1428,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
}
}
- fn merge(&mut self, other: &InferenceResult) {
+ fn merge(&mut self, other: &InferenceResult<'db>) {
let InferenceResult {
method_resolutions,
field_resolutions,
@@ -1567,7 +1583,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
// `InferenceResult` in the middle of inference. See the fixme comment in `consteval::eval_to_const`. If you
// used this function for another workaround, mention it here. If you really need this function and believe that
// there is no problem in it being `pub(crate)`, remove this comment.
- fn resolve_all(self) -> InferenceResult {
+ fn resolve_all(self) -> InferenceResult<'db> {
let InferenceContext {
table,
mut result,
@@ -1700,7 +1716,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
result
}
- fn collect_const(&mut self, id: ConstId, data: &ConstSignature) {
+ fn collect_const(&mut self, id: ConstId, data: &'db ConstSignature) {
let return_ty = self.make_ty(
data.type_ref,
&data.store,
@@ -1712,7 +1728,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
self.return_ty = return_ty;
}
- fn collect_static(&mut self, id: StaticId, data: &StaticSignature) {
+ fn collect_static(&mut self, id: StaticId, data: &'db StaticSignature) {
let return_ty = self.make_ty(
data.type_ref,
&data.store,
@@ -1921,7 +1937,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
fn with_ty_lowering<R>(
&mut self,
- store: &ExpressionStore,
+ store: &'db ExpressionStore,
types_source: InferenceTyDiagnosticSource,
store_owner: ExpressionStoreOwnerId,
lifetime_elision: LifetimeElisionKind<'db>,
@@ -1968,7 +1984,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
fn make_ty(
&mut self,
type_ref: TypeRefId,
- store: &ExpressionStore,
+ store: &'db ExpressionStore,
type_source: InferenceTyDiagnosticSource,
store_owner: ExpressionStoreOwnerId,
lifetime_elision: LifetimeElisionKind<'db>,
@@ -2560,7 +2576,7 @@ impl<'body, 'db> InferenceContext<'body, 'db> {
};
fn forbid_unresolved_segments<'db>(
- ctx: &InferenceContext<'_, 'db>,
+ ctx: &InferenceContext<'db>,
result: (Ty<'db>, Option<VariantId>),
unresolved: Option<usize>,
) -> (Ty<'db>, Option<VariantId>) {
@@ -2730,7 +2746,7 @@ impl<'db> Expectation<'db> {
/// which still is useful, because it informs integer literals and the like.
/// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
/// for examples of where this comes up,.
- fn rvalue_hint(ctx: &mut InferenceContext<'_, 'db>, ty: Ty<'db>) -> Self {
+ fn rvalue_hint(ctx: &mut InferenceContext<'db>, ty: Ty<'db>) -> Self {
match ctx.struct_tail_without_normalization(ty).kind() {
TyKind::Slice(_) | TyKind::Str | TyKind::Dynamic(..) => {
Expectation::RValueLikeUnsized(ty)