//! Type inference, i.e. the process of walking through the code and determining
//! the type of each expression and pattern.
//!
//! For type inference, compare the implementations in rustc (the various
//! check_* methods in rustc_hir_analysis/check/mod.rs are a good entry point) and
//! IntelliJ-Rust (org.rust.lang.core.types.infer). Our entry point for
//! inference here is the `infer` function, which infers the types of all
//! expressions in a given function.
//!
//! During inference, types (i.e. the `Ty` struct) can contain type 'variables'
//! which represent currently unknown types; as we walk through the expressions,
//! we might determine that certain variables need to be equal to each other, or
//! to certain types. To record this, we use the union-find implementation from
//! the `ena` crate, which is extracted from rustc.

pub(crate) mod cast;
pub(crate) mod closure;
mod coerce;
pub(crate) mod diagnostics;
mod expr;
mod mutability;
mod pat;
mod path;
pub(crate) mod unify;

use std::{cell::OnceCell, convert::identity, iter, ops::Index};

use chalk_ir::{
    DebruijnIndex, Mutability, Safety, Scalar, TyKind, TypeFlags, Variance,
    cast::Cast,
    fold::TypeFoldable,
    interner::HasInterner,
    visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor},
};
use either::Either;
use hir_def::{
    AdtId, AssocItemId, ConstId, DefWithBodyId, FieldId, FunctionId, GenericDefId, GenericParamId,
    ImplId, ItemContainerId, LocalFieldId, Lookup, TraitId, TupleFieldId, TupleId, TypeAliasId,
    VariantId,
    builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
    expr_store::{Body, ExpressionStore, HygieneId, path::Path},
    hir::{BindingAnnotation, BindingId, ExprId, ExprOrPatId, LabelId, PatId},
    lang_item::{LangItem, LangItemTarget, lang_item},
    layout::Integer,
    resolver::{HasResolver, ResolveValueResult, Resolver, TypeNs, ValueNs},
    signatures::{ConstSignature, StaticSignature},
    type_ref::{ConstRef, LifetimeRefId, TypeRefId},
};
use hir_expand::{mod_path::ModPath, name::Name};
use indexmap::IndexSet;
use intern::sym;
use la_arena::{ArenaMap, Entry};
use rustc_hash::{FxHashMap, FxHashSet};
use stdx::{always, never};
use triomphe::Arc;

use crate::{
    AliasEq, AliasTy, Binders, ClosureId, Const, DomainGoal, GenericArg, ImplTraitId, ImplTraitIdx,
    IncorrectGenericsLenKind, Interner, Lifetime, OpaqueTyId, ParamLoweringMode,
    PathLoweringDiagnostic, ProjectionTy, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt,
    db::HirDatabase,
    fold_tys,
    generics::Generics,
    infer::{
        coerce::CoerceMany,
        diagnostics::{Diagnostics, InferenceTyLoweringContext as TyLoweringContext},
        expr::ExprIsRead,
        unify::InferenceTable,
    },
    lower::{ImplTraitLoweringMode, LifetimeElisionKind, diagnostics::TyLoweringDiagnostic},
    mir::MirSpan,
    next_solver::{self, mapping::ChalkToNextSolver},
    static_lifetime, to_assoc_type_id,
    traits::FnTrait,
    utils::UnevaluatedConstEvaluatorFolder,
};

// This lint has a false positive here. See the link below for details.
//
// https://github.com/rust-lang/rust/issues/57411
#[allow(unreachable_pub)]
pub use coerce::could_coerce;
#[allow(unreachable_pub)]
pub use unify::{could_unify, could_unify_deeply};

use cast::{CastCheck, CastError};
pub(crate) use closure::{CaptureKind, CapturedItem, CapturedItemWithoutTy};

/// The entry point of type inference.
pub(crate) fn infer_query(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
    let _p = tracing::info_span!("infer_query").entered();
    let resolver = def.resolver(db);
    let body = db.body(def);
    let mut ctx = InferenceContext::new(db, def, &body, resolver);

    match def {
        DefWithBodyId::FunctionId(f) => {
            ctx.collect_fn(f);
        }
        DefWithBodyId::ConstId(c) => ctx.collect_const(c, &db.const_signature(c)),
        DefWithBodyId::StaticId(s) => ctx.collect_static(&db.static_signature(s)),
        DefWithBodyId::VariantId(v) => {
            ctx.return_ty = TyBuilder::builtin(
                match db.enum_signature(v.lookup(db).parent).variant_body_type() {
                    hir_def::layout::IntegerType::Pointer(signed) => match signed {
                        true => BuiltinType::Int(BuiltinInt::Isize),
                        false => BuiltinType::Uint(BuiltinUint::Usize),
                    },
                    hir_def::layout::IntegerType::Fixed(size, signed) => match signed {
                        true => BuiltinType::Int(match size {
                            Integer::I8 => BuiltinInt::I8,
                            Integer::I16 => BuiltinInt::I16,
                            Integer::I32 => BuiltinInt::I32,
                            Integer::I64 => BuiltinInt::I64,
                            Integer::I128 => BuiltinInt::I128,
                        }),
                        false => BuiltinType::Uint(match size {
                            Integer::I8 => BuiltinUint::U8,
                            Integer::I16 => BuiltinUint::U16,
                            Integer::I32 => BuiltinUint::U32,
                            Integer::I64 => BuiltinUint::U64,
                            Integer::I128 => BuiltinUint::U128,
                        }),
                    },
                },
            );
        }
    }

    ctx.infer_body();

    ctx.infer_mut_body();

    ctx.infer_closures();

    Arc::new(ctx.resolve_all())
}

pub(crate) fn infer_cycle_result(_: &dyn HirDatabase, _: DefWithBodyId) -> Arc<InferenceResult> {
    Arc::new(InferenceResult { has_errors: true, ..Default::default() })
}

/// Fully normalize all the types found within `ty` in context of `owner` body definition.
///
/// This is appropriate to use only after type-check: it assumes
/// that normalization will succeed, for example.
#[tracing::instrument(level = "debug", skip(db))]
pub(crate) fn normalize(db: &dyn HirDatabase, trait_env: Arc<TraitEnvironment>, ty: Ty) -> Ty {
    // FIXME: TypeFlags::HAS_CT_PROJECTION is not implemented in chalk, so TypeFlags::HAS_PROJECTION only
    // works for the type case, so we check array unconditionally. Remove the array part
    // when the bug in chalk becomes fixed.
    if !ty.data(Interner).flags.intersects(TypeFlags::HAS_PROJECTION)
        && !matches!(ty.kind(Interner), TyKind::Array(..))
    {
        return ty;
    }
    let mut table = unify::InferenceTable::new(db, trait_env);

    let ty_with_vars = table.normalize_associated_types_in(ty);
    table.resolve_obligations_as_possible();
    table.propagate_diverging_flag();
    table.resolve_completely(ty_with_vars)
}

/// Binding modes inferred for patterns.
/// <https://doc.rust-lang.org/reference/patterns.html#binding-modes>
#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)]
pub enum BindingMode {
    #[default]
    Move,
    Ref(Mutability),
}

impl BindingMode {
    fn convert(annotation: BindingAnnotation) -> BindingMode {
        match annotation {
            BindingAnnotation::Unannotated | BindingAnnotation::Mutable => BindingMode::Move,
            BindingAnnotation::Ref => BindingMode::Ref(Mutability::Not),
            BindingAnnotation::RefMut => BindingMode::Ref(Mutability::Mut),
        }
    }
}

#[derive(Debug)]
pub(crate) struct InferOk<'db, T> {
    value: T,
    goals: Vec<next_solver::Goal<'db, next_solver::Predicate<'db>>>,
}

impl<'db, T> InferOk<'db, T> {
    fn map<U>(self, f: impl FnOnce(T) -> U) -> InferOk<'db, U> {
        InferOk { value: f(self.value), goals: self.goals }
    }
}

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum InferenceTyDiagnosticSource {
    /// Diagnostics that come from types in the body.
    Body,
    /// Diagnostics that come from types in fn parameters/return type, or static & const types.
    Signature,
}

#[derive(Debug)]
pub(crate) struct TypeError;
pub(crate) type InferResult<'db, T> = Result<InferOk<'db, T>, TypeError>;

#[derive(Debug, PartialEq, Eq, Clone)]
pub enum InferenceDiagnostic {
    NoSuchField {
        field: ExprOrPatId,
        private: Option<LocalFieldId>,
        variant: VariantId,
    },
    PrivateField {
        expr: ExprId,
        field: FieldId,
    },
    PrivateAssocItem {
        id: ExprOrPatId,
        item: AssocItemId,
    },
    UnresolvedField {
        expr: ExprId,
        receiver: Ty,
        name: Name,
        method_with_same_name_exists: bool,
    },
    UnresolvedMethodCall {
        expr: ExprId,
        receiver: Ty,
        name: Name,
        /// Contains the type the field resolves to
        field_with_same_name: Option<Ty>,
        assoc_func_with_same_name: Option<FunctionId>,
    },
    UnresolvedAssocItem {
        id: ExprOrPatId,
    },
    UnresolvedIdent {
        id: ExprOrPatId,
    },
    // FIXME: This should be emitted in body lowering
    BreakOutsideOfLoop {
        expr: ExprId,
        is_break: bool,
        bad_value_break: bool,
    },
    MismatchedArgCount {
        call_expr: ExprId,
        expected: usize,
        found: usize,
    },
    MismatchedTupleStructPatArgCount {
        pat: ExprOrPatId,
        expected: usize,
        found: usize,
    },
    ExpectedFunction {
        call_expr: ExprId,
        found: Ty,
    },
    TypedHole {
        expr: ExprId,
        expected: Ty,
    },
    CastToUnsized {
        expr: ExprId,
        cast_ty: Ty,
    },
    InvalidCast {
        expr: ExprId,
        error: CastError,
        expr_ty: Ty,
        cast_ty: Ty,
    },
    TyDiagnostic {
        source: InferenceTyDiagnosticSource,
        diag: TyLoweringDiagnostic,
    },
    PathDiagnostic {
        node: ExprOrPatId,
        diag: PathLoweringDiagnostic,
    },
    MethodCallIncorrectGenericsLen {
        expr: ExprId,
        provided_count: u32,
        expected_count: u32,
        kind: IncorrectGenericsLenKind,
        def: GenericDefId,
    },
    MethodCallIncorrectGenericsOrder {
        expr: ExprId,
        param_id: GenericParamId,
        arg_idx: u32,
        /// Whether the `GenericArgs` contains a `Self` arg.
        has_self_arg: bool,
    },
}

/// A mismatch between an expected and an inferred type.
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct TypeMismatch {
    pub expected: Ty,
    pub actual: Ty,
}

#[derive(Clone, PartialEq, Eq, Debug)]
struct InternedStandardTypes {
    unknown: Ty,
    bool_: Ty,
    unit: Ty,
    never: Ty,
}

impl Default for InternedStandardTypes {
    fn default() -> Self {
        InternedStandardTypes {
            unknown: TyKind::Error.intern(Interner),
            bool_: TyKind::Scalar(Scalar::Bool).intern(Interner),
            unit: TyKind::Tuple(0, Substitution::empty(Interner)).intern(Interner),
            never: TyKind::Never.intern(Interner),
        }
    }
}
/// Represents coercing a value to a different type of value.
///
/// We transform values by following a number of `Adjust` steps in order.
/// See the documentation on variants of `Adjust` for more details.
///
/// Here are some common scenarios:
///
/// 1. The simplest cases are where a pointer is not adjusted fat vs thin.
///    Here the pointer will be dereferenced N times (where a dereference can
///    happen to raw or borrowed pointers or any smart pointer which implements
///    Deref, including Box<_>). The types of dereferences is given by
///    `autoderefs`. It can then be auto-referenced zero or one times, indicated
///    by `autoref`, to either a raw or borrowed pointer. In these cases unsize is
///    `false`.
///
/// 2. A thin-to-fat coercion involves unsizing the underlying data. We start
///    with a thin pointer, deref a number of times, unsize the underlying data,
///    then autoref. The 'unsize' phase may change a fixed length array to a
///    dynamically sized one, a concrete object to a trait object, or statically
///    sized struct to a dynamically sized one. E.g., &[i32; 4] -> &[i32] is
///    represented by:
///
///    ```ignore
///    Deref(None) -> [i32; 4],
///    Borrow(AutoBorrow::Ref) -> &[i32; 4],
///    Unsize -> &[i32],
///    ```
///
///    Note that for a struct, the 'deep' unsizing of the struct is not recorded.
///    E.g., `struct Foo<T> { it: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]>
///    The autoderef and -ref are the same as in the above example, but the type
///    stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about
///    the underlying conversions from `[i32; 4]` to `[i32]`.
///
/// 3. Coercing a `Box<T>` to `Box<dyn Trait>` is an interesting special case. In
///    that case, we have the pointer we need coming in, so there are no
///    autoderefs, and no autoref. Instead we just do the `Unsize` transformation.
///    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)]
pub struct Adjustment {
    pub kind: Adjust,
    pub target: Ty,
}

impl Adjustment {
    pub fn borrow(m: Mutability, ty: Ty, lt: Lifetime) -> Self {
        let ty = TyKind::Ref(m, lt.clone(), ty).intern(Interner);
        Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(lt, m)), target: ty }
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Adjust {
    /// Go from ! to any type.
    NeverToAny,
    /// Dereference once, producing a place.
    Deref(Option<OverloadedDeref>),
    /// Take the address and produce either a `&` or `*` pointer.
    Borrow(AutoBorrow),
    Pointer(PointerCast),
}

/// An overloaded autoderef step, representing a `Deref(Mut)::deref(_mut)`
/// call, with the signature `&'a T -> &'a U` or `&'a mut T -> &'a mut U`.
/// The target type is `U` in both cases, with the region and mutability
/// being those shared by both the receiver and the returned reference.
///
/// Mutability is `None` when we are not sure.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct OverloadedDeref(pub Option<Mutability>);

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum AutoBorrow {
    /// Converts from T to &T.
    Ref(Lifetime, Mutability),
    /// Converts from T to *T.
    RawPtr(Mutability),
}

impl AutoBorrow {
    fn mutability(&self) -> Mutability {
        let (AutoBorrow::Ref(_, m) | AutoBorrow::RawPtr(m)) = self;
        *m
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum PointerCast {
    /// Go from a fn-item type to a fn-pointer type.
    ReifyFnPointer,

    /// Go from a safe fn pointer to an unsafe fn pointer.
    UnsafeFnPointer,

    /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
    /// It cannot convert a closure that requires unsafe.
    ClosureFnPointer(Safety),

    /// Go from a mut raw pointer to a const raw pointer.
    MutToConstPointer,

    #[allow(dead_code)]
    /// Go from `*const [T; N]` to `*const T`
    ArrayToPointer,

    /// Unsize a pointer/reference value, e.g., `&[T; n]` to
    /// `&[T]`. Note that the source could be a thin or fat pointer.
    /// This will do things like convert thin pointers to fat
    /// pointers, or convert structs containing thin pointers to
    /// structs containing fat pointers, or convert between fat
    /// pointers. We don't store the details of how the transform is
    /// done (in fact, we don't know that, because it might depend on
    /// the precise type parameters). We just store the target
    /// type. Codegen backends and miri figure out what has to be done
    /// based on the precise source/target type at hand.
    Unsize,
}

/// The result of type inference: A mapping from expressions and patterns to types.
///
/// 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, Default)]
pub struct InferenceResult {
    /// For each method call expr, records the function it resolves to.
    method_resolutions: FxHashMap<ExprId, (FunctionId, Substitution)>,
    /// For each field access expr, records the field it resolves to.
    field_resolutions: FxHashMap<ExprId, Either<FieldId, TupleFieldId>>,
    /// For each struct literal or pattern, records the variant it resolves to.
    variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,
    /// For each associated item record what it resolves to
    assoc_resolutions: FxHashMap<ExprOrPatId, (AssocItemId, Substitution)>,
    /// 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, Substitution>,
    /// During inference this field is empty and [`InferenceContext::diagnostics`] is filled instead.
    diagnostics: Vec<InferenceDiagnostic>,
    pub(crate) type_of_expr: ArenaMap<ExprId, Ty>,
    /// 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.
    pub(crate) type_of_pat: ArenaMap<PatId, Ty>,
    pub(crate) type_of_binding: ArenaMap<BindingId, Ty>,
    pub(crate) type_of_rpit: ArenaMap<ImplTraitIdx, Ty>,
    type_mismatches: FxHashMap<ExprOrPatId, TypeMismatch>,
    /// Whether there are any type-mismatching errors in the result.
    // FIXME: This isn't as useful as initially thought due to us falling back placeholders to
    // `TyKind::Error`.
    // Which will then mark this field.
    pub(crate) has_errors: bool,
    /// Interned common types to return references to.
    // FIXME: Move this into `InferenceContext`
    standard_types: InternedStandardTypes,
    /// Stores the types which were implicitly dereferenced in pattern binding modes.
    pub(crate) pat_adjustments: FxHashMap<PatId, Vec<Ty>>,
    /// Stores the binding mode (`ref` in `let ref x = 2`) of bindings.
    ///
    /// This one is tied to the `PatId` instead of `BindingId`, because in some rare cases, a binding in an
    /// or pattern can have multiple binding modes. For example:
    /// ```
    /// fn foo(mut slice: &[u32]) -> usize {
    ///     slice = match slice {
    ///         [0, rest @ ..] | rest => rest,
    ///     };
    ///     0
    /// }
    /// ```
    /// the first `rest` has implicit `ref` binding mode, but the second `rest` binding mode is `move`.
    pub(crate) binding_modes: ArenaMap<PatId, BindingMode>,
    pub(crate) expr_adjustments: FxHashMap<ExprId, Box<[Adjustment]>>,
    pub(crate) closure_info: FxHashMap<ClosureId, (Vec<CapturedItem>, FnTrait)>,
    // FIXME: remove this field
    pub mutated_bindings_in_closure: FxHashSet<BindingId>,
    pub(crate) coercion_casts: FxHashSet<ExprId>,
}

impl InferenceResult {
    pub fn method_resolution(&self, expr: ExprId) -> Option<(FunctionId, Substitution)> {
        self.method_resolutions.get(&expr).cloned()
    }
    pub fn field_resolution(&self, expr: ExprId) -> Option<Either<FieldId, TupleFieldId>> {
        self.field_resolutions.get(&expr).copied()
    }
    pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {
        self.variant_resolutions.get(&id.into()).copied()
    }
    pub fn variant_resolution_for_pat(&self, id: PatId) -> Option<VariantId> {
        self.variant_resolutions.get(&id.into()).copied()
    }
    pub fn variant_resolution_for_expr_or_pat(&self, id: ExprOrPatId) -> Option<VariantId> {
        match id {
            ExprOrPatId::ExprId(id) => self.variant_resolution_for_expr(id),
            ExprOrPatId::PatId(id) => self.variant_resolution_for_pat(id),
        }
    }
    pub fn assoc_resolutions_for_expr(&self, id: ExprId) -> Option<(AssocItemId, Substitution)> {
        self.assoc_resolutions.get(&id.into()).cloned()
    }
    pub fn assoc_resolutions_for_pat(&self, id: PatId) -> Option<(AssocItemId, Substitution)> {
        self.assoc_resolutions.get(&id.into()).cloned()
    }
    pub fn assoc_resolutions_for_expr_or_pat(
        &self,
        id: ExprOrPatId,
    ) -> Option<(AssocItemId, Substitution)> {
        match id {
            ExprOrPatId::ExprId(id) => self.assoc_resolutions_for_expr(id),
            ExprOrPatId::PatId(id) => self.assoc_resolutions_for_pat(id),
        }
    }
    pub fn type_mismatch_for_expr(&self, expr: ExprId) -> Option<&TypeMismatch> {
        self.type_mismatches.get(&expr.into())
    }
    pub fn type_mismatch_for_pat(&self, pat: PatId) -> Option<&TypeMismatch> {
        self.type_mismatches.get(&pat.into())
    }
    pub fn type_mismatches(&self) -> impl Iterator<Item = (ExprOrPatId, &TypeMismatch)> {
        self.type_mismatches.iter().map(|(expr_or_pat, mismatch)| (*expr_or_pat, mismatch))
    }
    pub fn expr_type_mismatches(&self) -> impl Iterator<Item = (ExprId, &TypeMismatch)> {
        self.type_mismatches.iter().filter_map(|(expr_or_pat, mismatch)| match *expr_or_pat {
            ExprOrPatId::ExprId(expr) => Some((expr, mismatch)),
            _ => None,
        })
    }
    pub fn closure_info(&self, closure: &ClosureId) -> &(Vec<CapturedItem>, FnTrait) {
        self.closure_info.get(closure).unwrap()
    }
    pub fn type_of_expr_or_pat(&self, id: ExprOrPatId) -> Option<&Ty> {
        match id {
            ExprOrPatId::ExprId(id) => self.type_of_expr.get(id),
            ExprOrPatId::PatId(id) => self.type_of_pat.get(id),
        }
    }
    pub fn type_of_expr_with_adjust(&self, id: ExprId) -> Option<&Ty> {
        match self.expr_adjustments.get(&id).and_then(|adjustments| {
            adjustments
                .iter()
                .filter(|adj| {
                    // https://github.com/rust-lang/rust/blob/67819923ac8ea353aaa775303f4c3aacbf41d010/compiler/rustc_mir_build/src/thir/cx/expr.rs#L140
                    !matches!(
                        adj,
                        Adjustment {
                            kind: Adjust::NeverToAny,
                            target,
                        } if target.is_never()
                    )
                })
                .next_back()
        }) {
            Some(adjustment) => Some(&adjustment.target),
            None => self.type_of_expr.get(id),
        }
    }
    pub fn type_of_pat_with_adjust(&self, id: PatId) -> Option<&Ty> {
        match self.pat_adjustments.get(&id).and_then(|adjustments| adjustments.last()) {
            adjusted @ Some(_) => adjusted,
            None => self.type_of_pat.get(id),
        }
    }
    pub fn is_erroneous(&self) -> bool {
        self.has_errors && self.type_of_expr.iter().count() == 0
    }

    pub fn diagnostics(&self) -> &[InferenceDiagnostic] {
        &self.diagnostics
    }

    pub fn tuple_field_access_type(&self, id: TupleId) -> &Substitution {
        &self.tuple_field_access_types[&id]
    }

    pub fn pat_adjustment(&self, id: PatId) -> Option<&[Ty]> {
        self.pat_adjustments.get(&id).map(|it| &**it)
    }

    pub fn expr_adjustment(&self, id: ExprId) -> Option<&[Adjustment]> {
        self.expr_adjustments.get(&id).map(|it| &**it)
    }

    pub fn binding_mode(&self, id: PatId) -> Option<BindingMode> {
        self.binding_modes.get(id).copied()
    }
}

impl Index<ExprId> for InferenceResult {
    type Output = Ty;

    fn index(&self, expr: ExprId) -> &Ty {
        self.type_of_expr.get(expr).unwrap_or(&self.standard_types.unknown)
    }
}

impl Index<PatId> for InferenceResult {
    type Output = Ty;

    fn index(&self, pat: PatId) -> &Ty {
        self.type_of_pat.get(pat).unwrap_or(&self.standard_types.unknown)
    }
}

impl Index<ExprOrPatId> for InferenceResult {
    type Output = Ty;

    fn index(&self, id: ExprOrPatId) -> &Ty {
        self.type_of_expr_or_pat(id).unwrap_or(&self.standard_types.unknown)
    }
}

impl Index<BindingId> for InferenceResult {
    type Output = Ty;

    fn index(&self, b: BindingId) -> &Ty {
        self.type_of_binding.get(b).unwrap_or(&self.standard_types.unknown)
    }
}

/// The inference context contains all information needed during type inference.
#[derive(Clone, Debug)]
pub(crate) struct InferenceContext<'db> {
    pub(crate) db: &'db dyn HirDatabase,
    pub(crate) owner: DefWithBodyId,
    pub(crate) body: &'db Body,
    /// Generally you should not resolve things via this resolver. Instead create a TyLoweringContext
    /// and resolve the path via its methods. This will ensure proper error reporting.
    pub(crate) resolver: Resolver<'db>,
    generic_def: GenericDefId,
    generics: OnceCell<Generics>,
    table: unify::InferenceTable<'db>,
    /// The traits in scope, disregarding block modules. This is used for caching purposes.
    traits_in_scope: FxHashSet<TraitId>,
    pub(crate) result: InferenceResult,
    tuple_field_accesses_rev:
        IndexSet<Substitution, std::hash::BuildHasherDefault<rustc_hash::FxHasher>>,
    /// The return type of the function being inferred, the closure or async block if we're
    /// currently within one.
    ///
    /// We might consider using a nested inference context for checking
    /// closures so we can swap all shared things out at once.
    return_ty: Ty,
    /// If `Some`, this stores coercion information for returned
    /// expressions. If `None`, this is in a context where return is
    /// inappropriate, such as a const expression.
    return_coercion: Option<CoerceMany>,
    /// The resume type and the yield type, respectively, of the coroutine being inferred.
    resume_yield_tys: Option<(Ty, Ty)>,
    diverges: Diverges,
    breakables: Vec<BreakableContext>,

    /// Whether we are inside the pattern of a destructuring assignment.
    inside_assignment: bool,

    deferred_cast_checks: Vec<CastCheck>,

    // fields related to closure capture
    current_captures: Vec<CapturedItemWithoutTy>,
    /// A stack that has an entry for each projection in the current capture.
    ///
    /// For example, in `a.b.c`, we capture the spans of `a`, `a.b`, and `a.b.c`.
    /// We do that because sometimes we truncate projections (when a closure captures
    /// both `a.b` and `a.b.c`), and we want to provide accurate spans in this case.
    current_capture_span_stack: Vec<MirSpan>,
    current_closure: Option<ClosureId>,
    /// Stores the list of closure ids that need to be analyzed before this closure. See the
    /// comment on `InferenceContext::sort_closures`
    closure_dependencies: FxHashMap<ClosureId, Vec<ClosureId>>,
    deferred_closures: FxHashMap<ClosureId, Vec<(Ty, Ty, Vec<Ty>, ExprId)>>,

    diagnostics: Diagnostics,
}

#[derive(Clone, Debug)]
struct BreakableContext {
    /// Whether this context contains at least one break expression.
    may_break: bool,
    /// The coercion target of the context.
    coerce: Option<CoerceMany>,
    /// The optional label of the context.
    label: Option<LabelId>,
    kind: BreakableKind,
}

#[derive(Clone, Debug)]
enum BreakableKind {
    Block,
    Loop,
    /// A border is something like an async block, closure etc. Anything that prevents
    /// breaking/continuing through
    Border,
}

fn find_breakable(
    ctxs: &mut [BreakableContext],
    label: Option<LabelId>,
) -> Option<&mut BreakableContext> {
    let mut ctxs = ctxs
        .iter_mut()
        .rev()
        .take_while(|it| matches!(it.kind, BreakableKind::Block | BreakableKind::Loop));
    match label {
        Some(_) => ctxs.find(|ctx| ctx.label == label),
        None => ctxs.find(|ctx| matches!(ctx.kind, BreakableKind::Loop)),
    }
}

fn find_continuable(
    ctxs: &mut [BreakableContext],
    label: Option<LabelId>,
) -> Option<&mut BreakableContext> {
    match label {
        Some(_) => find_breakable(ctxs, label).filter(|it| matches!(it.kind, BreakableKind::Loop)),
        None => find_breakable(ctxs, label),
    }
}

enum ImplTraitReplacingMode {
    ReturnPosition(FxHashSet<Ty>),
    TypeAlias,
}

impl<'db> InferenceContext<'db> {
    fn new(
        db: &'db dyn HirDatabase,
        owner: DefWithBodyId,
        body: &'db Body,
        resolver: Resolver<'db>,
    ) -> Self {
        let trait_env = db.trait_environment_for_body(owner);
        InferenceContext {
            generics: OnceCell::new(),
            result: InferenceResult::default(),
            table: unify::InferenceTable::new(db, trait_env),
            tuple_field_accesses_rev: Default::default(),
            return_ty: TyKind::Error.intern(Interner), // set in collect_* calls
            resume_yield_tys: None,
            return_coercion: None,
            db,
            owner,
            generic_def: match owner {
                DefWithBodyId::FunctionId(it) => it.into(),
                DefWithBodyId::StaticId(it) => it.into(),
                DefWithBodyId::ConstId(it) => it.into(),
                DefWithBodyId::VariantId(it) => it.lookup(db).parent.into(),
            },
            body,
            traits_in_scope: resolver.traits_in_scope(db),
            resolver,
            diverges: Diverges::Maybe,
            breakables: Vec::new(),
            deferred_cast_checks: Vec::new(),
            current_captures: Vec::new(),
            current_capture_span_stack: Vec::new(),
            current_closure: None,
            deferred_closures: FxHashMap::default(),
            closure_dependencies: FxHashMap::default(),
            inside_assignment: false,
            diagnostics: Diagnostics::default(),
        }
    }

    pub(crate) fn generics(&self) -> &Generics {
        self.generics.get_or_init(|| crate::generics::generics(self.db, self.generic_def))
    }

    // FIXME: This function should be private in module. It is currently only used in the consteval, since we need
    // `InferenceResult` in the middle of inference. See the fixme comment in `consteval::eval_to_const`. If you
    // used this function for another workaround, mention it here. If you really need this function and believe that
    // there is no problem in it being `pub(crate)`, remove this comment.
    pub(crate) fn resolve_all(self) -> InferenceResult {
        let InferenceContext {
            mut table,
            mut result,
            mut deferred_cast_checks,
            tuple_field_accesses_rev,
            diagnostics,
            ..
        } = self;
        let mut diagnostics = diagnostics.finish();
        // Destructure every single field so whenever new fields are added to `InferenceResult` we
        // don't forget to handle them here.
        let InferenceResult {
            method_resolutions,
            field_resolutions: _,
            variant_resolutions: _,
            assoc_resolutions,
            type_of_expr,
            type_of_pat,
            type_of_binding,
            type_of_rpit,
            type_mismatches,
            has_errors,
            standard_types: _,
            pat_adjustments,
            binding_modes: _,
            expr_adjustments,
            // Types in `closure_info` have already been `resolve_completely()`'d during
            // `InferenceContext::infer_closures()` (in `HirPlace::ty()` specifically), so no need
            // to resolve them here.
            closure_info: _,
            mutated_bindings_in_closure: _,
            tuple_field_access_types: _,
            coercion_casts,
            diagnostics: _,
        } = &mut result;
        table.resolve_obligations_as_possible();
        table.fallback_if_possible();

        // Comment from rustc:
        // Even though coercion casts provide type hints, we check casts after fallback for
        // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
        let mut apply_adjustments = |expr, adj: Vec<_>| {
            expr_adjustments.insert(expr, adj.into_boxed_slice());
        };
        let mut set_coercion_cast = |expr| {
            coercion_casts.insert(expr);
        };
        for cast in deferred_cast_checks.iter_mut() {
            if let Err(diag) =
                cast.check(&mut table, &mut apply_adjustments, &mut set_coercion_cast)
            {
                diagnostics.push(diag);
            }
        }

        // FIXME resolve obligations as well (use Guidance if necessary)
        table.resolve_obligations_as_possible();

        // make sure diverging type variables are marked as such
        table.propagate_diverging_flag();
        for ty in type_of_expr.values_mut() {
            *ty = table.resolve_completely(ty.clone());
            *has_errors = *has_errors || ty.contains_unknown();
        }
        type_of_expr.shrink_to_fit();
        for ty in type_of_pat.values_mut() {
            *ty = table.resolve_completely(ty.clone());
            *has_errors = *has_errors || ty.contains_unknown();
        }
        type_of_pat.shrink_to_fit();
        for ty in type_of_binding.values_mut() {
            *ty = table.resolve_completely(ty.clone());
            *has_errors = *has_errors || ty.contains_unknown();
        }
        type_of_binding.shrink_to_fit();
        for ty in type_of_rpit.values_mut() {
            *ty = table.resolve_completely(ty.clone());
            *has_errors = *has_errors || ty.contains_unknown();
        }
        type_of_rpit.shrink_to_fit();

        *has_errors |= !type_mismatches.is_empty();

        type_mismatches.retain(|_, mismatch| {
            mismatch.expected = table.resolve_completely(mismatch.expected.clone());
            mismatch.actual = table.resolve_completely(mismatch.actual.clone());
            chalk_ir::zip::Zip::zip_with(
                &mut UnknownMismatch(self.db),
                Variance::Invariant,
                &mismatch.expected,
                &mismatch.actual,
            )
            .is_ok()
        });
        type_mismatches.shrink_to_fit();
        diagnostics.retain_mut(|diagnostic| {
            use InferenceDiagnostic::*;
            match diagnostic {
                ExpectedFunction { found: ty, .. }
                | UnresolvedField { receiver: ty, .. }
                | UnresolvedMethodCall { receiver: ty, .. } => {
                    *ty = table.resolve_completely(ty.clone());
                    // FIXME: Remove this when we are on par with rustc in terms of inference
                    if ty.contains_unknown() {
                        return false;
                    }

                    if let UnresolvedMethodCall { field_with_same_name, .. } = diagnostic
                        && let Some(ty) = field_with_same_name
                    {
                        *ty = table.resolve_completely(ty.clone());
                        if ty.contains_unknown() {
                            *field_with_same_name = None;
                        }
                    }
                }
                TypedHole { expected: ty, .. } => {
                    *ty = table.resolve_completely(ty.clone());
                }
                _ => (),
            }
            true
        });
        diagnostics.shrink_to_fit();
        for (_, subst) in method_resolutions.values_mut() {
            *subst = table.resolve_completely(subst.clone());
            *has_errors =
                *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
        }
        method_resolutions.shrink_to_fit();
        for (_, subst) in assoc_resolutions.values_mut() {
            *subst = table.resolve_completely(subst.clone());
            *has_errors =
                *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
        }
        assoc_resolutions.shrink_to_fit();
        for adjustment in expr_adjustments.values_mut().flatten() {
            adjustment.target = table.resolve_completely(adjustment.target.clone());
            *has_errors = *has_errors || adjustment.target.contains_unknown();
        }
        expr_adjustments.shrink_to_fit();
        for adjustment in pat_adjustments.values_mut().flatten() {
            *adjustment = table.resolve_completely(adjustment.clone());
            *has_errors = *has_errors || adjustment.contains_unknown();
        }
        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)| {
                *has_errors =
                    *has_errors || subst.type_parameters(Interner).any(|ty| ty.contains_unknown());
            })
            .collect();
        result.tuple_field_access_types.shrink_to_fit();

        result.diagnostics = diagnostics;

        result
    }

    fn collect_const(&mut self, id: ConstId, data: &ConstSignature) {
        let return_ty = self.make_ty(
            data.type_ref,
            &data.store,
            InferenceTyDiagnosticSource::Signature,
            LifetimeElisionKind::for_const(id.loc(self.db).container),
        );

        // Constants might be defining usage sites of TAITs.
        self.make_tait_coercion_table(iter::once(&return_ty));

        self.return_ty = return_ty;
    }

    fn collect_static(&mut self, data: &StaticSignature) {
        let return_ty = self.make_ty(
            data.type_ref,
            &data.store,
            InferenceTyDiagnosticSource::Signature,
            LifetimeElisionKind::Elided(static_lifetime()),
        );

        // Statics might be defining usage sites of TAITs.
        self.make_tait_coercion_table(iter::once(&return_ty));

        self.return_ty = return_ty;
    }

    fn collect_fn(&mut self, func: FunctionId) {
        let data = self.db.function_signature(func);
        let mut param_tys = self.with_ty_lowering(
            &data.store,
            InferenceTyDiagnosticSource::Signature,
            LifetimeElisionKind::for_fn_params(&data),
            |ctx| {
                ctx.type_param_mode(ParamLoweringMode::Placeholder);
                data.params.iter().map(|&type_ref| ctx.lower_ty(type_ref)).collect::<Vec<_>>()
            },
        );

        // Check if function contains a va_list, if it does then we append it to the parameter types
        // that are collected from the function data
        if data.is_varargs() {
            let va_list_ty = match self.resolve_va_list() {
                Some(va_list) => TyBuilder::adt(self.db, va_list)
                    .fill_with_defaults(self.db, || self.table.new_type_var())
                    .build(),
                None => self.err_ty(),
            };

            param_tys.push(va_list_ty);
        }
        let mut param_tys = param_tys.into_iter().chain(iter::repeat(self.table.new_type_var()));
        if let Some(self_param) = self.body.self_param
            && let Some(ty) = param_tys.next()
        {
            let ty = self.insert_type_vars(ty);
            let ty = self.normalize_associated_types_in(ty);
            self.write_binding_ty(self_param, ty);
        }
        let mut tait_candidates = FxHashSet::default();
        for (ty, pat) in param_tys.zip(&*self.body.params) {
            let ty = self.insert_type_vars(ty);
            let ty = self.normalize_associated_types_in(ty);

            self.infer_top_pat(*pat, &ty, None);
            if ty
                .data(Interner)
                .flags
                .intersects(TypeFlags::HAS_TY_OPAQUE.union(TypeFlags::HAS_TY_INFER))
            {
                tait_candidates.insert(ty);
            }
        }
        let return_ty = match data.ret_type {
            Some(return_ty) => {
                let return_ty = self.with_ty_lowering(
                    &data.store,
                    InferenceTyDiagnosticSource::Signature,
                    LifetimeElisionKind::for_fn_ret(),
                    |ctx| {
                        ctx.type_param_mode(ParamLoweringMode::Placeholder)
                            .impl_trait_mode(ImplTraitLoweringMode::Opaque);
                        ctx.lower_ty(return_ty)
                    },
                );
                let return_ty = self.insert_type_vars(return_ty);
                if let Some(rpits) = self.db.return_type_impl_traits(func) {
                    // RPIT opaque types use substitution of their parent function.
                    let fn_placeholders = TyBuilder::placeholder_subst(self.db, func);
                    let mut mode = ImplTraitReplacingMode::ReturnPosition(FxHashSet::default());
                    let result = self.insert_inference_vars_for_impl_trait(
                        return_ty,
                        fn_placeholders,
                        &mut mode,
                    );
                    if let ImplTraitReplacingMode::ReturnPosition(taits) = mode {
                        tait_candidates.extend(taits);
                    }
                    let rpits = rpits.skip_binders();
                    for (id, _) in rpits.impl_traits.iter() {
                        if let Entry::Vacant(e) = self.result.type_of_rpit.entry(id) {
                            never!("Missed RPIT in `insert_inference_vars_for_rpit`");
                            e.insert(TyKind::Error.intern(Interner));
                        }
                    }
                    result
                } else {
                    return_ty
                }
            }
            None => self.result.standard_types.unit.clone(),
        };

        self.return_ty = self.normalize_associated_types_in(return_ty);
        self.return_coercion = Some(CoerceMany::new(self.return_ty.clone()));

        // Functions might be defining usage sites of TAITs.
        // To define an TAITs, that TAIT must appear in the function's signatures.
        // So, it suffices to check for params and return types.
        fold_tys(
            self.return_ty.clone(),
            |ty, _| {
                match ty.kind(Interner) {
                    TyKind::OpaqueType(..)
                    | TyKind::Alias(AliasTy::Opaque(..))
                    | TyKind::InferenceVar(..) => {
                        tait_candidates.insert(self.return_ty.clone());
                    }
                    _ => {}
                }
                ty
            },
            DebruijnIndex::INNERMOST,
        );

        self.make_tait_coercion_table(tait_candidates.iter());
    }

    fn insert_inference_vars_for_impl_trait<T>(
        &mut self,
        t: T,
        placeholders: Substitution,
        mode: &mut ImplTraitReplacingMode,
    ) -> T
    where
        T: crate::HasInterner<Interner = Interner> + crate::TypeFoldable<Interner>,
    {
        fold_tys(
            t,
            |ty, _| {
                let opaque_ty_id = match ty.kind(Interner) {
                    TyKind::OpaqueType(opaque_ty_id, _) => *opaque_ty_id,
                    _ => return ty,
                };
                let (impl_traits, idx) =
                    match self.db.lookup_intern_impl_trait_id(opaque_ty_id.into()) {
                        // We don't replace opaque types from other kind with inference vars
                        // because `insert_inference_vars_for_impl_traits` for each kinds
                        // and unreplaced opaque types of other kind are resolved while
                        // inferencing because of `tait_coercion_table`.
                        // Moreover, calling `insert_inference_vars_for_impl_traits` with same
                        // `placeholders` for other kind may cause trouble because
                        // the substs for the bounds of each impl traits do not match
                        ImplTraitId::ReturnTypeImplTrait(def, idx) => {
                            if matches!(mode, ImplTraitReplacingMode::TypeAlias) {
                                // RPITs don't have `tait_coercion_table`, so use inserted inference
                                // vars for them.
                                if let Some(ty) = self.result.type_of_rpit.get(idx) {
                                    return ty.clone();
                                }
                                return ty;
                            }
                            (self.db.return_type_impl_traits(def), idx)
                        }
                        ImplTraitId::TypeAliasImplTrait(def, idx) => {
                            if let ImplTraitReplacingMode::ReturnPosition(taits) = mode {
                                // Gather TAITs while replacing RPITs because TAITs inside RPITs
                                // may not visited while replacing TAITs
                                taits.insert(ty.clone());
                                return ty;
                            }
                            (self.db.type_alias_impl_traits(def), idx)
                        }
                        _ => unreachable!(),
                    };
                let Some(impl_traits) = impl_traits else {
                    return ty;
                };
                let bounds = (*impl_traits)
                    .map_ref(|its| its.impl_traits[idx].bounds.map_ref(|it| it.iter()));
                let var = self.table.new_type_var();
                let var_subst = Substitution::from1(Interner, var.clone());
                for bound in bounds {
                    let predicate = bound.map(|it| it.cloned());
                    let predicate = predicate.substitute(Interner, &placeholders);
                    let (var_predicate, binders) =
                        predicate.substitute(Interner, &var_subst).into_value_and_skipped_binders();
                    always!(binders.is_empty(Interner)); // quantified where clauses not yet handled
                    let var_predicate = self.insert_inference_vars_for_impl_trait(
                        var_predicate,
                        placeholders.clone(),
                        mode,
                    );
                    self.push_obligation(var_predicate.cast(Interner));
                }
                self.result.type_of_rpit.insert(idx, var.clone());
                var
            },
            DebruijnIndex::INNERMOST,
        )
    }

    /// The coercion of a non-inference var into an opaque type should fail,
    /// but not in the defining sites of the TAITs.
    /// In such cases, we insert an proxy inference var for each TAIT,
    /// and coerce into it instead of TAIT itself.
    ///
    /// The inference var stretagy is effective because;
    ///
    /// - It can still unify types that coerced into TAITs
    /// - We are pushing `impl Trait` bounds into it
    ///
    /// This function inserts a map that maps the opaque type to that proxy inference var.
    fn make_tait_coercion_table<'b>(&mut self, tait_candidates: impl Iterator<Item = &'b Ty>) {
        struct TypeAliasImplTraitCollector<'a, 'b> {
            db: &'b dyn HirDatabase,
            table: &'b mut InferenceTable<'a>,
            assocs: FxHashMap<OpaqueTyId, (ImplId, Ty)>,
            non_assocs: FxHashMap<OpaqueTyId, Ty>,
        }

        impl TypeVisitor<Interner> for TypeAliasImplTraitCollector<'_, '_> {
            type BreakTy = ();

            fn as_dyn(&mut self) -> &mut dyn TypeVisitor<Interner, BreakTy = Self::BreakTy> {
                self
            }

            fn interner(&self) -> Interner {
                Interner
            }

            fn visit_ty(
                &mut self,
                ty: &chalk_ir::Ty<Interner>,
                outer_binder: DebruijnIndex,
            ) -> std::ops::ControlFlow<Self::BreakTy> {
                let ty = self.table.resolve_ty_shallow(ty);

                if let TyKind::OpaqueType(id, _) = ty.kind(Interner)
                    && let ImplTraitId::TypeAliasImplTrait(alias_id, _) =
                        self.db.lookup_intern_impl_trait_id((*id).into())
                {
                    let loc = self.db.lookup_intern_type_alias(alias_id);
                    match loc.container {
                        ItemContainerId::ImplId(impl_id) => {
                            self.assocs.insert(*id, (impl_id, ty.clone()));
                        }
                        ItemContainerId::ModuleId(..) | ItemContainerId::ExternBlockId(..) => {
                            self.non_assocs.insert(*id, ty.clone());
                        }
                        _ => {}
                    }
                }

                ty.super_visit_with(self, outer_binder)
            }
        }

        let mut collector = TypeAliasImplTraitCollector {
            db: self.db,
            table: &mut self.table,
            assocs: FxHashMap::default(),
            non_assocs: FxHashMap::default(),
        };
        for ty in tait_candidates {
            _ = ty.visit_with(collector.as_dyn(), DebruijnIndex::INNERMOST);
        }

        // Non-assoc TAITs can be define-used everywhere as long as they are
        // in function signatures or const types, etc
        let mut taits = collector.non_assocs;

        // assoc TAITs(ATPITs) can be only define-used inside their impl block.
        // They cannot be define-used in inner items like in the following;
        //
        // ```
        // impl Trait for Struct {
        //     type Assoc = impl Default;
        //
        //     fn assoc_fn() -> Self::Assoc {
        //         let foo: Self::Assoc = true; // Allowed here
        //
        //         fn inner() -> Self::Assoc {
        //              false                   // Not allowed here
        //         }
        //
        //         foo
        //     }
        // }
        // ```
        let impl_id = match self.owner {
            DefWithBodyId::FunctionId(it) => {
                let loc = self.db.lookup_intern_function(it);
                if let ItemContainerId::ImplId(impl_id) = loc.container {
                    Some(impl_id)
                } else {
                    None
                }
            }
            DefWithBodyId::ConstId(it) => {
                let loc = self.db.lookup_intern_const(it);
                if let ItemContainerId::ImplId(impl_id) = loc.container {
                    Some(impl_id)
                } else {
                    None
                }
            }
            _ => None,
        };

        if let Some(impl_id) = impl_id {
            taits.extend(collector.assocs.into_iter().filter_map(|(id, (impl_, ty))| {
                if impl_ == impl_id { Some((id, ty)) } else { None }
            }));
        }

        let tait_coercion_table: FxHashMap<_, _> = taits
            .into_iter()
            .filter_map(|(id, ty)| {
                if let ImplTraitId::TypeAliasImplTrait(alias_id, _) =
                    self.db.lookup_intern_impl_trait_id(id.into())
                {
                    let subst = TyBuilder::placeholder_subst(self.db, alias_id);
                    let ty = self.insert_inference_vars_for_impl_trait(
                        ty,
                        subst,
                        &mut ImplTraitReplacingMode::TypeAlias,
                    );
                    Some((id, ty))
                } else {
                    None
                }
            })
            .collect();

        if !tait_coercion_table.is_empty() {
            self.table.tait_coercion_table = Some(tait_coercion_table);
        }
    }

    fn infer_body(&mut self) {
        match self.return_coercion {
            Some(_) => self.infer_return(self.body.body_expr),
            None => {
                _ = self.infer_expr_coerce(
                    self.body.body_expr,
                    &Expectation::has_type(self.return_ty.clone()),
                    ExprIsRead::Yes,
                )
            }
        }
    }

    fn write_expr_ty(&mut self, expr: ExprId, ty: Ty) {
        self.result.type_of_expr.insert(expr, ty);
    }

    fn write_expr_adj(&mut self, expr: ExprId, adjustments: Box<[Adjustment]>) {
        if adjustments.is_empty() {
            return;
        }
        match self.result.expr_adjustments.entry(expr) {
            std::collections::hash_map::Entry::Occupied(mut entry) => {
                match (&mut entry.get_mut()[..], &adjustments[..]) {
                    (
                        [Adjustment { kind: Adjust::NeverToAny, target }],
                        [.., Adjustment { target: new_target, .. }],
                    ) => {
                        // NeverToAny coercion can target any type, so instead of adding a new
                        // adjustment on top we can change the target.
                        *target = new_target.clone();
                    }
                    _ => {
                        *entry.get_mut() = adjustments;
                    }
                }
            }
            std::collections::hash_map::Entry::Vacant(entry) => {
                entry.insert(adjustments);
            }
        }
    }

    fn write_method_resolution(&mut self, expr: ExprId, func: FunctionId, subst: Substitution) {
        self.result.method_resolutions.insert(expr, (func, subst));
    }

    fn write_variant_resolution(&mut self, id: ExprOrPatId, variant: VariantId) {
        self.result.variant_resolutions.insert(id, variant);
    }

    fn write_assoc_resolution(&mut self, id: ExprOrPatId, item: AssocItemId, subs: Substitution) {
        self.result.assoc_resolutions.insert(id, (item, subs));
    }

    fn write_pat_ty(&mut self, pat: PatId, ty: Ty) {
        self.result.type_of_pat.insert(pat, ty);
    }

    fn write_binding_ty(&mut self, id: BindingId, ty: Ty) {
        self.result.type_of_binding.insert(id, ty);
    }

    fn push_diagnostic(&self, diagnostic: InferenceDiagnostic) {
        self.diagnostics.push(diagnostic);
    }

    fn with_ty_lowering<R>(
        &mut self,
        store: &ExpressionStore,
        types_source: InferenceTyDiagnosticSource,
        lifetime_elision: LifetimeElisionKind,
        f: impl FnOnce(&mut TyLoweringContext<'_>) -> R,
    ) -> R {
        let mut ctx = TyLoweringContext::new(
            self.db,
            &self.resolver,
            store,
            &self.diagnostics,
            types_source,
            self.generic_def,
            lifetime_elision,
        );
        f(&mut ctx)
    }

    fn with_body_ty_lowering<R>(&mut self, f: impl FnOnce(&mut TyLoweringContext<'_>) -> R) -> R {
        self.with_ty_lowering(
            self.body,
            InferenceTyDiagnosticSource::Body,
            LifetimeElisionKind::Infer,
            f,
        )
    }

    fn make_ty(
        &mut self,
        type_ref: TypeRefId,
        store: &ExpressionStore,
        type_source: InferenceTyDiagnosticSource,
        lifetime_elision: LifetimeElisionKind,
    ) -> Ty {
        let ty = self
            .with_ty_lowering(store, type_source, lifetime_elision, |ctx| ctx.lower_ty(type_ref));
        let ty = self.insert_type_vars(ty);
        self.normalize_associated_types_in(ty)
    }

    fn make_body_ty(&mut self, type_ref: TypeRefId) -> Ty {
        self.make_ty(
            type_ref,
            self.body,
            InferenceTyDiagnosticSource::Body,
            LifetimeElisionKind::Infer,
        )
    }

    fn make_body_const(&mut self, const_ref: ConstRef, ty: Ty) -> Const {
        let const_ = self.with_ty_lowering(
            self.body,
            InferenceTyDiagnosticSource::Body,
            LifetimeElisionKind::Infer,
            |ctx| {
                ctx.type_param_mode = ParamLoweringMode::Placeholder;
                ctx.lower_const(&const_ref, ty)
            },
        );
        self.insert_type_vars(const_)
    }

    fn make_path_as_body_const(&mut self, path: &Path, ty: Ty) -> Const {
        let const_ = self.with_ty_lowering(
            self.body,
            InferenceTyDiagnosticSource::Body,
            LifetimeElisionKind::Infer,
            |ctx| {
                ctx.type_param_mode = ParamLoweringMode::Placeholder;
                ctx.lower_path_as_const(path, ty)
            },
        );
        self.insert_type_vars(const_)
    }

    fn err_ty(&self) -> Ty {
        self.result.standard_types.unknown.clone()
    }

    fn make_body_lifetime(&mut self, lifetime_ref: LifetimeRefId) -> Lifetime {
        let lt = self.with_ty_lowering(
            self.body,
            InferenceTyDiagnosticSource::Body,
            LifetimeElisionKind::Infer,
            |ctx| ctx.lower_lifetime(lifetime_ref),
        );
        self.insert_type_vars(lt)
    }

    /// Replaces `Ty::Error` by a new type var, so we can maybe still infer it.
    fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
        self.table.insert_type_vars_shallow(ty)
    }

    fn insert_type_vars<T>(&mut self, ty: T) -> T
    where
        T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
    {
        self.table.insert_type_vars(ty)
    }

    fn push_obligation(&mut self, o: DomainGoal) {
        let goal: crate::Goal = o.cast(Interner);
        self.table.register_obligation(goal.to_nextsolver(self.table.interner));
    }

    fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
        let ty1 = ty1
            .clone()
            .try_fold_with(
                &mut UnevaluatedConstEvaluatorFolder { db: self.db },
                DebruijnIndex::INNERMOST,
            )
            .unwrap();
        let ty2 = ty2
            .clone()
            .try_fold_with(
                &mut UnevaluatedConstEvaluatorFolder { db: self.db },
                DebruijnIndex::INNERMOST,
            )
            .unwrap();
        self.table.unify(&ty1, &ty2)
    }

    /// Attempts to returns the deeply last field of nested structures, but
    /// does not apply any normalization in its search. Returns the same type
    /// if input `ty` is not a structure at all.
    fn struct_tail_without_normalization(&mut self, ty: Ty) -> Ty {
        self.struct_tail_with_normalize(ty, identity)
    }

    /// Returns the deeply last field of nested structures, or the same type if
    /// not a structure at all. Corresponds to the only possible unsized field,
    /// and its type can be used to determine unsizing strategy.
    ///
    /// This is parameterized over the normalization strategy (i.e. how to
    /// handle `<T as Trait>::Assoc` and `impl Trait`); pass the identity
    /// function to indicate no normalization should take place.
    fn struct_tail_with_normalize(
        &mut self,
        mut ty: Ty,
        mut normalize: impl FnMut(Ty) -> Ty,
    ) -> Ty {
        // FIXME: fetch the limit properly
        let recursion_limit = 10;
        for iteration in 0.. {
            if iteration > recursion_limit {
                return self.err_ty();
            }
            match ty.kind(Interner) {
                TyKind::Adt(chalk_ir::AdtId(hir_def::AdtId::StructId(struct_id)), substs) => {
                    match self.db.field_types((*struct_id).into()).values().next_back().cloned() {
                        Some(field) => {
                            ty = field.substitute(Interner, substs);
                        }
                        None => break,
                    }
                }
                TyKind::Adt(..) => break,
                TyKind::Tuple(_, substs) => {
                    match substs
                        .as_slice(Interner)
                        .split_last()
                        .and_then(|(last_ty, _)| last_ty.ty(Interner))
                    {
                        Some(last_ty) => ty = last_ty.clone(),
                        None => break,
                    }
                }
                TyKind::Alias(..) => {
                    let normalized = normalize(ty.clone());
                    if ty == normalized {
                        return ty;
                    } else {
                        ty = normalized;
                    }
                }
                _ => break,
            }
        }
        ty
    }

    /// Recurses through the given type, normalizing associated types mentioned
    /// in it by replacing them by type variables and registering obligations to
    /// resolve later. This should be done once for every type we get from some
    /// type annotation (e.g. from a let type annotation, field type or function
    /// call). `make_ty` handles this already, but e.g. for field types we need
    /// to do it as well.
    fn normalize_associated_types_in<T>(&mut self, ty: T) -> T
    where
        T: HasInterner<Interner = Interner> + TypeFoldable<Interner>,
    {
        self.table.normalize_associated_types_in(ty)
    }

    fn resolve_ty_shallow(&mut self, ty: &Ty) -> Ty {
        self.table.resolve_ty_shallow(ty)
    }

    fn resolve_associated_type(&mut self, inner_ty: Ty, assoc_ty: Option<TypeAliasId>) -> Ty {
        self.resolve_associated_type_with_params(inner_ty, assoc_ty, &[])
    }

    fn resolve_associated_type_with_params(
        &mut self,
        inner_ty: Ty,
        assoc_ty: Option<TypeAliasId>,
        // FIXME(GATs): these are args for the trait ref, args for assoc type itself should be
        // handled when we support them.
        params: &[GenericArg],
    ) -> Ty {
        match assoc_ty {
            Some(res_assoc_ty) => {
                let trait_ = match res_assoc_ty.lookup(self.db).container {
                    hir_def::ItemContainerId::TraitId(trait_) => trait_,
                    _ => panic!("resolve_associated_type called with non-associated type"),
                };
                let ty = self.table.new_type_var();
                let mut param_iter = params.iter().cloned();
                let trait_ref = TyBuilder::trait_ref(self.db, trait_)
                    .push(inner_ty)
                    .fill(|_| param_iter.next().unwrap())
                    .build();
                let alias_eq = AliasEq {
                    alias: AliasTy::Projection(ProjectionTy {
                        associated_ty_id: to_assoc_type_id(res_assoc_ty),
                        substitution: trait_ref.substitution.clone(),
                    }),
                    ty: ty.clone(),
                };
                self.push_obligation(trait_ref.cast(Interner));
                self.push_obligation(alias_eq.cast(Interner));
                ty
            }
            None => self.err_ty(),
        }
    }

    fn resolve_variant(
        &mut self,
        node: ExprOrPatId,
        path: Option<&Path>,
        value_ns: bool,
    ) -> (Ty, Option<VariantId>) {
        let path = match path {
            Some(path) => path,
            None => return (self.err_ty(), None),
        };
        let mut ctx = TyLoweringContext::new(
            self.db,
            &self.resolver,
            &self.body.store,
            &self.diagnostics,
            InferenceTyDiagnosticSource::Body,
            self.generic_def,
            LifetimeElisionKind::Infer,
        );
        let mut path_ctx = ctx.at_path(path, node);
        let (resolution, unresolved) = if value_ns {
            let Some(res) = path_ctx.resolve_path_in_value_ns(HygieneId::ROOT) else {
                return (self.err_ty(), None);
            };
            match res {
                ResolveValueResult::ValueNs(value, _) => match value {
                    ValueNs::EnumVariantId(var) => {
                        let substs = path_ctx.substs_from_path(var.into(), true, false);
                        drop(ctx);
                        let ty = self.db.ty(var.lookup(self.db).parent.into());
                        let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                        return (ty, Some(var.into()));
                    }
                    ValueNs::StructId(strukt) => {
                        let substs = path_ctx.substs_from_path(strukt.into(), true, false);
                        drop(ctx);
                        let ty = self.db.ty(strukt.into());
                        let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                        return (ty, Some(strukt.into()));
                    }
                    ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None),
                    _ => {
                        drop(ctx);
                        return (self.err_ty(), None);
                    }
                },
                ResolveValueResult::Partial(typens, unresolved, _) => (typens, Some(unresolved)),
            }
        } else {
            match path_ctx.resolve_path_in_type_ns() {
                Some((it, idx)) => (it, idx),
                None => return (self.err_ty(), None),
            }
        };
        return match resolution {
            TypeNs::AdtId(AdtId::StructId(strukt)) => {
                let substs = path_ctx.substs_from_path(strukt.into(), true, false);
                drop(ctx);
                let ty = self.db.ty(strukt.into());
                let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                forbid_unresolved_segments((ty, Some(strukt.into())), unresolved)
            }
            TypeNs::AdtId(AdtId::UnionId(u)) => {
                let substs = path_ctx.substs_from_path(u.into(), true, false);
                drop(ctx);
                let ty = self.db.ty(u.into());
                let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                forbid_unresolved_segments((ty, Some(u.into())), unresolved)
            }
            TypeNs::EnumVariantId(var) => {
                let substs = path_ctx.substs_from_path(var.into(), true, false);
                drop(ctx);
                let ty = self.db.ty(var.lookup(self.db).parent.into());
                let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                forbid_unresolved_segments((ty, Some(var.into())), unresolved)
            }
            TypeNs::SelfType(impl_id) => {
                let generics = crate::generics::generics(self.db, impl_id.into());
                let substs = generics.placeholder_subst(self.db);
                let mut ty = self.db.impl_self_ty(impl_id).substitute(Interner, &substs);

                let Some(remaining_idx) = unresolved else {
                    drop(ctx);
                    let Some(mod_path) = path.mod_path() else {
                        never!("resolver should always resolve lang item paths");
                        return (self.err_ty(), None);
                    };
                    return self.resolve_variant_on_alias(ty, None, mod_path);
                };

                let mut remaining_segments = path.segments().skip(remaining_idx);

                if remaining_segments.len() >= 2 {
                    path_ctx.ignore_last_segment();
                }

                // We need to try resolving unresolved segments one by one because each may resolve
                // to a projection, which `TyLoweringContext` cannot handle on its own.
                let mut tried_resolving_once = false;
                while let Some(current_segment) = remaining_segments.first() {
                    // If we can resolve to an enum variant, it takes priority over associated type
                    // of the same name.
                    if let Some((AdtId::EnumId(id), _)) = ty.as_adt() {
                        let enum_data = id.enum_variants(self.db);
                        if let Some(variant) = enum_data.variant(current_segment.name) {
                            return if remaining_segments.len() == 1 {
                                (ty, Some(variant.into()))
                            } else {
                                // We still have unresolved paths, but enum variants never have
                                // associated types!
                                // FIXME: Report an error.
                                (self.err_ty(), None)
                            };
                        }
                    }

                    if tried_resolving_once {
                        // FIXME: with `inherent_associated_types` this is allowed, but our `lower_partly_resolved_path()`
                        // will need to be updated to err at the correct segment.
                        break;
                    }

                    // `lower_partly_resolved_path()` returns `None` as type namespace unless
                    // `remaining_segments` is empty, which is never the case here. We don't know
                    // which namespace the new `ty` is in until normalized anyway.
                    (ty, _) = path_ctx.lower_partly_resolved_path(resolution, true);
                    tried_resolving_once = true;

                    ty = self.table.insert_type_vars(ty);
                    ty = self.table.normalize_associated_types_in(ty);
                    ty = self.table.structurally_resolve_type(&ty);
                    if ty.is_unknown() {
                        return (self.err_ty(), None);
                    }

                    remaining_segments = remaining_segments.skip(1);
                }
                drop(ctx);

                let variant = ty.as_adt().and_then(|(id, _)| match id {
                    AdtId::StructId(s) => Some(VariantId::StructId(s)),
                    AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
                    AdtId::EnumId(_) => {
                        // FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
                        None
                    }
                });
                (ty, variant)
            }
            TypeNs::TypeAliasId(it) => {
                let Some(mod_path) = path.mod_path() else {
                    never!("resolver should always resolve lang item paths");
                    return (self.err_ty(), None);
                };
                let substs = path_ctx.substs_from_path_segment(it.into(), true, None, false);
                drop(ctx);
                let ty = self.db.ty(it.into());
                let ty = self.insert_type_vars(ty.substitute(Interner, &substs));

                self.resolve_variant_on_alias(ty, unresolved, mod_path)
            }
            TypeNs::AdtSelfType(_) => {
                // FIXME this could happen in array size expressions, once we're checking them
                (self.err_ty(), None)
            }
            TypeNs::GenericParam(_) => {
                // FIXME potentially resolve assoc type
                (self.err_ty(), None)
            }
            TypeNs::AdtId(AdtId::EnumId(_))
            | TypeNs::BuiltinType(_)
            | TypeNs::TraitId(_)
            | TypeNs::ModuleId(_) => {
                // FIXME diagnostic
                (self.err_ty(), None)
            }
        };

        fn forbid_unresolved_segments(
            result: (Ty, Option<VariantId>),
            unresolved: Option<usize>,
        ) -> (Ty, Option<VariantId>) {
            if unresolved.is_none() {
                result
            } else {
                // FIXME diagnostic
                (TyKind::Error.intern(Interner), None)
            }
        }
    }

    fn resolve_variant_on_alias(
        &mut self,
        ty: Ty,
        unresolved: Option<usize>,
        path: &ModPath,
    ) -> (Ty, Option<VariantId>) {
        let remaining = unresolved.map(|it| path.segments()[it..].len()).filter(|it| it > &0);
        let ty = match ty.kind(Interner) {
            TyKind::Alias(AliasTy::Projection(proj_ty)) => {
                let ty = self.table.normalize_projection_ty(proj_ty.clone());
                self.table.structurally_resolve_type(&ty)
            }
            _ => ty,
        };
        match remaining {
            None => {
                let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id {
                    AdtId::StructId(s) => Some(VariantId::StructId(s)),
                    AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
                    AdtId::EnumId(_) => {
                        // FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
                        None
                    }
                });
                (ty, variant)
            }
            Some(1) => {
                let segment = path.segments().last().unwrap();
                // this could be an enum variant or associated type
                if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
                    let enum_data = enum_id.enum_variants(self.db);
                    if let Some(variant) = enum_data.variant(segment) {
                        return (ty, Some(variant.into()));
                    }
                }
                // FIXME potentially resolve assoc type
                (self.err_ty(), None)
            }
            Some(_) => {
                // FIXME diagnostic
                (self.err_ty(), None)
            }
        }
    }

    fn resolve_lang_item(&self, item: LangItem) -> Option<LangItemTarget> {
        let krate = self.resolver.krate();
        lang_item(self.db, krate, item)
    }

    fn resolve_output_on(&self, trait_: TraitId) -> Option<TypeAliasId> {
        trait_.trait_items(self.db).associated_type_by_name(&Name::new_symbol_root(sym::Output))
    }

    fn resolve_lang_trait(&self, lang: LangItem) -> Option<TraitId> {
        self.resolve_lang_item(lang)?.as_trait()
    }

    fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
        self.resolve_output_on(self.resolve_lang_trait(LangItem::Neg)?)
    }

    fn resolve_ops_not_output(&self) -> Option<TypeAliasId> {
        self.resolve_output_on(self.resolve_lang_trait(LangItem::Not)?)
    }

    fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
        let ItemContainerId::TraitId(trait_) = self
            .resolve_lang_item(LangItem::IntoFutureIntoFuture)?
            .as_function()?
            .lookup(self.db)
            .container
        else {
            return None;
        };
        self.resolve_output_on(trait_)
    }

    fn resolve_boxed_box(&self) -> Option<AdtId> {
        let struct_ = self.resolve_lang_item(LangItem::OwnedBox)?.as_struct()?;
        Some(struct_.into())
    }

    fn resolve_range_full(&self) -> Option<AdtId> {
        let struct_ = self.resolve_lang_item(LangItem::RangeFull)?.as_struct()?;
        Some(struct_.into())
    }

    fn resolve_range(&self) -> Option<AdtId> {
        let struct_ = self.resolve_lang_item(LangItem::Range)?.as_struct()?;
        Some(struct_.into())
    }

    fn resolve_range_inclusive(&self) -> Option<AdtId> {
        let struct_ = self.resolve_lang_item(LangItem::RangeInclusiveStruct)?.as_struct()?;
        Some(struct_.into())
    }

    fn resolve_range_from(&self) -> Option<AdtId> {
        let struct_ = self.resolve_lang_item(LangItem::RangeFrom)?.as_struct()?;
        Some(struct_.into())
    }

    fn resolve_range_to(&self) -> Option<AdtId> {
        let struct_ = self.resolve_lang_item(LangItem::RangeTo)?.as_struct()?;
        Some(struct_.into())
    }

    fn resolve_range_to_inclusive(&self) -> Option<AdtId> {
        let struct_ = self.resolve_lang_item(LangItem::RangeToInclusive)?.as_struct()?;
        Some(struct_.into())
    }

    fn resolve_ops_index_output(&self) -> Option<TypeAliasId> {
        self.resolve_output_on(self.resolve_lang_trait(LangItem::Index)?)
    }

    fn resolve_va_list(&self) -> Option<AdtId> {
        let struct_ = self.resolve_lang_item(LangItem::VaList)?.as_struct()?;
        Some(struct_.into())
    }

    fn get_traits_in_scope(&self) -> Either<FxHashSet<TraitId>, &FxHashSet<TraitId>> {
        let mut b_traits = self.resolver.traits_in_scope_from_block_scopes().peekable();
        if b_traits.peek().is_some() {
            Either::Left(self.traits_in_scope.iter().copied().chain(b_traits).collect())
        } else {
            Either::Right(&self.traits_in_scope)
        }
    }
}

/// When inferring an expression, we propagate downward whatever type hint we
/// are able in the form of an `Expectation`.
#[derive(Clone, PartialEq, Eq, Debug)]
pub(crate) enum Expectation {
    None,
    HasType(Ty),
    #[allow(dead_code)]
    Castable(Ty),
    RValueLikeUnsized(Ty),
}

impl Expectation {
    /// The expectation that the type of the expression needs to equal the given
    /// type.
    fn has_type(ty: Ty) -> Self {
        if ty.is_unknown() {
            // FIXME: get rid of this?
            Expectation::None
        } else {
            Expectation::HasType(ty)
        }
    }

    /// The following explanation is copied straight from rustc:
    /// Provides an expectation for an rvalue expression given an *optional*
    /// hint, which is not required for type safety (the resulting type might
    /// be checked higher up, as is the case with `&expr` and `box expr`), but
    /// is useful in determining the concrete type.
    ///
    /// The primary use case is where the expected type is a fat pointer,
    /// like `&[isize]`. For example, consider the following statement:
    ///
    ///     let it: &[isize] = &[1, 2, 3];
    ///
    /// In this case, the expected type for the `&[1, 2, 3]` expression is
    /// `&[isize]`. If however we were to say that `[1, 2, 3]` has the
    /// expectation `ExpectHasType([isize])`, that would be too strong --
    /// `[1, 2, 3]` does not have the type `[isize]` but rather `[isize; 3]`.
    /// It is only the `&[1, 2, 3]` expression as a whole that can be coerced
    /// to the type `&[isize]`. Therefore, we propagate this more limited hint,
    /// which still is useful, because it informs integer literals and the like.
    /// See the test case `test/ui/coerce-expect-unsized.rs` and #20169
    /// for examples of where this comes up,.
    fn rvalue_hint(ctx: &mut InferenceContext<'_>, ty: Ty) -> Self {
        match ctx.struct_tail_without_normalization(ty.clone()).kind(Interner) {
            TyKind::Slice(_) | TyKind::Str | TyKind::Dyn(_) => Expectation::RValueLikeUnsized(ty),
            _ => Expectation::has_type(ty),
        }
    }

    /// This expresses no expectation on the type.
    fn none() -> Self {
        Expectation::None
    }

    fn resolve(&self, table: &mut unify::InferenceTable<'_>) -> Expectation {
        match self {
            Expectation::None => Expectation::None,
            Expectation::HasType(t) => Expectation::HasType(table.resolve_ty_shallow(t)),
            Expectation::Castable(t) => Expectation::Castable(table.resolve_ty_shallow(t)),
            Expectation::RValueLikeUnsized(t) => {
                Expectation::RValueLikeUnsized(table.resolve_ty_shallow(t))
            }
        }
    }

    fn to_option(&self, table: &mut unify::InferenceTable<'_>) -> Option<Ty> {
        match self.resolve(table) {
            Expectation::None => None,
            Expectation::HasType(t)
            | Expectation::Castable(t)
            | Expectation::RValueLikeUnsized(t) => Some(t),
        }
    }

    fn only_has_type(&self, table: &mut unify::InferenceTable<'_>) -> Option<Ty> {
        match self {
            Expectation::HasType(t) => Some(table.resolve_ty_shallow(t)),
            Expectation::Castable(_) | Expectation::RValueLikeUnsized(_) | Expectation::None => {
                None
            }
        }
    }

    fn coercion_target_type(&self, table: &mut unify::InferenceTable<'_>) -> Ty {
        self.only_has_type(table).unwrap_or_else(|| table.new_type_var())
    }

    /// Comment copied from rustc:
    /// Disregard "castable to" expectations because they
    /// can lead us astray. Consider for example `if cond
    /// {22} else {c} as u8` -- if we propagate the
    /// "castable to u8" constraint to 22, it will pick the
    /// type 22u8, which is overly constrained (c might not
    /// be a u8). In effect, the problem is that the
    /// "castable to" expectation is not the tightest thing
    /// we can say, so we want to drop it in this case.
    /// The tightest thing we can say is "must unify with
    /// else branch". Note that in the case of a "has type"
    /// constraint, this limitation does not hold.
    ///
    /// If the expected type is just a type variable, then don't use
    /// an expected type. Otherwise, we might write parts of the type
    /// when checking the 'then' block which are incompatible with the
    /// 'else' branch.
    fn adjust_for_branches(&self, table: &mut unify::InferenceTable<'_>) -> Expectation {
        match self {
            Expectation::HasType(ety) => {
                let ety = table.structurally_resolve_type(ety);
                if ety.is_ty_var() { Expectation::None } else { Expectation::HasType(ety) }
            }
            Expectation::RValueLikeUnsized(ety) => Expectation::RValueLikeUnsized(ety.clone()),
            _ => Expectation::None,
        }
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
enum Diverges {
    Maybe,
    Always,
}

impl Diverges {
    fn is_always(self) -> bool {
        self == Diverges::Always
    }
}

impl std::ops::BitAnd for Diverges {
    type Output = Self;
    fn bitand(self, other: Self) -> Self {
        std::cmp::min(self, other)
    }
}

impl std::ops::BitOr for Diverges {
    type Output = Self;
    fn bitor(self, other: Self) -> Self {
        std::cmp::max(self, other)
    }
}

impl std::ops::BitAndAssign for Diverges {
    fn bitand_assign(&mut self, other: Self) {
        *self = *self & other;
    }
}

impl std::ops::BitOrAssign for Diverges {
    fn bitor_assign(&mut self, other: Self) {
        *self = *self | other;
    }
}

/// A zipper that checks for unequal occurrences of `{unknown}` and unresolved projections
/// in the two types. Used to filter out mismatch diagnostics that only differ in
/// `{unknown}` and unresolved projections. These mismatches are usually not helpful.
/// As the cause is usually an underlying name resolution problem
struct UnknownMismatch<'db>(&'db dyn HirDatabase);
impl chalk_ir::zip::Zipper<Interner> for UnknownMismatch<'_> {
    fn zip_tys(&mut self, variance: Variance, a: &Ty, b: &Ty) -> chalk_ir::Fallible<()> {
        let zip_substs = |this: &mut Self,
                          variances,
                          sub_a: &Substitution,
                          sub_b: &Substitution| {
            this.zip_substs(variance, variances, sub_a.as_slice(Interner), sub_b.as_slice(Interner))
        };
        match (a.kind(Interner), b.kind(Interner)) {
            (TyKind::Adt(id_a, sub_a), TyKind::Adt(id_b, sub_b)) if id_a == id_b => zip_substs(
                self,
                Some(self.unification_database().adt_variance(*id_a)),
                sub_a,
                sub_b,
            )?,
            (
                TyKind::AssociatedType(assoc_ty_a, sub_a),
                TyKind::AssociatedType(assoc_ty_b, sub_b),
            ) if assoc_ty_a == assoc_ty_b => zip_substs(self, None, sub_a, sub_b)?,
            (TyKind::Tuple(arity_a, sub_a), TyKind::Tuple(arity_b, sub_b))
                if arity_a == arity_b =>
            {
                zip_substs(self, None, sub_a, sub_b)?
            }
            (TyKind::OpaqueType(opaque_ty_a, sub_a), TyKind::OpaqueType(opaque_ty_b, sub_b))
                if opaque_ty_a == opaque_ty_b =>
            {
                zip_substs(self, None, sub_a, sub_b)?
            }
            (TyKind::Slice(ty_a), TyKind::Slice(ty_b)) => self.zip_tys(variance, ty_a, ty_b)?,
            (TyKind::FnDef(fn_def_a, sub_a), TyKind::FnDef(fn_def_b, sub_b))
                if fn_def_a == fn_def_b =>
            {
                zip_substs(
                    self,
                    Some(self.unification_database().fn_def_variance(*fn_def_a)),
                    sub_a,
                    sub_b,
                )?
            }
            (TyKind::Ref(mutability_a, _, ty_a), TyKind::Ref(mutability_b, _, ty_b))
                if mutability_a == mutability_b =>
            {
                self.zip_tys(variance, ty_a, ty_b)?
            }
            (TyKind::Raw(mutability_a, ty_a), TyKind::Raw(mutability_b, ty_b))
                if mutability_a == mutability_b =>
            {
                self.zip_tys(variance, ty_a, ty_b)?
            }
            (TyKind::Array(ty_a, const_a), TyKind::Array(ty_b, const_b)) if const_a == const_b => {
                self.zip_tys(variance, ty_a, ty_b)?
            }
            (TyKind::Closure(id_a, sub_a), TyKind::Closure(id_b, sub_b)) if id_a == id_b => {
                zip_substs(self, None, sub_a, sub_b)?
            }
            (TyKind::Coroutine(coroutine_a, sub_a), TyKind::Coroutine(coroutine_b, sub_b))
                if coroutine_a == coroutine_b =>
            {
                zip_substs(self, None, sub_a, sub_b)?
            }
            (
                TyKind::CoroutineWitness(coroutine_a, sub_a),
                TyKind::CoroutineWitness(coroutine_b, sub_b),
            ) if coroutine_a == coroutine_b => zip_substs(self, None, sub_a, sub_b)?,
            (TyKind::Function(fn_ptr_a), TyKind::Function(fn_ptr_b))
                if fn_ptr_a.sig == fn_ptr_b.sig && fn_ptr_a.num_binders == fn_ptr_b.num_binders =>
            {
                zip_substs(self, None, &fn_ptr_a.substitution.0, &fn_ptr_b.substitution.0)?
            }
            (TyKind::Error, TyKind::Error) => (),
            (TyKind::Error, _)
            | (_, TyKind::Error)
            | (TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(_, _), _)
            | (_, TyKind::Alias(AliasTy::Projection(_)) | TyKind::AssociatedType(_, _)) => {
                return Err(chalk_ir::NoSolution);
            }
            _ => (),
        }

        Ok(())
    }

    fn zip_lifetimes(&mut self, _: Variance, _: &Lifetime, _: &Lifetime) -> chalk_ir::Fallible<()> {
        Ok(())
    }

    fn zip_consts(&mut self, _: Variance, _: &Const, _: &Const) -> chalk_ir::Fallible<()> {
        Ok(())
    }

    fn zip_binders<T>(
        &mut self,
        variance: Variance,
        a: &Binders<T>,
        b: &Binders<T>,
    ) -> chalk_ir::Fallible<()>
    where
        T: Clone
            + HasInterner<Interner = Interner>
            + chalk_ir::zip::Zip<Interner>
            + TypeFoldable<Interner>,
    {
        chalk_ir::zip::Zip::zip_with(self, variance, a.skip_binders(), b.skip_binders())
    }

    fn interner(&self) -> Interner {
        Interner
    }

    fn unification_database(&self) -> &dyn chalk_ir::UnificationDatabase<Interner> {
        &self.0
    }
}
