src/tools/rust-analyzer/crates/hir-ty/src/infer.rs RUST 2,534 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 2,534.
1//! Type inference, i.e. the process of walking through the code and determining2//! the type of each expression and pattern.3//!4//! For type inference, compare the implementations in rustc (the various5//! check_* methods in rustc_hir_analysis/check/mod.rs are a good entry point) and6//! IntelliJ-Rust (org.rust.lang.core.types.infer). Our entry point for7//! inference here is the `infer` function, which infers the types of all8//! expressions in a given function.9//!10//! During inference, types (i.e. the `Ty` struct) can contain type 'variables'11//! which represent currently unknown types; as we walk through the expressions,12//! we might determine that certain variables need to be equal to each other, or13//! to certain types. To record this, we use the union-find implementation from14//! the `ena` crate, which is extracted from rustc.1516mod autoderef;17mod callee;18pub(crate) mod cast;19pub(crate) mod closure;20mod coerce;21pub(crate) mod diagnostics;22mod expr;23mod fallback;24mod mutability;25mod op;26mod opaques;27mod pat;28mod path;29mod place_op;30pub(crate) mod unify;3132use std::{cell::OnceCell, convert::identity, fmt, iter, ops::Deref};3334use base_db::{Crate, FxIndexMap};35use either::Either;36use hir_def::{37    AdtId, AssocItemId, ConstId, ConstParamId, DefWithBodyId, ExpressionStoreOwnerId, FieldId,38    FunctionId, GenericDefId, GenericParamId, ItemContainerId, LocalFieldId, Lookup, TraitId,39    TupleFieldId, TupleId, TypeAliasId, TypeOrConstParamId, VariantId,40    expr_store::{Body, ExpressionStore, HygieneId, RootExprOrigin, path::Path},41    hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},42    lang_item::LangItems,43    layout::Integer,44    resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},45    signatures::{ConstSignature, EnumSignature, FunctionSignature, StaticSignature},46    type_ref::{ConstRef, LifetimeRefId, TypeRef, TypeRefId},47};48use hir_expand::{mod_path::ModPath, name::Name};49use indexmap::IndexSet;50use intern::sym;51use la_arena::ArenaMap;52use rustc_ast_ir::Mutability;53use rustc_hash::{FxHashMap, FxHashSet};54use rustc_type_ir::{55    AliasTyKind, TypeFoldable,56    inherent::{AdtDef, IntoKind, Ty as _},57};58use smallvec::SmallVec;59use span::Edition;60use stdx::never;61use thin_vec::ThinVec;6263use crate::{64    ImplTraitId, IncorrectGenericsLenKind, PathLoweringDiagnostic, TargetFeatures,65    closure_analysis::PlaceBase,66    collect_type_inference_vars,67    db::{HirDatabase, InternedOpaqueTyId},68    infer::{69        callee::DeferredCallResolution,70        closure::analysis::{71            BorrowKind,72            expr_use_visitor::{FakeReadCause, Place},73        },74        coerce::{CoerceMany, DynamicCoerceMany},75        diagnostics::{Diagnostics, InferenceTyLoweringContext as TyLoweringContext},76        expr::ExprIsRead,77    },78    lower::{79        ImplTraitIdx, ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic,80    },81    method_resolution::{CandidateId, MethodResolutionUnstableFeatures},82    next_solver::{83        AliasTy, Const, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs, Region,84        StoredGenericArgs, StoredTy, StoredTys, Ty, TyKind, Tys,85        abi::Safety,86        infer::{InferCtxt, ObligationInspector, traits::ObligationCause},87    },88    utils::TargetFeatureIsSafeInTarget,89};9091// This lint has a false positive here. See the link below for details.92//93// https://github.com/rust-lang/rust/issues/5741194#[allow(unreachable_pub)]95pub use coerce::could_coerce;96#[allow(unreachable_pub)]97pub use unify::{could_unify, could_unify_deeply};9899use cast::{CastCheck, CastError};100101/// The entry point of type inference.102fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult {103    infer_query_with_inspect(db, def, None)104}105106pub fn infer_query_with_inspect<'db>(107    db: &'db dyn HirDatabase,108    def: DefWithBodyId,109    inspect: Option<ObligationInspector<'db>>,110) -> InferenceResult {111    let _p = tracing::info_span!("infer_query").entered();112    let resolver = def.resolver(db);113    let body = Body::of(db, def);114    let mut ctx =115        InferenceContext::new(db, ExpressionStoreOwnerId::Body(def), &body.store, resolver);116117    if let Some(inspect) = inspect {118        ctx.table.infer_ctxt.attach_obligation_inspector(inspect);119    }120121    match def {122        DefWithBodyId::FunctionId(f) => ctx.collect_fn(f, body.self_param, &body.params),123        DefWithBodyId::ConstId(c) => ctx.collect_const(c, ConstSignature::of(db, c)),124        DefWithBodyId::StaticId(s) => ctx.collect_static(StaticSignature::of(db, s)),125        DefWithBodyId::VariantId(v) => {126            ctx.return_ty = match EnumSignature::variant_body_type(db, v.lookup(db).parent) {127                hir_def::layout::IntegerType::Pointer(signed) => match signed {128                    true => ctx.types.types.isize,129                    false => ctx.types.types.usize,130                },131                hir_def::layout::IntegerType::Fixed(size, signed) => match signed {132                    true => match size {133                        Integer::I8 => ctx.types.types.i8,134                        Integer::I16 => ctx.types.types.i16,135                        Integer::I32 => ctx.types.types.i32,136                        Integer::I64 => ctx.types.types.i64,137                        Integer::I128 => ctx.types.types.i128,138                    },139                    false => match size {140                        Integer::I8 => ctx.types.types.u8,141                        Integer::I16 => ctx.types.types.u16,142                        Integer::I32 => ctx.types.types.u32,143                        Integer::I64 => ctx.types.types.u64,144                        Integer::I128 => ctx.types.types.u128,145                    },146                },147            };148        }149    }150151    ctx.infer_body(body.root_expr());152153    ctx.infer_mut_body(body.root_expr());154155    infer_finalize(ctx)156}157158fn infer_cycle_result(db: &dyn HirDatabase, _: salsa::Id, _: DefWithBodyId) -> InferenceResult {159    InferenceResult {160        has_errors: true,161        ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))162    }163}164165/// Infer types for all const expressions in an item's signature.166///167/// This handles const expressions that appear in type positions within a generic168/// item's signature, such as array lengths (`[T; N]`) and const generic arguments169/// (`Foo<{ expr }>`). Each root expression is inferred independently within170/// a shared `InferenceContext`, accumulating results into a single `InferenceResult`.171fn infer_signature_query(db: &dyn HirDatabase, def: GenericDefId) -> InferenceResult {172    let _p = tracing::info_span!("infer_signature_query").entered();173    let store = ExpressionStore::of(db, def.into());174    let mut roots = store.expr_roots_with_origins().peekable();175    let Some(_) = roots.peek() else {176        return InferenceResult::new(crate::next_solver::default_types(db).types.error);177    };178179    let resolver = def.resolver(db);180    let owner = ExpressionStoreOwnerId::Signature(def);181182    let mut ctx = InferenceContext::new(db, owner, store, resolver);183184    for (root_expr, origin) in roots {185        let expected = match origin {186            // Array lengths are always `usize`.187            RootExprOrigin::ArrayLength => Expectation::has_type(ctx.types.types.usize),188            // Const parameter default: look up the param's declared type.189            RootExprOrigin::ConstParam(local_id) => Expectation::has_type(db.const_param_ty_ns(190                ConstParamId::from_unchecked(TypeOrConstParamId { parent: def, local_id }),191            )),192            // Path const generic args: determining the expected type requires193            // path resolution.194            // FIXME195            RootExprOrigin::GenericArgsPath => Expectation::None,196            RootExprOrigin::BodyRoot => Expectation::None,197        };198        ctx.infer_expr(root_expr, &expected, ExprIsRead::Yes);199    }200201    infer_finalize(ctx)202}203204fn infer_variant_fields_query(db: &dyn HirDatabase, def: VariantId) -> InferenceResult {205    let _p = tracing::info_span!("infer_variant_fields_query").entered();206    let store = ExpressionStore::of(db, def.into());207    let mut roots = store.expr_roots_with_origins().peekable();208    let Some(_) = roots.peek() else {209        return InferenceResult::new(crate::next_solver::default_types(db).types.error);210    };211212    let resolver = def.resolver(db);213    let owner = ExpressionStoreOwnerId::VariantFields(def);214215    let mut ctx = InferenceContext::new(db, owner, store, resolver);216217    for (root_expr, origin) in roots {218        let expected = match origin {219            // Array lengths are always `usize`.220            RootExprOrigin::ArrayLength => Expectation::has_type(ctx.types.types.usize),221            // unreachable222            RootExprOrigin::ConstParam(_) => Expectation::None,223            // Path const generic args: determining the expected type requires224            // path resolution.225            // FIXME226            RootExprOrigin::GenericArgsPath => Expectation::None,227            RootExprOrigin::BodyRoot => Expectation::None,228        };229        ctx.infer_expr(root_expr, &expected, ExprIsRead::Yes);230    }231232    infer_finalize(ctx)233}234235fn infer_signature_cycle_result(236    db: &dyn HirDatabase,237    _: salsa::Id,238    _: GenericDefId,239) -> InferenceResult {240    InferenceResult {241        has_errors: true,242        ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))243    }244}245246fn infer_variant_fields_cycle_result(247    db: &dyn HirDatabase,248    _: salsa::Id,249    _: VariantId,250) -> InferenceResult {251    InferenceResult {252        has_errors: true,253        ..InferenceResult::new(Ty::new_error(DbInterner::new_no_crate(db), ErrorGuaranteed))254    }255}256257fn infer_finalize(mut ctx: InferenceContext<'_, '_>) -> InferenceResult {258    ctx.handle_opaque_type_uses();259260    ctx.type_inference_fallback();261262    // Comment from rustc:263    // Even though coercion casts provide type hints, we check casts after fallback for264    // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.265    let cast_checks = std::mem::take(&mut ctx.deferred_cast_checks);266    for mut cast in cast_checks.into_iter() {267        if let Err(diag) = cast.check(&mut ctx) {268            ctx.diagnostics.push(diag);269        }270    }271272    ctx.table.select_obligations_where_possible();273274    // Closure and coroutine analysis may run after fallback275    // because they don't constrain other type variables.276    ctx.closure_analyze();277    assert!(ctx.deferred_call_resolutions.is_empty());278279    ctx.table.select_obligations_where_possible();280281    ctx.handle_opaque_type_uses();282283    ctx.resolve_all()284}285/// Binding modes inferred for patterns.286/// <https://doc.rust-lang.org/reference/patterns.html#binding-modes>287#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]288pub enum BindingMode {289    #[default]290    Move,291    Ref(Mutability),292}293294impl BindingMode {295    fn convert(annotation: BindingAnnotation) -> BindingMode {296        match annotation {297            BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move,298            BindingAnnotation::Ref => BindingMode::Ref(Mutability::Not),299            BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut),300        }301    }302}303304#[derive(Debug, PartialEq, Eq, Clone, Copy)]305pub enum InferenceTyDiagnosticSource {306    /// Diagnostics that come from types in the body.307    Body,308    /// Diagnostics that come from types in fn parameters/return type, or static & const types.309    Signature,310}311312#[derive(Debug, PartialEq, Eq, Clone)]313pub enum InferenceDiagnostic {314    NoSuchField {315        field: ExprOrPatId,316        private: Option<LocalFieldId>,317        variant: VariantId,318    },319    PrivateField {320        expr: ExprId,321        field: FieldId,322    },323    PrivateAssocItem {324        id: ExprOrPatId,325        item: AssocItemId,326    },327    UnresolvedField {328        expr: ExprId,329        receiver: StoredTy,330        name: Name,331        method_with_same_name_exists: bool,332    },333    UnresolvedMethodCall {334        expr: ExprId,335        receiver: StoredTy,336        name: Name,337        /// Contains the type the field resolves to338        field_with_same_name: Option<StoredTy>,339        assoc_func_with_same_name: Option<FunctionId>,340    },341    UnresolvedAssocItem {342        id: ExprOrPatId,343    },344    UnresolvedIdent {345        id: ExprOrPatId,346    },347    // FIXME: This should be emitted in body lowering348    BreakOutsideOfLoop {349        expr: ExprId,350        is_break: bool,351        bad_value_break: bool,352    },353    MismatchedArgCount {354        call_expr: ExprId,355        expected: usize,356        found: usize,357    },358    MismatchedTupleStructPatArgCount {359        pat: ExprOrPatId,360        expected: usize,361        found: usize,362    },363    ExpectedFunction {364        call_expr: ExprId,365        found: StoredTy,366    },367    TypedHole {368        expr: ExprId,369        expected: StoredTy,370    },371    CastToUnsized {372        expr: ExprId,373        cast_ty: StoredTy,374    },375    InvalidCast {376        expr: ExprId,377        error: CastError,378        expr_ty: StoredTy,379        cast_ty: StoredTy,380    },381    TyDiagnostic {382        source: InferenceTyDiagnosticSource,383        diag: TyLoweringDiagnostic,384    },385    PathDiagnostic {386        node: ExprOrPatId,387        diag: PathLoweringDiagnostic,388    },389    MethodCallIncorrectGenericsLen {390        expr: ExprId,391        provided_count: u32,392        expected_count: u32,393        kind: IncorrectGenericsLenKind,394        def: GenericDefId,395    },396    MethodCallIncorrectGenericsOrder {397        expr: ExprId,398        param_id: GenericParamId,399        arg_idx: u32,400        /// Whether the `GenericArgs` contains a `Self` arg.401        has_self_arg: bool,402    },403}404405/// A mismatch between an expected and an inferred type.406#[derive(Clone, PartialEq, Eq, Debug, Hash)]407pub struct TypeMismatch {408    pub expected: StoredTy,409    pub actual: StoredTy,410}411412/// Represents coercing a value to a different type of value.413///414/// We transform values by following a number of `Adjust` steps in order.415/// See the documentation on variants of `Adjust` for more details.416///417/// Here are some common scenarios:418///419/// 1. The simplest cases are where a pointer is not adjusted fat vs thin.420///    Here the pointer will be dereferenced N times (where a dereference can421///    happen to raw or borrowed pointers or any smart pointer which implements422///    Deref, including Box<_>). The types of dereferences is given by423///    `autoderefs`. It can then be auto-referenced zero or one times, indicated424///    by `autoref`, to either a raw or borrowed pointer. In these cases unsize is425///    `false`.426///427/// 2. A thin-to-fat coercion involves unsizing the underlying data. We start428///    with a thin pointer, deref a number of times, unsize the underlying data,429///    then autoref. The 'unsize' phase may change a fixed length array to a430///    dynamically sized one, a concrete object to a trait object, or statically431///    sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is432///    represented by:433///434///    ```ignore435///    Deref(None) -> [i32; 4],436///    Borrow(AutoBorrow::Ref) -> &[i32; 4],437///    Unsize -> &[i32],438///    ```439///440///    Note that for a struct, the 'deep' unsizing of the struct is not recorded.441///    E.g., `struct Foo<T> { it: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>442///    The autoderef and -ref are the same as in the above example, but the type443///    stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about444///    the underlying conversions from `[i32; 4]` to `[i32]`.445///446/// 3. Coercing a `Box<T>` to `Box<dyn Trait>` is an interesting special case. In447///    that case, we have the pointer we need coming in, so there are no448///    autoderefs, and no autoref. Instead we just do the `Unsize` transformation.449///    At some point, of course, `Box` should move out of the compiler, in which450///    case this is analogous to transforming a struct. E.g., Box<[i32; 4]> ->451///    Box<[i32]> is an `Adjust::Unsize` with the target `Box<[i32]>`.452#[derive(Clone, Debug, PartialEq, Eq, Hash)]453pub struct Adjustment {454    pub kind: Adjust,455    pub target: StoredTy,456}457458impl Adjustment {459    pub fn borrow<'db>(460        interner: DbInterner<'db>,461        m: Mutability,462        ty: Ty<'db>,463        lt: Region<'db>,464    ) -> Self {465        let ty = Ty::new_ref(interner, lt, ty, m);466        Adjustment {467            kind: Adjust::Borrow(AutoBorrow::Ref(AutoBorrowMutability::new(m, AllowTwoPhase::No))),468            target: ty.store(),469        }470    }471}472473/// At least for initial deployment, we want to limit two-phase borrows to474/// only a few specific cases. Right now, those are mostly "things that desugar"475/// into method calls:476/// - using `x.some_method()` syntax, where some_method takes `&mut self`,477/// - using `Foo::some_method(&mut x, ...)` syntax,478/// - binary assignment operators (`+=`, `-=`, `*=`, etc.).479///480/// Anything else should be rejected until generalized two-phase borrow support481/// is implemented. Right now, dataflow can't handle the general case where there482/// is more than one use of a mutable borrow, and we don't want to accept too much483/// new code via two-phase borrows, so we try to limit where we create two-phase484/// capable mutable borrows.485/// See #49434 for tracking.486#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]487pub enum AllowTwoPhase {488    // FIXME: We should use this when appropriate.489    Yes,490    No,491}492493#[derive(Clone, Debug, PartialEq, Eq, Hash)]494pub enum Adjust {495    /// Go from ! to any type.496    NeverToAny,497    /// Dereference once, producing a place.498    Deref(Option<OverloadedDeref>),499    /// Take the address and produce either a `&` or `*` pointer.500    Borrow(AutoBorrow),501    Pointer(PointerCast),502}503504/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`505/// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.506/// The target type is `U` in both cases, with the region and mutability507/// being those shared by both the receiver and the returned reference.508#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]509pub struct OverloadedDeref(pub Mutability);510511#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]512pub enum AutoBorrowMutability {513    Mut { allow_two_phase_borrow: AllowTwoPhase },514    Not,515}516517impl AutoBorrowMutability {518    /// Creates an `AutoBorrowMutability` from a mutability and allowance of two phase borrows.519    ///520    /// Note that when `mutbl.is_not()`, `allow_two_phase_borrow` is ignored521    pub fn new(mutbl: Mutability, allow_two_phase_borrow: AllowTwoPhase) -> Self {522        match mutbl {523            Mutability::Not => Self::Not,524            Mutability::Mut => Self::Mut { allow_two_phase_borrow },525        }526    }527}528529impl From<AutoBorrowMutability> for Mutability {530    fn from(m: AutoBorrowMutability) -> Self {531        match m {532            AutoBorrowMutability::Mut { .. } => Mutability::Mut,533            AutoBorrowMutability::Not => Mutability::Not,534        }535    }536}537538#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]539pub enum AutoBorrow {540    /// Converts from T to &T.541    Ref(AutoBorrowMutability),542    /// Converts from T to *T.543    RawPtr(Mutability),544}545546#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]547pub enum PointerCast {548    /// Go from a fn-item type to a fn-pointer type.549    ReifyFnPointer,550551    /// Go from a safe fn pointer to an unsafe fn pointer.552    UnsafeFnPointer,553554    /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.555    /// It cannot convert a closure that requires unsafe.556    ClosureFnPointer(Safety),557558    /// Go from a mut raw pointer to a const raw pointer.559    MutToConstPointer,560561    #[allow(dead_code)]562    /// Go from `*const [T; N]` to `*const T`563    ArrayToPointer,564565    /// Unsize a pointer/reference value, e.g., `&[T; n]` to566    /// `&[T]`. Note that the source could be a thin or fat pointer.567    /// This will do things like convert thin pointers to fat568    /// pointers, or convert structs containing thin pointers to569    /// structs containing fat pointers, or convert between fat570    /// pointers. We don't store the details of how the transform is571    /// done (in fact, we don't know that, because it might depend on572    /// the precise type parameters). We just store the target573    /// type. Codegen backends and miri figure out what has to be done574    /// based on the precise source/target type at hand.575    Unsize,576}577578/// The result of type inference: A mapping from expressions and patterns to types.579///580/// When you add a field that stores types (including `Substitution` and the like), don't forget581/// `resolve_completely()`'ing  them in `InferenceContext::resolve_all()`. Inference variables must582/// not appear in the final inference result.583#[derive(Clone, PartialEq, Eq, Debug)]584pub struct InferenceResult {585    /// For each method call expr, records the function it resolves to.586    method_resolutions: FxHashMap<ExprId, (FunctionId, StoredGenericArgs)>,587    /// For each field access expr, records the field it resolves to.588    field_resolutions: FxHashMap<ExprId, Either<FieldId, TupleFieldId>>,589    /// For each struct literal or pattern, records the variant it resolves to.590    variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,591    /// For each associated item record what it resolves to592    assoc_resolutions: FxHashMap<ExprOrPatId, (CandidateId, StoredGenericArgs)>,593    /// Whenever a tuple field expression access a tuple field, we allocate a tuple id in594    /// [`InferenceContext`] and store the tuples substitution there. This map is the reverse of595    /// that which allows us to resolve a [`TupleFieldId`]s type.596    tuple_field_access_types: ThinVec<StoredTys>,597598    pub(crate) type_of_expr: ArenaMap<ExprId, StoredTy>,599    /// For each pattern record the type it resolves to.600    ///601    /// **Note**: When a pattern type is resolved it may still contain602    /// unresolved or missing subpatterns or subpatterns of mismatched types.603    pub(crate) type_of_pat: ArenaMap<PatId, StoredTy>,604    pub(crate) type_of_binding: ArenaMap<BindingId, StoredTy>,605    pub(crate) type_of_type_placeholder: FxHashMap<TypeRefId, StoredTy>,606    pub(crate) type_of_opaque: FxHashMap<InternedOpaqueTyId, StoredTy>,607608    pub(crate) type_mismatches: Option<Box<FxHashMap<ExprOrPatId, TypeMismatch>>>,609    /// Whether there are any type-mismatching errors in the result.610    // FIXME: This isn't as useful as initially thought due to us falling back placeholders to611    // `TyKind::Error`.612    // Which will then mark this field.613    pub(crate) has_errors: bool,614    /// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.615    diagnostics: ThinVec<InferenceDiagnostic>,616617    /// Interned `Error` type to return references to.618    // FIXME: Remove this.619    error_ty: StoredTy,620621    pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment]>>,622    /// Stores the types which were implicitly dereferenced in pattern binding modes.623    pub(crate) pat_adjustments: FxHashMap<PatId, Vec<StoredTy>>,624    /// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.625    ///626    /// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an627    /// or pattern can have multiple binding modes. For example:628    /// ```629    /// fn foo(mut slice: &[u32]) -> usize {630    ///     slice = match slice {631    ///         [0, rest @ ..] | rest => rest,632    ///     };633    ///     0634    /// }635    /// ```636    /// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`.637    pub(crate) binding_modes: ArenaMap<PatId, BindingMode>,638639    pub(crate) coercion_casts: FxHashSet<ExprId>,640641    pub closures_data: FxHashMap<ExprId, ClosureData>,642}643644#[derive(Clone, PartialEq, Eq, Debug, Default)]645pub struct ClosureData {646    /// Tracks the minimum captures required for a closure;647    /// see `MinCaptureInformationMap` for more details.648    pub min_captures: RootVariableMinCaptureList,649650    /// Tracks the fake reads required for a closure and the reason for the fake read.651    /// When performing pattern matching for closures, there are times we don't end up652    /// reading places that are mentioned in a closure (because of _ patterns). However,653    /// to ensure the places are initialized, we introduce fake reads.654    /// Consider these two examples:655    /// ```ignore (discriminant matching with only wildcard arm)656    /// let x: u8;657    /// let c = || match x { _ => () };658    /// ```659    /// In this example, we don't need to actually read/borrow `x` in `c`, and so we don't660    /// want to capture it. However, we do still want an error here, because `x` should have661    /// to be initialized at the point where c is created. Therefore, we add a "fake read"662    /// instead.663    /// ```ignore (destructured assignments)664    /// let c = || {665    ///     let (t1, t2) = t;666    /// }667    /// ```668    /// In the second example, we capture the disjoint fields of `t` (`t.0` & `t.1`), but669    /// we never capture `t`. This becomes an issue when we build MIR as we require670    /// information on `t` in order to create place `t.0` and `t.1`. We can solve this671    /// issue by fake reading `t`.672    pub fake_reads: Box<[(Place, FakeReadCause, SmallVec<[CaptureSourceStack; 2]>)]>,673}674675/// Part of `MinCaptureInformationMap`; Maps a root variable to the list of `CapturedPlace`.676/// Used to track the minimum set of `Place`s that need to be captured to support all677/// Places captured by the closure starting at a given root variable.678///679/// This provides a convenient and quick way of checking if a variable being used within680/// a closure is a capture of a local variable.681pub(crate) type RootVariableMinCaptureList = FxIndexMap<BindingId, MinCaptureList>;682683/// Part of `MinCaptureInformationMap`; List of `CapturePlace`s.684pub(crate) type MinCaptureList = Vec<CapturedPlace>;685686/// A composite describing a `Place` that is captured by a closure.687#[derive(Eq, PartialEq, Clone, Debug, Hash)]688pub struct CapturedPlace {689    /// The `Place` that is captured.690    pub place: Place,691692    /// `CaptureKind` and expression(s) that resulted in such capture of `place`.693    pub info: CaptureInfo,694695    /// Represents if `place` can be mutated or not.696    pub mutability: Mutability,697}698699impl CapturedPlace {700    pub fn is_by_ref(&self) -> bool {701        match self.info.capture_kind {702            UpvarCapture::ByValue | UpvarCapture::ByUse => false,703            UpvarCapture::ByRef(..) => true,704        }705    }706707    pub fn captured_local(&self) -> BindingId {708        match self.place.base {709            PlaceBase::Upvar { var_id: local, .. } | PlaceBase::Local(local) => local,710            PlaceBase::Rvalue | PlaceBase::StaticItem => {711                unreachable!("only locals can be captured")712            }713        }714    }715716    /// The type of the capture stored in the closure, which is different from the type of the captured place717    /// if we capture by reference.718    pub fn captured_ty<'db>(&self, db: &'db dyn HirDatabase) -> Ty<'db> {719        let place_ty = self.place.ty();720        let make_ref = |mutbl| {721            let interner = DbInterner::new_no_crate(db);722            let region = Region::new_erased(interner);723            Ty::new_ref(interner, region, place_ty, mutbl)724        };725        match self.info.capture_kind {726            UpvarCapture::ByUse | UpvarCapture::ByValue => place_ty,727            UpvarCapture::ByRef(kind) => make_ref(kind.to_mutbl_lossy()),728        }729    }730}731732#[derive(Clone)]733pub struct CaptureSourceStack(CaptureSourceStackRepr);734735#[derive(Clone)]736enum CaptureSourceStackRepr {737    One(ExprOrPatId),738    Two([ExprOrPatId; 2]),739    Many(ThinVec<ExprOrPatId>),740}741742impl PartialEq for CaptureSourceStack {743    fn eq(&self, other: &Self) -> bool {744        **self == **other745    }746}747748impl Eq for CaptureSourceStack {}749750impl std::hash::Hash for CaptureSourceStack {751    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {752        (**self).hash(state);753    }754}755756const _: () = assert!(size_of::<CaptureSourceStack>() == 16);757758impl Deref for CaptureSourceStack {759    type Target = [ExprOrPatId];760761    #[inline]762    fn deref(&self) -> &Self::Target {763        match &self.0 {764            CaptureSourceStackRepr::One(it) => std::slice::from_ref(it),765            CaptureSourceStackRepr::Two(it) => it,766            CaptureSourceStackRepr::Many(it) => it,767        }768    }769}770771impl fmt::Debug for CaptureSourceStack {772    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {773        f.debug_tuple("CaptureSourceStack").field(&&**self).finish()774    }775}776777impl CaptureSourceStack {778    #[inline]779    pub fn len(&self) -> usize {780        match &self.0 {781            CaptureSourceStackRepr::One(_) => 1,782            CaptureSourceStackRepr::Two(_) => 2,783            CaptureSourceStackRepr::Many(it) => it.len(),784        }785    }786787    #[inline]788    pub(crate) fn from_single(id: ExprOrPatId) -> Self {789        Self(CaptureSourceStackRepr::One(id))790    }791792    #[inline]793    pub fn final_source(&self) -> ExprOrPatId {794        *self.last().expect("should always have a final source")795    }796797    pub fn push(&mut self, new_id: ExprOrPatId) {798        match &mut self.0 {799            CaptureSourceStackRepr::One(old_id) => {800                self.0 = CaptureSourceStackRepr::Two([*old_id, new_id])801            }802            CaptureSourceStackRepr::Two([old_id1, old_id2]) => {803                self.0 = CaptureSourceStackRepr::Many(ThinVec::from([*old_id1, *old_id2, new_id]));804            }805            CaptureSourceStackRepr::Many(old_ids) => old_ids.push(new_id),806        }807    }808809    pub fn truncate(&mut self, new_len: usize) {810        debug_assert!(new_len > 0);811        match &mut self.0 {812            CaptureSourceStackRepr::One(_) => {}813            CaptureSourceStackRepr::Two([first, _]) => {814                if new_len == 1 {815                    self.0 = CaptureSourceStackRepr::One(*first)816                }817            }818            CaptureSourceStackRepr::Many(ids) => ids.truncate(new_len),819        }820    }821822    pub fn shrink_to_fit(&mut self) {823        match &mut self.0 {824            CaptureSourceStackRepr::One(_) | CaptureSourceStackRepr::Two(_) => {}825            CaptureSourceStackRepr::Many(ids) => match **ids {826                [one] => self.0 = CaptureSourceStackRepr::One(one),827                [first, second] => self.0 = CaptureSourceStackRepr::Two([first, second]),828                _ => ids.shrink_to_fit(),829            },830        }831    }832}833834/// Part of `MinCaptureInformationMap`; describes the capture kind (&, &mut, move)835/// for a particular capture as well as identifying the part of the source code836/// that triggered this capture to occur.837#[derive(Eq, PartialEq, Clone, Debug, Hash)]838pub struct CaptureInfo {839    pub sources: SmallVec<[CaptureSourceStack; 2]>,840841    /// Capture mode that was selected842    pub capture_kind: UpvarCapture,843}844845/// Information describing the capture of an upvar. This is computed846/// during `typeck`, specifically by `regionck`.847#[derive(Eq, PartialEq, Clone, Debug, Copy, Hash)]848pub enum UpvarCapture {849    /// Upvar is captured by value. This is always true when the850    /// closure is labeled `move`, but can also be true in other cases851    /// depending on inference.852    ByValue,853854    /// Upvar is captured by use. This is true when the closure is labeled `use`.855    ByUse,856857    /// Upvar is captured by reference.858    ByRef(BorrowKind),859}860861#[salsa::tracked]862impl InferenceResult {863    #[salsa::tracked(returns(ref), cycle_result = infer_cycle_result)]864    fn for_body(db: &dyn HirDatabase, def: DefWithBodyId) -> InferenceResult {865        infer_query(db, def)866    }867868    /// Infer types for all const expressions in an item's signature.869    ///870    /// Returns an `InferenceResult` containing type information for array lengths,871    /// const generic arguments, and other const expressions appearing in type872    /// positions within the item's signature.873    #[salsa::tracked(returns(ref), cycle_result = infer_signature_cycle_result)]874    fn for_signature(db: &dyn HirDatabase, def: GenericDefId) -> InferenceResult {875        infer_signature_query(db, def)876    }877878    #[salsa::tracked(returns(ref), cycle_result = infer_variant_fields_cycle_result)]879    fn for_variant_fields(db: &dyn HirDatabase, def: VariantId) -> InferenceResult {880        infer_variant_fields_query(db, def)881    }882}883884impl InferenceResult {885    pub fn of(db: &dyn HirDatabase, def: impl Into<ExpressionStoreOwnerId>) -> &InferenceResult {886        match def.into() {887            ExpressionStoreOwnerId::Signature(generic_def_id) => {888                Self::for_signature(db, generic_def_id)889            }890            ExpressionStoreOwnerId::Body(def_with_body_id) => Self::for_body(db, def_with_body_id),891            ExpressionStoreOwnerId::VariantFields(variant_id) => {892                Self::for_variant_fields(db, variant_id)893            }894        }895    }896897    fn new(error_ty: Ty<'_>) -> Self {898        Self {899            method_resolutions: Default::default(),900            field_resolutions: Default::default(),901            variant_resolutions: Default::default(),902            assoc_resolutions: Default::default(),903            tuple_field_access_types: Default::default(),904            diagnostics: Default::default(),905            type_of_expr: Default::default(),906            type_of_pat: Default::default(),907            type_of_binding: Default::default(),908            type_of_type_placeholder: Default::default(),909            type_of_opaque: Default::default(),910            type_mismatches: Default::default(),911            has_errors: Default::default(),912            error_ty: error_ty.store(),913            pat_adjustments: Default::default(),914            binding_modes: Default::default(),915            expr_adjustments: Default::default(),916            coercion_casts: Default::default(),917            closures_data: Default::default(),918        }919    }920921    pub fn method_resolution<'db>(&self, expr: ExprId) -> Option<(FunctionId, GenericArgs<'db>)> {922        self.method_resolutions.get(&expr).map(|(func, args)| (*func, args.as_ref()))923    }924    pub fn field_resolution(&self, expr: ExprId) -> Option<Either<FieldId, TupleFieldId>> {925        self.field_resolutions.get(&expr).copied()926    }927    pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {928        self.variant_resolutions.get(&id.into()).copied()929    }930    pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantId> {931        self.variant_resolutions.get(&id.into()).copied()932    }933    pub fn variant_resolution_for_expr_or_pat(&self, id: ExprOrPatId) -> Option<VariantId> {934        match id {935            ExprOrPatId::ExprId(id) => self.variant_resolution_for_expr(id),936            ExprOrPatId::PatId(id) => self.variant_resolution_for_pat(id),937        }938    }939    pub fn assoc_resolutions_for_expr<'db>(940        &self,941        id: ExprId,942    ) -> Option<(CandidateId, GenericArgs<'db>)> {943        self.assoc_resolutions.get(&id.into()).map(|(assoc, args)| (*assoc, args.as_ref()))944    }945    pub fn assoc_resolutions_for_pat<'db>(946        &self,947        id: PatId,948    ) -> Option<(CandidateId, GenericArgs<'db>)> {949        self.assoc_resolutions.get(&id.into()).map(|(assoc, args)| (*assoc, args.as_ref()))950    }951    pub fn assoc_resolutions_for_expr_or_pat<'db>(952        &self,953        id: ExprOrPatId,954    ) -> Option<(CandidateId, GenericArgs<'db>)> {955        match id {956            ExprOrPatId::ExprId(id) => self.assoc_resolutions_for_expr(id),957            ExprOrPatId::PatId(id) => self.assoc_resolutions_for_pat(id),958        }959    }960    pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {961        self.type_mismatches.as_deref()?.get(&expr.into())962    }963    pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch> {964        self.type_mismatches.as_deref()?.get(&pat.into())965    }966    pub fn type_mismatches(&self) -> impl Iterator<Item = (ExprOrPatId, &TypeMismatch)> {967        self.type_mismatches968            .as_deref()969            .into_iter()970            .flatten()971            .map(|(expr_or_pat, mismatch)| (*expr_or_pat, mismatch))972    }973    pub fn expr_type_mismatches(&self) -> impl Iterator<Item = (ExprId, &TypeMismatch)> {974        self.type_mismatches.as_deref().into_iter().flatten().filter_map(975            |(expr_or_pat, mismatch)| match *expr_or_pat {976                ExprOrPatId::ExprId(expr) => Some((expr, mismatch)),977                _ => None,978            },979        )980    }981    pub fn placeholder_types<'db>(&self) -> impl Iterator<Item = (TypeRefId, Ty<'db>)> {982        self.type_of_type_placeholder.iter().map(|(&type_ref, ty)| (type_ref, ty.as_ref()))983    }984    pub fn type_of_type_placeholder<'db>(&self, type_ref: TypeRefId) -> Option<Ty<'db>> {985        self.type_of_type_placeholder.get(&type_ref).map(|ty| ty.as_ref())986    }987    pub fn type_of_expr_or_pat<'db>(&self, id: ExprOrPatId) -> Option<Ty<'db>> {988        match id {989            ExprOrPatId::ExprId(id) => self.type_of_expr.get(id).map(|it| it.as_ref()),990            ExprOrPatId::PatId(id) => self.type_of_pat.get(id).map(|it| it.as_ref()),991        }992    }993    pub fn type_of_expr_with_adjust<'db>(&self, id: ExprId) -> Option<Ty<'db>> {994        match self.expr_adjustments.get(&id).and_then(|adjustments| {995            adjustments.iter().rfind(|adj| {996                // https://github.com/rust-lang/rust/blob/67819923ac8ea353aaa775303f4c3aacbf41d010/compiler/rustc_mir_build/src/thir/cx/expr.rs#L140997                !matches!(998                    adj,999                    Adjustment {1000                        kind: Adjust::NeverToAny,1001                        target,1002                    } if target.as_ref().is_never()1003                )1004            })1005        }) {1006            Some(adjustment) => Some(adjustment.target.as_ref()),1007            None => self.type_of_expr.get(id).map(|it| it.as_ref()),1008        }1009    }1010    pub fn type_of_pat_with_adjust<'db>(&self, id: PatId) -> Option<Ty<'db>> {1011        match self.pat_adjustments.get(&id).and_then(|adjustments| adjustments.last()) {1012            Some(adjusted) => Some(adjusted.as_ref()),1013            None => self.type_of_pat.get(id).map(|it| it.as_ref()),1014        }1015    }1016    pub fn is_erroneous(&self) -> bool {1017        self.has_errors && self.type_of_expr.iter().count() == 01018    }10191020    pub fn diagnostics(&self) -> &[InferenceDiagnostic] {1021        &self.diagnostics1022    }10231024    pub fn tuple_field_access_type<'db>(&self, id: TupleId) -> Tys<'db> {1025        self.tuple_field_access_types[id.0 as usize].as_ref()1026    }10271028    pub fn pat_adjustment(&self, id: PatId) -> Option<&[StoredTy]> {1029        self.pat_adjustments.get(&id).map(|it| &**it)1030    }10311032    pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment]> {1033        self.expr_adjustments.get(&id).map(|it| &**it)1034    }10351036    pub fn binding_mode(&self, id: PatId) -> Option<BindingMode> {1037        self.binding_modes.get(id).copied()1038    }10391040    // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1041    pub fn expression_types<'db>(&self) -> impl Iterator<Item = (ExprId, Ty<'db>)> {1042        self.type_of_expr.iter().map(|(k, v)| (k, v.as_ref()))1043    }10441045    // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1046    pub fn pattern_types<'db>(&self) -> impl Iterator<Item = (PatId, Ty<'db>)> {1047        self.type_of_pat.iter().map(|(k, v)| (k, v.as_ref()))1048    }10491050    // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1051    pub fn binding_types<'db>(&self) -> impl Iterator<Item = (BindingId, Ty<'db>)> {1052        self.type_of_binding.iter().map(|(k, v)| (k, v.as_ref()))1053    }10541055    // This method is consumed by external tools to run rust-analyzer as a library. Don't remove, please.1056    pub fn return_position_impl_trait_types<'db>(1057        &'db self,1058        db: &'db dyn HirDatabase,1059    ) -> impl Iterator<Item = (ImplTraitIdx, Ty<'db>)> {1060        self.type_of_opaque.iter().filter_map(move |(&id, ty)| {1061            let ImplTraitId::ReturnTypeImplTrait(_, rpit_idx) = id.loc(db) else {1062                return None;1063            };1064            Some((rpit_idx, ty.as_ref()))1065        })1066    }10671068    pub fn expr_ty<'db>(&self, id: ExprId) -> Ty<'db> {1069        self.type_of_expr.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())1070    }10711072    pub fn pat_ty<'db>(&self, id: PatId) -> Ty<'db> {1073        self.type_of_pat.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())1074    }10751076    pub fn expr_or_pat_ty<'db>(&self, id: ExprOrPatId) -> Ty<'db> {1077        self.type_of_expr_or_pat(id).unwrap_or(self.error_ty.as_ref())1078    }10791080    pub fn binding_ty<'db>(&self, id: BindingId) -> Ty<'db> {1081        self.type_of_binding.get(id).map_or(self.error_ty.as_ref(), |it| it.as_ref())1082    }10831084    /// This does not deduplicate, which means you'll get the types once per capture.1085    pub fn closure_captures_tys<'db>(&self, closure: ExprId) -> impl Iterator<Item = Ty<'db>> {1086        self.closures_data[&closure]1087            .min_captures1088            .values()1089            .flat_map(|captures| captures.iter().map(|capture| capture.place.ty()))1090    }10911092    /// Like [`Self::closure_captures_tys()`], but using [`CapturedPlace::captured_ty()`].1093    pub fn closure_captures_captured_tys<'db>(1094        &self,1095        db: &'db dyn HirDatabase,1096        closure: ExprId,1097    ) -> impl Iterator<Item = Ty<'db>> {1098        self.closures_data[&closure]1099            .min_captures1100            .values()1101            .flat_map(|captures| captures.iter().map(|capture| capture.captured_ty(db)))1102    }1103}11041105/// The inference context contains all information needed during type inference.1106#[derive(Clone, Debug)]1107pub(crate) struct InferenceContext<'body, 'db> {1108    pub(crate) db: &'db dyn HirDatabase,1109    pub(crate) owner: ExpressionStoreOwnerId,1110    pub(crate) store: &'body ExpressionStore,1111    /// Generally you should not resolve things via this resolver. Instead create a TyLoweringContext1112    /// and resolve the path via its methods. This will ensure proper error reporting.1113    pub(crate) resolver: Resolver<'db>,1114    target_features: OnceCell<(TargetFeatures<'db>, TargetFeatureIsSafeInTarget)>,1115    pub(crate) unstable_features: MethodResolutionUnstableFeatures,1116    pub(crate) edition: Edition,1117    pub(crate) generic_def: GenericDefId,1118    pub(crate) table: unify::InferenceTable<'db>,1119    pub(crate) lang_items: &'db LangItems,1120    /// The traits in scope, disregarding block modules. This is used for caching purposes.1121    traits_in_scope: FxHashSet<TraitId>,1122    pub(crate) result: InferenceResult,1123    tuple_field_accesses_rev:1124        IndexSet<Tys<'db>, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>,1125    /// The return type of the function being inferred, the closure or async block if we're1126    /// currently within one.1127    ///1128    /// We might consider using a nested inference context for checking1129    /// closures so we can swap all shared things out at once.1130    return_ty: Ty<'db>,1131    /// If `Some`, this stores coercion information for returned1132    /// expressions. If `None`, this is in a context where return is1133    /// inappropriate, such as a const expression.1134    return_coercion: Option<DynamicCoerceMany<'db>>,1135    /// The resume type and the yield type, respectively, of the coroutine being inferred.1136    resume_yield_tys: Option<(Ty<'db>, Ty<'db>)>,1137    diverges: Diverges,1138    breakables: Vec<BreakableContext<'db>>,1139    types: &'db crate::next_solver::DefaultAny<'db>,11401141    /// Whether we are inside the pattern of a destructuring assignment.1142    inside_assignment: bool,11431144    deferred_cast_checks: Vec<CastCheck<'db>>,11451146    /// The key is an expression defining a closure or a coroutine closure.1147    deferred_call_resolutions: FxHashMap<ExprId, Vec<DeferredCallResolution<'db>>>,11481149    diagnostics: Diagnostics,1150}11511152#[derive(Clone, Debug)]1153struct BreakableContext<'db> {1154    /// Whether this context contains at least one break expression.1155    may_break: bool,1156    /// The coercion target of the context.1157    coerce: Option<DynamicCoerceMany<'db>>,1158    /// The optional label of the context.1159    label: Option<LabelId>,1160    kind: BreakableKind,1161}11621163#[derive(Clone, Debug)]1164enum BreakableKind {1165    Block,1166    Loop,1167    /// A border is something like an async block, closure etc. Anything that prevents1168    /// breaking/continuing through1169    Border,1170}11711172fn find_breakable<'a, 'db>(1173    ctxs: &'a mut [BreakableContext<'db>],1174    label: Option<LabelId>,1175) -> Option<&'a mut BreakableContext<'db>> {1176    let mut ctxs = ctxs1177        .iter_mut()1178        .rev()1179        .take_while(|it| matches!(it.kind, BreakableKind::Block | BreakableKind::Loop));1180    match label {1181        Some(_) => ctxs.find(|ctx| ctx.label == label),1182        None => ctxs.find(|ctx| matches!(ctx.kind, BreakableKind::Loop)),1183    }1184}11851186fn find_continuable<'a, 'db>(1187    ctxs: &'a mut [BreakableContext<'db>],1188    label: Option<LabelId>,1189) -> Option<&'a mut BreakableContext<'db>> {1190    match label {1191        Some(_) => find_breakable(ctxs, label).filter(|it| matches!(it.kind, BreakableKind::Loop)),1192        None => find_breakable(ctxs, label),1193    }1194}11951196impl<'body, 'db> InferenceContext<'body, 'db> {1197    fn new(1198        db: &'db dyn HirDatabase,1199        owner: ExpressionStoreOwnerId,1200        store: &'body ExpressionStore,1201        resolver: Resolver<'db>,1202    ) -> Self {1203        let trait_env = match owner {1204            ExpressionStoreOwnerId::Signature(generic_def_id) => {1205                db.trait_environment(ExpressionStoreOwnerId::from(generic_def_id))1206            }1207            ExpressionStoreOwnerId::Body(def_with_body_id) => {1208                db.trait_environment(ExpressionStoreOwnerId::Body(def_with_body_id))1209            }1210            ExpressionStoreOwnerId::VariantFields(variant_id) => {1211                db.trait_environment(ExpressionStoreOwnerId::VariantFields(variant_id))1212            }1213        };1214        let table = unify::InferenceTable::new(db, trait_env, resolver.krate(), Some(owner));1215        let types = crate::next_solver::default_types(db);1216        InferenceContext {1217            result: InferenceResult::new(types.types.error),1218            return_ty: types.types.error, // set in collect_* calls1219            types,1220            target_features: OnceCell::new(),1221            unstable_features: MethodResolutionUnstableFeatures::from_def_map(1222                resolver.top_level_def_map(),1223            ),1224            lang_items: table.interner().lang_items(),1225            edition: resolver.krate().data(db).edition,1226            table,1227            tuple_field_accesses_rev: Default::default(),1228            resume_yield_tys: None,1229            return_coercion: None,1230            db,1231            owner,1232            generic_def: owner.generic_def(db),1233            store,1234            traits_in_scope: resolver.traits_in_scope(db),1235            resolver,1236            diverges: Diverges::Maybe,1237            breakables: Vec::new(),1238            deferred_cast_checks: Vec::new(),1239            inside_assignment: false,1240            diagnostics: Diagnostics::default(),1241            deferred_call_resolutions: FxHashMap::default(),1242        }1243    }12441245    #[inline]1246    fn krate(&self) -> Crate {1247        self.resolver.krate()1248    }12491250    fn target_features(&self) -> (&TargetFeatures<'db>, TargetFeatureIsSafeInTarget) {1251        let (target_features, target_feature_is_safe) = self.target_features.get_or_init(|| {1252            let target_features = match self.owner {1253                ExpressionStoreOwnerId::Body(DefWithBodyId::FunctionId(id)) => {1254                    TargetFeatures::from_fn(self.db, id)1255                }1256                _ => TargetFeatures::default(),1257            };1258            let target_feature_is_safe = match &self.krate().workspace_data(self.db).target {1259                Ok(target) => crate::utils::target_feature_is_safe_in_target(target),1260                Err(_) => TargetFeatureIsSafeInTarget::No,1261            };1262            (target_features, target_feature_is_safe)1263        });1264        (target_features, *target_feature_is_safe)1265    }12661267    #[inline]1268    fn set_tainted_by_errors(&mut self) {1269        self.result.has_errors = true;1270    }12711272    /// Clones `self` and calls `resolve_all()` on it.1273    // FIXME: Remove this.1274    pub(crate) fn fixme_resolve_all_clone(&self) -> InferenceResult {1275        let mut ctx = self.clone();12761277        ctx.type_inference_fallback();12781279        // Comment from rustc:1280        // Even though coercion casts provide type hints, we check casts after fallback for1281        // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.1282        let cast_checks = std::mem::take(&mut ctx.deferred_cast_checks);1283        for mut cast in cast_checks.into_iter() {1284            if let Err(diag) = cast.check(&mut ctx) {1285                ctx.diagnostics.push(diag);1286            }1287        }12881289        ctx.table.select_obligations_where_possible();12901291        ctx.resolve_all()1292    }12931294    // FIXME: This function should be private in module. It is currently only used in the consteval, since we need1295    // `InferenceResult` in the middle of inference. See the fixme comment in `consteval::eval_to_const`. If you1296    // used this function for another workaround, mention it here. If you really need this function and believe that1297    // there is no problem in it being `pub(crate)`, remove this comment.1298    fn resolve_all(self) -> InferenceResult {1299        let InferenceContext {1300            mut table,1301            mut result,1302            tuple_field_accesses_rev,1303            diagnostics,1304            types,1305            ..1306        } = self;1307        let mut diagnostics = diagnostics.finish();1308        // Destructure every single field so whenever new fields are added to `InferenceResult` we1309        // don't forget to handle them here.1310        let InferenceResult {1311            method_resolutions,1312            field_resolutions: _,1313            variant_resolutions: _,1314            assoc_resolutions,1315            type_of_expr,1316            type_of_pat,1317            type_of_binding,1318            type_of_type_placeholder,1319            type_of_opaque,1320            type_mismatches,1321            closures_data,1322            has_errors,1323            error_ty: _,1324            pat_adjustments,1325            binding_modes: _,1326            expr_adjustments,1327            tuple_field_access_types: _,1328            coercion_casts: _,1329            diagnostics: _,1330        } = &mut result;13311332        for ty in type_of_expr.values_mut() {1333            *ty = table.resolve_completely(ty.as_ref()).store();1334            *has_errors = *has_errors || ty.as_ref().references_non_lt_error();1335        }1336        type_of_expr.shrink_to_fit();1337        for ty in type_of_pat.values_mut() {1338            *ty = table.resolve_completely(ty.as_ref()).store();1339            *has_errors = *has_errors || ty.as_ref().references_non_lt_error();1340        }1341        type_of_pat.shrink_to_fit();1342        for ty in type_of_binding.values_mut() {1343            *ty = table.resolve_completely(ty.as_ref()).store();1344            *has_errors = *has_errors || ty.as_ref().references_non_lt_error();1345        }1346        type_of_binding.shrink_to_fit();1347        for ty in type_of_type_placeholder.values_mut() {1348            *ty = table.resolve_completely(ty.as_ref()).store();1349            *has_errors = *has_errors || ty.as_ref().references_non_lt_error();1350        }1351        type_of_type_placeholder.shrink_to_fit();1352        type_of_opaque.shrink_to_fit();13531354        if let Some(type_mismatches) = type_mismatches {1355            *has_errors = true;1356            for mismatch in type_mismatches.values_mut() {1357                mismatch.expected = table.resolve_completely(mismatch.expected.as_ref()).store();1358                mismatch.actual = table.resolve_completely(mismatch.actual.as_ref()).store();1359            }1360            type_mismatches.shrink_to_fit();1361        }1362        diagnostics.retain_mut(|diagnostic| {1363            use InferenceDiagnostic::*;1364            match diagnostic {1365                ExpectedFunction { found: ty, .. }1366                | UnresolvedField { receiver: ty, .. }1367                | UnresolvedMethodCall { receiver: ty, .. } => {1368                    *ty = table.resolve_completely(ty.as_ref()).store();1369                    // FIXME: Remove this when we are on par with rustc in terms of inference1370                    if ty.as_ref().references_non_lt_error() {1371                        return false;1372                    }13731374                    if let UnresolvedMethodCall { field_with_same_name, .. } = diagnostic1375                        && let Some(ty) = field_with_same_name1376                    {1377                        *ty = table.resolve_completely(ty.as_ref()).store();1378                        if ty.as_ref().references_non_lt_error() {1379                            *field_with_same_name = None;1380                        }1381                    }1382                }1383                TypedHole { expected: ty, .. } => {1384                    *ty = table.resolve_completely(ty.as_ref()).store();1385                }1386                _ => (),1387            }1388            true1389        });1390        diagnostics.shrink_to_fit();1391        for (_, subst) in method_resolutions.values_mut() {1392            *subst = table.resolve_completely(subst.as_ref()).store();1393            *has_errors =1394                *has_errors || subst.as_ref().types().any(|ty| ty.references_non_lt_error());1395        }1396        method_resolutions.shrink_to_fit();1397        for (_, subst) in assoc_resolutions.values_mut() {1398            *subst = table.resolve_completely(subst.as_ref()).store();1399            *has_errors =1400                *has_errors || subst.as_ref().types().any(|ty| ty.references_non_lt_error());1401        }1402        assoc_resolutions.shrink_to_fit();1403        for adjustment in expr_adjustments.values_mut().flatten() {1404            adjustment.target = table.resolve_completely(adjustment.target.as_ref()).store();1405            *has_errors = *has_errors || adjustment.target.as_ref().references_non_lt_error();1406        }1407        expr_adjustments.shrink_to_fit();1408        for adjustment in pat_adjustments.values_mut().flatten() {1409            *adjustment = table.resolve_completely(adjustment.as_ref()).store();1410            *has_errors = *has_errors || adjustment.as_ref().references_non_lt_error();1411        }1412        pat_adjustments.shrink_to_fit();1413        for closure_data in closures_data.values_mut() {1414            let ClosureData { min_captures, fake_reads } = closure_data;1415            let dummy_place = || Place {1416                base_ty: types.types.error.store(),1417                base: closure::analysis::expr_use_visitor::PlaceBase::Rvalue,1418                projections: Vec::new(),1419            };14201421            for (place, _, sources) in fake_reads {1422                *place = table.resolve_completely(std::mem::replace(place, dummy_place()));1423                place.projections.shrink_to_fit();1424                for source in &mut *sources {1425                    source.shrink_to_fit();1426                }1427                sources.shrink_to_fit();1428            }14291430            for min_capture in min_captures.values_mut() {1431                for captured in &mut *min_capture {1432                    let CapturedPlace { place, info, mutability: _ } = captured;1433                    *place = table.resolve_completely(std::mem::replace(place, dummy_place()));1434                    let CaptureInfo { sources, capture_kind: _ } = info;1435                    for source in &mut *sources {1436                        source.shrink_to_fit();1437                    }1438                    sources.shrink_to_fit();1439                }1440                min_capture.shrink_to_fit();1441            }1442            min_captures.shrink_to_fit();1443        }1444        closures_data.shrink_to_fit();1445        result.tuple_field_access_types = tuple_field_accesses_rev1446            .into_iter()1447            .map(|subst| table.resolve_completely(subst).store())1448            .inspect(|subst| {1449                *has_errors =1450                    *has_errors || subst.as_ref().iter().any(|ty| ty.references_non_lt_error());1451            })1452            .collect();1453        result.tuple_field_access_types.shrink_to_fit();14541455        result.diagnostics = diagnostics;14561457        result1458    }14591460    fn collect_const(&mut self, id: ConstId, data: &ConstSignature) {1461        let return_ty = self.make_ty(1462            data.type_ref,1463            &data.store,1464            InferenceTyDiagnosticSource::Signature,1465            LifetimeElisionKind::for_const(self.interner(), id.loc(self.db).container),1466        );14671468        self.return_ty = return_ty;1469    }14701471    fn collect_static(&mut self, data: &StaticSignature) {1472        let return_ty = self.make_ty(1473            data.type_ref,1474            &data.store,1475            InferenceTyDiagnosticSource::Signature,1476            LifetimeElisionKind::Elided(self.types.regions.statik),1477        );14781479        self.return_ty = return_ty;1480    }14811482    fn collect_fn(&mut self, func: FunctionId, self_param: Option<BindingId>, params: &[PatId]) {1483        let data = FunctionSignature::of(self.db, func);1484        let mut param_tys = self.with_ty_lowering(1485            &data.store,1486            InferenceTyDiagnosticSource::Signature,1487            LifetimeElisionKind::for_fn_params(data),1488            |ctx| data.params.iter().map(|&type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>(),1489        );14901491        // Check if function contains a va_list, if it does then we append it to the parameter types1492        // that are collected from the function data1493        if data.is_varargs() {1494            let va_list_ty = match self.resolve_va_list() {1495                Some(va_list) => Ty::new_adt(1496                    self.interner(),1497                    va_list,1498                    GenericArgs::for_item_with_defaults(1499                        self.interner(),1500                        va_list.into(),1501                        |_, id, _| self.table.next_var_for_param(id),1502                    ),1503                ),1504                None => self.err_ty(),1505            };15061507            param_tys.push(va_list_ty);1508        }1509        let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.next_ty_var()));1510        if let Some(self_param) = self_param1511            && let Some(ty) = param_tys.next()1512        {1513            let ty = self.process_user_written_ty(ty);1514            self.write_binding_ty(self_param, ty);1515        }1516        for (ty, pat) in param_tys.zip(params) {1517            let ty = self.process_user_written_ty(ty);15181519            self.infer_top_pat(*pat, ty, None);1520        }1521        self.return_ty = match data.ret_type {1522            Some(return_ty) => {1523                let return_ty = self.with_ty_lowering(1524                    &data.store,1525                    InferenceTyDiagnosticSource::Signature,1526                    LifetimeElisionKind::for_fn_ret(self.interner()),1527                    |ctx| {1528                        ctx.impl_trait_mode(ImplTraitLoweringMode::Opaque);1529                        ctx.lower_ty(return_ty)1530                    },1531                );1532                self.process_user_written_ty(return_ty)1533            }1534            None => self.types.types.unit,1535        };15361537        self.return_coercion = Some(CoerceMany::new(self.return_ty));1538    }15391540    #[inline]1541    pub(crate) fn interner(&self) -> DbInterner<'db> {1542        self.table.interner()1543    }15441545    #[inline]1546    pub(crate) fn infcx(&self) -> &InferCtxt<'db> {1547        &self.table.infer_ctxt1548    }15491550    fn infer_body(&mut self, body_expr: ExprId) {1551        match self.return_coercion {1552            Some(_) => self.infer_return(body_expr),1553            None => {1554                _ = self.infer_expr_coerce(1555                    body_expr,1556                    &Expectation::has_type(self.return_ty),1557                    ExprIsRead::Yes,1558                )1559            }1560        }1561    }15621563    fn write_expr_ty(&mut self, expr: ExprId, ty: Ty<'db>) {1564        self.result.type_of_expr.insert(expr, ty.store());1565    }15661567    pub(crate) fn write_expr_adj(&mut self, expr: ExprId, adjustments: Box<[Adjustment]>) {1568        if adjustments.is_empty() {1569            return;1570        }1571        match self.result.expr_adjustments.entry(expr) {1572            std::collections::hash_map::Entry::Occupied(mut entry) => {1573                match (&mut entry.get_mut()[..], &adjustments[..]) {1574                    (1575                        [Adjustment { kind: Adjust::NeverToAny, target }],1576                        [.., Adjustment { target: new_target, .. }],1577                    ) => {1578                        // NeverToAny coercion can target any type, so instead of adding a new1579                        // adjustment on top we can change the target.1580                        *target = new_target.clone();1581                    }1582                    _ => {1583                        *entry.get_mut() = adjustments;1584                    }1585                }1586            }1587            std::collections::hash_map::Entry::Vacant(entry) => {1588                entry.insert(adjustments);1589            }1590        }1591    }15921593    fn write_pat_adj(&mut self, pat: PatId, adjustments: Box<[StoredTy]>) {1594        if adjustments.is_empty() {1595            return;1596        }1597        self.result.pat_adjustments.entry(pat).or_default().extend(adjustments);1598    }15991600    pub(crate) fn write_method_resolution(1601        &mut self,1602        expr: ExprId,1603        func: FunctionId,1604        subst: GenericArgs<'db>,1605    ) {1606        self.result.method_resolutions.insert(expr, (func, subst.store()));1607    }16081609    fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantId) {1610        self.result.variant_resolutions.insert(id, variant);1611    }16121613    fn write_assoc_resolution(1614        &mut self,1615        id: ExprOrPatId,1616        item: CandidateId,1617        subs: GenericArgs<'db>,1618    ) {1619        self.result.assoc_resolutions.insert(id, (item, subs.store()));1620    }16211622    fn write_pat_ty(&mut self, pat: PatId, ty: Ty<'db>) {1623        self.result.type_of_pat.insert(pat, ty.store());1624    }16251626    fn write_type_placeholder_ty(&mut self, type_ref: TypeRefId, ty: Ty<'db>) {1627        self.result.type_of_type_placeholder.insert(type_ref, ty.store());1628    }16291630    fn write_binding_ty(&mut self, id: BindingId, ty: Ty<'db>) {1631        self.result.type_of_binding.insert(id, ty.store());1632    }16331634    pub(crate) fn push_diagnostic(&self, diagnostic: InferenceDiagnostic) {1635        self.diagnostics.push(diagnostic);1636    }16371638    fn record_deferred_call_resolution(1639        &mut self,1640        closure_def_id: ExprId,1641        r: DeferredCallResolution<'db>,1642    ) {1643        self.deferred_call_resolutions.entry(closure_def_id).or_default().push(r);1644    }16451646    fn remove_deferred_call_resolutions(1647        &mut self,1648        closure_def_id: ExprId,1649    ) -> Vec<DeferredCallResolution<'db>> {1650        self.deferred_call_resolutions.remove(&closure_def_id).unwrap_or_default()1651    }16521653    fn with_ty_lowering<R>(1654        &mut self,1655        store: &ExpressionStore,1656        types_source: InferenceTyDiagnosticSource,1657        lifetime_elision: LifetimeElisionKind<'db>,1658        f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R,1659    ) -> R {1660        let mut ctx = TyLoweringContext::new(1661            self.db,1662            &self.resolver,1663            store,1664            &self.diagnostics,1665            types_source,1666            self.generic_def,1667            lifetime_elision,1668        );1669        f(&mut ctx)1670    }16711672    fn with_body_ty_lowering<R>(1673        &mut self,1674        f: impl FnOnce(&mut TyLoweringContext<'db, '_>) -> R,1675    ) -> R {1676        self.with_ty_lowering(1677            self.store,1678            InferenceTyDiagnosticSource::Body,1679            LifetimeElisionKind::Infer,1680            f,1681        )1682    }16831684    fn make_ty(1685        &mut self,1686        type_ref: TypeRefId,1687        store: &ExpressionStore,1688        type_source: InferenceTyDiagnosticSource,1689        lifetime_elision: LifetimeElisionKind<'db>,1690    ) -> Ty<'db> {1691        let ty = self1692            .with_ty_lowering(store, type_source, lifetime_elision, |ctx| ctx.lower_ty(type_ref));1693        let ty = self.process_user_written_ty(ty);16941695        // Record the association from placeholders' TypeRefId to type variables.1696        // We only record them if their number matches. This assumes TypeRef::walk and TypeVisitable process the items in the same order.1697        let type_variables = collect_type_inference_vars(&ty);1698        let mut placeholder_ids = vec![];1699        TypeRef::walk(type_ref, store, &mut |type_ref_id, type_ref| {1700            if matches!(type_ref, TypeRef::Placeholder) {1701                placeholder_ids.push(type_ref_id);1702            }1703        });17041705        if placeholder_ids.len() == type_variables.len() {1706            for (placeholder_id, type_variable) in placeholder_ids.into_iter().zip(type_variables) {1707                self.write_type_placeholder_ty(placeholder_id, type_variable);1708            }1709        }17101711        ty1712    }17131714    pub(crate) fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty<'db> {1715        self.make_ty(1716            type_ref,1717            self.store,1718            InferenceTyDiagnosticSource::Body,1719            LifetimeElisionKind::Infer,1720        )1721    }17221723    pub(crate) fn make_body_const(&mut self, const_ref: ConstRef, ty: Ty<'db>) -> Const<'db> {1724        let const_ = self.with_ty_lowering(1725            self.store,1726            InferenceTyDiagnosticSource::Body,1727            LifetimeElisionKind::Infer,1728            |ctx| ctx.lower_const(const_ref, ty),1729        );1730        self.insert_type_vars(const_)1731    }17321733    pub(crate) fn make_path_as_body_const(&mut self, path: &Path, ty: Ty<'db>) -> Const<'db> {1734        let const_ = self.with_ty_lowering(1735            self.store,1736            InferenceTyDiagnosticSource::Body,1737            LifetimeElisionKind::Infer,1738            |ctx| ctx.lower_path_as_const(path, ty),1739        );1740        self.insert_type_vars(const_)1741    }17421743    fn err_ty(&self) -> Ty<'db> {1744        self.types.types.error1745    }17461747    pub(crate) fn make_body_lifetime(&mut self, lifetime_ref: LifetimeRefId) -> Region<'db> {1748        let lt = self.with_ty_lowering(1749            self.store,1750            InferenceTyDiagnosticSource::Body,1751            LifetimeElisionKind::Infer,1752            |ctx| ctx.lower_lifetime(lifetime_ref),1753        );1754        self.insert_type_vars(lt)1755    }17561757    /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.1758    fn insert_type_vars_shallow(&mut self, ty: Ty<'db>) -> Ty<'db> {1759        self.table.insert_type_vars_shallow(ty)1760    }17611762    fn insert_type_vars<T>(&mut self, ty: T) -> T1763    where1764        T: TypeFoldable<DbInterner<'db>>,1765    {1766        self.table.insert_type_vars(ty)1767    }17681769    fn unify(&mut self, ty1: Ty<'db>, ty2: Ty<'db>) -> bool {1770        self.table.unify(ty1, ty2)1771    }17721773    /// Attempts to returns the deeply last field of nested structures, but1774    /// does not apply any normalization in its search. Returns the same type1775    /// if input `ty` is not a structure at all.1776    fn struct_tail_without_normalization(&mut self, ty: Ty<'db>) -> Ty<'db> {1777        self.struct_tail_with_normalize(ty, identity)1778    }17791780    /// Returns the deeply last field of nested structures, or the same type if1781    /// not a structure at all. Corresponds to the only possible unsized field,1782    /// and its type can be used to determine unsizing strategy.1783    ///1784    /// This is parameterized over the normalization strategy (i.e. how to1785    /// handle `<T as Trait>::Assoc` and `impl Trait`); pass the identity1786    /// function to indicate no normalization should take place.1787    fn struct_tail_with_normalize(1788        &mut self,1789        mut ty: Ty<'db>,1790        mut normalize: impl FnMut(Ty<'db>) -> Ty<'db>,1791    ) -> Ty<'db> {1792        // FIXME: fetch the limit properly1793        let recursion_limit = 10;1794        for iteration in 0.. {1795            if iteration > recursion_limit {1796                return self.err_ty();1797            }1798            match ty.kind() {1799                TyKind::Adt(adt_def, substs) => match adt_def.def_id().0 {1800                    AdtId::StructId(struct_id) => {1801                        match self1802                            .db1803                            .field_types(struct_id.into())1804                            .values()1805                            .next_back()1806                            .map(|it| it.get())1807                        {1808                            Some(field) => {1809                                ty = field.instantiate(self.interner(), substs);1810                            }1811                            None => break,1812                        }1813                    }1814                    _ => break,1815                },1816                TyKind::Tuple(substs) => match substs.as_slice().split_last() {1817                    Some((last_ty, _)) => ty = *last_ty,1818                    None => break,1819                },1820                TyKind::Alias(..) => {1821                    let normalized = normalize(ty);1822                    if ty == normalized {1823                        return ty;1824                    } else {1825                        ty = normalized;1826                    }1827                }1828                _ => break,1829            }1830        }1831        ty1832    }18331834    /// Whenever you lower a user-written type, you should call this.1835    fn process_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {1836        self.table.process_user_written_ty(ty)1837    }18381839    /// The difference of this method from `process_user_written_ty()` is that this method doesn't register a well-formed obligation,1840    /// while `process_user_written_ty()` should (but doesn't currently).1841    fn process_remote_user_written_ty(&mut self, ty: Ty<'db>) -> Ty<'db> {1842        self.table.process_remote_user_written_ty(ty)1843    }18441845    fn shallow_resolve(&self, ty: Ty<'db>) -> Ty<'db> {1846        self.table.shallow_resolve(ty)1847    }18481849    fn resolve_associated_type(1850        &mut self,1851        inner_ty: Ty<'db>,1852        assoc_ty: Option<TypeAliasId>,1853    ) -> Ty<'db> {1854        self.resolve_associated_type_with_params(inner_ty, assoc_ty, &[])1855    }18561857    fn demand_eqtype(1858        &mut self,1859        id: ExprOrPatId,1860        expected: Ty<'db>,1861        actual: Ty<'db>,1862    ) -> Result<(), ()> {1863        let result = self.demand_eqtype_fixme_no_diag(expected, actual);1864        if result.is_err() {1865            self.result1866                .type_mismatches1867                .get_or_insert_default()1868                .insert(id, TypeMismatch { expected: expected.store(), actual: actual.store() });1869        }1870        result1871    }18721873    fn demand_eqtype_fixme_no_diag(1874        &mut self,1875        expected: Ty<'db>,1876        actual: Ty<'db>,1877    ) -> Result<(), ()> {1878        let result = self1879            .table1880            .at(&ObligationCause::new())1881            .eq(expected, actual)1882            .map(|infer_ok| self.table.register_infer_ok(infer_ok));1883        result.map_err(drop)1884    }18851886    fn demand_suptype(&mut self, expected: Ty<'db>, actual: Ty<'db>) {1887        let result = self1888            .table1889            .at(&ObligationCause::new())1890            .sup(expected, actual)1891            .map(|infer_ok| self.table.register_infer_ok(infer_ok));1892        if let Err(_err) = result {1893            // FIXME: Emit diagnostic.1894        }1895    }18961897    fn demand_coerce(1898        &mut self,1899        expr: ExprId,1900        checked_ty: Ty<'db>,1901        expected: Ty<'db>,1902        allow_two_phase: AllowTwoPhase,1903        expr_is_read: ExprIsRead,1904    ) -> Ty<'db> {1905        let result = self.coerce(expr.into(), checked_ty, expected, allow_two_phase, expr_is_read);1906        if let Err(_err) = result {1907            // FIXME: Emit diagnostic.1908        }1909        result.unwrap_or(self.types.types.error)1910    }19111912    pub(crate) fn type_must_be_known_at_this_point(1913        &self,1914        _id: ExprOrPatId,1915        _ty: Ty<'db>,1916    ) -> Ty<'db> {1917        // FIXME: Emit an diagnostic.1918        self.types.types.error1919    }19201921    pub(crate) fn require_type_is_sized(&mut self, ty: Ty<'db>) {1922        if !ty.references_non_lt_error()1923            && let Some(sized_trait) = self.lang_items.Sized1924        {1925            self.table.register_bound(ty, sized_trait, ObligationCause::new());1926        }1927    }19281929    fn expr_ty(&self, expr: ExprId) -> Ty<'db> {1930        self.result.expr_ty(expr)1931    }19321933    fn expr_ty_after_adjustments(&self, e: ExprId) -> Ty<'db> {1934        let mut ty = None;1935        if let Some(it) = self.result.expr_adjustments.get(&e)1936            && let Some(it) = it.last()1937        {1938            ty = Some(it.target.as_ref());1939        }1940        ty.unwrap_or_else(|| self.expr_ty(e))1941    }19421943    fn resolve_associated_type_with_params(1944        &mut self,1945        inner_ty: Ty<'db>,1946        assoc_ty: Option<TypeAliasId>,1947        // FIXME(GATs): these are args for the trait ref, args for assoc type itself should be1948        // handled when we support them.1949        params: &[GenericArg<'db>],1950    ) -> Ty<'db> {1951        match assoc_ty {1952            Some(res_assoc_ty) => {1953                let alias = Ty::new_alias(1954                    self.interner(),1955                    AliasTy::new(1956                        self.interner(),1957                        AliasTyKind::Projection { def_id: res_assoc_ty.into() },1958                        iter::once(inner_ty.into()).chain(params.iter().copied()),1959                    ),1960                );1961                self.table.try_structurally_resolve_type(alias)1962            }1963            None => self.err_ty(),1964        }1965    }19661967    fn resolve_variant(1968        &mut self,1969        node: ExprOrPatId,1970        path: Option<&Path>,1971        value_ns: bool,1972    ) -> (Ty<'db>, Option<VariantId>) {1973        let path = match path {1974            Some(path) => path,1975            None => return (self.err_ty(), None),1976        };1977        let mut ctx = TyLoweringContext::new(1978            self.db,1979            &self.resolver,1980            self.store,1981            &self.diagnostics,1982            InferenceTyDiagnosticSource::Body,1983            self.generic_def,1984            LifetimeElisionKind::Infer,1985        );19861987        if let Some(type_anchor) = path.type_anchor() {1988            let mut segments = path.segments();1989            if segments.is_empty() {1990                return (self.err_ty(), None);1991            }1992            let (mut ty, type_ns) = ctx.lower_ty_ext(type_anchor);1993            ty = self.table.process_user_written_ty(ty);19941995            if let Some(TypeNs::SelfType(impl_)) = type_ns1996                && let Some(trait_ref) = self.db.impl_trait(impl_)1997                && let trait_ref = trait_ref.instantiate_identity()1998                && let Some(assoc_type) = trait_ref1999                    .def_id2000                    .0

Code quality findings 34

Critical: Use of 'unsafe' keyword bypasses Rust's safety guarantees. Requires careful auditing, clear justification (FFI, specific optimizations), and minimal scope.
error safety unsafe-block
/// Go from a safe fn pointer to an unsafe fn pointer.
Critical: Use of 'unsafe' keyword bypasses Rust's safety guarantees. Requires careful auditing, clear justification (FFI, specific optimizations), and minimal scope.
error safety unsafe-block
/// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// Go from `*const [T; N]` to `*const T`
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// that which allows us to resolve a [`TupleFieldId`]s type.
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.
Warning: '.expect()' will panic with a custom message on None/Err. While better than unwrap() for debugging, prefer non-panicking error handling in production code (match, if let, ?).
warning correctness expect-usage
*self.last().expect("should always have a final source")
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
self.tuple_field_access_types[id.0 as usize].as_ref()
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
self.closures_data[&closure]
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
/// Like [`Self::closure_captures_tys()`], but using [`CapturedPlace::captured_ty()`].
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
self.closures_data[&closure]
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
ctxs: &'a mut [BreakableContext<'db>],
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
ctxs: &'a mut [BreakableContext<'db>],
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
match (&mut entry.get_mut()[..], &adjustments[..]) {
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
.associated_type_by_name(segments.first().unwrap().name)
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
let remaining = unresolved.map(|it| path.segments()[it..].len()).filter(|it| it > &0);
Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
let segment = path.segments().last().unwrap();
Info: Usage of `#[allow(...)]` suppresses compiler lints. Ensure the allowance is justified, well-scoped, and ideally temporary. Overuse can hide potential issues.
info maintainability allow-lint
#[allow(unreachable_pub)]
Info: Usage of `#[allow(...)]` suppresses compiler lints. Ensure the allowance is justified, well-scoped, and ideally temporary. Overuse can hide potential issues.
info maintainability allow-lint
#[allow(unreachable_pub)]
Performance Info: Calling .push() repeatedly inside a loop without prior capacity reservation can lead to multiple reallocations. Consider using `Vec::with_capacity(n)` or `vec.reserve(n)` if the approximate number of elements is known.
info performance push-without-reserve
ctx.diagnostics.push(diag);
Info: Usage of `#[allow(...)]` suppresses compiler lints. Ensure the allowance is justified, well-scoped, and ideally temporary. Overuse can hide potential issues.
info maintainability allow-lint
#[allow(dead_code)]
Info: Use of raw pointers (*const T, *mut T) typically requires 'unsafe' blocks for dereferencing. Ensure usage is justified (FFI, low-level optimizations) and memory safety is manually upheld.
info safety raw-pointer
/// Go from `*const [T; N]` to `*const T`
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match &mut self.0 {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
CaptureSourceStackRepr::Many(ids) => match **ids {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
|(expr_or_pat, mismatch)| match *expr_or_pat {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
let target_features = match self.owner {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
let target_feature_is_safe = match &self.krate().workspace_data(self.db).target {
Performance Info: Frequent cloning, especially of Strings, Vecs, or other heap-allocated types inside loops, can be expensive. Consider using references/borrowing where possible.
info performance clone-in-loop
let mut ctx = self.clone();
Performance Info: Calling .push() repeatedly inside a loop without prior capacity reservation can lead to multiple reallocations. Consider using `Vec::with_capacity(n)` or `vec.reserve(n)` if the approximate number of elements is known.
info performance push-without-reserve
ctx.diagnostics.push(diag);
Info: Wildcard imports (`use some::path::*;`) can obscure the origin of names and lead to conflicts. Prefer importing specific items explicitly.
info maintainability wildcard-import
use InferenceDiagnostic::*;
Performance Info: Calling .push() repeatedly inside a loop without prior capacity reservation can lead to multiple reallocations. Consider using `Vec::with_capacity(n)` or `vec.reserve(n)` if the approximate number of elements is known.
info performance push-without-reserve
param_tys.push(va_list_ty);
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match (&mut entry.get_mut()[..], &adjustments[..]) {
Performance Info: Calling .push() repeatedly inside a loop without prior capacity reservation can lead to multiple reallocations. Consider using `Vec::with_capacity(n)` or `vec.reserve(n)` if the approximate number of elements is known.
info performance push-without-reserve
placeholder_ids.push(type_ref_id);
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match ctx.struct_tail_without_normalization(ty).kind() {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match *self {

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.