Merge pull request #21169 from Veykril/push-psyltyvxtpoz

internal: New style salsa infer query
This commit is contained in:
Lukas Wirth
2025-11-29 19:11:24 +00:00
committed by GitHub
27 changed files with 168 additions and 126 deletions
@@ -45,7 +45,7 @@
// FIXME: Encode this as a single u32, we won't ever reach all 32 bits especially given these counts
// are local to the body.
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, salsa::Update)]
pub enum ExprOrPatId {
ExprId(ExprId),
PatId(PatId),
@@ -600,17 +600,17 @@ fn module(&self, _db: &dyn DefDatabase) -> ModuleId {
/// An ID of a module, **local** to a `DefMap`.
pub type LocalModuleId = Idx<nameres::ModuleData>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Update)]
pub struct FieldId {
// FIXME: Store this as an erased `salsa::Id` to save space
pub parent: VariantId,
pub local_id: LocalFieldId,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Update)]
pub struct TupleId(pub u32);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Update)]
pub struct TupleFieldId {
pub tuple: TupleId,
pub index: u32,
@@ -1014,7 +1014,7 @@ fn from(vid: VariantId) -> Self {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa_macros::Supertype, salsa::Update)]
pub enum VariantId {
EnumVariantId(EnumVariantId),
StructId(StructId),
@@ -12,7 +12,7 @@
use triomphe::Arc;
use crate::{
ImplTraitId, InferenceResult, TraitEnvironment, TyDefId, ValueTyDefId,
ImplTraitId, TraitEnvironment, TyDefId, ValueTyDefId,
consteval::ConstEvalError,
dyn_compatibility::DynCompatibilityViolation,
layout::{Layout, LayoutError},
@@ -23,10 +23,6 @@
#[query_group::query_group]
pub trait HirDatabase: DefDatabase + std::fmt::Debug {
#[salsa::invoke(crate::infer::infer_query)]
#[salsa::cycle(cycle_result = crate::infer::infer_cycle_result)]
fn infer<'db>(&'db self, def: DefWithBodyId) -> Arc<InferenceResult<'db>>;
// region:mir
// FXME: Collapse `mir_body_for_closure` into `mir_body`
@@ -76,7 +76,7 @@ pub fn collect(
validate_lints: bool,
) -> Vec<BodyValidationDiagnostic> {
let _p = tracing::info_span!("BodyValidationDiagnostic::collect").entered();
let infer = db.infer(owner);
let infer = InferenceResult::for_body(db, owner);
let body = db.body(owner);
let env = db.trait_environment_for_body(owner);
let interner = DbInterner::new_with(db, env.krate, env.block);
@@ -99,7 +99,7 @@ pub fn collect(
struct ExprValidator<'db> {
owner: DefWithBodyId,
body: Arc<Body>,
infer: Arc<InferenceResult<'db>>,
infer: &'db InferenceResult<'db>,
env: Arc<TraitEnvironment<'db>>,
diagnostics: Vec<BodyValidationDiagnostic>,
validate_lints: bool,
@@ -124,7 +124,7 @@ fn validate_body(&mut self) {
for (id, expr) in body.exprs() {
if let Some((variant, missed_fields, true)) =
record_literal_missing_fields(db, &self.infer, id, expr)
record_literal_missing_fields(db, self.infer, id, expr)
{
self.diagnostics.push(BodyValidationDiagnostic::RecordMissingFields {
record: Either::Left(id),
@@ -155,7 +155,7 @@ fn validate_body(&mut self) {
for (id, pat) in body.pats() {
if let Some((variant, missed_fields, true)) =
record_pattern_missing_fields(db, &self.infer, id, pat)
record_pattern_missing_fields(db, self.infer, id, pat)
{
self.diagnostics.push(BodyValidationDiagnostic::RecordMissingFields {
record: Either::Right(id),
@@ -240,7 +240,7 @@ fn validate_match(&mut self, match_expr: ExprId, scrutinee_expr: ExprId, arms: &
.as_reference()
.map(|(match_expr_ty, ..)| match_expr_ty == pat_ty)
.unwrap_or(false))
&& types_of_subpatterns_do_match(arm.pat, &self.body, &self.infer)
&& types_of_subpatterns_do_match(arm.pat, &self.body, self.infer)
{
// If we had a NotUsefulMatchArm diagnostic, we could
// check the usefulness of each pattern as we added it
@@ -388,7 +388,7 @@ fn lower_pattern<'a>(
pat: PatId,
have_errors: &mut bool,
) -> DeconstructedPat<'a, 'db> {
let mut patcx = match_check::PatCtxt::new(self.db(), &self.infer, &self.body);
let mut patcx = match_check::PatCtxt::new(self.db(), self.infer, &self.body);
let pattern = patcx.lower_pattern(pat);
let pattern = cx.lower_pat(&pattern);
if !patcx.errors.is_empty() {
@@ -42,7 +42,7 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> MissingUnsafe
let mut res = MissingUnsafeResult { fn_is_unsafe: is_unsafe, ..MissingUnsafeResult::default() };
let body = db.body(def);
let infer = db.infer(def);
let infer = InferenceResult::for_body(db, def);
let mut callback = |diag| match diag {
UnsafeDiagnostic::UnsafeOperation { node, inside_unsafe_block, reason } => {
if inside_unsafe_block == InsideUnsafeBlock::No {
@@ -55,7 +55,7 @@ pub fn missing_unsafe(db: &dyn HirDatabase, def: DefWithBodyId) -> MissingUnsafe
}
}
};
let mut visitor = UnsafeVisitor::new(db, &infer, &body, def, &mut callback);
let mut visitor = UnsafeVisitor::new(db, infer, &body, def, &mut callback);
visitor.walk_expr(body.body_expr);
if !is_unsafe {
@@ -47,7 +47,7 @@
use triomphe::Arc;
use crate::{
CallableDefId, FnAbi, ImplTraitId, MemoryMap, TraitEnvironment, consteval,
CallableDefId, FnAbi, ImplTraitId, InferenceResult, MemoryMap, TraitEnvironment, consteval,
db::{HirDatabase, InternedClosure, InternedCoroutine},
generics::generics,
layout::Layout,
@@ -1398,7 +1398,7 @@ fn hir_fmt(
if let Some(sig) = sig {
let sig = sig.skip_binder();
let InternedClosure(def, _) = db.lookup_intern_closure(id);
let infer = db.infer(def);
let infer = InferenceResult::for_body(db, def);
let (_, kind) = infer.closure_info(id);
match f.closure_style {
ClosureStyle::ImplFn => write!(f, "impl {kind:?}(")?,
@@ -7,7 +7,7 @@
use triomphe::Arc;
use crate::{
TraitEnvironment, consteval,
InferenceResult, TraitEnvironment, consteval,
method_resolution::TraitImpls,
next_solver::{
DbInterner, SimplifiedType, Ty, TyKind,
@@ -137,7 +137,7 @@ fn has_drop_glue_impl<'db>(
TyKind::Slice(ty) => has_drop_glue_impl(infcx, ty, env, visited),
TyKind::Closure(closure_id, subst) => {
let owner = db.lookup_intern_closure(closure_id.0).0;
let infer = db.infer(owner);
let infer = InferenceResult::for_body(db, owner);
let (captures, _) = infer.closure_info(closure_id.0);
let env = db.trait_environment_for_body(owner);
captures
@@ -54,10 +54,10 @@
AliasTyKind, TypeFoldable,
inherent::{AdtDef, IntoKind, Region as _, SliceLike, Ty as _},
};
use salsa::Update;
use span::Edition;
use stdx::never;
use thin_vec::ThinVec;
use triomphe::Arc;
use crate::{
ImplTraitId, IncorrectGenericsLenKind, PathLoweringDiagnostic, TargetFeatures,
@@ -95,7 +95,7 @@
pub(crate) use closure::analysis::{CaptureKind, CapturedItem, CapturedItemWithoutTy};
/// The entry point of type inference.
pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult<'_>> {
fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'_> {
let _p = tracing::info_span!("infer_query").entered();
let resolver = def.resolver(db);
let body = db.body(def);
@@ -159,17 +159,14 @@ pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<Infer
ctx.handle_opaque_type_uses();
Arc::new(ctx.resolve_all())
ctx.resolve_all()
}
pub(crate) fn infer_cycle_result(
db: &dyn HirDatabase,
_: DefWithBodyId,
) -> Arc<InferenceResult<'_>> {
Arc::new(InferenceResult {
fn infer_cycle_result(db: &dyn HirDatabase, _: DefWithBodyId) -> InferenceResult<'_> {
InferenceResult {
has_errors: true,
..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))
})
}
}
/// Binding modes inferred for patterns.
@@ -199,7 +196,7 @@ pub enum InferenceTyDiagnosticSource {
Signature,
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[derive(Debug, PartialEq, Eq, Clone, Update)]
pub enum InferenceDiagnostic<'db> {
NoSuchField {
field: ExprOrPatId,
@@ -293,7 +290,7 @@ pub enum InferenceDiagnostic<'db> {
}
/// A mismatch between an expected and an inferred type.
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
#[derive(Clone, PartialEq, Eq, Debug, Hash, Update)]
pub struct TypeMismatch<'db> {
pub expected: Ty<'db>,
pub actual: Ty<'db>,
@@ -339,7 +336,7 @@ pub struct TypeMismatch<'db> {
/// At some point, of course, `Box` should move out of the compiler, in which
/// case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->
/// Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeVisitable, TypeFoldable)]
#[derive(Clone, Debug, PartialEq, Eq, Hash, TypeVisitable, TypeFoldable, Update)]
pub struct Adjustment<'db> {
#[type_visitable(ignore)]
#[type_foldable(identity)]
@@ -476,9 +473,10 @@ pub enum PointerCast {
/// 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)]
#[derive(Clone, PartialEq, Eq, Debug, Update)]
pub struct InferenceResult<'db> {
/// For each method call expr, records the function it resolves to.
#[update(unsafe(with(crate::utils::unsafe_update_eq /* expr id is technically update */)))]
method_resolutions: FxHashMap<ExprId, (FunctionId, GenericArgs<'db>)>,
/// For each field access expr, records the field it resolves to.
field_resolutions: FxHashMap<ExprId, Either<FieldId, TupleFieldId>>,
@@ -489,15 +487,20 @@ pub struct InferenceResult<'db> {
/// Whenever a tuple field expression access a tuple field, we allocate a tuple id in
/// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of
/// that which allows us to resolve a [`TupleFieldId`]s type.
tuple_field_access_types: FxHashMap<TupleId, Tys<'db>>,
#[update(unsafe(with(crate::utils::unsafe_update_eq /* thinvec is technically update */)))]
tuple_field_access_types: ThinVec<Tys<'db>>,
#[update(unsafe(with(crate::utils::unsafe_update_eq /* expr id is technically update */)))]
pub(crate) type_of_expr: ArenaMap<ExprId, Ty<'db>>,
/// For each pattern record the type it resolves to.
///
/// **Note**: When a pattern type is resolved it may still contain
/// unresolved or missing subpatterns or subpatterns of mismatched types.
#[update(unsafe(with(crate::utils::unsafe_update_eq /* pat id is technically update */)))]
pub(crate) type_of_pat: ArenaMap<PatId, Ty<'db>>,
#[update(unsafe(with(crate::utils::unsafe_update_eq /* binding id is technically update */)))]
pub(crate) type_of_binding: ArenaMap<BindingId, Ty<'db>>,
#[update(unsafe(with(crate::utils::unsafe_update_eq /* type ref id is technically update */)))]
pub(crate) type_of_type_placeholder: FxHashMap<TypeRefId, Ty<'db>>,
pub(crate) type_of_opaque: FxHashMap<InternedOpaqueTyId, Ty<'db>>,
@@ -508,14 +511,17 @@ pub struct InferenceResult<'db> {
// Which will then mark this field.
pub(crate) has_errors: bool,
/// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.
#[update(unsafe(with(crate::utils::unsafe_update_eq /* thinvec is technically update */)))]
diagnostics: ThinVec<InferenceDiagnostic<'db>>,
/// Interned `Error` type to return references to.
// FIXME: Remove this.
error_ty: Ty<'db>,
#[update(unsafe(with(crate::utils::unsafe_update_eq /* expr id is technically update */)))]
pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment<'db>]>>,
/// Stores the types which were implicitly dereferenced in pattern binding modes.
#[update(unsafe(with(crate::utils::unsafe_update_eq /* pat id is technically update */)))]
pub(crate) pat_adjustments: FxHashMap<PatId, Vec<Ty<'db>>>,
/// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.
///
@@ -539,6 +545,14 @@ pub struct InferenceResult<'db> {
pub(crate) coercion_casts: FxHashSet<ExprId>,
}
#[salsa::tracked]
impl<'db> InferenceResult<'db> {
#[salsa::tracked(returns(ref), cycle_result = infer_cycle_result)]
pub fn for_body(db: &'db dyn HirDatabase, def: DefWithBodyId) -> InferenceResult<'db> {
infer_query(db, def)
}
}
impl<'db> InferenceResult<'db> {
fn new(error_ty: Ty<'db>) -> Self {
Self {
@@ -672,7 +686,7 @@ pub fn diagnostics(&self) -> &[InferenceDiagnostic<'db>] {
}
pub fn tuple_field_access_type(&self, id: TupleId) -> Tys<'db> {
self.tuple_field_access_types[&id]
self.tuple_field_access_types[id.0 as usize]
}
pub fn pat_adjustment(&self, id: PatId) -> Option<&[Ty<'db>]> {
@@ -1135,9 +1149,8 @@ fn resolve_all(self) -> InferenceResult<'db> {
pat_adjustments.shrink_to_fit();
result.tuple_field_access_types = tuple_field_accesses_rev
.into_iter()
.enumerate()
.map(|(idx, subst)| (TupleId(idx as u32), table.resolve_completely(subst)))
.inspect(|(_, subst)| {
.map(|subst| table.resolve_completely(subst))
.inspect(|subst| {
*has_errors = *has_errors || subst.iter().any(|ty| ty.references_non_lt_error());
})
.collect();
@@ -31,10 +31,10 @@
// The below functions handle capture and closure kind (Fn, FnMut, ..)
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, PartialEq, Eq, Hash, salsa::Update)]
pub(crate) struct HirPlace<'db> {
pub(crate) local: BindingId,
pub(crate) projections: Vec<ProjectionElem<Infallible, Ty<'db>>>,
pub(crate) projections: Vec<ProjectionElem<'db, Infallible>>,
}
impl<'db> HirPlace<'db> {
@@ -76,7 +76,7 @@ pub enum CaptureKind {
ByValue,
}
#[derive(Debug, Clone, PartialEq, Eq)]
#[derive(Debug, Clone, PartialEq, Eq, salsa::Update)]
pub struct CapturedItem<'db> {
pub(crate) place: HirPlace<'db>,
pub(crate) kind: CaptureKind,
@@ -87,6 +87,7 @@ pub struct CapturedItem<'db> {
/// copy all captures of the inner closure to the outer closure, and then we may
/// truncate them, and we want the correct span to be reported.
span_stacks: SmallVec<[SmallVec<[MirSpan; 3]>; 3]>,
#[update(unsafe(with(crate::utils::unsafe_update_eq)))]
pub(crate) ty: EarlyBinder<'db, Ty<'db>>,
}
@@ -21,7 +21,7 @@
use triomphe::Arc;
use crate::{
TraitEnvironment,
InferenceResult, TraitEnvironment,
consteval::try_const_usize,
db::HirDatabase,
next_solver::{
@@ -322,7 +322,7 @@ pub fn layout_of_ty_query<'db>(
}
TyKind::Closure(id, args) => {
let def = db.lookup_intern_closure(id.0);
let infer = db.infer(def.0);
let infer = InferenceResult::for_body(db, def.0);
let (captures, _) = infer.closure_info(id.0);
let fields = captures
.iter()
@@ -9,6 +9,7 @@
use triomphe::Arc;
use crate::{
InferenceResult,
db::HirDatabase,
layout::{Layout, LayoutError},
next_solver::{DbInterner, GenericArgs},
@@ -136,7 +137,7 @@ fn eval_expr(
.find(|x| x.1.name.display_no_db(file_id.edition(&db)).to_smolstr() == "goal")
.unwrap()
.0;
let infer = db.infer(function_id.into());
let infer = InferenceResult::for_body(&db, function_id.into());
let goal_ty = infer.type_of_binding[b];
db.layout_of_ty(goal_ty, db.trait_environment(function_id.into()))
})
@@ -81,7 +81,7 @@ pub struct MethodResolutionContext<'a, 'db> {
pub unstable_features: &'a MethodResolutionUnstableFeatures,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, salsa::Update)]
pub enum CandidateId {
FunctionId(FunctionId),
ConstId(ConstId),
@@ -140,21 +140,21 @@ fn from_fn(
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum ProjectionElem<V, T> {
#[derive(Debug, Clone, PartialEq, Eq, Hash, salsa::Update)]
pub enum ProjectionElem<'db, V: PartialEq> {
Deref,
Field(Either<FieldId, TupleFieldId>),
// FIXME: get rid of this, and use FieldId for tuples and closures
ClosureField(usize),
Index(V),
Index(#[update(unsafe(with(crate::utils::unsafe_update_eq)))] V),
ConstantIndex { offset: u64, from_end: bool },
Subslice { from: u64, to: u64 },
//Downcast(Option<Symbol>, VariantIdx),
OpaqueCast(T),
OpaqueCast(Ty<'db>),
}
impl<V, T> ProjectionElem<V, T> {
pub fn projected_ty<'db>(
impl<'db, V: PartialEq> ProjectionElem<'db, V> {
pub fn projected_ty(
&self,
infcx: &InferCtxt<'db>,
mut base: Ty<'db>,
@@ -254,7 +254,7 @@ pub fn projected_ty<'db>(
}
}
type PlaceElem<'db> = ProjectionElem<LocalId<'db>, Ty<'db>>;
type PlaceElem<'db> = ProjectionElem<'db, LocalId<'db>>;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ProjectionId(u32);
@@ -12,7 +12,7 @@
use triomphe::Arc;
use crate::{
TraitEnvironment,
InferenceResult, TraitEnvironment,
db::{HirDatabase, InternedClosure, InternedClosureId},
display::DisplayTarget,
mir::OperandKind,
@@ -121,7 +121,7 @@ fn make_fetch_closure_field<'db>(
) -> impl FnOnce(InternedClosureId, GenericArgs<'db>, usize) -> Ty<'db> + use<'db> {
|c: InternedClosureId, subst: GenericArgs<'db>, f: usize| {
let InternedClosure(def, _) = db.lookup_intern_closure(c);
let infer = db.infer(def);
let infer = InferenceResult::for_body(db, def);
let (captures, _) = infer.closure_info(c);
let parent_subst = subst.split_closure_args_untupled().parent_args;
let interner = DbInterner::new_no_crate(db);
@@ -34,7 +34,7 @@
use triomphe::Arc;
use crate::{
CallableDefId, ComplexMemoryMap, MemoryMap, TraitEnvironment,
CallableDefId, ComplexMemoryMap, InferenceResult, MemoryMap, TraitEnvironment,
consteval::{self, ConstEvalError, try_const_usize},
db::{HirDatabase, InternedClosure, InternedClosureId},
display::{ClosureStyle, DisplayTarget, HirDisplay},
@@ -722,7 +722,7 @@ fn projected_ty(&self, ty: Ty<'db>, proj: PlaceElem<'db>) -> Ty<'db> {
ty,
|c, subst, f| {
let InternedClosure(def, _) = self.db.lookup_intern_closure(c);
let infer = self.db.infer(def);
let infer = InferenceResult::for_body(self.db, def);
let (captures, _) = infer.closure_info(c);
let parent_subst = subst.split_closure_args_untupled().parent_args;
captures
@@ -883,7 +883,8 @@ fn operand_ty(&self, o: &Operand<'db>, locals: &Locals<'db>) -> Result<'db, Ty<'
OperandKind::Copy(p) | OperandKind::Move(p) => self.place_ty(p, locals)?,
OperandKind::Constant { konst: _, ty } => *ty,
&OperandKind::Static(s) => {
let ty = self.db.infer(s.into())[self.db.body(s.into()).body_expr];
let ty =
InferenceResult::for_body(self.db, s.into())[self.db.body(s.into()).body_expr];
Ty::new_ref(
self.interner(),
Region::new_static(self.interner()),
@@ -2809,7 +2810,8 @@ fn eval_static(&mut self, st: StaticId, locals: &Locals<'db>) -> Result<'db, Add
})?;
self.allocate_const_in_heap(locals, konst)?
} else {
let ty = self.db.infer(st.into())[self.db.body(st.into()).body_expr];
let ty =
InferenceResult::for_body(self.db, st.into())[self.db.body(st.into()).body_expr];
let Some((size, align)) = self.size_align_of(ty, locals)? else {
not_supported!("unsized extern static");
};
@@ -10,6 +10,7 @@
use stdx::never;
use crate::{
InferenceResult,
display::DisplayTarget,
drop::{DropGlue, has_drop_glue},
mir::eval::{
@@ -167,7 +168,7 @@ fn exec_clone(
};
let addr = Address::from_bytes(arg.get(self)?)?;
let InternedClosure(closure_owner, _) = self.db.lookup_intern_closure(id.0);
let infer = self.db.infer(closure_owner);
let infer = InferenceResult::for_body(self.db, closure_owner);
let (captures, _) = infer.closure_info(id.0);
let layout = self.layout(self_ty)?;
let db = self.db;
@@ -2111,7 +2111,7 @@ pub fn mir_body_for_closure_query<'db>(
) -> Result<'db, Arc<MirBody<'db>>> {
let InternedClosure(owner, expr) = db.lookup_intern_closure(closure);
let body = db.body(owner);
let infer = db.infer(owner);
let infer = InferenceResult::for_body(db, owner);
let Expr::Closure { args, body: root, .. } = &body[expr] else {
implementation_error!("closure expression is not closure");
};
@@ -2119,7 +2119,7 @@ pub fn mir_body_for_closure_query<'db>(
implementation_error!("closure expression is not closure");
};
let (captures, kind) = infer.closure_info(closure);
let mut ctx = MirLowerCtx::new(db, owner, &body, &infer);
let mut ctx = MirLowerCtx::new(db, owner, &body, infer);
// 0 is return local
ctx.result.locals.alloc(Local { ty: infer[*root] });
let closure_local = ctx.result.locals.alloc(Local {
@@ -2249,8 +2249,8 @@ pub fn mir_body_query<'db>(
};
let _p = tracing::info_span!("mir_body_query", ?detail).entered();
let body = db.body(def);
let infer = db.infer(def);
let mut result = lower_to_mir(db, def, &body, &infer, body.body_expr)?;
let infer = InferenceResult::for_body(db, def);
let mut result = lower_to_mir(db, def, &body, infer, body.body_expr)?;
result.shrink_to_fit();
Ok(Arc::new(result))
}
@@ -9,7 +9,7 @@
use syntax::ast;
use crate::{
ImplTraitId,
ImplTraitId, InferenceResult,
db::{HirDatabase, InternedOpaqueTyId},
lower::{ImplTraitIdx, ImplTraits},
next_solver::{
@@ -94,7 +94,7 @@ pub(crate) fn rpit_hidden_types<'db>(
db: &'db dyn HirDatabase,
function: FunctionId,
) -> ArenaMap<ImplTraitIdx<'db>, EarlyBinder<'db, Ty<'db>>> {
let infer = db.infer(function.into());
let infer = InferenceResult::for_body(db, function.into());
let mut result = ArenaMap::new();
for (opaque, hidden_type) in infer.return_position_impl_trait_types(db) {
result.insert(opaque, EarlyBinder::bind(hidden_type));
@@ -128,7 +128,7 @@ pub(crate) fn tait_hidden_types<'db>(
let mut result = ArenaMap::with_capacity(taits_count);
for defining_body in defining_bodies {
let infer = db.infer(defining_body);
let infer = InferenceResult::for_body(db, defining_body);
for (&opaque, &hidden_type) in &infer.type_of_opaque {
let ImplTraitId::TypeAliasImplTrait(opaque_owner, opaque_idx) = opaque.loc(db) else {
continue;
@@ -38,7 +38,6 @@
use crate::{
InferenceResult,
db::HirDatabase,
display::{DisplayTarget, HirDisplay},
infer::{Adjustment, TypeMismatch},
next_solver::Ty,
@@ -148,7 +147,7 @@ fn check_impl(
for (def, krate) in defs {
let display_target = DisplayTarget::from_crate(&db, krate);
let (body, body_source_map) = db.body_with_source_map(def);
let inference_result = db.infer(def);
let inference_result = InferenceResult::for_body(&db, def);
for (pat, mut ty) in inference_result.type_of_pat.iter() {
if let Pat::Bind { id, .. } = body[pat] {
@@ -319,7 +318,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
crate::attach_db(&db, || {
let mut buf = String::new();
let mut infer_def = |inference_result: Arc<InferenceResult<'_>>,
let mut infer_def = |inference_result: &InferenceResult<'_>,
body: Arc<Body>,
body_source_map: Arc<BodySourceMap>,
krate: Crate| {
@@ -443,7 +442,7 @@ fn infer_with_mismatches(content: &str, include_mismatches: bool) -> String {
});
for (def, krate) in defs {
let (body, source_map) = db.body_with_source_map(def);
let infer = db.infer(def);
let infer = InferenceResult::for_body(&db, def);
infer_def(infer, body, source_map, krate);
}
@@ -595,13 +594,16 @@ fn main() {
let module = db.module_for_file(pos.file_id.file_id(&db));
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module.local_id, &mut |def| {
db.infer(match def {
ModuleDefId::FunctionId(it) => it.into(),
ModuleDefId::EnumVariantId(it) => it.into(),
ModuleDefId::ConstId(it) => it.into(),
ModuleDefId::StaticId(it) => it.into(),
_ => return,
});
InferenceResult::for_body(
&db,
match def {
ModuleDefId::FunctionId(it) => it.into(),
ModuleDefId::EnumVariantId(it) => it.into(),
ModuleDefId::ConstId(it) => it.into(),
ModuleDefId::StaticId(it) => it.into(),
_ => return,
},
);
});
});
@@ -636,13 +638,16 @@ fn main() {
let module = db.module_for_file(pos.file_id.file_id(&db));
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module.local_id, &mut |def| {
db.infer(match def {
ModuleDefId::FunctionId(it) => it.into(),
ModuleDefId::EnumVariantId(it) => it.into(),
ModuleDefId::ConstId(it) => it.into(),
ModuleDefId::StaticId(it) => it.into(),
_ => return,
});
InferenceResult::for_body(
&db,
match def {
ModuleDefId::FunctionId(it) => it.into(),
ModuleDefId::EnumVariantId(it) => it.into(),
ModuleDefId::ConstId(it) => it.into(),
ModuleDefId::StaticId(it) => it.into(),
_ => return,
},
);
});
})
}
@@ -7,6 +7,7 @@
use test_fixture::WithFixture;
use crate::{
InferenceResult,
db::HirDatabase,
display::{DisplayTarget, HirDisplay},
mir::MirSpan,
@@ -34,7 +35,7 @@ fn check_closure_captures(#[rust_analyzer::rust_fixture] ra_fixture: &str, expec
hir_def::ModuleDefId::StaticId(it) => it.into(),
_ => continue,
};
let infer = db.infer(def);
let infer = InferenceResult::for_body(&db, def);
let db = &db;
captures_info.extend(infer.closure_info.iter().flat_map(
|(closure_id, (captures, _))| {
@@ -4,7 +4,7 @@
use salsa::EventKind;
use test_fixture::WithFixture;
use crate::{db::HirDatabase, method_resolution::TraitImpls, test_db::TestDB};
use crate::{InferenceResult, method_resolution::TraitImpls, test_db::TestDB};
use super::visit_module;
@@ -24,11 +24,11 @@ fn foo() -> i32 {
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module.local_id, &mut |def| {
if let ModuleDefId::FunctionId(it) = def {
db.infer(it.into());
InferenceResult::for_body(&db, it.into());
}
});
},
&[("infer_shim", 1)],
&[("InferenceResult < 'db >::for_body_", 1)],
expect_test::expect![[r#"
[
"crate_local_def_map",
@@ -36,7 +36,7 @@ fn foo() -> i32 {
"ast_id_map_shim",
"parse_shim",
"real_span_map_shim",
"infer_shim",
"InferenceResult < 'db >::for_body_",
"function_signature_shim",
"function_signature_with_source_map_shim",
"AttrFlags::query_",
@@ -68,11 +68,11 @@ fn foo() -> i32 {
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module.local_id, &mut |def| {
if let ModuleDefId::FunctionId(it) = def {
db.infer(it.into());
InferenceResult::for_body(&db, it.into());
}
});
},
&[("infer_shim", 0)],
&[("InferenceResult < 'db >::for_body_", 0)],
expect_test::expect![[r#"
[
"parse_shim",
@@ -111,11 +111,11 @@ fn baz() -> i32 {
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module.local_id, &mut |def| {
if let ModuleDefId::FunctionId(it) = def {
db.infer(it.into());
InferenceResult::for_body(&db, it.into());
}
});
},
&[("infer_shim", 3)],
&[("InferenceResult < 'db >::for_body_", 3)],
expect_test::expect![[r#"
[
"crate_local_def_map",
@@ -123,7 +123,7 @@ fn baz() -> i32 {
"ast_id_map_shim",
"parse_shim",
"real_span_map_shim",
"infer_shim",
"InferenceResult < 'db >::for_body_",
"function_signature_shim",
"function_signature_with_source_map_shim",
"AttrFlags::query_",
@@ -137,7 +137,7 @@ fn baz() -> i32 {
"GenericPredicates < 'db >::query_with_diagnostics_",
"ImplTraits < 'db >::return_type_impl_traits_",
"expr_scopes_shim",
"infer_shim",
"InferenceResult < 'db >::for_body_",
"function_signature_shim",
"function_signature_with_source_map_shim",
"body_shim",
@@ -146,7 +146,7 @@ fn baz() -> i32 {
"GenericPredicates < 'db >::query_with_diagnostics_",
"ImplTraits < 'db >::return_type_impl_traits_",
"expr_scopes_shim",
"infer_shim",
"InferenceResult < 'db >::for_body_",
"function_signature_shim",
"function_signature_with_source_map_shim",
"body_shim",
@@ -180,11 +180,11 @@ fn baz() -> i32 {
let crate_def_map = module.def_map(&db);
visit_module(&db, crate_def_map, module.local_id, &mut |def| {
if let ModuleDefId::FunctionId(it) = def {
db.infer(it.into());
InferenceResult::for_body(&db, it.into());
}
});
},
&[("infer_shim", 1)],
&[("InferenceResult < 'db >::for_body_", 1)],
expect_test::expect![[r#"
[
"parse_shim",
@@ -202,7 +202,7 @@ fn baz() -> i32 {
"function_signature_shim",
"body_with_source_map_shim",
"body_shim",
"infer_shim",
"InferenceResult < 'db >::for_body_",
"expr_scopes_shim",
"function_signature_with_source_map_shim",
"function_signature_shim",
@@ -558,7 +558,7 @@ fn main() {
});
for def in defs {
let _inference_result = db.infer(def);
let _inference_result = InferenceResult::for_body(&db, def);
}
},
&[("trait_solve_shim", 0)],
@@ -574,7 +574,7 @@ fn main() {
"body_with_source_map_shim",
"AttrFlags::query_",
"ImplItems::of_",
"infer_shim",
"InferenceResult < 'db >::for_body_",
"trait_signature_shim",
"trait_signature_with_source_map_shim",
"AttrFlags::query_",
@@ -591,7 +591,7 @@ fn main() {
"GenericPredicates < 'db >::query_with_diagnostics_",
"GenericPredicates < 'db >::query_with_diagnostics_",
"ImplTraits < 'db >::return_type_impl_traits_",
"infer_shim",
"InferenceResult < 'db >::for_body_",
"function_signature_shim",
"function_signature_with_source_map_shim",
"trait_environment_shim",
@@ -655,7 +655,7 @@ fn main() {
});
for def in defs {
let _inference_result = db.infer(def);
let _inference_result = InferenceResult::for_body(&db, def);
}
},
&[("trait_solve_shim", 0)],
@@ -671,7 +671,7 @@ fn main() {
"AttrFlags::query_",
"body_shim",
"ImplItems::of_",
"infer_shim",
"InferenceResult < 'db >::for_body_",
"AttrFlags::query_",
"trait_signature_with_source_map_shim",
"AttrFlags::query_",
@@ -686,7 +686,7 @@ fn main() {
"GenericPredicates < 'db >::query_with_diagnostics_",
"GenericPredicates < 'db >::query_with_diagnostics_",
"ImplTraits < 'db >::return_type_impl_traits_",
"infer_shim",
"InferenceResult < 'db >::for_body_",
"function_signature_with_source_map_shim",
"GenericPredicates < 'db >::query_with_diagnostics_",
"ImplTraits < 'db >::return_type_impl_traits_",
@@ -151,7 +151,7 @@ pub fn next_trait_solve_in_ctxt<'db, 'a>(
res
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, salsa::Update)]
pub enum FnTrait {
// Warning: Order is important. If something implements `x` it should also implement
// `y` if `y <= x`.
@@ -25,6 +25,26 @@
mir::pad16,
};
/// SAFETY: `old_pointer` must be valid for unique writes
pub(crate) unsafe fn unsafe_update_eq<T>(old_pointer: *mut T, new_value: T) -> bool
where
T: PartialEq,
{
// SAFETY: Caller obligation
let old_ref: &mut T = unsafe { &mut *old_pointer };
if *old_ref != new_value {
*old_ref = new_value;
true
} else {
// Subtle but important: Eq impls can be buggy or define equality
// in surprising ways. If it says that the value has not changed,
// we do not modify the existing value, and thus do not have to
// update the revision, as downstream code will not see the new value.
false
}
}
pub(crate) fn fn_traits(lang_items: &LangItems) -> impl Iterator<Item = TraitId> + '_ {
[lang_items.Fn, lang_items.FnMut, lang_items.FnOnce].into_iter().flatten()
}
@@ -76,8 +76,8 @@
AstId, MacroCallKind, RenderedExpandError, ValueResult, proc_macro::ProcMacroKind,
};
use hir_ty::{
GenericPredicates, TraitEnvironment, TyDefId, TyLoweringDiagnostic, ValueTyDefId,
all_super_traits, autoderef, check_orphan_rules,
GenericPredicates, InferenceResult, TraitEnvironment, TyDefId, TyLoweringDiagnostic,
ValueTyDefId, all_super_traits, autoderef, check_orphan_rules,
consteval::try_const_usize,
db::{InternedClosureId, InternedCoroutineId},
diagnostics::BodyValidationDiagnostic,
@@ -1239,8 +1239,7 @@ pub fn name(&self) -> Name {
pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
let interner = DbInterner::new_no_crate(db);
let ty = db
.infer(self.owner)
let ty = InferenceResult::for_body(db, self.owner)
.tuple_field_access_type(self.tuple)
.as_slice()
.get(self.index as usize)
@@ -1956,7 +1955,7 @@ pub fn diagnostics<'db>(
expr_store_diagnostics(db, acc, &source_map);
let infer = db.infer(self.into());
let infer = InferenceResult::for_body(db, self.into());
for d in infer.diagnostics() {
acc.extend(AnyDiagnostic::inference_diagnostic(
db,
@@ -3844,7 +3843,7 @@ pub fn module(self, db: &dyn HirDatabase) -> Module {
pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
let def = self.parent;
let infer = db.infer(def);
let infer = InferenceResult::for_body(db, def);
let ty = infer[self.binding_id];
Type::new(db, def, ty)
}
@@ -4540,7 +4539,7 @@ pub fn captured_items(&self, db: &'db dyn HirDatabase) -> Vec<ClosureCapture<'db
return Vec::new();
};
let owner = db.lookup_intern_closure(id).0;
let infer = db.infer(owner);
let infer = InferenceResult::for_body(db, owner);
let info = infer.closure_info(id);
info.0
.iter()
@@ -4555,7 +4554,7 @@ pub fn capture_types(&self, db: &'db dyn HirDatabase) -> Vec<Type<'db>> {
return Vec::new();
};
let owner = db.lookup_intern_closure(id).0;
let infer = db.infer(owner);
let infer = InferenceResult::for_body(db, owner);
let (captures, _) = infer.closure_info(id);
let env = db.trait_environment_for_body(owner);
captures
@@ -4568,7 +4567,7 @@ pub fn fn_trait(&self, db: &dyn HirDatabase) -> FnTrait {
match self.id {
AnyClosureId::ClosureId(id) => {
let owner = db.lookup_intern_closure(id).0;
let infer = db.infer(owner);
let infer = InferenceResult::for_body(db, owner);
let info = infer.closure_info(id);
info.1.into()
}
@@ -28,6 +28,7 @@
name::AsName,
};
use hir_ty::{
InferenceResult,
diagnostics::{unsafe_operations, unsafe_operations_for_body},
next_solver::DbInterner,
};
@@ -1777,9 +1778,9 @@ pub fn resolve_macro_call_arm(&self, macro_call: &ast::MacroCall) -> Option<u32>
pub fn get_unsafe_ops(&self, def: DefWithBody) -> FxHashSet<ExprOrPatSource> {
let def = DefWithBodyId::from(def);
let (body, source_map) = self.db.body_with_source_map(def);
let infer = self.db.infer(def);
let infer = InferenceResult::for_body(self.db, def);
let mut res = FxHashSet::default();
unsafe_operations_for_body(self.db, &infer, def, &body, &mut |node| {
unsafe_operations_for_body(self.db, infer, def, &body, &mut |node| {
if let Ok(node) = source_map.expr_or_pat_syntax(node) {
res.insert(node);
}
@@ -1793,12 +1794,12 @@ pub fn get_unsafe_ops_for_unsafe_block(&self, block: ast::BlockExpr) -> Vec<Expr
let Some(def) = self.body_for(block.syntax()) else { return Vec::new() };
let def = def.into();
let (body, source_map) = self.db.body_with_source_map(def);
let infer = self.db.infer(def);
let infer = InferenceResult::for_body(self.db, def);
let Some(ExprOrPatId::ExprId(block)) = source_map.node_expr(block.as_ref()) else {
return Vec::new();
};
let mut res = Vec::default();
unsafe_operations(self.db, &infer, def, &body, block, &mut |node, _| {
unsafe_operations(self.db, infer, def, &body, block, &mut |node, _| {
if let Ok(node) = source_map.expr_or_pat_syntax(node) {
res.push(node);
}
@@ -78,7 +78,7 @@ pub(crate) enum BodyOrSig<'db> {
def: DefWithBodyId,
body: Arc<Body>,
source_map: Arc<BodySourceMap>,
infer: Option<Arc<InferenceResult<'db>>>,
infer: Option<&'db InferenceResult<'db>>,
},
// To be folded into body once it is considered one
VariantFields {
@@ -101,7 +101,7 @@ pub(crate) fn new_for_body(
node: InFile<&SyntaxNode>,
offset: Option<TextSize>,
) -> SourceAnalyzer<'db> {
Self::new_for_body_(db, def, node, offset, Some(db.infer(def)))
Self::new_for_body_(db, def, node, offset, Some(InferenceResult::for_body(db, def)))
}
pub(crate) fn new_for_body_no_infer(
@@ -118,7 +118,7 @@ pub(crate) fn new_for_body_(
def: DefWithBodyId,
node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
offset: Option<TextSize>,
infer: Option<Arc<InferenceResult<'db>>>,
infer: Option<&'db InferenceResult<'db>>,
) -> SourceAnalyzer<'db> {
let (body, source_map) = db.body_with_source_map(def);
let scopes = db.expr_scopes(def);
@@ -20,6 +20,7 @@
expr_store::BodySourceMap,
hir::{ExprId, PatId},
};
use hir_ty::InferenceResult;
use ide::{
Analysis, AnalysisHost, AnnotationConfig, DiagnosticsConfig, Edition, InlayFieldsToResolve,
InlayHintsConfig, LineCol, RootDatabase,
@@ -745,7 +746,7 @@ fn run_inference(
.par_iter()
.map_with(db.clone(), |snap, &body| {
snap.body(body.into());
snap.infer(body.into());
InferenceResult::for_body(snap, body.into());
})
.count();
eprintln!("{:<20} {}", "Parallel Inference:", inference_sw.elapsed());
@@ -802,7 +803,8 @@ fn run_inference(
}
bar.set_message(msg);
let body = db.body(body_id.into());
let inference_result = catch_unwind(AssertUnwindSafe(|| db.infer(body_id.into())));
let inference_result =
catch_unwind(AssertUnwindSafe(|| InferenceResult::for_body(db, body_id.into())));
let inference_result = match inference_result {
Ok(inference_result) => inference_result,
Err(p) => {