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.rs | 138 |
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) |