//! HIR (previously known as descriptors) provides a high-level object-oriented
//! access to Rust code.
//!
//! The principal difference between HIR and syntax trees is that HIR is bound
//! to a particular crate instance. That is, it has cfg flags and features
//! applied. So, the relation between syntax and HIR is many-to-one.
//!
//! HIR is the public API of the all of the compiler logic above syntax trees.
//! It is written in "OO" style. Each type is self contained (as in, it knows its
//! parents and full context). It should be "clean code".
//!
//! `hir_*` crates are the implementation of the compiler logic.
//! They are written in "ECS" style, with relatively little abstractions.
//! Many types are not self-contained, and explicitly use local indexes, arenas, etc.
//!
//! `hir` is what insulates the "we don't know how to actually write an incremental compiler"
//! from the ide with completions, hovers, etc. It is a (soft, internal) boundary:
//! <https://www.tedinski.com/2018/02/06/system-boundaries.html>.

#![cfg_attr(feature = "in-rust-tree", feature(rustc_private))]
#![recursion_limit = "512"]

extern crate ra_ap_rustc_type_ir as rustc_type_ir;

mod attrs;
mod from_id;
mod has_source;
mod semantics;
mod source_analyzer;

pub mod db;
pub mod diagnostics;
pub mod symbols;
pub mod term_search;

mod display;

#[doc(hidden)]
pub use hir_def::ModuleId;

use std::{
    fmt,
    mem::discriminant,
    ops::{ControlFlow, Not},
};

use arrayvec::ArrayVec;
use base_db::{CrateDisplayName, CrateOrigin, LangCrateOrigin};
use either::Either;
use hir_def::{
    AdtId, AssocItemId, AssocItemLoc, AttrDefId, CallableDefId, ConstId, ConstParamId,
    CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId, ExternBlockId, ExternCrateId,
    FunctionId, GenericDefId, GenericParamId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
    LocalFieldId, Lookup, MacroExpander, MacroId, StaticId, StructId, SyntheticSyntax, TupleId,
    TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
    expr_store::{ExpressionStoreDiagnostics, ExpressionStoreSourceMap},
    hir::{
        BindingAnnotation, BindingId, Expr, ExprId, ExprOrPatId, LabelId, Pat,
        generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
    },
    item_tree::ImportAlias,
    layout::{self, ReprOptions, TargetDataLayout},
    nameres::{
        assoc::TraitItems,
        diagnostics::{DefDiagnostic, DefDiagnosticKind},
    },
    per_ns::PerNs,
    resolver::{HasResolver, Resolver},
    signatures::{ImplFlags, StaticFlags, StructFlags, TraitFlags, VariantFields},
    src::HasSource as _,
    visibility::visibility_from_ast,
};
use hir_expand::{
    AstId, MacroCallKind, RenderedExpandError, ValueResult, attrs::collect_attrs,
    proc_macro::ProcMacroKind,
};
use hir_ty::{
    GenericPredicates, TraitEnvironment, TyDefId, TyLoweringDiagnostic, ValueTyDefId,
    all_super_traits, autoderef, check_orphan_rules,
    consteval::try_const_usize,
    db::{InternedClosureId, InternedCoroutineId},
    diagnostics::BodyValidationDiagnostic,
    direct_super_traits, known_const_to_ast,
    layout::{Layout as TyLayout, RustcEnumVariantIdx, RustcFieldIdx, TagEncoding},
    method_resolution::{
        self, InherentImpls, MethodResolutionContext, MethodResolutionUnstableFeatures,
    },
    mir::{MutBorrowKind, interpret_mir},
    next_solver::{
        AliasTy, ClauseKind, ConstKind, DbInterner, ErrorGuaranteed, GenericArg, GenericArgs,
        PolyFnSig, Region, SolverDefId, Ty, TyKind, TypingMode,
        infer::{DbInternerInferExt, InferCtxt},
    },
    traits::{self, FnTrait, is_inherent_impl_coherent, structurally_normalize_ty},
};
use itertools::Itertools;
use rustc_hash::FxHashSet;
use rustc_type_ir::{
    AliasTyKind, TypeSuperVisitable, TypeVisitable, TypeVisitor, fast_reject,
    inherent::{AdtDef, GenericArgs as _, IntoKind, SliceLike, Term as _, Ty as _},
};
use smallvec::SmallVec;
use span::{AstIdNode, Edition, FileId};
use stdx::{format_to, impl_from, never};
use syntax::{
    AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, T, TextRange, ToSmolStr,
    ast::{self, HasAttrs as _, HasName, HasVisibility as _},
    format_smolstr,
};
use triomphe::{Arc, ThinArc};

use crate::db::{DefDatabase, HirDatabase};

pub use crate::{
    attrs::{HasAttrs, resolve_doc_path_on},
    diagnostics::*,
    has_source::HasSource,
    semantics::{
        PathResolution, PathResolutionPerNs, Semantics, SemanticsImpl, SemanticsScope, TypeInfo,
        VisibleTraits,
    },
};

// Be careful with these re-exports.
//
// `hir` is the boundary between the compiler and the IDE. It should try hard to
// isolate the compiler from the ide, to allow the two to be refactored
// independently. Re-exporting something from the compiler is the sure way to
// breach the boundary.
//
// Generally, a refactoring which *removes* a name from this list is a good
// idea!
pub use {
    cfg::{CfgAtom, CfgExpr, CfgOptions},
    hir_def::{
        Complete,
        FindPathConfig,
        attr::{AttrSourceMap, Attrs, AttrsWithOwner},
        find_path::PrefixKind,
        import_map,
        lang_item::{LangItem, crate_lang_items},
        nameres::{DefMap, ModuleSource, crate_def_map},
        per_ns::Namespace,
        type_ref::{Mutability, TypeRef},
        visibility::Visibility,
        // FIXME: This is here since some queries take it as input that are used
        // outside of hir.
        {ModuleDefId, TraitId},
    },
    hir_expand::{
        EditionedFileId, ExpandResult, HirFileId, MacroCallId, MacroKind,
        attrs::{Attr, AttrId},
        change::ChangeWithProcMacros,
        files::{
            FilePosition, FilePositionWrapper, FileRange, FileRangeWrapper, HirFilePosition,
            HirFileRange, InFile, InFileWrapper, InMacroFile, InRealFile, MacroFilePosition,
            MacroFileRange,
        },
        inert_attr_macro::AttributeTemplate,
        mod_path::{ModPath, PathKind, tool_path},
        name::Name,
        prettify_macro_expansion,
        proc_macro::{ProcMacros, ProcMacrosBuilder},
        tt,
    },
    // FIXME: Properly encapsulate mir
    hir_ty::mir,
    hir_ty::{
        CastError, FnAbi, PointerCast, attach_db, attach_db_allow_change,
        consteval::ConstEvalError,
        diagnostics::UnsafetyReason,
        display::{ClosureStyle, DisplayTarget, HirDisplay, HirDisplayError, HirWrite},
        drop::DropGlue,
        dyn_compatibility::{DynCompatibilityViolation, MethodViolationCode},
        layout::LayoutError,
        mir::{MirEvalError, MirLowerError},
        next_solver::abi::Safety,
        next_solver::clear_tls_solver_cache,
    },
    // FIXME: These are needed for import assets, properly encapsulate them.
    hir_ty::{method_resolution::TraitImpls, next_solver::SimplifiedType},
    intern::{Symbol, sym},
};

// These are negative re-exports: pub using these names is forbidden, they
// should remain private to hir internals.
#[allow(unused)]
use {
    hir_def::expr_store::path::Path,
    hir_expand::{
        name::AsName,
        span_map::{ExpansionSpanMap, RealSpanMap, SpanMap, SpanMapRef},
    },
};

/// hir::Crate describes a single crate. It's the main interface with which
/// a crate's dependencies interact. Mostly, it should be just a proxy for the
/// root module.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Crate {
    pub(crate) id: base_db::Crate,
}

#[derive(Debug)]
pub struct CrateDependency {
    pub krate: Crate,
    pub name: Name,
}

impl Crate {
    pub fn base(self) -> base_db::Crate {
        self.id
    }

    pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin {
        self.id.data(db).origin.clone()
    }

    pub fn is_builtin(self, db: &dyn HirDatabase) -> bool {
        matches!(self.origin(db), CrateOrigin::Lang(_))
    }

    pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
        self.id
            .data(db)
            .dependencies
            .iter()
            .map(|dep| {
                let krate = Crate { id: dep.crate_id };
                let name = dep.as_name();
                CrateDependency { krate, name }
            })
            .collect()
    }

    pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
        let all_crates = db.all_crates();
        all_crates
            .iter()
            .copied()
            .filter(|&krate| krate.data(db).dependencies.iter().any(|it| it.crate_id == self.id))
            .map(|id| Crate { id })
            .collect()
    }

    pub fn transitive_reverse_dependencies(
        self,
        db: &dyn HirDatabase,
    ) -> impl Iterator<Item = Crate> {
        self.id.transitive_rev_deps(db).into_iter().map(|id| Crate { id })
    }

    pub fn notable_traits_in_deps(self, db: &dyn HirDatabase) -> impl Iterator<Item = &TraitId> {
        self.id
            .transitive_deps(db)
            .into_iter()
            .filter_map(|krate| db.crate_notable_traits(krate))
            .flatten()
    }

    pub fn root_module(self) -> Module {
        Module { id: CrateRootModuleId::from(self.id).into() }
    }

    pub fn modules(self, db: &dyn HirDatabase) -> Vec<Module> {
        let def_map = crate_def_map(db, self.id);
        def_map.modules().map(|(id, _)| def_map.module_id(id).into()).collect()
    }

    pub fn root_file(self, db: &dyn HirDatabase) -> FileId {
        self.id.data(db).root_file_id
    }

    pub fn edition(self, db: &dyn HirDatabase) -> Edition {
        self.id.data(db).edition
    }

    pub fn version(self, db: &dyn HirDatabase) -> Option<String> {
        self.id.extra_data(db).version.clone()
    }

    pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateDisplayName> {
        self.id.extra_data(db).display_name.clone()
    }

    pub fn query_external_importables(
        self,
        db: &dyn DefDatabase,
        query: import_map::Query,
    ) -> impl Iterator<Item = (Either<ModuleDef, Macro>, Complete)> {
        let _p = tracing::info_span!("query_external_importables").entered();
        import_map::search_dependencies(db, self.into(), &query).into_iter().map(
            |(item, do_not_complete)| {
                let item = match ItemInNs::from(item) {
                    ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id),
                    ItemInNs::Macros(mac_id) => Either::Right(mac_id),
                };
                (item, do_not_complete)
            },
        )
    }

    pub fn all(db: &dyn HirDatabase) -> Vec<Crate> {
        db.all_crates().iter().map(|&id| Crate { id }).collect()
    }

    /// Try to get the root URL of the documentation of a crate.
    pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
        // Look for #![doc(html_root_url = "...")]
        let attrs = db.attrs(AttrDefId::ModuleId(self.root_module().into()));
        let doc_url = attrs.by_key(sym::doc).find_string_value_in_tt(sym::html_root_url);
        doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
    }

    pub fn cfg<'db>(&self, db: &'db dyn HirDatabase) -> &'db CfgOptions {
        self.id.cfg_options(db)
    }

    pub fn potential_cfg<'db>(&self, db: &'db dyn HirDatabase) -> &'db CfgOptions {
        let data = self.id.extra_data(db);
        data.potential_cfg_options.as_ref().unwrap_or_else(|| self.id.cfg_options(db))
    }

    pub fn to_display_target(self, db: &dyn HirDatabase) -> DisplayTarget {
        DisplayTarget::from_crate(db, self.id)
    }

    fn core(db: &dyn HirDatabase) -> Option<Crate> {
        db.all_crates()
            .iter()
            .copied()
            .find(|&krate| {
                matches!(krate.data(db).origin, CrateOrigin::Lang(LangCrateOrigin::Core))
            })
            .map(Crate::from)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Module {
    pub(crate) id: ModuleId,
}

/// The defs which can be visible in the module.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ModuleDef {
    Module(Module),
    Function(Function),
    Adt(Adt),
    // Can't be directly declared, but can be imported.
    // FIXME: Rename to `EnumVariant`
    Variant(Variant),
    Const(Const),
    Static(Static),
    Trait(Trait),
    TypeAlias(TypeAlias),
    BuiltinType(BuiltinType),
    Macro(Macro),
}
impl_from!(
    Module,
    Function,
    Adt(Struct, Enum, Union),
    Variant,
    Const,
    Static,
    Trait,
    TypeAlias,
    BuiltinType,
    Macro
    for ModuleDef
);

impl From<VariantDef> for ModuleDef {
    fn from(var: VariantDef) -> Self {
        match var {
            VariantDef::Struct(t) => Adt::from(t).into(),
            VariantDef::Union(t) => Adt::from(t).into(),
            VariantDef::Variant(t) => t.into(),
        }
    }
}

impl ModuleDef {
    pub fn module(self, db: &dyn HirDatabase) -> Option<Module> {
        match self {
            ModuleDef::Module(it) => it.parent(db),
            ModuleDef::Function(it) => Some(it.module(db)),
            ModuleDef::Adt(it) => Some(it.module(db)),
            ModuleDef::Variant(it) => Some(it.module(db)),
            ModuleDef::Const(it) => Some(it.module(db)),
            ModuleDef::Static(it) => Some(it.module(db)),
            ModuleDef::Trait(it) => Some(it.module(db)),
            ModuleDef::TypeAlias(it) => Some(it.module(db)),
            ModuleDef::Macro(it) => Some(it.module(db)),
            ModuleDef::BuiltinType(_) => None,
        }
    }

    pub fn canonical_path(&self, db: &dyn HirDatabase, edition: Edition) -> Option<String> {
        let mut segments = vec![self.name(db)?];
        for m in self.module(db)?.path_to_root(db) {
            segments.extend(m.name(db))
        }
        segments.reverse();
        Some(segments.iter().map(|it| it.display(db, edition)).join("::"))
    }

    pub fn canonical_module_path(
        &self,
        db: &dyn HirDatabase,
    ) -> Option<impl Iterator<Item = Module>> {
        self.module(db).map(|it| it.path_to_root(db).into_iter().rev())
    }

    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
        let name = match self {
            ModuleDef::Module(it) => it.name(db)?,
            ModuleDef::Const(it) => it.name(db)?,
            ModuleDef::Adt(it) => it.name(db),
            ModuleDef::Trait(it) => it.name(db),
            ModuleDef::Function(it) => it.name(db),
            ModuleDef::Variant(it) => it.name(db),
            ModuleDef::TypeAlias(it) => it.name(db),
            ModuleDef::Static(it) => it.name(db),
            ModuleDef::Macro(it) => it.name(db),
            ModuleDef::BuiltinType(it) => it.name(),
        };
        Some(name)
    }

    pub fn diagnostics<'db>(
        self,
        db: &'db dyn HirDatabase,
        style_lints: bool,
    ) -> Vec<AnyDiagnostic<'db>> {
        let id = match self {
            ModuleDef::Adt(it) => match it {
                Adt::Struct(it) => it.id.into(),
                Adt::Enum(it) => it.id.into(),
                Adt::Union(it) => it.id.into(),
            },
            ModuleDef::Trait(it) => it.id.into(),
            ModuleDef::Function(it) => it.id.into(),
            ModuleDef::TypeAlias(it) => it.id.into(),
            ModuleDef::Module(it) => it.id.into(),
            ModuleDef::Const(it) => it.id.into(),
            ModuleDef::Static(it) => it.id.into(),
            ModuleDef::Variant(it) => it.id.into(),
            ModuleDef::BuiltinType(_) | ModuleDef::Macro(_) => return Vec::new(),
        };

        let mut acc = Vec::new();

        match self.as_def_with_body() {
            Some(def) => {
                def.diagnostics(db, &mut acc, style_lints);
            }
            None => {
                for diag in hir_ty::diagnostics::incorrect_case(db, id) {
                    acc.push(diag.into())
                }
            }
        }

        if let Some(def) = self.as_self_generic_def() {
            def.diagnostics(db, &mut acc);
        }

        acc
    }

    pub fn as_def_with_body(self) -> Option<DefWithBody> {
        match self {
            ModuleDef::Function(it) => Some(it.into()),
            ModuleDef::Const(it) => Some(it.into()),
            ModuleDef::Static(it) => Some(it.into()),
            ModuleDef::Variant(it) => Some(it.into()),

            ModuleDef::Module(_)
            | ModuleDef::Adt(_)
            | ModuleDef::Trait(_)
            | ModuleDef::TypeAlias(_)
            | ModuleDef::Macro(_)
            | ModuleDef::BuiltinType(_) => None,
        }
    }

    /// Returns only defs that have generics from themselves, not their parent.
    pub fn as_self_generic_def(self) -> Option<GenericDef> {
        match self {
            ModuleDef::Function(it) => Some(it.into()),
            ModuleDef::Adt(it) => Some(it.into()),
            ModuleDef::Trait(it) => Some(it.into()),
            ModuleDef::TypeAlias(it) => Some(it.into()),
            ModuleDef::Module(_)
            | ModuleDef::Variant(_)
            | ModuleDef::Static(_)
            | ModuleDef::Const(_)
            | ModuleDef::BuiltinType(_)
            | ModuleDef::Macro(_) => None,
        }
    }

    pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
        Some(match self {
            ModuleDef::Module(it) => it.attrs(db),
            ModuleDef::Function(it) => it.attrs(db),
            ModuleDef::Adt(it) => it.attrs(db),
            ModuleDef::Variant(it) => it.attrs(db),
            ModuleDef::Const(it) => it.attrs(db),
            ModuleDef::Static(it) => it.attrs(db),
            ModuleDef::Trait(it) => it.attrs(db),
            ModuleDef::TypeAlias(it) => it.attrs(db),
            ModuleDef::Macro(it) => it.attrs(db),
            ModuleDef::BuiltinType(_) => return None,
        })
    }
}

impl HasCrate for ModuleDef {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        match self.module(db) {
            Some(module) => module.krate(),
            None => Crate::core(db).unwrap_or_else(|| db.all_crates()[0].into()),
        }
    }
}

impl HasVisibility for ModuleDef {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        match *self {
            ModuleDef::Module(it) => it.visibility(db),
            ModuleDef::Function(it) => it.visibility(db),
            ModuleDef::Adt(it) => it.visibility(db),
            ModuleDef::Const(it) => it.visibility(db),
            ModuleDef::Static(it) => it.visibility(db),
            ModuleDef::Trait(it) => it.visibility(db),
            ModuleDef::TypeAlias(it) => it.visibility(db),
            ModuleDef::Variant(it) => it.visibility(db),
            ModuleDef::Macro(it) => it.visibility(db),
            ModuleDef::BuiltinType(_) => Visibility::Public,
        }
    }
}

impl Module {
    /// Name of this module.
    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
        self.id.name(db)
    }

    /// Returns the crate this module is part of.
    pub fn krate(self) -> Crate {
        Crate { id: self.id.krate() }
    }

    /// Topmost parent of this module. Every module has a `crate_root`, but some
    /// might be missing `krate`. This can happen if a module's file is not included
    /// in the module tree of any target in `Cargo.toml`.
    pub fn crate_root(self, db: &dyn HirDatabase) -> Module {
        let def_map = crate_def_map(db, self.id.krate());
        Module { id: def_map.crate_root().into() }
    }

    pub fn is_crate_root(self) -> bool {
        DefMap::ROOT == self.id.local_id
    }

    /// Iterates over all child modules.
    pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> {
        let def_map = self.id.def_map(db);
        let children = def_map[self.id.local_id]
            .children
            .values()
            .map(|module_id| Module { id: def_map.module_id(*module_id) })
            .collect::<Vec<_>>();
        children.into_iter()
    }

    /// Finds a parent module.
    pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> {
        let def_map = self.id.def_map(db);
        let parent_id = def_map.containing_module(self.id.local_id)?;
        Some(Module { id: parent_id })
    }

    /// Finds nearest non-block ancestor `Module` (`self` included).
    pub fn nearest_non_block_module(self, db: &dyn HirDatabase) -> Module {
        let mut id = self.id;
        while id.is_block_module() {
            id = id.containing_module(db).expect("block without parent module");
        }
        Module { id }
    }

    pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> {
        let mut res = vec![self];
        let mut curr = self;
        while let Some(next) = curr.parent(db) {
            res.push(next);
            curr = next
        }
        res
    }

    /// Returns a `ModuleScope`: a set of items, visible in this module.
    pub fn scope(
        self,
        db: &dyn HirDatabase,
        visible_from: Option<Module>,
    ) -> Vec<(Name, ScopeDef)> {
        self.id.def_map(db)[self.id.local_id]
            .scope
            .entries()
            .filter_map(|(name, def)| {
                if let Some(m) = visible_from {
                    let filtered = def.filter_visibility(|vis| vis.is_visible_from(db, m.id));
                    if filtered.is_none() && !def.is_none() { None } else { Some((name, filtered)) }
                } else {
                    Some((name, def))
                }
            })
            .flat_map(|(name, def)| {
                ScopeDef::all_items(def).into_iter().map(move |item| (name.clone(), item))
            })
            .collect()
    }

    pub fn resolve_mod_path(
        &self,
        db: &dyn HirDatabase,
        segments: impl IntoIterator<Item = Name>,
    ) -> Option<impl Iterator<Item = ItemInNs>> {
        let items = self
            .id
            .resolver(db)
            .resolve_module_path_in_items(db, &ModPath::from_segments(PathKind::Plain, segments));
        Some(items.iter_items().map(|(item, _)| item.into()))
    }

    /// Fills `acc` with the module's diagnostics.
    pub fn diagnostics<'db>(
        self,
        db: &'db dyn HirDatabase,
        acc: &mut Vec<AnyDiagnostic<'db>>,
        style_lints: bool,
    ) {
        let _p = tracing::info_span!("diagnostics", name = ?self.name(db)).entered();
        let edition = self.id.krate().data(db).edition;
        let def_map = self.id.def_map(db);
        for diag in def_map.diagnostics() {
            if diag.in_module != self.id.local_id {
                // FIXME: This is accidentally quadratic.
                continue;
            }
            emit_def_diagnostic(db, acc, diag, edition);
        }

        if !self.id.is_block_module() {
            // These are reported by the body of block modules
            let scope = &def_map[self.id.local_id].scope;
            scope.all_macro_calls().for_each(|it| macro_call_diagnostics(db, it, acc));
        }

        for def in self.declarations(db) {
            match def {
                ModuleDef::Module(m) => {
                    // Only add diagnostics from inline modules
                    if def_map[m.id.local_id].origin.is_inline() {
                        m.diagnostics(db, acc, style_lints)
                    }
                    acc.extend(def.diagnostics(db, style_lints))
                }
                ModuleDef::Trait(t) => {
                    for diag in TraitItems::query_with_diagnostics(db, t.id).1.iter() {
                        emit_def_diagnostic(db, acc, diag, edition);
                    }

                    for item in t.items(db) {
                        item.diagnostics(db, acc, style_lints);
                    }

                    t.all_macro_calls(db)
                        .iter()
                        .for_each(|&(_ast, call_id)| macro_call_diagnostics(db, call_id, acc));

                    acc.extend(def.diagnostics(db, style_lints))
                }
                ModuleDef::Adt(adt) => {
                    match adt {
                        Adt::Struct(s) => {
                            let source_map = db.struct_signature_with_source_map(s.id).1;
                            expr_store_diagnostics(db, acc, &source_map);
                            let source_map = &s.id.fields_with_source_map(db).1;
                            expr_store_diagnostics(db, acc, source_map);
                            push_ty_diagnostics(
                                db,
                                acc,
                                db.field_types_with_diagnostics(s.id.into()).1,
                                source_map,
                            );
                        }
                        Adt::Union(u) => {
                            let source_map = db.union_signature_with_source_map(u.id).1;
                            expr_store_diagnostics(db, acc, &source_map);
                            let source_map = &u.id.fields_with_source_map(db).1;
                            expr_store_diagnostics(db, acc, source_map);
                            push_ty_diagnostics(
                                db,
                                acc,
                                db.field_types_with_diagnostics(u.id.into()).1,
                                source_map,
                            );
                        }
                        Adt::Enum(e) => {
                            let source_map = db.enum_signature_with_source_map(e.id).1;
                            expr_store_diagnostics(db, acc, &source_map);
                            let (variants, diagnostics) = e.id.enum_variants_with_diagnostics(db);
                            let file = e.id.lookup(db).id.file_id;
                            let ast_id_map = db.ast_id_map(file);
                            if let Some(diagnostics) = &diagnostics {
                                for diag in diagnostics.iter() {
                                    acc.push(
                                        InactiveCode {
                                            node: InFile::new(
                                                file,
                                                ast_id_map.get(diag.ast_id).syntax_node_ptr(),
                                            ),
                                            cfg: diag.cfg.clone(),
                                            opts: diag.opts.clone(),
                                        }
                                        .into(),
                                    );
                                }
                            }
                            for &(v, _, _) in &variants.variants {
                                let source_map = &v.fields_with_source_map(db).1;
                                push_ty_diagnostics(
                                    db,
                                    acc,
                                    db.field_types_with_diagnostics(v.into()).1,
                                    source_map,
                                );
                                expr_store_diagnostics(db, acc, source_map);
                            }
                        }
                    }
                    acc.extend(def.diagnostics(db, style_lints))
                }
                ModuleDef::Macro(m) => emit_macro_def_diagnostics(db, acc, m),
                ModuleDef::TypeAlias(type_alias) => {
                    let source_map = db.type_alias_signature_with_source_map(type_alias.id).1;
                    expr_store_diagnostics(db, acc, &source_map);
                    push_ty_diagnostics(
                        db,
                        acc,
                        db.type_for_type_alias_with_diagnostics(type_alias.id).1,
                        &source_map,
                    );
                    acc.extend(def.diagnostics(db, style_lints));
                }
                _ => acc.extend(def.diagnostics(db, style_lints)),
            }
        }
        self.legacy_macros(db).into_iter().for_each(|m| emit_macro_def_diagnostics(db, acc, m));

        let interner = DbInterner::new_with(db, Some(self.id.krate()), self.id.containing_block());
        let infcx = interner.infer_ctxt().build(TypingMode::non_body_analysis());

        let mut impl_assoc_items_scratch = vec![];
        for impl_def in self.impl_defs(db) {
            GenericDef::Impl(impl_def).diagnostics(db, acc);

            let loc = impl_def.id.lookup(db);
            let (impl_signature, source_map) = db.impl_signature_with_source_map(impl_def.id);
            expr_store_diagnostics(db, acc, &source_map);

            let file_id = loc.id.file_id;
            if file_id.macro_file().is_some_and(|it| it.kind(db) == MacroKind::DeriveBuiltIn) {
                // these expansion come from us, diagnosing them is a waste of resources
                // FIXME: Once we diagnose the inputs to builtin derives, we should at least extract those diagnostics somehow
                continue;
            }
            impl_def
                .all_macro_calls(db)
                .iter()
                .for_each(|&(_ast, call_id)| macro_call_diagnostics(db, call_id, acc));

            let ast_id_map = db.ast_id_map(file_id);

            for diag in impl_def.id.impl_items_with_diagnostics(db).1.iter() {
                emit_def_diagnostic(db, acc, diag, edition);
            }

            if impl_signature.target_trait.is_none()
                && !is_inherent_impl_coherent(db, def_map, impl_def.id)
            {
                acc.push(IncoherentImpl { impl_: ast_id_map.get(loc.id.value), file_id }.into())
            }

            if !impl_def.check_orphan_rules(db) {
                acc.push(TraitImplOrphan { impl_: ast_id_map.get(loc.id.value), file_id }.into())
            }

            let trait_ = impl_def.trait_(db);
            let mut trait_is_unsafe = trait_.is_some_and(|t| t.is_unsafe(db));
            let impl_is_negative = impl_def.is_negative(db);
            let impl_is_unsafe = impl_def.is_unsafe(db);

            let trait_is_unresolved = trait_.is_none() && impl_signature.target_trait.is_some();
            if trait_is_unresolved {
                // Ignore trait safety errors when the trait is unresolved, as otherwise we'll treat it as safe,
                // which may not be correct.
                trait_is_unsafe = impl_is_unsafe;
            }

            let drop_maybe_dangle = (|| {
                // FIXME: This can be simplified a lot by exposing hir-ty's utils.rs::Generics helper
                let trait_ = trait_?;
                let drop_trait = LangItem::Drop.resolve_trait(db, self.krate().into())?;
                if drop_trait != trait_.into() {
                    return None;
                }
                let parent = impl_def.id.into();
                let generic_params = db.generic_params(parent);
                let lifetime_params = generic_params.iter_lt().map(|(local_id, _)| {
                    GenericParamId::LifetimeParamId(LifetimeParamId { parent, local_id })
                });
                let type_params = generic_params
                    .iter_type_or_consts()
                    .filter(|(_, it)| it.type_param().is_some())
                    .map(|(local_id, _)| {
                        GenericParamId::TypeParamId(TypeParamId::from_unchecked(
                            TypeOrConstParamId { parent, local_id },
                        ))
                    });
                let res = type_params.chain(lifetime_params).any(|p| {
                    db.attrs(AttrDefId::GenericParamId(p)).by_key(sym::may_dangle).exists()
                });
                Some(res)
            })()
            .unwrap_or(false);

            match (impl_is_unsafe, trait_is_unsafe, impl_is_negative, drop_maybe_dangle) {
                // unsafe negative impl
                (true, _, true, _) |
                // unsafe impl for safe trait
                (true, false, _, false) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(loc.id.value), file_id, should_be_safe: true }.into()),
                // safe impl for unsafe trait
                (false, true, false, _) |
                // safe impl of dangling drop
                (false, false, _, true) => acc.push(TraitImplIncorrectSafety { impl_: ast_id_map.get(loc.id.value), file_id, should_be_safe: false }.into()),
                _ => (),
            };

            // Negative impls can't have items, don't emit missing items diagnostic for them
            if let (false, Some(trait_)) = (impl_is_negative, trait_) {
                let items = &trait_.id.trait_items(db).items;
                let required_items = items.iter().filter(|&(_, assoc)| match *assoc {
                    AssocItemId::FunctionId(it) => !db.function_signature(it).has_body(),
                    AssocItemId::ConstId(id) => !db.const_signature(id).has_body(),
                    AssocItemId::TypeAliasId(it) => db.type_alias_signature(it).ty.is_none(),
                });
                impl_assoc_items_scratch.extend(impl_def.id.impl_items(db).items.iter().cloned());

                let redundant = impl_assoc_items_scratch
                    .iter()
                    .filter(|(name, id)| {
                        !items.iter().any(|(impl_name, impl_item)| {
                            discriminant(impl_item) == discriminant(id) && impl_name == name
                        })
                    })
                    .map(|(name, item)| (name.clone(), AssocItem::from(*item)));
                for (name, assoc_item) in redundant {
                    acc.push(
                        TraitImplRedundantAssocItems {
                            trait_,
                            file_id,
                            impl_: ast_id_map.get(loc.id.value),
                            assoc_item: (name, assoc_item),
                        }
                        .into(),
                    )
                }

                let mut missing: Vec<_> = required_items
                    .filter(|(name, id)| {
                        !impl_assoc_items_scratch.iter().any(|(impl_name, impl_item)| {
                            discriminant(impl_item) == discriminant(id) && impl_name == name
                        })
                    })
                    .map(|(name, item)| (name.clone(), AssocItem::from(*item)))
                    .collect();

                if !missing.is_empty() {
                    let self_ty = db.impl_self_ty(impl_def.id).instantiate_identity();
                    let self_ty = structurally_normalize_ty(
                        &infcx,
                        self_ty,
                        db.trait_environment(impl_def.id.into()),
                    );
                    let self_ty_is_guaranteed_unsized = matches!(
                        self_ty.kind(),
                        TyKind::Dynamic(..) | TyKind::Slice(..) | TyKind::Str
                    );
                    if self_ty_is_guaranteed_unsized {
                        missing.retain(|(_, assoc_item)| {
                            let assoc_item = match *assoc_item {
                                AssocItem::Function(it) => it.id.into(),
                                AssocItem::Const(it) => it.id.into(),
                                AssocItem::TypeAlias(it) => it.id.into(),
                            };
                            !hir_ty::dyn_compatibility::generics_require_sized_self(db, assoc_item)
                        });
                    }
                }

                if !missing.is_empty() {
                    acc.push(
                        TraitImplMissingAssocItems {
                            impl_: ast_id_map.get(loc.id.value),
                            file_id,
                            missing,
                        }
                        .into(),
                    )
                }
                impl_assoc_items_scratch.clear();
            }

            push_ty_diagnostics(
                db,
                acc,
                db.impl_self_ty_with_diagnostics(impl_def.id).1,
                &source_map,
            );
            push_ty_diagnostics(
                db,
                acc,
                db.impl_trait_with_diagnostics(impl_def.id).and_then(|it| it.1),
                &source_map,
            );

            for &(_, item) in impl_def.id.impl_items(db).items.iter() {
                AssocItem::from(item).diagnostics(db, acc, style_lints);
            }
        }
    }

    pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> {
        let def_map = self.id.def_map(db);
        let scope = &def_map[self.id.local_id].scope;
        scope
            .declarations()
            .map(ModuleDef::from)
            .chain(scope.unnamed_consts().map(|id| ModuleDef::Const(Const::from(id))))
            .collect()
    }

    pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> {
        let def_map = self.id.def_map(db);
        let scope = &def_map[self.id.local_id].scope;
        scope.legacy_macros().flat_map(|(_, it)| it).map(|&it| it.into()).collect()
    }

    pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
        let def_map = self.id.def_map(db);
        def_map[self.id.local_id].scope.impls().map(Impl::from).collect()
    }

    /// Finds a path that can be used to refer to the given item from within
    /// this module, if possible.
    pub fn find_path(
        self,
        db: &dyn DefDatabase,
        item: impl Into<ItemInNs>,
        cfg: FindPathConfig,
    ) -> Option<ModPath> {
        hir_def::find_path::find_path(
            db,
            item.into().into(),
            self.into(),
            PrefixKind::Plain,
            false,
            cfg,
        )
    }

    /// Finds a path that can be used to refer to the given item from within
    /// this module, if possible. This is used for returning import paths for use-statements.
    pub fn find_use_path(
        self,
        db: &dyn DefDatabase,
        item: impl Into<ItemInNs>,
        prefix_kind: PrefixKind,
        cfg: FindPathConfig,
    ) -> Option<ModPath> {
        hir_def::find_path::find_path(db, item.into().into(), self.into(), prefix_kind, true, cfg)
    }
}

fn macro_call_diagnostics<'db>(
    db: &'db dyn HirDatabase,
    macro_call_id: MacroCallId,
    acc: &mut Vec<AnyDiagnostic<'db>>,
) {
    let Some(e) = db.parse_macro_expansion_error(macro_call_id) else {
        return;
    };
    let ValueResult { value: parse_errors, err } = &*e;
    if let Some(err) = err {
        let loc = db.lookup_intern_macro_call(macro_call_id);
        let file_id = loc.kind.file_id();
        let node =
            InFile::new(file_id, db.ast_id_map(file_id).get_erased(loc.kind.erased_ast_id()));
        let RenderedExpandError { message, error, kind } = err.render_to_string(db);
        let editioned_file_id = EditionedFileId::from_span(db, err.span().anchor.file_id);
        let precise_location = if editioned_file_id == file_id {
            Some(
                err.span().range
                    + db.ast_id_map(editioned_file_id.into())
                        .get_erased(err.span().anchor.ast_id)
                        .text_range()
                        .start(),
            )
        } else {
            None
        };
        acc.push(MacroError { node, precise_location, message, error, kind }.into());
    }

    if !parse_errors.is_empty() {
        let loc = db.lookup_intern_macro_call(macro_call_id);
        let (node, precise_location) = precise_macro_call_location(&loc.kind, db);
        acc.push(
            MacroExpansionParseError { node, precise_location, errors: parse_errors.clone() }
                .into(),
        )
    }
}

fn emit_macro_def_diagnostics<'db>(
    db: &'db dyn HirDatabase,
    acc: &mut Vec<AnyDiagnostic<'db>>,
    m: Macro,
) {
    let id = db.macro_def(m.id);
    if let hir_expand::db::TokenExpander::DeclarativeMacro(expander) = db.macro_expander(id)
        && let Some(e) = expander.mac.err()
    {
        let Some(ast) = id.ast_id().left() else {
            never!("declarative expander for non decl-macro: {:?}", e);
            return;
        };
        let krate = HasModule::krate(&m.id, db);
        let edition = krate.data(db).edition;
        emit_def_diagnostic_(
            db,
            acc,
            &DefDiagnosticKind::MacroDefError { ast, message: e.to_string() },
            edition,
        );
    }
}

fn emit_def_diagnostic<'db>(
    db: &'db dyn HirDatabase,
    acc: &mut Vec<AnyDiagnostic<'db>>,
    diag: &DefDiagnostic,
    edition: Edition,
) {
    emit_def_diagnostic_(db, acc, &diag.kind, edition)
}

fn emit_def_diagnostic_<'db>(
    db: &'db dyn HirDatabase,
    acc: &mut Vec<AnyDiagnostic<'db>>,
    diag: &DefDiagnosticKind,
    edition: Edition,
) {
    match diag {
        DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => {
            let decl = declaration.to_ptr(db);
            acc.push(
                UnresolvedModule {
                    decl: InFile::new(declaration.file_id, decl),
                    candidates: candidates.clone(),
                }
                .into(),
            )
        }
        DefDiagnosticKind::UnresolvedExternCrate { ast } => {
            let item = ast.to_ptr(db);
            acc.push(UnresolvedExternCrate { decl: InFile::new(ast.file_id, item) }.into());
        }

        DefDiagnosticKind::MacroError { ast, path, err } => {
            let item = ast.to_ptr(db);
            let RenderedExpandError { message, error, kind } = err.render_to_string(db);
            acc.push(
                MacroError {
                    node: InFile::new(ast.file_id, item.syntax_node_ptr()),
                    precise_location: None,
                    message: format!("{}: {message}", path.display(db, edition)),
                    error,
                    kind,
                }
                .into(),
            )
        }
        DefDiagnosticKind::UnresolvedImport { id, index } => {
            let file_id = id.file_id;

            let use_tree = hir_def::src::use_tree_to_ast(db, *id, *index);
            acc.push(
                UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }.into(),
            );
        }

        DefDiagnosticKind::UnconfiguredCode { ast_id, cfg, opts } => {
            let ast_id_map = db.ast_id_map(ast_id.file_id);
            let ptr = ast_id_map.get_erased(ast_id.value);
            acc.push(
                InactiveCode {
                    node: InFile::new(ast_id.file_id, ptr),
                    cfg: cfg.clone(),
                    opts: opts.clone(),
                }
                .into(),
            );
        }
        DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
            let (node, precise_location) = precise_macro_call_location(ast, db);
            acc.push(
                UnresolvedMacroCall {
                    macro_call: node,
                    precise_location,
                    path: path.clone(),
                    is_bang: matches!(ast, MacroCallKind::FnLike { .. }),
                }
                .into(),
            );
        }
        DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
            let node = ast.to_node(db);
            // Must have a name, otherwise we wouldn't emit it.
            let name = node.name().expect("unimplemented builtin macro with no name");
            acc.push(
                UnimplementedBuiltinMacro {
                    node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&name))),
                }
                .into(),
            );
        }
        DefDiagnosticKind::InvalidDeriveTarget { ast, id } => {
            let node = ast.to_node(db);
            let derive = node.attrs().nth(*id);
            match derive {
                Some(derive) => {
                    acc.push(
                        InvalidDeriveTarget {
                            node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
                        }
                        .into(),
                    );
                }
                None => stdx::never!("derive diagnostic on item without derive attribute"),
            }
        }
        DefDiagnosticKind::MalformedDerive { ast, id } => {
            let node = ast.to_node(db);
            let derive = node.attrs().nth(*id);
            match derive {
                Some(derive) => {
                    acc.push(
                        MalformedDerive {
                            node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
                        }
                        .into(),
                    );
                }
                None => stdx::never!("derive diagnostic on item without derive attribute"),
            }
        }
        DefDiagnosticKind::MacroDefError { ast, message } => {
            let node = ast.to_node(db);
            acc.push(
                MacroDefError {
                    node: InFile::new(ast.file_id, AstPtr::new(&node)),
                    name: node.name().map(|it| it.syntax().text_range()),
                    message: message.clone(),
                }
                .into(),
            );
        }
    }
}

fn precise_macro_call_location(
    ast: &MacroCallKind,
    db: &dyn HirDatabase,
) -> (InFile<SyntaxNodePtr>, Option<TextRange>) {
    // FIXME: maybe we actually want slightly different ranges for the different macro diagnostics
    // - e.g. the full attribute for macro errors, but only the name for name resolution
    match ast {
        MacroCallKind::FnLike { ast_id, .. } => {
            let node = ast_id.to_node(db);
            (
                ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
                node.path()
                    .and_then(|it| it.segment())
                    .and_then(|it| it.name_ref())
                    .map(|it| it.syntax().text_range()),
            )
        }
        MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
            let node = ast_id.to_node(db);
            // Compute the precise location of the macro name's token in the derive
            // list.
            let token = (|| {
                let derive_attr = collect_attrs(&node)
                    .nth(derive_attr_index.ast_index())
                    .and_then(|x| Either::left(x.1))?;
                let token_tree = derive_attr.meta()?.token_tree()?;
                let chunk_by = token_tree
                    .syntax()
                    .children_with_tokens()
                    .filter_map(|elem| match elem {
                        syntax::NodeOrToken::Token(tok) => Some(tok),
                        _ => None,
                    })
                    .chunk_by(|t| t.kind() == T![,]);
                let (_, mut group) = chunk_by
                    .into_iter()
                    .filter(|&(comma, _)| !comma)
                    .nth(*derive_index as usize)?;
                group.find(|t| t.kind() == T![ident])
            })();
            (
                ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
                token.as_ref().map(|tok| tok.text_range()),
            )
        }
        MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
            let node = ast_id.to_node(db);
            let attr = collect_attrs(&node)
                .nth(invoc_attr_index.ast_index())
                .and_then(|x| Either::left(x.1))
                .unwrap_or_else(|| {
                    panic!("cannot find attribute #{}", invoc_attr_index.ast_index())
                });

            (
                ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
                Some(attr.syntax().text_range()),
            )
        }
    }
}

impl HasVisibility for Module {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        let def_map = self.id.def_map(db);
        let module_data = &def_map[self.id.local_id];
        module_data.visibility
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Field {
    pub(crate) parent: VariantDef,
    pub(crate) id: LocalFieldId,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InstantiatedField<'db> {
    pub(crate) inner: Field,
    pub(crate) args: GenericArgs<'db>,
}

impl<'db> InstantiatedField<'db> {
    /// Returns the type as in the signature of the struct.
    pub fn ty(&self, db: &'db dyn HirDatabase) -> TypeNs<'db> {
        let krate = self.inner.krate(db);
        let interner = DbInterner::new_with(db, Some(krate.base()), None);

        let var_id = self.inner.parent.into();
        let field = db.field_types(var_id)[self.inner.id];
        let ty = field.instantiate(interner, self.args);
        TypeNs::new(db, var_id, ty)
    }
}

#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
pub struct TupleField {
    pub owner: DefWithBodyId,
    pub tuple: TupleId,
    pub index: u32,
}

impl TupleField {
    pub fn name(&self) -> Name {
        Name::new_tuple_field(self.index as usize)
    }

    pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
        let interner = DbInterner::new_with(db, None, None);
        let ty = db
            .infer(self.owner)
            .tuple_field_access_type(self.tuple)
            .as_slice()
            .get(self.index as usize)
            .copied()
            .unwrap_or_else(|| Ty::new_error(interner, ErrorGuaranteed));
        Type { env: db.trait_environment_for_body(self.owner), ty }
    }
}

#[derive(Debug, PartialEq, Eq)]
pub enum FieldSource {
    Named(ast::RecordField),
    Pos(ast::TupleField),
}

impl AstNode for FieldSource {
    fn can_cast(kind: syntax::SyntaxKind) -> bool
    where
        Self: Sized,
    {
        ast::RecordField::can_cast(kind) || ast::TupleField::can_cast(kind)
    }

    fn cast(syntax: SyntaxNode) -> Option<Self>
    where
        Self: Sized,
    {
        if ast::RecordField::can_cast(syntax.kind()) {
            <ast::RecordField as AstNode>::cast(syntax).map(FieldSource::Named)
        } else if ast::TupleField::can_cast(syntax.kind()) {
            <ast::TupleField as AstNode>::cast(syntax).map(FieldSource::Pos)
        } else {
            None
        }
    }

    fn syntax(&self) -> &SyntaxNode {
        match self {
            FieldSource::Named(it) => it.syntax(),
            FieldSource::Pos(it) => it.syntax(),
        }
    }
}

impl Field {
    pub fn name(&self, db: &dyn HirDatabase) -> Name {
        VariantId::from(self.parent).fields(db).fields()[self.id].name.clone()
    }

    pub fn index(&self) -> usize {
        u32::from(self.id.into_raw()) as usize
    }

    /// Returns the type as in the signature of the struct. Only use this in the
    /// context of the field definition.
    pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> TypeNs<'db> {
        let var_id = self.parent.into();
        let ty = db.field_types(var_id)[self.id].skip_binder();
        TypeNs::new(db, var_id, ty)
    }

    // FIXME: Find better API to also handle const generics
    pub fn ty_with_args<'db>(
        &self,
        db: &'db dyn HirDatabase,
        generics: impl Iterator<Item = Type<'db>>,
    ) -> Type<'db> {
        let var_id = self.parent.into();
        let def_id: AdtId = match self.parent {
            VariantDef::Struct(it) => it.id.into(),
            VariantDef::Union(it) => it.id.into(),
            VariantDef::Variant(it) => it.parent_enum(db).id.into(),
        };
        let interner = DbInterner::new_with(db, None, None);
        let args = generic_args_from_tys(interner, def_id.into(), generics.map(|ty| ty.ty));
        let ty = db.field_types(var_id)[self.id].instantiate(interner, args);
        Type::new(db, var_id, ty)
    }

    pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
        db.layout_of_ty(
            self.ty(db).ty,
            db.trait_environment(match hir_def::VariantId::from(self.parent) {
                hir_def::VariantId::EnumVariantId(id) => {
                    GenericDefId::AdtId(id.lookup(db).parent.into())
                }
                hir_def::VariantId::StructId(id) => GenericDefId::AdtId(id.into()),
                hir_def::VariantId::UnionId(id) => GenericDefId::AdtId(id.into()),
            }),
        )
        .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).into()).unwrap()))
    }

    pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
        self.parent
    }
}

impl HasVisibility for Field {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        let variant_data = VariantId::from(self.parent).fields(db);
        let visibility = &variant_data.fields()[self.id].visibility;
        let parent_id: hir_def::VariantId = self.parent.into();
        // FIXME: RawVisibility::Public doesn't need to construct a resolver
        Visibility::resolve(db, &parent_id.resolver(db), visibility)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Struct {
    pub(crate) id: StructId,
}

impl Struct {
    pub fn module(self, db: &dyn HirDatabase) -> Module {
        Module { id: self.id.lookup(db).container }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        db.struct_signature(self.id).name.clone()
    }

    pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
        self.id
            .fields(db)
            .fields()
            .iter()
            .map(|(id, _)| Field { parent: self.into(), id })
            .collect()
    }

    pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::from_def(db, self.id)
    }

    pub fn ty_params(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::from_def_params(db, self.id)
    }

    pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::from_value_def(db, self.id)
    }

    pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
        db.struct_signature(self.id).repr
    }

    pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
        match self.variant_fields(db).shape {
            hir_def::item_tree::FieldsShape::Record => StructKind::Record,
            hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
            hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
        }
    }

    fn variant_fields(self, db: &dyn HirDatabase) -> &VariantFields {
        self.id.fields(db)
    }

    pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
        db.attrs(self.id.into()).is_unstable()
    }

    pub fn instantiate_infer<'db>(self, infer_ctxt: &InferCtxt<'db>) -> InstantiatedStruct<'db> {
        let args = infer_ctxt.fresh_args_for_item(self.id.into());
        InstantiatedStruct { inner: self, args }
    }
}

impl HasVisibility for Struct {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        let loc = self.id.lookup(db);
        let source = loc.source(db);
        visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InstantiatedStruct<'db> {
    pub(crate) inner: Struct,
    pub(crate) args: GenericArgs<'db>,
}

impl<'db> InstantiatedStruct<'db> {
    pub fn fields(self, db: &dyn HirDatabase) -> Vec<InstantiatedField<'db>> {
        self.inner
            .id
            .fields(db)
            .fields()
            .iter()
            .map(|(id, _)| InstantiatedField {
                inner: Field { parent: self.inner.into(), id },
                args: self.args,
            })
            .collect()
    }

    pub fn ty(self, db: &'db dyn HirDatabase) -> TypeNs<'db> {
        let krate = self.inner.krate(db);
        let interner = DbInterner::new_with(db, Some(krate.base()), None);

        let ty = db.ty(self.inner.id.into());
        TypeNs::new(db, self.inner.id, ty.instantiate(interner, self.args))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Union {
    pub(crate) id: UnionId,
}

impl Union {
    pub fn name(self, db: &dyn HirDatabase) -> Name {
        db.union_signature(self.id).name.clone()
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        Module { id: self.id.lookup(db).container }
    }

    pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::from_def(db, self.id)
    }

    pub fn ty_params(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::from_def_params(db, self.id)
    }

    pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::from_value_def(db, self.id)
    }

    pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
        match self.id.fields(db).shape {
            hir_def::item_tree::FieldsShape::Record => StructKind::Record,
            hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
            hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
        }
    }

    pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
        self.id
            .fields(db)
            .fields()
            .iter()
            .map(|(id, _)| Field { parent: self.into(), id })
            .collect()
    }
    pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
        db.attrs(self.id.into()).is_unstable()
    }
}

impl HasVisibility for Union {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        let loc = self.id.lookup(db);
        let source = loc.source(db);
        visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Enum {
    pub(crate) id: EnumId,
}

impl Enum {
    pub fn module(self, db: &dyn HirDatabase) -> Module {
        Module { id: self.id.lookup(db).container }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        db.enum_signature(self.id).name.clone()
    }

    pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> {
        self.id.enum_variants(db).variants.iter().map(|&(id, _, _)| Variant { id }).collect()
    }

    pub fn num_variants(self, db: &dyn HirDatabase) -> usize {
        self.id.enum_variants(db).variants.len()
    }

    pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprOptions> {
        db.enum_signature(self.id).repr
    }

    pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
        Type::from_def(db, self.id)
    }

    pub fn ty_params<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
        Type::from_def_params(db, self.id)
    }

    /// The type of the enum variant bodies.
    pub fn variant_body_ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
        let interner = DbInterner::new_with(db, None, None);
        Type::new_for_crate(
            self.id.lookup(db).container.krate(),
            match db.enum_signature(self.id).variant_body_type() {
                layout::IntegerType::Pointer(sign) => match sign {
                    true => Ty::new_int(interner, rustc_type_ir::IntTy::Isize),
                    false => Ty::new_uint(interner, rustc_type_ir::UintTy::Usize),
                },
                layout::IntegerType::Fixed(i, sign) => match sign {
                    true => Ty::new_int(
                        interner,
                        match i {
                            layout::Integer::I8 => rustc_type_ir::IntTy::I8,
                            layout::Integer::I16 => rustc_type_ir::IntTy::I16,
                            layout::Integer::I32 => rustc_type_ir::IntTy::I32,
                            layout::Integer::I64 => rustc_type_ir::IntTy::I64,
                            layout::Integer::I128 => rustc_type_ir::IntTy::I128,
                        },
                    ),
                    false => Ty::new_uint(
                        interner,
                        match i {
                            layout::Integer::I8 => rustc_type_ir::UintTy::U8,
                            layout::Integer::I16 => rustc_type_ir::UintTy::U16,
                            layout::Integer::I32 => rustc_type_ir::UintTy::U32,
                            layout::Integer::I64 => rustc_type_ir::UintTy::U64,
                            layout::Integer::I128 => rustc_type_ir::UintTy::U128,
                        },
                    ),
                },
            },
        )
    }

    /// Returns true if at least one variant of this enum is a non-unit variant.
    pub fn is_data_carrying(self, db: &dyn HirDatabase) -> bool {
        self.variants(db).iter().any(|v| !matches!(v.kind(db), StructKind::Unit))
    }

    pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
        Adt::from(self).layout(db)
    }

    pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
        db.attrs(self.id.into()).is_unstable()
    }
}

impl HasVisibility for Enum {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        let loc = self.id.lookup(db);
        let source = loc.source(db);
        visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InstantiatedEnum<'db> {
    pub(crate) inner: Enum,
    pub(crate) args: GenericArgs<'db>,
}

impl<'db> InstantiatedEnum<'db> {
    pub fn ty(self, db: &'db dyn HirDatabase) -> TypeNs<'db> {
        let krate = self.inner.krate(db);
        let interner = DbInterner::new_with(db, Some(krate.base()), None);

        let ty = db.ty(self.inner.id.into());
        TypeNs::new(db, self.inner.id, ty.instantiate(interner, self.args))
    }
}

impl From<&Variant> for DefWithBodyId {
    fn from(&v: &Variant) -> Self {
        DefWithBodyId::VariantId(v.into())
    }
}

// FIXME: Rename to `EnumVariant`
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Variant {
    pub(crate) id: EnumVariantId,
}

impl Variant {
    pub fn module(self, db: &dyn HirDatabase) -> Module {
        Module { id: self.id.module(db) }
    }

    pub fn parent_enum(self, db: &dyn HirDatabase) -> Enum {
        self.id.lookup(db).parent.into()
    }

    pub fn constructor_ty(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::from_value_def(db, self.id)
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        let lookup = self.id.lookup(db);
        let enum_ = lookup.parent;
        enum_.enum_variants(db).variants[lookup.index as usize].1.clone()
    }

    pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
        self.id
            .fields(db)
            .fields()
            .iter()
            .map(|(id, _)| Field { parent: self.into(), id })
            .collect()
    }

    pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
        match self.id.fields(db).shape {
            hir_def::item_tree::FieldsShape::Record => StructKind::Record,
            hir_def::item_tree::FieldsShape::Tuple => StructKind::Tuple,
            hir_def::item_tree::FieldsShape::Unit => StructKind::Unit,
        }
    }

    pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
        self.source(db)?.value.expr()
    }

    pub fn eval(self, db: &dyn HirDatabase) -> Result<i128, ConstEvalError<'_>> {
        db.const_eval_discriminant(self.into())
    }

    pub fn layout(&self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
        let parent_enum = self.parent_enum(db);
        let parent_layout = parent_enum.layout(db)?;
        Ok(match &parent_layout.0.variants {
            layout::Variants::Multiple { variants, .. } => Layout(
                {
                    let lookup = self.id.lookup(db);
                    let rustc_enum_variant_idx = RustcEnumVariantIdx(lookup.index as usize);
                    Arc::new(variants[rustc_enum_variant_idx].clone())
                },
                db.target_data_layout(parent_enum.krate(db).into()).unwrap(),
            ),
            _ => parent_layout,
        })
    }

    pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
        db.attrs(self.id.into()).is_unstable()
    }

    pub fn instantiate_infer<'db>(self, infer_ctxt: &InferCtxt<'db>) -> InstantiatedVariant<'db> {
        let args =
            infer_ctxt.fresh_args_for_item(self.parent_enum(infer_ctxt.interner.db()).id.into());
        InstantiatedVariant { inner: self, args }
    }
}

// FIXME: Rename to `EnumVariant`
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct InstantiatedVariant<'db> {
    pub(crate) inner: Variant,
    pub(crate) args: GenericArgs<'db>,
}

impl<'db> InstantiatedVariant<'db> {
    pub fn parent_enum(self, db: &dyn HirDatabase) -> InstantiatedEnum<'db> {
        InstantiatedEnum { inner: self.inner.id.lookup(db).parent.into(), args: self.args }
    }

    pub fn fields(self, db: &dyn HirDatabase) -> Vec<InstantiatedField<'db>> {
        self.inner
            .id
            .fields(db)
            .fields()
            .iter()
            .map(|(id, _)| InstantiatedField {
                inner: Field { parent: self.inner.into(), id },
                args: self.args,
            })
            .collect()
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum StructKind {
    Record,
    Tuple,
    Unit,
}

/// Variants inherit visibility from the parent enum.
impl HasVisibility for Variant {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        self.parent_enum(db).visibility(db)
    }
}

/// A Data Type
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum Adt {
    Struct(Struct),
    Union(Union),
    Enum(Enum),
}
impl_from!(Struct, Union, Enum for Adt);

impl Adt {
    pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
        has_non_default_type_params(db, self.into())
    }

    pub fn layout(self, db: &dyn HirDatabase) -> Result<Layout, LayoutError> {
        let env = db.trait_environment(self.into());
        let interner = DbInterner::new_with(db, Some(env.krate), env.block);
        let adt_id = AdtId::from(self);
        let args = GenericArgs::for_item_with_defaults(interner, adt_id.into(), |_, id, _| {
            GenericArg::error_from_id(interner, id)
        });
        db.layout_of_adt(adt_id, args, env)
            .map(|layout| Layout(layout, db.target_data_layout(self.krate(db).id).unwrap()))
    }

    /// Turns this ADT into a type. Any type parameters of the ADT will be
    /// turned into unknown types, which is good for e.g. finding the most
    /// general set of completions, but will not look very nice when printed.
    pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
        let id = AdtId::from(self);
        Type::from_def(db, id)
    }

    /// Turns this ADT into a type with the given type parameters. This isn't
    /// the greatest API, FIXME find a better one.
    pub fn ty_with_args<'db>(
        self,
        db: &'db dyn HirDatabase,
        args: impl IntoIterator<Item = Type<'db>>,
    ) -> Type<'db> {
        let id = AdtId::from(self);
        let interner = DbInterner::new_with(db, None, None);
        let ty = Ty::new_adt(
            interner,
            id,
            generic_args_from_tys(interner, id.into(), args.into_iter().map(|ty| ty.ty)),
        );
        Type::new(db, id, ty)
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        match self {
            Adt::Struct(s) => s.module(db),
            Adt::Union(s) => s.module(db),
            Adt::Enum(e) => e.module(db),
        }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        match self {
            Adt::Struct(s) => s.name(db),
            Adt::Union(u) => u.name(db),
            Adt::Enum(e) => e.name(db),
        }
    }

    /// Returns the lifetime of the DataType
    pub fn lifetime(&self, db: &dyn HirDatabase) -> Option<LifetimeParamData> {
        let resolver = match self {
            Adt::Struct(s) => s.id.resolver(db),
            Adt::Union(u) => u.id.resolver(db),
            Adt::Enum(e) => e.id.resolver(db),
        };
        resolver
            .generic_params()
            .and_then(|gp| {
                gp.iter_lt()
                    // there should only be a single lifetime
                    // but `Arena` requires to use an iterator
                    .nth(0)
            })
            .map(|arena| arena.1.clone())
    }

    pub fn as_struct(&self) -> Option<Struct> {
        if let Self::Struct(v) = self { Some(*v) } else { None }
    }

    pub fn as_enum(&self) -> Option<Enum> {
        if let Self::Enum(v) = self { Some(*v) } else { None }
    }
}

impl HasVisibility for Adt {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        match self {
            Adt::Struct(it) => it.visibility(db),
            Adt::Union(it) => it.visibility(db),
            Adt::Enum(it) => it.visibility(db),
        }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum VariantDef {
    Struct(Struct),
    Union(Union),
    Variant(Variant),
}
impl_from!(Struct, Union, Variant for VariantDef);

impl VariantDef {
    pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
        match self {
            VariantDef::Struct(it) => it.fields(db),
            VariantDef::Union(it) => it.fields(db),
            VariantDef::Variant(it) => it.fields(db),
        }
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        match self {
            VariantDef::Struct(it) => it.module(db),
            VariantDef::Union(it) => it.module(db),
            VariantDef::Variant(it) => it.module(db),
        }
    }

    pub fn name(&self, db: &dyn HirDatabase) -> Name {
        match self {
            VariantDef::Struct(s) => s.name(db),
            VariantDef::Union(u) => u.name(db),
            VariantDef::Variant(e) => e.name(db),
        }
    }
}

/// The defs which have a body.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum DefWithBody {
    Function(Function),
    Static(Static),
    Const(Const),
    Variant(Variant),
}
impl_from!(Function, Const, Static, Variant for DefWithBody);

impl DefWithBody {
    pub fn module(self, db: &dyn HirDatabase) -> Module {
        match self {
            DefWithBody::Const(c) => c.module(db),
            DefWithBody::Function(f) => f.module(db),
            DefWithBody::Static(s) => s.module(db),
            DefWithBody::Variant(v) => v.module(db),
        }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
        match self {
            DefWithBody::Function(f) => Some(f.name(db)),
            DefWithBody::Static(s) => Some(s.name(db)),
            DefWithBody::Const(c) => c.name(db),
            DefWithBody::Variant(v) => Some(v.name(db)),
        }
    }

    /// Returns the type this def's body has to evaluate to.
    pub fn body_type(self, db: &dyn HirDatabase) -> Type<'_> {
        match self {
            DefWithBody::Function(it) => it.ret_type(db),
            DefWithBody::Static(it) => it.ty(db),
            DefWithBody::Const(it) => it.ty(db),
            DefWithBody::Variant(it) => it.parent_enum(db).variant_body_ty(db),
        }
    }

    fn id(&self) -> DefWithBodyId {
        match self {
            DefWithBody::Function(it) => it.id.into(),
            DefWithBody::Static(it) => it.id.into(),
            DefWithBody::Const(it) => it.id.into(),
            DefWithBody::Variant(it) => it.into(),
        }
    }

    /// A textual representation of the HIR of this def's body for debugging purposes.
    pub fn debug_hir(self, db: &dyn HirDatabase) -> String {
        let body = db.body(self.id());
        body.pretty_print(db, self.id(), Edition::CURRENT)
    }

    /// A textual representation of the MIR of this def's body for debugging purposes.
    pub fn debug_mir(self, db: &dyn HirDatabase) -> String {
        let body = db.mir_body(self.id());
        match body {
            Ok(body) => body.pretty_print(db, self.module(db).krate().to_display_target(db)),
            Err(e) => format!("error:\n{e:?}"),
        }
    }

    pub fn diagnostics<'db>(
        self,
        db: &'db dyn HirDatabase,
        acc: &mut Vec<AnyDiagnostic<'db>>,
        style_lints: bool,
    ) {
        let krate = self.module(db).id.krate();

        let (body, source_map) = db.body_with_source_map(self.into());
        let sig_source_map = match self {
            DefWithBody::Function(id) => db.function_signature_with_source_map(id.into()).1,
            DefWithBody::Static(id) => db.static_signature_with_source_map(id.into()).1,
            DefWithBody::Const(id) => db.const_signature_with_source_map(id.into()).1,
            DefWithBody::Variant(variant) => {
                let enum_id = variant.parent_enum(db).id;
                db.enum_signature_with_source_map(enum_id).1
            }
        };

        for (_, def_map) in body.blocks(db) {
            Module { id: def_map.module_id(DefMap::ROOT) }.diagnostics(db, acc, style_lints);
        }

        expr_store_diagnostics(db, acc, &source_map);

        let infer = db.infer(self.into());
        for d in infer.diagnostics() {
            acc.extend(AnyDiagnostic::inference_diagnostic(
                db,
                self.into(),
                d,
                &source_map,
                &sig_source_map,
            ));
        }

        for (pat_or_expr, mismatch) in infer.type_mismatches() {
            let expr_or_pat = match pat_or_expr {
                ExprOrPatId::ExprId(expr) => source_map.expr_syntax(expr).map(Either::Left),
                ExprOrPatId::PatId(pat) => source_map.pat_syntax(pat).map(Either::Right),
            };
            let expr_or_pat = match expr_or_pat {
                Ok(Either::Left(expr)) => expr,
                Ok(Either::Right(InFile { file_id, value: pat })) => {
                    // cast from Either<Pat, SelfParam> -> Either<_, Pat>
                    let Some(ptr) = AstPtr::try_from_raw(pat.syntax_node_ptr()) else {
                        continue;
                    };
                    InFile { file_id, value: ptr }
                }
                Err(SyntheticSyntax) => continue,
            };

            acc.push(
                TypeMismatch {
                    expr_or_pat,
                    expected: Type::new(db, DefWithBodyId::from(self), mismatch.expected),
                    actual: Type::new(db, DefWithBodyId::from(self), mismatch.actual),
                }
                .into(),
            );
        }

        let missing_unsafe = hir_ty::diagnostics::missing_unsafe(db, self.into());
        for (node, reason) in missing_unsafe.unsafe_exprs {
            match source_map.expr_or_pat_syntax(node) {
                Ok(node) => acc.push(
                    MissingUnsafe {
                        node,
                        lint: if missing_unsafe.fn_is_unsafe {
                            UnsafeLint::UnsafeOpInUnsafeFn
                        } else {
                            UnsafeLint::HardError
                        },
                        reason,
                    }
                    .into(),
                ),
                Err(SyntheticSyntax) => {
                    // FIXME: Here and elsewhere in this file, the `expr` was
                    // desugared, report or assert that this doesn't happen.
                }
            }
        }
        for node in missing_unsafe.deprecated_safe_calls {
            match source_map.expr_syntax(node) {
                Ok(node) => acc.push(
                    MissingUnsafe {
                        node,
                        lint: UnsafeLint::DeprecatedSafe2024,
                        reason: UnsafetyReason::UnsafeFnCall,
                    }
                    .into(),
                ),
                Err(SyntheticSyntax) => never!("synthetic DeprecatedSafe2024"),
            }
        }

        if let Ok(borrowck_results) = db.borrowck(self.into()) {
            for borrowck_result in borrowck_results.iter() {
                let mir_body = &borrowck_result.mir_body;
                for moof in &borrowck_result.moved_out_of_ref {
                    let span: InFile<SyntaxNodePtr> = match moof.span {
                        mir::MirSpan::ExprId(e) => match source_map.expr_syntax(e) {
                            Ok(s) => s.map(|it| it.into()),
                            Err(_) => continue,
                        },
                        mir::MirSpan::PatId(p) => match source_map.pat_syntax(p) {
                            Ok(s) => s.map(|it| it.into()),
                            Err(_) => continue,
                        },
                        mir::MirSpan::SelfParam => match source_map.self_param_syntax() {
                            Some(s) => s.map(|it| it.into()),
                            None => continue,
                        },
                        mir::MirSpan::BindingId(b) => {
                            match source_map
                                .patterns_for_binding(b)
                                .iter()
                                .find_map(|p| source_map.pat_syntax(*p).ok())
                            {
                                Some(s) => s.map(|it| it.into()),
                                None => continue,
                            }
                        }
                        mir::MirSpan::Unknown => continue,
                    };
                    acc.push(MovedOutOfRef { ty: Type::new_for_crate(krate, moof.ty), span }.into())
                }
                let mol = &borrowck_result.mutability_of_locals;
                for (binding_id, binding_data) in body.bindings() {
                    if binding_data.problems.is_some() {
                        // We should report specific diagnostics for these problems, not `need-mut` and `unused-mut`.
                        continue;
                    }
                    let Some(&local) = mir_body.binding_locals.get(binding_id) else {
                        continue;
                    };
                    if source_map
                        .patterns_for_binding(binding_id)
                        .iter()
                        .any(|&pat| source_map.pat_syntax(pat).is_err())
                    {
                        // Skip synthetic bindings
                        continue;
                    }
                    let mut need_mut = &mol[local];
                    if body[binding_id].name == sym::self_
                        && need_mut == &mir::MutabilityReason::Unused
                    {
                        need_mut = &mir::MutabilityReason::Not;
                    }
                    let local = Local { parent: self.into(), binding_id };
                    let is_mut = body[binding_id].mode == BindingAnnotation::Mutable;

                    match (need_mut, is_mut) {
                        (mir::MutabilityReason::Unused, _) => {
                            let should_ignore = body[binding_id].name.as_str().starts_with('_');
                            if !should_ignore {
                                acc.push(UnusedVariable { local }.into())
                            }
                        }
                        (mir::MutabilityReason::Mut { .. }, true)
                        | (mir::MutabilityReason::Not, false) => (),
                        (mir::MutabilityReason::Mut { spans }, false) => {
                            for span in spans {
                                let span: InFile<SyntaxNodePtr> = match span {
                                    mir::MirSpan::ExprId(e) => match source_map.expr_syntax(*e) {
                                        Ok(s) => s.map(|it| it.into()),
                                        Err(_) => continue,
                                    },
                                    mir::MirSpan::PatId(p) => match source_map.pat_syntax(*p) {
                                        Ok(s) => s.map(|it| it.into()),
                                        Err(_) => continue,
                                    },
                                    mir::MirSpan::BindingId(b) => {
                                        match source_map
                                            .patterns_for_binding(*b)
                                            .iter()
                                            .find_map(|p| source_map.pat_syntax(*p).ok())
                                        {
                                            Some(s) => s.map(|it| it.into()),
                                            None => continue,
                                        }
                                    }
                                    mir::MirSpan::SelfParam => match source_map.self_param_syntax()
                                    {
                                        Some(s) => s.map(|it| it.into()),
                                        None => continue,
                                    },
                                    mir::MirSpan::Unknown => continue,
                                };
                                acc.push(NeedMut { local, span }.into());
                            }
                        }
                        (mir::MutabilityReason::Not, true) => {
                            if !infer.mutated_bindings_in_closure.contains(&binding_id) {
                                let should_ignore = body[binding_id].name.as_str().starts_with('_');
                                if !should_ignore {
                                    acc.push(UnusedMut { local }.into())
                                }
                            }
                        }
                    }
                }
            }
        }

        for diagnostic in BodyValidationDiagnostic::collect(db, self.into(), style_lints) {
            acc.extend(AnyDiagnostic::body_validation_diagnostic(db, diagnostic, &source_map));
        }

        let def: ModuleDef = match self {
            DefWithBody::Function(it) => it.into(),
            DefWithBody::Static(it) => it.into(),
            DefWithBody::Const(it) => it.into(),
            DefWithBody::Variant(it) => it.into(),
        };
        for diag in hir_ty::diagnostics::incorrect_case(db, def.into()) {
            acc.push(diag.into())
        }
    }
}

fn expr_store_diagnostics<'db>(
    db: &'db dyn HirDatabase,
    acc: &mut Vec<AnyDiagnostic<'db>>,
    source_map: &ExpressionStoreSourceMap,
) {
    for diag in source_map.diagnostics() {
        acc.push(match diag {
            ExpressionStoreDiagnostics::InactiveCode { node, cfg, opts } => {
                InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into()
            }
            ExpressionStoreDiagnostics::UnresolvedMacroCall { node, path } => UnresolvedMacroCall {
                macro_call: (*node).map(|ast_ptr| ast_ptr.into()),
                precise_location: None,
                path: path.clone(),
                is_bang: true,
            }
            .into(),
            ExpressionStoreDiagnostics::AwaitOutsideOfAsync { node, location } => {
                AwaitOutsideOfAsync { node: *node, location: location.clone() }.into()
            }
            ExpressionStoreDiagnostics::UnreachableLabel { node, name } => {
                UnreachableLabel { node: *node, name: name.clone() }.into()
            }
            ExpressionStoreDiagnostics::UndeclaredLabel { node, name } => {
                UndeclaredLabel { node: *node, name: name.clone() }.into()
            }
        });
    }

    source_map
        .macro_calls()
        .for_each(|(_ast_id, call_id)| macro_call_diagnostics(db, call_id, acc));
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Function {
    pub(crate) id: FunctionId,
}

impl Function {
    pub fn module(self, db: &dyn HirDatabase) -> Module {
        self.id.module(db).into()
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        db.function_signature(self.id).name.clone()
    }

    pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::from_value_def(db, self.id)
    }

    pub fn fn_ptr_type(self, db: &dyn HirDatabase) -> Type<'_> {
        let resolver = self.id.resolver(db);
        let interner = DbInterner::new_with(db, None, None);
        // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
        let callable_sig = db.callable_item_signature(self.id.into()).instantiate_identity();
        let ty = Ty::new_fn_ptr(interner, callable_sig);
        Type::new_with_resolver_inner(db, &resolver, ty)
    }

    // FIXME: Find a better API to express all combinations here, perhaps we should have `PreInstantiationType`?

    /// Get this function's return type
    pub fn ret_type(self, db: &dyn HirDatabase) -> Type<'_> {
        let resolver = self.id.resolver(db);
        // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
        let ty = db
            .callable_item_signature(self.id.into())
            .instantiate_identity()
            .skip_binder()
            .output();
        Type::new_with_resolver_inner(db, &resolver, ty)
    }

    // FIXME: Find better API to also handle const generics
    pub fn ret_type_with_args<'db>(
        self,
        db: &'db dyn HirDatabase,
        generics: impl Iterator<Item = Type<'db>>,
    ) -> Type<'db> {
        let resolver = self.id.resolver(db);
        let interner = DbInterner::new_with(db, None, None);
        let args = generic_args_from_tys(interner, self.id.into(), generics.map(|ty| ty.ty));

        let interner = DbInterner::new_with(db, None, None);
        let ty = db
            .callable_item_signature(self.id.into())
            .instantiate(interner, args)
            .skip_binder()
            .output();
        Type::new_with_resolver_inner(db, &resolver, ty)
    }

    pub fn async_ret_type<'db>(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
        if !self.is_async(db) {
            return None;
        }
        let resolver = self.id.resolver(db);
        // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
        let ret_ty = db
            .callable_item_signature(self.id.into())
            .instantiate_identity()
            .skip_binder()
            .output();
        for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() {
            if let ClauseKind::Projection(projection) = pred.kind().skip_binder()
                && let Some(output_ty) = projection.term.as_type()
            {
                return Type::new_with_resolver_inner(db, &resolver, output_ty).into();
            }
        }
        None
    }

    pub fn has_self_param(self, db: &dyn HirDatabase) -> bool {
        db.function_signature(self.id).has_self_param()
    }

    pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
        self.has_self_param(db).then_some(SelfParam { func: self.id })
    }

    pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param<'_>> {
        let environment = db.trait_environment(self.id.into());
        // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
        let callable_sig =
            db.callable_item_signature(self.id.into()).instantiate_identity().skip_binder();
        callable_sig
            .inputs()
            .iter()
            .enumerate()
            .map(|(idx, ty)| {
                let ty = Type { env: environment.clone(), ty };
                Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
            })
            .collect()
    }

    pub fn num_params(self, db: &dyn HirDatabase) -> usize {
        db.function_signature(self.id).params.len()
    }

    pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param<'_>>> {
        self.self_param(db)?;
        Some(self.params_without_self(db))
    }

    pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec<Param<'_>> {
        let environment = db.trait_environment(self.id.into());
        // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
        let callable_sig =
            db.callable_item_signature(self.id.into()).instantiate_identity().skip_binder();
        let skip = if db.function_signature(self.id).has_self_param() { 1 } else { 0 };
        callable_sig
            .inputs()
            .iter()
            .enumerate()
            .skip(skip)
            .map(|(idx, ty)| {
                let ty = Type { env: environment.clone(), ty };
                Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
            })
            .collect()
    }

    // FIXME: Find better API to also handle const generics
    pub fn params_without_self_with_args<'db>(
        self,
        db: &'db dyn HirDatabase,
        generics: impl Iterator<Item = Type<'db>>,
    ) -> Vec<Param<'db>> {
        let environment = db.trait_environment(self.id.into());
        let interner = DbInterner::new_with(db, None, None);
        let args = generic_args_from_tys(interner, self.id.into(), generics.map(|ty| ty.ty));
        let callable_sig =
            db.callable_item_signature(self.id.into()).instantiate(interner, args).skip_binder();
        let skip = if db.function_signature(self.id).has_self_param() { 1 } else { 0 };
        callable_sig
            .inputs()
            .iter()
            .enumerate()
            .skip(skip)
            .map(|(idx, ty)| {
                let ty = Type { env: environment.clone(), ty };
                Param { func: Callee::Def(CallableDefId::FunctionId(self.id)), ty, idx }
            })
            .collect()
    }

    pub fn is_const(self, db: &dyn HirDatabase) -> bool {
        db.function_signature(self.id).is_const()
    }

    pub fn is_async(self, db: &dyn HirDatabase) -> bool {
        db.function_signature(self.id).is_async()
    }

    pub fn is_varargs(self, db: &dyn HirDatabase) -> bool {
        db.function_signature(self.id).is_varargs()
    }

    pub fn extern_block(self, db: &dyn HirDatabase) -> Option<ExternBlock> {
        match self.id.lookup(db).container {
            ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }),
            _ => None,
        }
    }

    pub fn returns_impl_future(self, db: &dyn HirDatabase) -> bool {
        if self.is_async(db) {
            return true;
        }

        let ret_type = self.ret_type(db);
        let Some(impl_traits) = ret_type.as_impl_traits(db) else { return false };
        let Some(future_trait_id) = LangItem::Future.resolve_trait(db, self.ty(db).env.krate)
        else {
            return false;
        };
        let Some(sized_trait_id) = LangItem::Sized.resolve_trait(db, self.ty(db).env.krate) else {
            return false;
        };

        let mut has_impl_future = false;
        impl_traits
            .filter(|t| {
                let fut = t.id == future_trait_id;
                has_impl_future |= fut;
                !fut && t.id != sized_trait_id
            })
            // all traits but the future trait must be auto traits
            .all(|t| t.is_auto(db))
            && has_impl_future
    }

    /// Does this function have `#[test]` attribute?
    pub fn is_test(self, db: &dyn HirDatabase) -> bool {
        db.attrs(self.id.into()).is_test()
    }

    /// is this a `fn main` or a function with an `export_name` of `main`?
    pub fn is_main(self, db: &dyn HirDatabase) -> bool {
        db.attrs(self.id.into()).export_name() == Some(&sym::main)
            || self.module(db).is_crate_root() && db.function_signature(self.id).name == sym::main
    }

    /// Is this a function with an `export_name` of `main`?
    pub fn exported_main(self, db: &dyn HirDatabase) -> bool {
        db.attrs(self.id.into()).export_name() == Some(&sym::main)
    }

    /// Does this function have the ignore attribute?
    pub fn is_ignore(self, db: &dyn HirDatabase) -> bool {
        db.attrs(self.id.into()).is_ignore()
    }

    /// Does this function have `#[bench]` attribute?
    pub fn is_bench(self, db: &dyn HirDatabase) -> bool {
        db.attrs(self.id.into()).is_bench()
    }

    /// Is this function marked as unstable with `#[feature]` attribute?
    pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
        db.attrs(self.id.into()).is_unstable()
    }

    pub fn is_unsafe_to_call(
        self,
        db: &dyn HirDatabase,
        caller: Option<Function>,
        call_edition: Edition,
    ) -> bool {
        let (target_features, target_feature_is_safe_in_target) = caller
            .map(|caller| {
                let target_features =
                    hir_ty::TargetFeatures::from_attrs(&db.attrs(caller.id.into()));
                let target_feature_is_safe_in_target =
                    match &caller.krate(db).id.workspace_data(db).target {
                        Ok(target) => hir_ty::target_feature_is_safe_in_target(target),
                        Err(_) => hir_ty::TargetFeatureIsSafeInTarget::No,
                    };
                (target_features, target_feature_is_safe_in_target)
            })
            .unwrap_or_else(|| {
                (hir_ty::TargetFeatures::default(), hir_ty::TargetFeatureIsSafeInTarget::No)
            });
        matches!(
            hir_ty::is_fn_unsafe_to_call(
                db,
                self.id,
                &target_features,
                call_edition,
                target_feature_is_safe_in_target
            ),
            hir_ty::Unsafety::Unsafe
        )
    }

    /// Whether this function declaration has a definition.
    ///
    /// This is false in the case of required (not provided) trait methods.
    pub fn has_body(self, db: &dyn HirDatabase) -> bool {
        db.function_signature(self.id).has_body()
    }

    pub fn as_proc_macro(self, db: &dyn HirDatabase) -> Option<Macro> {
        let attrs = db.attrs(self.id.into());
        // FIXME: Store this in FunctionData flags?
        if !(attrs.is_proc_macro()
            || attrs.is_proc_macro_attribute()
            || attrs.is_proc_macro_derive())
        {
            return None;
        }
        let def_map = crate_def_map(db, HasModule::krate(&self.id, db));
        def_map.fn_as_proc_macro(self.id).map(|id| Macro { id: id.into() })
    }

    pub fn eval(
        self,
        db: &dyn HirDatabase,
        span_formatter: impl Fn(FileId, TextRange) -> String,
    ) -> Result<String, ConstEvalError<'_>> {
        let interner = DbInterner::new_with(db, None, None);
        let body = db.monomorphized_mir_body(
            self.id.into(),
            GenericArgs::new_from_iter(interner, []),
            db.trait_environment(self.id.into()),
        )?;
        let (result, output) = interpret_mir(db, body, false, None)?;
        let mut text = match result {
            Ok(_) => "pass".to_owned(),
            Err(e) => {
                let mut r = String::new();
                _ = e.pretty_print(
                    &mut r,
                    db,
                    &span_formatter,
                    self.krate(db).to_display_target(db),
                );
                r
            }
        };
        let stdout = output.stdout().into_owned();
        if !stdout.is_empty() {
            text += "\n--------- stdout ---------\n";
            text += &stdout;
        }
        let stderr = output.stdout().into_owned();
        if !stderr.is_empty() {
            text += "\n--------- stderr ---------\n";
            text += &stderr;
        }
        Ok(text)
    }
}

// Note: logically, this belongs to `hir_ty`, but we are not using it there yet.
#[derive(Clone, Copy, PartialEq, Eq)]
pub enum Access {
    Shared,
    Exclusive,
    Owned,
}

impl From<hir_ty::next_solver::Mutability> for Access {
    fn from(mutability: hir_ty::next_solver::Mutability) -> Access {
        match mutability {
            hir_ty::next_solver::Mutability::Not => Access::Shared,
            hir_ty::next_solver::Mutability::Mut => Access::Exclusive,
        }
    }
}

#[derive(Clone, PartialEq, Eq, Hash, Debug)]
pub struct Param<'db> {
    func: Callee<'db>,
    /// The index in parameter list, including self parameter.
    idx: usize,
    ty: Type<'db>,
}

impl<'db> Param<'db> {
    pub fn parent_fn(&self) -> Option<Function> {
        match self.func {
            Callee::Def(CallableDefId::FunctionId(f)) => Some(f.into()),
            _ => None,
        }
    }

    // pub fn parent_closure(&self) -> Option<Closure> {
    //     self.func.as_ref().right().cloned()
    // }

    pub fn index(&self) -> usize {
        self.idx
    }

    pub fn ty(&self) -> &Type<'db> {
        &self.ty
    }

    pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
        Some(self.as_local(db)?.name(db))
    }

    pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
        match self.func {
            Callee::Def(CallableDefId::FunctionId(it)) => {
                let parent = DefWithBodyId::FunctionId(it);
                let body = db.body(parent);
                if let Some(self_param) = body.self_param.filter(|_| self.idx == 0) {
                    Some(Local { parent, binding_id: self_param })
                } else if let Pat::Bind { id, .. } =
                    &body[body.params[self.idx - body.self_param.is_some() as usize]]
                {
                    Some(Local { parent, binding_id: *id })
                } else {
                    None
                }
            }
            Callee::Closure(closure, _) => {
                let c = db.lookup_intern_closure(closure);
                let body = db.body(c.0);
                if let Expr::Closure { args, .. } = &body[c.1]
                    && let Pat::Bind { id, .. } = &body[args[self.idx]]
                {
                    return Some(Local { parent: c.0, binding_id: *id });
                }
                None
            }
            _ => None,
        }
    }

    pub fn pattern_source(self, db: &dyn HirDatabase) -> Option<ast::Pat> {
        self.source(db).and_then(|p| p.value.right()?.pat())
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SelfParam {
    func: FunctionId,
}

impl SelfParam {
    pub fn access(self, db: &dyn HirDatabase) -> Access {
        let func_data = db.function_signature(self.func);
        func_data
            .params
            .first()
            .map(|&param| match &func_data.store[param] {
                TypeRef::Reference(ref_) => match ref_.mutability {
                    hir_def::type_ref::Mutability::Shared => Access::Shared,
                    hir_def::type_ref::Mutability::Mut => Access::Exclusive,
                },
                _ => Access::Owned,
            })
            .unwrap_or(Access::Owned)
    }

    pub fn parent_fn(&self) -> Function {
        Function::from(self.func)
    }

    pub fn ty<'db>(&self, db: &'db dyn HirDatabase) -> Type<'db> {
        // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
        let callable_sig =
            db.callable_item_signature(self.func.into()).instantiate_identity().skip_binder();
        let environment = db.trait_environment(self.func.into());
        let ty = callable_sig.inputs().as_slice()[0];
        Type { env: environment, ty }
    }

    // FIXME: Find better API to also handle const generics
    pub fn ty_with_args<'db>(
        &self,
        db: &'db dyn HirDatabase,
        generics: impl Iterator<Item = Type<'db>>,
    ) -> Type<'db> {
        let interner = DbInterner::new_with(db, None, None);
        let args = generic_args_from_tys(interner, self.func.into(), generics.map(|ty| ty.ty));
        let callable_sig =
            db.callable_item_signature(self.func.into()).instantiate(interner, args).skip_binder();
        let environment = db.trait_environment(self.func.into());
        let ty = callable_sig.inputs().as_slice()[0];
        Type { env: environment, ty }
    }
}

impl HasVisibility for Function {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        db.assoc_visibility(self.id.into())
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ExternCrateDecl {
    pub(crate) id: ExternCrateId,
}

impl ExternCrateDecl {
    pub fn module(self, db: &dyn HirDatabase) -> Module {
        self.id.module(db).into()
    }

    pub fn resolved_crate(self, db: &dyn HirDatabase) -> Option<Crate> {
        let loc = self.id.lookup(db);
        let krate = loc.container.krate();
        let name = self.name(db);
        if name == sym::self_ {
            Some(krate.into())
        } else {
            krate.data(db).dependencies.iter().find_map(|dep| {
                if dep.name.symbol() == name.symbol() { Some(dep.crate_id.into()) } else { None }
            })
        }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        let loc = self.id.lookup(db);
        let source = loc.source(db);
        as_name_opt(source.value.name_ref())
    }

    pub fn alias(self, db: &dyn HirDatabase) -> Option<ImportAlias> {
        let loc = self.id.lookup(db);
        let source = loc.source(db);
        let rename = source.value.rename()?;
        if let Some(name) = rename.name() {
            Some(ImportAlias::Alias(name.as_name()))
        } else if rename.underscore_token().is_some() {
            Some(ImportAlias::Underscore)
        } else {
            None
        }
    }

    /// Returns the name under which this crate is made accessible, taking `_` into account.
    pub fn alias_or_name(self, db: &dyn HirDatabase) -> Option<Name> {
        match self.alias(db) {
            Some(ImportAlias::Underscore) => None,
            Some(ImportAlias::Alias(alias)) => Some(alias),
            None => Some(self.name(db)),
        }
    }
}

impl HasVisibility for ExternCrateDecl {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        let loc = self.id.lookup(db);
        let source = loc.source(db);
        visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Const {
    pub(crate) id: ConstId,
}

impl Const {
    pub fn module(self, db: &dyn HirDatabase) -> Module {
        Module { id: self.id.module(db) }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
        db.const_signature(self.id).name.clone()
    }

    pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
        self.source(db)?.value.body()
    }

    pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::from_value_def(db, self.id)
    }

    /// Evaluate the constant.
    pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError<'_>> {
        let interner = DbInterner::new_with(db, None, None);
        let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity();
        db.const_eval(self.id, GenericArgs::new_from_iter(interner, []), None)
            .map(|it| EvaluatedConst { const_: it, def: self.id.into(), ty })
    }
}

impl HasVisibility for Const {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        db.assoc_visibility(self.id.into())
    }
}

pub struct EvaluatedConst<'db> {
    def: DefWithBodyId,
    const_: hir_ty::next_solver::Const<'db>,
    ty: Ty<'db>,
}

impl<'db> EvaluatedConst<'db> {
    pub fn render(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
        format!("{}", self.const_.display(db, display_target))
    }

    pub fn render_debug(&self, db: &'db dyn HirDatabase) -> Result<String, MirEvalError<'db>> {
        let kind = self.const_.kind();
        if let ConstKind::Value(c) = kind
            && let ty = c.ty.kind()
            && let TyKind::Int(_) | TyKind::Uint(_) = ty
        {
            let b = &c.value.inner().memory;
            let value = u128::from_le_bytes(mir::pad16(b, false));
            let value_signed = i128::from_le_bytes(mir::pad16(b, matches!(ty, TyKind::Int(_))));
            let mut result =
                if let TyKind::Int(_) = ty { value_signed.to_string() } else { value.to_string() };
            if value >= 10 {
                format_to!(result, " ({value:#X})");
                return Ok(result);
            } else {
                return Ok(result);
            }
        }
        mir::render_const_using_debug_impl(db, self.def, self.const_, self.ty)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Static {
    pub(crate) id: StaticId,
}

impl Static {
    pub fn module(self, db: &dyn HirDatabase) -> Module {
        Module { id: self.id.module(db) }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        db.static_signature(self.id).name.clone()
    }

    pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
        db.static_signature(self.id).flags.contains(StaticFlags::MUTABLE)
    }

    pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
        self.source(db)?.value.body()
    }

    pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::from_value_def(db, self.id)
    }

    pub fn extern_block(self, db: &dyn HirDatabase) -> Option<ExternBlock> {
        match self.id.lookup(db).container {
            ItemContainerId::ExternBlockId(id) => Some(ExternBlock { id }),
            _ => None,
        }
    }

    /// Evaluate the static initializer.
    pub fn eval(self, db: &dyn HirDatabase) -> Result<EvaluatedConst<'_>, ConstEvalError<'_>> {
        let ty = db.value_ty(self.id.into()).unwrap().instantiate_identity();
        db.const_eval_static(self.id).map(|it| EvaluatedConst {
            const_: it,
            def: self.id.into(),
            ty,
        })
    }
}

impl HasVisibility for Static {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        let loc = self.id.lookup(db);
        let source = loc.source(db);
        visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Trait {
    pub(crate) id: TraitId,
}

impl Trait {
    pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait> {
        LangItem::from_name(name)?.resolve_trait(db, krate.into()).map(Into::into)
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        Module { id: self.id.lookup(db).container }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        db.trait_signature(self.id).name.clone()
    }

    pub fn direct_supertraits(self, db: &dyn HirDatabase) -> Vec<Trait> {
        let traits = direct_super_traits(db, self.into());
        traits.iter().map(|tr| Trait::from(*tr)).collect()
    }

    pub fn all_supertraits(self, db: &dyn HirDatabase) -> Vec<Trait> {
        let traits = all_super_traits(db, self.into());
        traits.iter().map(|tr| Trait::from(*tr)).collect()
    }

    pub fn function(self, db: &dyn HirDatabase, name: impl PartialEq<Name>) -> Option<Function> {
        self.id.trait_items(db).items.iter().find(|(n, _)| name == *n).and_then(|&(_, it)| match it
        {
            AssocItemId::FunctionId(id) => Some(Function { id }),
            _ => None,
        })
    }

    pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
        self.id.trait_items(db).items.iter().map(|(_name, it)| (*it).into()).collect()
    }

    pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
        self.all_supertraits(db).into_iter().flat_map(|tr| tr.items(db)).collect()
    }

    pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
        db.trait_signature(self.id).flags.contains(TraitFlags::AUTO)
    }

    pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool {
        db.trait_signature(self.id).flags.contains(TraitFlags::UNSAFE)
    }

    pub fn type_or_const_param_count(
        &self,
        db: &dyn HirDatabase,
        count_required_only: bool,
    ) -> usize {
        db.generic_params(self.id.into())
            .iter_type_or_consts()
            .filter(|(_, ty)| !matches!(ty, TypeOrConstParamData::TypeParamData(ty) if ty.provenance != TypeParamProvenance::TypeParamList))
            .filter(|(_, ty)| !count_required_only || !ty.has_default())
            .count()
    }

    pub fn dyn_compatibility(&self, db: &dyn HirDatabase) -> Option<DynCompatibilityViolation> {
        hir_ty::dyn_compatibility::dyn_compatibility(db, self.id)
    }

    pub fn dyn_compatibility_all_violations(
        &self,
        db: &dyn HirDatabase,
    ) -> Option<Vec<DynCompatibilityViolation>> {
        let mut violations = vec![];
        _ = hir_ty::dyn_compatibility::dyn_compatibility_with_callback(
            db,
            self.id,
            &mut |violation| {
                violations.push(violation);
                ControlFlow::Continue(())
            },
        );
        violations.is_empty().not().then_some(violations)
    }

    fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
        self.id.trait_items(db).macro_calls.to_vec().into_boxed_slice()
    }

    /// `#[rust_analyzer::completions(...)]` mode.
    pub fn complete(self, db: &dyn HirDatabase) -> Complete {
        Complete::extract(true, &self.attrs(db))
    }
}

impl HasVisibility for Trait {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        let loc = self.id.lookup(db);
        let source = loc.source(db);
        visibility_from_ast(db, self.id, source.map(|src| src.visibility()))
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct TypeAlias {
    pub(crate) id: TypeAliasId,
}

impl TypeAlias {
    pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
        has_non_default_type_params(db, self.id.into())
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        Module { id: self.id.module(db) }
    }

    pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::from_def(db, self.id)
    }

    pub fn ty_params(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::from_def_params(db, self.id)
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        db.type_alias_signature(self.id).name.clone()
    }
}

impl HasVisibility for TypeAlias {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        db.assoc_visibility(self.id.into())
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ExternBlock {
    pub(crate) id: ExternBlockId,
}

impl ExternBlock {
    pub fn module(self, db: &dyn HirDatabase) -> Module {
        Module { id: self.id.module(db) }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StaticLifetime;

impl StaticLifetime {
    pub fn name(self) -> Name {
        Name::new_symbol_root(sym::tick_static)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct BuiltinType {
    pub(crate) inner: hir_def::builtin_type::BuiltinType,
}

impl BuiltinType {
    // Constructors are added on demand, feel free to add more.
    pub fn str() -> BuiltinType {
        BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
    }

    pub fn i32() -> BuiltinType {
        BuiltinType {
            inner: hir_def::builtin_type::BuiltinType::Int(hir_ty::primitive::BuiltinInt::I32),
        }
    }

    pub fn ty<'db>(self, db: &'db dyn HirDatabase) -> Type<'db> {
        let core = Crate::core(db).map(|core| core.id).unwrap_or_else(|| db.all_crates()[0]);
        let interner = DbInterner::new_with(db, None, None);
        Type::new_for_crate(core, Ty::from_builtin_type(interner, self.inner))
    }

    pub fn name(self) -> Name {
        self.inner.as_name()
    }

    pub fn is_int(&self) -> bool {
        matches!(self.inner, hir_def::builtin_type::BuiltinType::Int(_))
    }

    pub fn is_uint(&self) -> bool {
        matches!(self.inner, hir_def::builtin_type::BuiltinType::Uint(_))
    }

    pub fn is_float(&self) -> bool {
        matches!(self.inner, hir_def::builtin_type::BuiltinType::Float(_))
    }

    pub fn is_f16(&self) -> bool {
        matches!(
            self.inner,
            hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F16)
        )
    }

    pub fn is_f32(&self) -> bool {
        matches!(
            self.inner,
            hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F32)
        )
    }

    pub fn is_f64(&self) -> bool {
        matches!(
            self.inner,
            hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F64)
        )
    }

    pub fn is_f128(&self) -> bool {
        matches!(
            self.inner,
            hir_def::builtin_type::BuiltinType::Float(hir_def::builtin_type::BuiltinFloat::F128)
        )
    }

    pub fn is_char(&self) -> bool {
        matches!(self.inner, hir_def::builtin_type::BuiltinType::Char)
    }

    pub fn is_bool(&self) -> bool {
        matches!(self.inner, hir_def::builtin_type::BuiltinType::Bool)
    }

    pub fn is_str(&self) -> bool {
        matches!(self.inner, hir_def::builtin_type::BuiltinType::Str)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Macro {
    pub(crate) id: MacroId,
}

impl Macro {
    pub fn module(self, db: &dyn HirDatabase) -> Module {
        Module { id: self.id.module(db) }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        match self.id {
            MacroId::Macro2Id(id) => {
                let loc = id.lookup(db);
                let source = loc.source(db);
                as_name_opt(source.value.name())
            }
            MacroId::MacroRulesId(id) => {
                let loc = id.lookup(db);
                let source = loc.source(db);
                as_name_opt(source.value.name())
            }
            MacroId::ProcMacroId(id) => {
                let loc = id.lookup(db);
                let source = loc.source(db);
                match loc.kind {
                    ProcMacroKind::CustomDerive => db
                        .attrs(id.into())
                        .parse_proc_macro_derive()
                        .map_or_else(|| as_name_opt(source.value.name()), |(it, _)| it),
                    ProcMacroKind::Bang | ProcMacroKind::Attr => as_name_opt(source.value.name()),
                }
            }
        }
    }

    pub fn is_macro_export(self, db: &dyn HirDatabase) -> bool {
        matches!(self.id, MacroId::MacroRulesId(_) if db.attrs(self.id.into()).by_key(sym::macro_export).exists())
    }

    pub fn is_proc_macro(self) -> bool {
        matches!(self.id, MacroId::ProcMacroId(_))
    }

    pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
        match self.id {
            MacroId::Macro2Id(it) => match it.lookup(db).expander {
                MacroExpander::Declarative => MacroKind::Declarative,
                MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => {
                    MacroKind::DeclarativeBuiltIn
                }
                MacroExpander::BuiltInAttr(_) => MacroKind::AttrBuiltIn,
                MacroExpander::BuiltInDerive(_) => MacroKind::DeriveBuiltIn,
            },
            MacroId::MacroRulesId(it) => match it.lookup(db).expander {
                MacroExpander::Declarative => MacroKind::Declarative,
                MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => {
                    MacroKind::DeclarativeBuiltIn
                }
                MacroExpander::BuiltInAttr(_) => MacroKind::AttrBuiltIn,
                MacroExpander::BuiltInDerive(_) => MacroKind::DeriveBuiltIn,
            },
            MacroId::ProcMacroId(it) => match it.lookup(db).kind {
                ProcMacroKind::CustomDerive => MacroKind::Derive,
                ProcMacroKind::Bang => MacroKind::ProcMacro,
                ProcMacroKind::Attr => MacroKind::Attr,
            },
        }
    }

    pub fn is_fn_like(&self, db: &dyn HirDatabase) -> bool {
        matches!(
            self.kind(db),
            MacroKind::Declarative | MacroKind::DeclarativeBuiltIn | MacroKind::ProcMacro
        )
    }

    pub fn is_builtin_derive(&self, db: &dyn HirDatabase) -> bool {
        match self.id {
            MacroId::Macro2Id(it) => {
                matches!(it.lookup(db).expander, MacroExpander::BuiltInDerive(_))
            }
            MacroId::MacroRulesId(it) => {
                matches!(it.lookup(db).expander, MacroExpander::BuiltInDerive(_))
            }
            MacroId::ProcMacroId(_) => false,
        }
    }

    pub fn is_env_or_option_env(&self, db: &dyn HirDatabase) -> bool {
        match self.id {
            MacroId::Macro2Id(it) => {
                matches!(it.lookup(db).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
            }
            MacroId::MacroRulesId(it) => {
                matches!(it.lookup(db).expander, MacroExpander::BuiltInEager(eager) if eager.is_env_or_option_env())
            }
            MacroId::ProcMacroId(_) => false,
        }
    }

    /// Is this `asm!()`, or a variant of it (e.g. `global_asm!()`)?
    pub fn is_asm_like(&self, db: &dyn HirDatabase) -> bool {
        match self.id {
            MacroId::Macro2Id(it) => {
                matches!(it.lookup(db).expander, MacroExpander::BuiltIn(m) if m.is_asm())
            }
            MacroId::MacroRulesId(it) => {
                matches!(it.lookup(db).expander, MacroExpander::BuiltIn(m) if m.is_asm())
            }
            MacroId::ProcMacroId(_) => false,
        }
    }

    pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
        matches!(self.kind(db), MacroKind::Attr | MacroKind::AttrBuiltIn)
    }

    pub fn is_derive(&self, db: &dyn HirDatabase) -> bool {
        matches!(self.kind(db), MacroKind::Derive | MacroKind::DeriveBuiltIn)
    }
}

impl HasVisibility for Macro {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        match self.id {
            MacroId::Macro2Id(id) => {
                let loc = id.lookup(db);
                let source = loc.source(db);
                visibility_from_ast(db, id, source.map(|src| src.visibility()))
            }
            MacroId::MacroRulesId(_) => Visibility::Public,
            MacroId::ProcMacroId(_) => Visibility::Public,
        }
    }
}

#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum ItemInNs {
    Types(ModuleDef),
    Values(ModuleDef),
    Macros(Macro),
}

impl From<Macro> for ItemInNs {
    fn from(it: Macro) -> Self {
        Self::Macros(it)
    }
}

impl From<ModuleDef> for ItemInNs {
    fn from(module_def: ModuleDef) -> Self {
        match module_def {
            ModuleDef::Static(_) | ModuleDef::Const(_) | ModuleDef::Function(_) => {
                ItemInNs::Values(module_def)
            }
            ModuleDef::Macro(it) => ItemInNs::Macros(it),
            _ => ItemInNs::Types(module_def),
        }
    }
}

impl ItemInNs {
    pub fn into_module_def(self) -> ModuleDef {
        match self {
            ItemInNs::Types(id) | ItemInNs::Values(id) => id,
            ItemInNs::Macros(id) => ModuleDef::Macro(id),
        }
    }

    /// Returns the crate defining this item (or `None` if `self` is built-in).
    pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
        match self {
            ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate()),
            ItemInNs::Macros(id) => Some(id.module(db).krate()),
        }
    }

    pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
        match self {
            ItemInNs::Types(it) | ItemInNs::Values(it) => it.attrs(db),
            ItemInNs::Macros(it) => Some(it.attrs(db)),
        }
    }
}

/// Invariant: `inner.as_extern_assoc_item(db).is_some()`
/// We do not actively enforce this invariant.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum ExternAssocItem {
    Function(Function),
    Static(Static),
    TypeAlias(TypeAlias),
}

pub trait AsExternAssocItem {
    fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem>;
}

impl AsExternAssocItem for Function {
    fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
        as_extern_assoc_item(db, ExternAssocItem::Function, self.id)
    }
}

impl AsExternAssocItem for Static {
    fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
        as_extern_assoc_item(db, ExternAssocItem::Static, self.id)
    }
}

impl AsExternAssocItem for TypeAlias {
    fn as_extern_assoc_item(self, db: &dyn HirDatabase) -> Option<ExternAssocItem> {
        as_extern_assoc_item(db, ExternAssocItem::TypeAlias, self.id)
    }
}

/// Invariant: `inner.as_assoc_item(db).is_some()`
/// We do not actively enforce this invariant.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum AssocItem {
    Function(Function),
    Const(Const),
    TypeAlias(TypeAlias),
}

impl From<method_resolution::CandidateId> for AssocItem {
    fn from(value: method_resolution::CandidateId) -> Self {
        match value {
            method_resolution::CandidateId::FunctionId(id) => AssocItem::Function(Function { id }),
            method_resolution::CandidateId::ConstId(id) => AssocItem::Const(Const { id }),
        }
    }
}

#[derive(Debug, Clone)]
pub enum AssocItemContainer {
    Trait(Trait),
    Impl(Impl),
}

pub trait AsAssocItem {
    fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>;
}

impl AsAssocItem for Function {
    fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
        as_assoc_item(db, AssocItem::Function, self.id)
    }
}

impl AsAssocItem for Const {
    fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
        as_assoc_item(db, AssocItem::Const, self.id)
    }
}

impl AsAssocItem for TypeAlias {
    fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
        as_assoc_item(db, AssocItem::TypeAlias, self.id)
    }
}

impl AsAssocItem for ModuleDef {
    fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
        match self {
            ModuleDef::Function(it) => it.as_assoc_item(db),
            ModuleDef::Const(it) => it.as_assoc_item(db),
            ModuleDef::TypeAlias(it) => it.as_assoc_item(db),
            _ => None,
        }
    }
}

impl AsAssocItem for DefWithBody {
    fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
        match self {
            DefWithBody::Function(it) => it.as_assoc_item(db),
            DefWithBody::Const(it) => it.as_assoc_item(db),
            DefWithBody::Static(_) | DefWithBody::Variant(_) => None,
        }
    }
}

fn as_assoc_item<'db, ID, DEF, LOC>(
    db: &(dyn HirDatabase + 'db),
    ctor: impl FnOnce(DEF) -> AssocItem,
    id: ID,
) -> Option<AssocItem>
where
    ID: Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<LOC>>,
    DEF: From<ID>,
    LOC: AstIdNode,
{
    match id.lookup(db).container {
        ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
        ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
    }
}

fn as_extern_assoc_item<'db, ID, DEF, LOC>(
    db: &(dyn HirDatabase + 'db),
    ctor: impl FnOnce(DEF) -> ExternAssocItem,
    id: ID,
) -> Option<ExternAssocItem>
where
    ID: Lookup<Database = dyn DefDatabase, Data = AssocItemLoc<LOC>>,
    DEF: From<ID>,
    LOC: AstIdNode,
{
    match id.lookup(db).container {
        ItemContainerId::ExternBlockId(_) => Some(ctor(DEF::from(id))),
        ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) | ItemContainerId::ModuleId(_) => {
            None
        }
    }
}

impl ExternAssocItem {
    pub fn name(self, db: &dyn HirDatabase) -> Name {
        match self {
            Self::Function(it) => it.name(db),
            Self::Static(it) => it.name(db),
            Self::TypeAlias(it) => it.name(db),
        }
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        match self {
            Self::Function(f) => f.module(db),
            Self::Static(c) => c.module(db),
            Self::TypeAlias(t) => t.module(db),
        }
    }

    pub fn as_function(self) -> Option<Function> {
        match self {
            Self::Function(v) => Some(v),
            _ => None,
        }
    }

    pub fn as_static(self) -> Option<Static> {
        match self {
            Self::Static(v) => Some(v),
            _ => None,
        }
    }

    pub fn as_type_alias(self) -> Option<TypeAlias> {
        match self {
            Self::TypeAlias(v) => Some(v),
            _ => None,
        }
    }
}

impl AssocItem {
    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
        match self {
            AssocItem::Function(it) => Some(it.name(db)),
            AssocItem::Const(it) => it.name(db),
            AssocItem::TypeAlias(it) => Some(it.name(db)),
        }
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        match self {
            AssocItem::Function(f) => f.module(db),
            AssocItem::Const(c) => c.module(db),
            AssocItem::TypeAlias(t) => t.module(db),
        }
    }

    pub fn container(self, db: &dyn HirDatabase) -> AssocItemContainer {
        let container = match self {
            AssocItem::Function(it) => it.id.lookup(db).container,
            AssocItem::Const(it) => it.id.lookup(db).container,
            AssocItem::TypeAlias(it) => it.id.lookup(db).container,
        };
        match container {
            ItemContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
            ItemContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()),
            ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
                panic!("invalid AssocItem")
            }
        }
    }

    pub fn container_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
        match self.container(db) {
            AssocItemContainer::Trait(t) => Some(t),
            _ => None,
        }
    }

    pub fn implemented_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
        match self.container(db) {
            AssocItemContainer::Impl(i) => i.trait_(db),
            _ => None,
        }
    }

    pub fn container_or_implemented_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
        match self.container(db) {
            AssocItemContainer::Trait(t) => Some(t),
            AssocItemContainer::Impl(i) => i.trait_(db),
        }
    }

    pub fn implementing_ty(self, db: &dyn HirDatabase) -> Option<Type<'_>> {
        match self.container(db) {
            AssocItemContainer::Impl(i) => Some(i.self_ty(db)),
            _ => None,
        }
    }

    pub fn as_function(self) -> Option<Function> {
        match self {
            Self::Function(v) => Some(v),
            _ => None,
        }
    }

    pub fn as_const(self) -> Option<Const> {
        match self {
            Self::Const(v) => Some(v),
            _ => None,
        }
    }

    pub fn as_type_alias(self) -> Option<TypeAlias> {
        match self {
            Self::TypeAlias(v) => Some(v),
            _ => None,
        }
    }

    pub fn diagnostics<'db>(
        self,
        db: &'db dyn HirDatabase,
        acc: &mut Vec<AnyDiagnostic<'db>>,
        style_lints: bool,
    ) {
        match self {
            AssocItem::Function(func) => {
                GenericDef::Function(func).diagnostics(db, acc);
                DefWithBody::from(func).diagnostics(db, acc, style_lints);
            }
            AssocItem::Const(const_) => {
                GenericDef::Const(const_).diagnostics(db, acc);
                DefWithBody::from(const_).diagnostics(db, acc, style_lints);
            }
            AssocItem::TypeAlias(type_alias) => {
                GenericDef::TypeAlias(type_alias).diagnostics(db, acc);
                push_ty_diagnostics(
                    db,
                    acc,
                    db.type_for_type_alias_with_diagnostics(type_alias.id).1,
                    &db.type_alias_signature_with_source_map(type_alias.id).1,
                );
                for diag in hir_ty::diagnostics::incorrect_case(db, type_alias.id.into()) {
                    acc.push(diag.into());
                }
            }
        }
    }
}

impl HasVisibility for AssocItem {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
        match self {
            AssocItem::Function(f) => f.visibility(db),
            AssocItem::Const(c) => c.visibility(db),
            AssocItem::TypeAlias(t) => t.visibility(db),
        }
    }
}

impl From<AssocItem> for ModuleDef {
    fn from(assoc: AssocItem) -> Self {
        match assoc {
            AssocItem::Function(it) => ModuleDef::Function(it),
            AssocItem::Const(it) => ModuleDef::Const(it),
            AssocItem::TypeAlias(it) => ModuleDef::TypeAlias(it),
        }
    }
}

#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
pub enum GenericDef {
    Function(Function),
    Adt(Adt),
    Trait(Trait),
    TypeAlias(TypeAlias),
    Impl(Impl),
    // consts can have type parameters from their parents (i.e. associated consts of traits)
    Const(Const),
    Static(Static),
}
impl_from!(
    Function,
    Adt(Struct, Enum, Union),
    Trait,
    TypeAlias,
    Impl,
    Const,
    Static
    for GenericDef
);

impl GenericDef {
    pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
        let generics = db.generic_params(self.into());
        let ty_params = generics.iter_type_or_consts().map(|(local_id, _)| {
            let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
            match toc.split(db) {
                Either::Left(it) => GenericParam::ConstParam(it),
                Either::Right(it) => GenericParam::TypeParam(it),
            }
        });
        self.lifetime_params(db)
            .into_iter()
            .map(GenericParam::LifetimeParam)
            .chain(ty_params)
            .collect()
    }

    pub fn lifetime_params(self, db: &dyn HirDatabase) -> Vec<LifetimeParam> {
        let generics = db.generic_params(self.into());
        generics
            .iter_lt()
            .map(|(local_id, _)| LifetimeParam {
                id: LifetimeParamId { parent: self.into(), local_id },
            })
            .collect()
    }

    pub fn type_or_const_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
        let generics = db.generic_params(self.into());
        generics
            .iter_type_or_consts()
            .map(|(local_id, _)| TypeOrConstParam {
                id: TypeOrConstParamId { parent: self.into(), local_id },
            })
            .collect()
    }

    fn id(self) -> GenericDefId {
        match self {
            GenericDef::Function(it) => it.id.into(),
            GenericDef::Adt(it) => it.into(),
            GenericDef::Trait(it) => it.id.into(),
            GenericDef::TypeAlias(it) => it.id.into(),
            GenericDef::Impl(it) => it.id.into(),
            GenericDef::Const(it) => it.id.into(),
            GenericDef::Static(it) => it.id.into(),
        }
    }

    pub fn diagnostics<'db>(self, db: &'db dyn HirDatabase, acc: &mut Vec<AnyDiagnostic<'db>>) {
        let def = self.id();

        let generics = db.generic_params(def);

        if generics.is_empty() && generics.has_no_predicates() {
            return;
        }

        let source_map = match def {
            GenericDefId::AdtId(AdtId::EnumId(it)) => db.enum_signature_with_source_map(it).1,
            GenericDefId::AdtId(AdtId::StructId(it)) => db.struct_signature_with_source_map(it).1,
            GenericDefId::AdtId(AdtId::UnionId(it)) => db.union_signature_with_source_map(it).1,
            GenericDefId::ConstId(_) => return,
            GenericDefId::FunctionId(it) => db.function_signature_with_source_map(it).1,
            GenericDefId::ImplId(it) => db.impl_signature_with_source_map(it).1,
            GenericDefId::StaticId(_) => return,
            GenericDefId::TraitId(it) => db.trait_signature_with_source_map(it).1,
            GenericDefId::TypeAliasId(it) => db.type_alias_signature_with_source_map(it).1,
        };

        expr_store_diagnostics(db, acc, &source_map);
        push_ty_diagnostics(db, acc, db.generic_defaults_with_diagnostics(def).1, &source_map);
        push_ty_diagnostics(
            db,
            acc,
            GenericPredicates::query_with_diagnostics(db, def).1.clone(),
            &source_map,
        );
        for (param_id, param) in generics.iter_type_or_consts() {
            if let TypeOrConstParamData::ConstParamData(_) = param {
                push_ty_diagnostics(
                    db,
                    acc,
                    db.const_param_ty_with_diagnostics(ConstParamId::from_unchecked(
                        TypeOrConstParamId { parent: def, local_id: param_id },
                    ))
                    .1,
                    &source_map,
                );
            }
        }
    }

    /// Returns a string describing the kind of this type.
    #[inline]
    pub fn description(self) -> &'static str {
        match self {
            GenericDef::Function(_) => "function",
            GenericDef::Adt(Adt::Struct(_)) => "struct",
            GenericDef::Adt(Adt::Enum(_)) => "enum",
            GenericDef::Adt(Adt::Union(_)) => "union",
            GenericDef::Trait(_) => "trait",
            GenericDef::TypeAlias(_) => "type alias",
            GenericDef::Impl(_) => "impl",
            GenericDef::Const(_) => "constant",
            GenericDef::Static(_) => "static",
        }
    }
}

// We cannot call this `Substitution` unfortunately...
#[derive(Debug)]
pub struct GenericSubstitution<'db> {
    def: GenericDefId,
    subst: GenericArgs<'db>,
    env: Arc<TraitEnvironment<'db>>,
}

impl<'db> GenericSubstitution<'db> {
    fn new(def: GenericDefId, subst: GenericArgs<'db>, env: Arc<TraitEnvironment<'db>>) -> Self {
        Self { def, subst, env }
    }

    pub fn types(&self, db: &'db dyn HirDatabase) -> Vec<(Symbol, Type<'db>)> {
        let container = match self.def {
            GenericDefId::ConstId(id) => Some(id.lookup(db).container),
            GenericDefId::FunctionId(id) => Some(id.lookup(db).container),
            GenericDefId::TypeAliasId(id) => Some(id.lookup(db).container),
            _ => None,
        };
        let container_type_params = container
            .and_then(|container| match container {
                ItemContainerId::ImplId(container) => Some(container.into()),
                ItemContainerId::TraitId(container) => Some(container.into()),
                _ => None,
            })
            .map(|container| {
                db.generic_params(container)
                    .iter_type_or_consts()
                    .filter_map(|param| match param.1 {
                        TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
                        TypeOrConstParamData::ConstParamData(_) => None,
                    })
                    .collect::<Vec<_>>()
            });
        let generics = db.generic_params(self.def);
        let type_params = generics.iter_type_or_consts().filter_map(|param| match param.1 {
            TypeOrConstParamData::TypeParamData(param) => Some(param.name.clone()),
            TypeOrConstParamData::ConstParamData(_) => None,
        });
        let parent_len = self.subst.len()
            - generics
                .iter_type_or_consts()
                .filter(|g| matches!(g.1, TypeOrConstParamData::TypeParamData(..)))
                .count();
        let container_params = self.subst.as_slice()[..parent_len]
            .iter()
            .filter_map(|param| param.ty())
            .zip(container_type_params.into_iter().flatten());
        let self_params = self.subst.as_slice()[parent_len..]
            .iter()
            .filter_map(|param| param.ty())
            .zip(type_params);
        container_params
            .chain(self_params)
            .filter_map(|(ty, name)| {
                Some((name?.symbol().clone(), Type { ty, env: self.env.clone() }))
            })
            .collect()
    }
}

/// A single local definition.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Local {
    pub(crate) parent: DefWithBodyId,
    pub(crate) binding_id: BindingId,
}

pub struct LocalSource {
    pub local: Local,
    pub source: InFile<Either<ast::IdentPat, ast::SelfParam>>,
}

impl LocalSource {
    pub fn as_ident_pat(&self) -> Option<&ast::IdentPat> {
        match &self.source.value {
            Either::Left(it) => Some(it),
            Either::Right(_) => None,
        }
    }

    pub fn into_ident_pat(self) -> Option<ast::IdentPat> {
        match self.source.value {
            Either::Left(it) => Some(it),
            Either::Right(_) => None,
        }
    }

    pub fn original_file(&self, db: &dyn HirDatabase) -> EditionedFileId {
        self.source.file_id.original_file(db)
    }

    pub fn file(&self) -> HirFileId {
        self.source.file_id
    }

    pub fn name(&self) -> Option<InFile<ast::Name>> {
        self.source.as_ref().map(|it| it.name()).transpose()
    }

    pub fn syntax(&self) -> &SyntaxNode {
        self.source.value.syntax()
    }

    pub fn syntax_ptr(self) -> InFile<SyntaxNodePtr> {
        self.source.map(|it| SyntaxNodePtr::new(it.syntax()))
    }
}

impl Local {
    pub fn is_param(self, db: &dyn HirDatabase) -> bool {
        // FIXME: This parses!
        let src = self.primary_source(db);
        match src.source.value {
            Either::Left(pat) => pat
                .syntax()
                .ancestors()
                .map(|it| it.kind())
                .take_while(|&kind| ast::Pat::can_cast(kind) || ast::Param::can_cast(kind))
                .any(ast::Param::can_cast),
            Either::Right(_) => true,
        }
    }

    pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
        match self.parent {
            DefWithBodyId::FunctionId(func) if self.is_self(db) => Some(SelfParam { func }),
            _ => None,
        }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        let body = db.body(self.parent);
        body[self.binding_id].name.clone()
    }

    pub fn is_self(self, db: &dyn HirDatabase) -> bool {
        self.name(db) == sym::self_
    }

    pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
        let body = db.body(self.parent);
        body[self.binding_id].mode == BindingAnnotation::Mutable
    }

    pub fn is_ref(self, db: &dyn HirDatabase) -> bool {
        let body = db.body(self.parent);
        matches!(body[self.binding_id].mode, BindingAnnotation::Ref | BindingAnnotation::RefMut)
    }

    pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
        self.parent.into()
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        self.parent(db).module(db)
    }

    pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
        let def = self.parent;
        let infer = db.infer(def);
        let ty = infer[self.binding_id];
        Type::new(db, def, ty)
    }

    /// All definitions for this local. Example: `let (a$0, _) | (_, a$0) = it;`
    pub fn sources(self, db: &dyn HirDatabase) -> Vec<LocalSource> {
        let (body, source_map) = db.body_with_source_map(self.parent);
        match body.self_param.zip(source_map.self_param_syntax()) {
            Some((param, source)) if param == self.binding_id => {
                let root = source.file_syntax(db);
                vec![LocalSource {
                    local: self,
                    source: source.map(|ast| Either::Right(ast.to_node(&root))),
                }]
            }
            _ => source_map
                .patterns_for_binding(self.binding_id)
                .iter()
                .map(|&definition| {
                    let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
                    let root = src.file_syntax(db);
                    LocalSource {
                        local: self,
                        source: src.map(|ast| match ast.to_node(&root) {
                            Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
                            _ => unreachable!("local with non ident-pattern"),
                        }),
                    }
                })
                .collect(),
        }
    }

    /// The leftmost definition for this local. Example: `let (a$0, _) | (_, a) = it;`
    pub fn primary_source(self, db: &dyn HirDatabase) -> LocalSource {
        let (body, source_map) = db.body_with_source_map(self.parent);
        match body.self_param.zip(source_map.self_param_syntax()) {
            Some((param, source)) if param == self.binding_id => {
                let root = source.file_syntax(db);
                LocalSource {
                    local: self,
                    source: source.map(|ast| Either::Right(ast.to_node(&root))),
                }
            }
            _ => source_map
                .patterns_for_binding(self.binding_id)
                .first()
                .map(|&definition| {
                    let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
                    let root = src.file_syntax(db);
                    LocalSource {
                        local: self,
                        source: src.map(|ast| match ast.to_node(&root) {
                            Either::Right(ast::Pat::IdentPat(it)) => Either::Left(it),
                            _ => unreachable!("local with non ident-pattern"),
                        }),
                    }
                })
                .unwrap(),
        }
    }
}

impl PartialOrd for Local {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for Local {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        self.binding_id.cmp(&other.binding_id)
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct DeriveHelper {
    pub(crate) derive: MacroId,
    pub(crate) idx: u32,
}

impl DeriveHelper {
    pub fn derive(&self) -> Macro {
        Macro { id: self.derive }
    }

    pub fn name(&self, db: &dyn HirDatabase) -> Name {
        match self.derive {
            makro @ MacroId::Macro2Id(_) => db
                .attrs(makro.into())
                .parse_rustc_builtin_macro()
                .and_then(|(_, helpers)| helpers.get(self.idx as usize).cloned()),
            MacroId::MacroRulesId(_) => None,
            makro @ MacroId::ProcMacroId(_) => db
                .attrs(makro.into())
                .parse_proc_macro_derive()
                .and_then(|(_, helpers)| helpers.get(self.idx as usize).cloned()),
        }
        .unwrap_or_else(Name::missing)
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct BuiltinAttr {
    idx: u32,
}

impl BuiltinAttr {
    fn builtin(name: &str) -> Option<Self> {
        hir_expand::inert_attr_macro::find_builtin_attr_idx(&Symbol::intern(name))
            .map(|idx| BuiltinAttr { idx: idx as u32 })
    }

    pub fn name(&self) -> Name {
        Name::new_symbol_root(Symbol::intern(
            hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].name,
        ))
    }

    pub fn template(&self) -> Option<AttributeTemplate> {
        Some(hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].template)
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ToolModule {
    krate: base_db::Crate,
    idx: u32,
}

impl ToolModule {
    pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
        let krate = krate.id;
        let idx =
            crate_def_map(db, krate).registered_tools().iter().position(|it| it.as_str() == name)?
                as u32;
        Some(ToolModule { krate, idx })
    }

    pub fn name(&self, db: &dyn HirDatabase) -> Name {
        Name::new_symbol_root(
            crate_def_map(db, self.krate).registered_tools()[self.idx as usize].clone(),
        )
    }

    pub fn krate(&self) -> Crate {
        Crate { id: self.krate }
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Label {
    pub(crate) parent: DefWithBodyId,
    pub(crate) label_id: LabelId,
}

impl Label {
    pub fn module(self, db: &dyn HirDatabase) -> Module {
        self.parent(db).module(db)
    }

    pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
        self.parent.into()
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        let body = db.body(self.parent);
        body[self.label_id].name.clone()
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum GenericParam {
    TypeParam(TypeParam),
    ConstParam(ConstParam),
    LifetimeParam(LifetimeParam),
}
impl_from!(TypeParam, ConstParam, LifetimeParam for GenericParam);

impl GenericParam {
    pub fn module(self, db: &dyn HirDatabase) -> Module {
        match self {
            GenericParam::TypeParam(it) => it.module(db),
            GenericParam::ConstParam(it) => it.module(db),
            GenericParam::LifetimeParam(it) => it.module(db),
        }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        match self {
            GenericParam::TypeParam(it) => it.name(db),
            GenericParam::ConstParam(it) => it.name(db),
            GenericParam::LifetimeParam(it) => it.name(db),
        }
    }

    pub fn parent(self) -> GenericDef {
        match self {
            GenericParam::TypeParam(it) => it.id.parent().into(),
            GenericParam::ConstParam(it) => it.id.parent().into(),
            GenericParam::LifetimeParam(it) => it.id.parent.into(),
        }
    }

    pub fn variance(self, db: &dyn HirDatabase) -> Option<Variance> {
        let parent = match self {
            GenericParam::TypeParam(it) => it.id.parent(),
            // const parameters are always invariant
            GenericParam::ConstParam(_) => return None,
            GenericParam::LifetimeParam(it) => it.id.parent,
        };
        let generics = hir_ty::generics::generics(db, parent);
        let index = match self {
            GenericParam::TypeParam(it) => generics.type_or_const_param_idx(it.id.into())?,
            GenericParam::ConstParam(_) => return None,
            GenericParam::LifetimeParam(it) => generics.lifetime_idx(it.id)?,
        };
        db.variances_of(parent).get(index).map(Into::into)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Variance {
    Bivariant,
    Covariant,
    Contravariant,
    Invariant,
}

impl From<rustc_type_ir::Variance> for Variance {
    #[inline]
    fn from(value: rustc_type_ir::Variance) -> Self {
        match value {
            rustc_type_ir::Variance::Covariant => Variance::Covariant,
            rustc_type_ir::Variance::Invariant => Variance::Invariant,
            rustc_type_ir::Variance::Contravariant => Variance::Contravariant,
            rustc_type_ir::Variance::Bivariant => Variance::Bivariant,
        }
    }
}

impl fmt::Display for Variance {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let description = match self {
            Variance::Bivariant => "bivariant",
            Variance::Covariant => "covariant",
            Variance::Contravariant => "contravariant",
            Variance::Invariant => "invariant",
        };
        f.pad(description)
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct TypeParam {
    pub(crate) id: TypeParamId,
}

impl TypeParam {
    pub fn merge(self) -> TypeOrConstParam {
        TypeOrConstParam { id: self.id.into() }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        self.merge().name(db)
    }

    pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
        self.id.parent().into()
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        self.id.parent().module(db).into()
    }

    /// Is this type parameter implicitly introduced (eg. `Self` in a trait or an `impl Trait`
    /// argument)?
    pub fn is_implicit(self, db: &dyn HirDatabase) -> bool {
        let params = db.generic_params(self.id.parent());
        let data = &params[self.id.local_id()];
        match data.type_param().unwrap().provenance {
            TypeParamProvenance::TypeParamList => false,
            TypeParamProvenance::TraitSelf | TypeParamProvenance::ArgumentImplTrait => true,
        }
    }

    pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
        let resolver = self.id.parent().resolver(db);
        let interner = DbInterner::new_with(db, None, None);
        let index = hir_ty::param_idx(db, self.id.into()).unwrap();
        let ty = Ty::new_param(interner, self.id, index as u32);
        Type::new_with_resolver_inner(db, &resolver, ty)
    }

    /// FIXME: this only lists trait bounds from the item defining the type
    /// parameter, not additional bounds that might be added e.g. by a method if
    /// the parameter comes from an impl!
    pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
        let self_ty = self.ty(db).ty;
        GenericPredicates::query_explicit(db, self.id.parent())
            .iter_identity_copied()
            .filter_map(|pred| match &pred.kind().skip_binder() {
                ClauseKind::Trait(trait_ref) if trait_ref.self_ty() == self_ty => {
                    Some(Trait::from(trait_ref.def_id().0))
                }
                _ => None,
            })
            .collect()
    }

    pub fn default(self, db: &dyn HirDatabase) -> Option<Type<'_>> {
        let ty = generic_arg_from_param(db, self.id.into())?;
        let resolver = self.id.parent().resolver(db);
        match ty {
            GenericArg::Ty(it) if !it.is_ty_error() => {
                Some(Type::new_with_resolver_inner(db, &resolver, it))
            }
            _ => None,
        }
    }

    pub fn is_unstable(self, db: &dyn HirDatabase) -> bool {
        db.attrs(GenericParamId::from(self.id).into()).is_unstable()
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct LifetimeParam {
    pub(crate) id: LifetimeParamId,
}

impl LifetimeParam {
    pub fn name(self, db: &dyn HirDatabase) -> Name {
        let params = db.generic_params(self.id.parent);
        params[self.id.local_id].name.clone()
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        self.id.parent.module(db).into()
    }

    pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
        self.id.parent.into()
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct ConstParam {
    pub(crate) id: ConstParamId,
}

impl ConstParam {
    pub fn merge(self) -> TypeOrConstParam {
        TypeOrConstParam { id: self.id.into() }
    }

    pub fn name(self, db: &dyn HirDatabase) -> Name {
        let params = db.generic_params(self.id.parent());
        match params[self.id.local_id()].name() {
            Some(it) => it.clone(),
            None => {
                never!();
                Name::missing()
            }
        }
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        self.id.parent().module(db).into()
    }

    pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
        self.id.parent().into()
    }

    pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
        Type::new(db, self.id.parent(), db.const_param_ty_ns(self.id))
    }

    pub fn default(
        self,
        db: &dyn HirDatabase,
        display_target: DisplayTarget,
    ) -> Option<ast::ConstArg> {
        let arg = generic_arg_from_param(db, self.id.into())?;
        known_const_to_ast(arg.konst()?, db, display_target)
    }
}

fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg<'_>> {
    let local_idx = hir_ty::param_idx(db, id)?;
    let defaults = db.generic_defaults(id.parent);
    let ty = defaults.get(local_idx)?;
    // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
    Some(ty.instantiate_identity())
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct TypeOrConstParam {
    pub(crate) id: TypeOrConstParamId,
}

impl TypeOrConstParam {
    pub fn name(self, db: &dyn HirDatabase) -> Name {
        let params = db.generic_params(self.id.parent);
        match params[self.id.local_id].name() {
            Some(n) => n.clone(),
            _ => Name::missing(),
        }
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        self.id.parent.module(db).into()
    }

    pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
        self.id.parent.into()
    }

    pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
        let params = db.generic_params(self.id.parent);
        match &params[self.id.local_id] {
            TypeOrConstParamData::TypeParamData(_) => {
                Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
            }
            TypeOrConstParamData::ConstParamData(_) => {
                Either::Left(ConstParam { id: ConstParamId::from_unchecked(self.id) })
            }
        }
    }

    pub fn ty(self, db: &dyn HirDatabase) -> Type<'_> {
        match self.split(db) {
            Either::Left(it) => it.ty(db),
            Either::Right(it) => it.ty(db),
        }
    }

    pub fn as_type_param(self, db: &dyn HirDatabase) -> Option<TypeParam> {
        let params = db.generic_params(self.id.parent);
        match &params[self.id.local_id] {
            TypeOrConstParamData::TypeParamData(_) => {
                Some(TypeParam { id: TypeParamId::from_unchecked(self.id) })
            }
            TypeOrConstParamData::ConstParamData(_) => None,
        }
    }

    pub fn as_const_param(self, db: &dyn HirDatabase) -> Option<ConstParam> {
        let params = db.generic_params(self.id.parent);
        match &params[self.id.local_id] {
            TypeOrConstParamData::TypeParamData(_) => None,
            TypeOrConstParamData::ConstParamData(_) => {
                Some(ConstParam { id: ConstParamId::from_unchecked(self.id) })
            }
        }
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Impl {
    pub(crate) id: ImplId,
}

impl Impl {
    pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<Impl> {
        let mut result = Vec::new();
        extend_with_def_map(db, crate_def_map(db, krate.id), &mut result);
        return result;

        fn extend_with_def_map(db: &dyn HirDatabase, def_map: &DefMap, result: &mut Vec<Impl>) {
            for (_, module) in def_map.modules() {
                result.extend(module.scope.impls().map(Impl::from));

                for unnamed_const in module.scope.unnamed_consts() {
                    for (_, block_def_map) in db.body(unnamed_const.into()).blocks(db) {
                        extend_with_def_map(db, block_def_map, result);
                    }
                }
            }
        }
    }

    pub fn all_in_module(db: &dyn HirDatabase, module: Module) -> Vec<Impl> {
        module.id.def_map(db)[module.id.local_id].scope.impls().map(Into::into).collect()
    }

    /// **Note:** This is an **approximation** that strives to give the *human-perceived notion* of an "impl for type",
    /// **not** answer the technical question "what are all impls applying to this type". In particular, it excludes
    /// blanket impls, and only does a shallow type constructor check. In fact, this should've probably been on `Adt`
    /// etc., and not on `Type`. If you would want to create a precise list of all impls applying to a type,
    /// you would need to include blanket impls, and try to prove to predicates for each candidate.
    pub fn all_for_type<'db>(db: &'db dyn HirDatabase, Type { ty, env }: Type<'db>) -> Vec<Impl> {
        let mut result = Vec::new();
        let interner = DbInterner::new_with(db, Some(env.krate), env.block);
        let Some(simplified_ty) =
            fast_reject::simplify_type(interner, ty, fast_reject::TreatParams::AsRigid)
        else {
            return Vec::new();
        };
        let mut extend_with_impls =
            |impls: &[ImplId]| result.extend(impls.iter().copied().map(Impl::from));
        extend_with_impls(method_resolution::incoherent_inherent_impls(db, simplified_ty));
        if let Some(module) = method_resolution::simplified_type_module(db, &simplified_ty) {
            InherentImpls::for_each_crate_and_block(
                db,
                module.krate(),
                module.containing_block(),
                &mut |impls| extend_with_impls(impls.for_self_ty(&simplified_ty)),
            );
            std::iter::successors(module.containing_block(), |block| {
                block.loc(db).module.containing_block()
            })
            .filter_map(|block| TraitImpls::for_block(db, block).as_deref())
            .for_each(|impls| impls.for_self_ty(&simplified_ty, &mut extend_with_impls));
            for &krate in &**db.all_crates() {
                TraitImpls::for_crate(db, krate)
                    .for_self_ty(&simplified_ty, &mut extend_with_impls);
            }
        } else {
            for &krate in &**db.all_crates() {
                TraitImpls::for_crate(db, krate)
                    .for_self_ty(&simplified_ty, &mut extend_with_impls);
            }
        }
        result
    }

    pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
        let module = trait_.module(db).id;
        let mut all = Vec::new();
        let mut handle_impls = |impls: &TraitImpls| {
            impls.for_trait(trait_.id, |impls| all.extend(impls.iter().copied().map(Impl::from)));
        };
        for krate in module.krate().transitive_rev_deps(db) {
            handle_impls(TraitImpls::for_crate(db, krate));
        }
        if let Some(block) = module.containing_block()
            && let Some(impls) = TraitImpls::for_block(db, block)
        {
            handle_impls(impls);
        }
        all
    }

    pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> {
        let trait_ref = db.impl_trait(self.id)?;
        let id = trait_ref.skip_binder().def_id;
        Some(Trait { id: id.0 })
    }

    pub fn trait_ref(self, db: &dyn HirDatabase) -> Option<TraitRef<'_>> {
        let trait_ref = db.impl_trait(self.id)?.instantiate_identity();
        let resolver = self.id.resolver(db);
        Some(TraitRef::new_with_resolver(db, &resolver, trait_ref))
    }

    pub fn self_ty(self, db: &dyn HirDatabase) -> Type<'_> {
        let resolver = self.id.resolver(db);
        // FIXME: This shouldn't be `instantiate_identity()`, we shouldn't leak `TyKind::Param`s.
        let ty = db.impl_self_ty(self.id).instantiate_identity();
        Type::new_with_resolver_inner(db, &resolver, ty)
    }

    pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
        self.id.impl_items(db).items.iter().map(|&(_, it)| it.into()).collect()
    }

    pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
        db.impl_signature(self.id).flags.contains(ImplFlags::NEGATIVE)
    }

    pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
        db.impl_signature(self.id).flags.contains(ImplFlags::UNSAFE)
    }

    pub fn module(self, db: &dyn HirDatabase) -> Module {
        self.id.lookup(db).container.into()
    }

    pub fn as_builtin_derive_path(self, db: &dyn HirDatabase) -> Option<InMacroFile<ast::Path>> {
        let src = self.source(db)?;

        let macro_file = src.file_id.macro_file()?;
        let loc = macro_file.lookup(db);
        let (derive_attr, derive_index) = match loc.kind {
            MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
                let module_id = self.id.lookup(db).container;
                (
                    crate_def_map(db, module_id.krate())[module_id.local_id]
                        .scope
                        .derive_macro_invoc(ast_id, derive_attr_index)?,
                    derive_index,
                )
            }
            _ => return None,
        };
        let path = db
            .parse_macro_expansion(derive_attr)
            .value
            .0
            .syntax_node()
            .children()
            .nth(derive_index as usize)
            .and_then(<ast::Attr as AstNode>::cast)
            .and_then(|it| it.path())?;
        Some(InMacroFile { file_id: derive_attr, value: path })
    }

    pub fn check_orphan_rules(self, db: &dyn HirDatabase) -> bool {
        check_orphan_rules(db, self.id)
    }

    fn all_macro_calls(&self, db: &dyn HirDatabase) -> Box<[(AstId<ast::Item>, MacroCallId)]> {
        self.id.impl_items(db).macro_calls.to_vec().into_boxed_slice()
    }
}

#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct TraitRef<'db> {
    env: Arc<TraitEnvironment<'db>>,
    trait_ref: hir_ty::next_solver::TraitRef<'db>,
}

impl<'db> TraitRef<'db> {
    pub(crate) fn new_with_resolver(
        db: &'db dyn HirDatabase,
        resolver: &Resolver<'_>,
        trait_ref: hir_ty::next_solver::TraitRef<'db>,
    ) -> Self {
        let env = resolver
            .generic_def()
            .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
        TraitRef { env, trait_ref }
    }

    pub fn trait_(&self) -> Trait {
        Trait { id: self.trait_ref.def_id.0 }
    }

    pub fn self_ty(&self) -> TypeNs<'_> {
        let ty = self.trait_ref.self_ty();
        TypeNs { env: self.env.clone(), ty }
    }

    /// Returns `idx`-th argument of this trait reference if it is a type argument. Note that the
    /// first argument is the `Self` type.
    pub fn get_type_argument(&self, idx: usize) -> Option<TypeNs<'db>> {
        self.trait_ref
            .args
            .as_slice()
            .get(idx)
            .and_then(|arg| arg.ty())
            .map(|ty| TypeNs { env: self.env.clone(), ty })
    }
}

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
enum AnyClosureId {
    ClosureId(InternedClosureId),
    CoroutineClosureId(InternedCoroutineId),
}

#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Closure<'db> {
    id: AnyClosureId,
    subst: GenericArgs<'db>,
}

impl<'db> Closure<'db> {
    fn as_ty(&self, db: &'db dyn HirDatabase) -> Ty<'db> {
        let interner = DbInterner::new_with(db, None, None);
        match self.id {
            AnyClosureId::ClosureId(id) => Ty::new_closure(interner, id.into(), self.subst),
            AnyClosureId::CoroutineClosureId(id) => {
                Ty::new_coroutine_closure(interner, id.into(), self.subst)
            }
        }
    }

    pub fn display_with_id(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
        self.as_ty(db)
            .display(db, display_target)
            .with_closure_style(ClosureStyle::ClosureWithId)
            .to_string()
    }

    pub fn display_with_impl(&self, db: &dyn HirDatabase, display_target: DisplayTarget) -> String {
        self.as_ty(db)
            .display(db, display_target)
            .with_closure_style(ClosureStyle::ImplFn)
            .to_string()
    }

    pub fn captured_items(&self, db: &'db dyn HirDatabase) -> Vec<ClosureCapture<'db>> {
        let AnyClosureId::ClosureId(id) = self.id else {
            // FIXME: Infer coroutine closures' captures.
            return Vec::new();
        };
        let owner = db.lookup_intern_closure(id).0;
        let infer = db.infer(owner);
        let info = infer.closure_info(id);
        info.0
            .iter()
            .cloned()
            .map(|capture| ClosureCapture { owner, closure: id, capture })
            .collect()
    }

    pub fn capture_types(&self, db: &'db dyn HirDatabase) -> Vec<Type<'db>> {
        let AnyClosureId::ClosureId(id) = self.id else {
            // FIXME: Infer coroutine closures' captures.
            return Vec::new();
        };
        let owner = db.lookup_intern_closure(id).0;
        let infer = db.infer(owner);
        let (captures, _) = infer.closure_info(id);
        let env = db.trait_environment_for_body(owner);
        captures
            .iter()
            .map(|capture| Type { env: env.clone(), ty: capture.ty(db, self.subst) })
            .collect()
    }

    pub fn fn_trait(&self, db: &dyn HirDatabase) -> FnTrait {
        match self.id {
            AnyClosureId::ClosureId(id) => {
                let owner = db.lookup_intern_closure(id).0;
                let infer = db.infer(owner);
                let info = infer.closure_info(id);
                info.1
            }
            AnyClosureId::CoroutineClosureId(_id) => {
                // FIXME: Infer kind for coroutine closures.
                match self.subst.as_coroutine_closure().kind() {
                    rustc_type_ir::ClosureKind::Fn => FnTrait::AsyncFn,
                    rustc_type_ir::ClosureKind::FnMut => FnTrait::AsyncFnMut,
                    rustc_type_ir::ClosureKind::FnOnce => FnTrait::AsyncFnOnce,
                }
            }
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ClosureCapture<'db> {
    owner: DefWithBodyId,
    closure: InternedClosureId,
    capture: hir_ty::CapturedItem<'db>,
}

impl<'db> ClosureCapture<'db> {
    pub fn local(&self) -> Local {
        Local { parent: self.owner, binding_id: self.capture.local() }
    }

    /// Returns whether this place has any field (aka. non-deref) projections.
    pub fn has_field_projections(&self) -> bool {
        self.capture.has_field_projections()
    }

    pub fn usages(&self) -> CaptureUsages {
        CaptureUsages { parent: self.owner, spans: self.capture.spans() }
    }

    pub fn kind(&self) -> CaptureKind {
        match self.capture.kind() {
            hir_ty::CaptureKind::ByRef(
                hir_ty::mir::BorrowKind::Shallow | hir_ty::mir::BorrowKind::Shared,
            ) => CaptureKind::SharedRef,
            hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Mut {
                kind: MutBorrowKind::ClosureCapture,
            }) => CaptureKind::UniqueSharedRef,
            hir_ty::CaptureKind::ByRef(hir_ty::mir::BorrowKind::Mut {
                kind: MutBorrowKind::Default | MutBorrowKind::TwoPhasedBorrow,
            }) => CaptureKind::MutableRef,
            hir_ty::CaptureKind::ByValue => CaptureKind::Move,
        }
    }

    /// Converts the place to a name that can be inserted into source code.
    pub fn place_to_name(&self, db: &dyn HirDatabase) -> String {
        self.capture.place_to_name(self.owner, db)
    }

    pub fn display_place_source_code(&self, db: &dyn HirDatabase) -> String {
        self.capture.display_place_source_code(self.owner, db)
    }

    pub fn display_place(&self, db: &dyn HirDatabase) -> String {
        self.capture.display_place(self.owner, db)
    }
}

#[derive(Clone, Copy, PartialEq, Eq)]
pub enum CaptureKind {
    SharedRef,
    UniqueSharedRef,
    MutableRef,
    Move,
}

#[derive(Debug, Clone)]
pub struct CaptureUsages {
    parent: DefWithBodyId,
    spans: SmallVec<[mir::MirSpan; 3]>,
}

impl CaptureUsages {
    pub fn sources(&self, db: &dyn HirDatabase) -> Vec<CaptureUsageSource> {
        let (body, source_map) = db.body_with_source_map(self.parent);

        let mut result = Vec::with_capacity(self.spans.len());
        for &span in self.spans.iter() {
            let is_ref = span.is_ref_span(&body);
            match span {
                mir::MirSpan::ExprId(expr) => {
                    if let Ok(expr) = source_map.expr_syntax(expr) {
                        result.push(CaptureUsageSource { is_ref, source: expr })
                    }
                }
                mir::MirSpan::PatId(pat) => {
                    if let Ok(pat) = source_map.pat_syntax(pat) {
                        result.push(CaptureUsageSource { is_ref, source: pat });
                    }
                }
                mir::MirSpan::BindingId(binding) => result.extend(
                    source_map
                        .patterns_for_binding(binding)
                        .iter()
                        .filter_map(|&pat| source_map.pat_syntax(pat).ok())
                        .map(|pat| CaptureUsageSource { is_ref, source: pat }),
                ),
                mir::MirSpan::SelfParam | mir::MirSpan::Unknown => {
                    unreachable!("invalid capture usage span")
                }
            }
        }
        result
    }
}

#[derive(Debug)]
pub struct CaptureUsageSource {
    is_ref: bool,
    source: InFile<AstPtr<Either<ast::Expr, ast::Pat>>>,
}

impl CaptureUsageSource {
    pub fn source(&self) -> AstPtr<Either<ast::Expr, ast::Pat>> {
        self.source.value
    }

    pub fn file_id(&self) -> HirFileId {
        self.source.file_id
    }

    pub fn is_ref(&self) -> bool {
        self.is_ref
    }
}

#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct Type<'db> {
    env: Arc<TraitEnvironment<'db>>,
    ty: Ty<'db>,
}

impl<'db> Type<'db> {
    pub(crate) fn new_with_resolver(
        db: &'db dyn HirDatabase,
        resolver: &Resolver<'_>,
        ty: Ty<'db>,
    ) -> Self {
        Type::new_with_resolver_inner(db, resolver, ty)
    }

    pub(crate) fn new_with_resolver_inner(
        db: &'db dyn HirDatabase,
        resolver: &Resolver<'_>,
        ty: Ty<'db>,
    ) -> Self {
        let environment = resolver
            .generic_def()
            .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
        Type { env: environment, ty }
    }

    pub(crate) fn new_for_crate(krate: base_db::Crate, ty: Ty<'db>) -> Self {
        Type { env: TraitEnvironment::empty(krate), ty }
    }

    fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty<'db>) -> Self {
        let resolver = lexical_env.resolver(db);
        let environment = resolver
            .generic_def()
            .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
        Type { env: environment, ty }
    }

    fn from_def(db: &'db dyn HirDatabase, def: impl Into<TyDefId> + HasResolver) -> Self {
        let interner = DbInterner::new_with(db, None, None);
        let ty = db.ty(def.into());
        let def = match def.into() {
            TyDefId::AdtId(it) => GenericDefId::AdtId(it),
            TyDefId::TypeAliasId(it) => GenericDefId::TypeAliasId(it),
            TyDefId::BuiltinType(_) => {
                return Type::new(db, def, ty.skip_binder());
            }
        };
        let args = GenericArgs::error_for_item(interner, def.into());
        Type::new(db, def, ty.instantiate(interner, args))
    }

    // FIXME: We shouldn't leak `TyKind::Param`s.
    fn from_def_params(db: &'db dyn HirDatabase, def: impl Into<TyDefId> + HasResolver) -> Self {
        let ty = db.ty(def.into());
        Type::new(db, def, ty.instantiate_identity())
    }

    fn from_value_def(
        db: &'db dyn HirDatabase,
        def: impl Into<ValueTyDefId> + HasResolver,
    ) -> Self {
        let interner = DbInterner::new_with(db, None, None);
        let Some(ty) = db.value_ty(def.into()) else {
            return Type::new(db, def, Ty::new_error(interner, ErrorGuaranteed));
        };
        let def = match def.into() {
            ValueTyDefId::ConstId(it) => GenericDefId::ConstId(it),
            ValueTyDefId::FunctionId(it) => GenericDefId::FunctionId(it),
            ValueTyDefId::StructId(it) => GenericDefId::AdtId(AdtId::StructId(it)),
            ValueTyDefId::UnionId(it) => GenericDefId::AdtId(AdtId::UnionId(it)),
            ValueTyDefId::EnumVariantId(it) => {
                GenericDefId::AdtId(AdtId::EnumId(it.lookup(db).parent))
            }
            ValueTyDefId::StaticId(_) => {
                return Type::new(db, def, ty.skip_binder());
            }
        };
        let args = GenericArgs::error_for_item(interner, def.into());
        Type::new(db, def, ty.instantiate(interner, args))
    }

    pub fn new_slice(ty: Self) -> Self {
        let interner = DbInterner::conjure();
        Type { env: ty.env, ty: Ty::new_slice(interner, ty.ty) }
    }

    pub fn new_tuple(krate: base_db::Crate, tys: &[Self]) -> Self {
        let tys = tys.iter().map(|it| it.ty);
        let interner = DbInterner::conjure();
        Type { env: TraitEnvironment::empty(krate), ty: Ty::new_tup_from_iter(interner, tys) }
    }

    pub fn is_unit(&self) -> bool {
        self.ty.is_unit()
    }

    pub fn is_bool(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Bool)
    }

    pub fn is_str(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Str)
    }

    pub fn is_never(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Never)
    }

    pub fn is_mutable_reference(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Ref(.., hir_ty::next_solver::Mutability::Mut))
    }

    pub fn is_reference(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Ref(..))
    }

    pub fn contains_reference(&self, db: &'db dyn HirDatabase) -> bool {
        let interner = DbInterner::new_with(db, None, None);
        return self.ty.visit_with(&mut Visitor { interner }).is_break();

        fn is_phantom_data(db: &dyn HirDatabase, adt_id: AdtId) -> bool {
            match adt_id {
                AdtId::StructId(s) => {
                    let flags = db.struct_signature(s).flags;
                    flags.contains(StructFlags::IS_PHANTOM_DATA)
                }
                AdtId::UnionId(_) | AdtId::EnumId(_) => false,
            }
        }

        struct Visitor<'db> {
            interner: DbInterner<'db>,
        }

        impl<'db> TypeVisitor<DbInterner<'db>> for Visitor<'db> {
            type Result = ControlFlow<()>;

            fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
                match ty.kind() {
                    // Reference itself
                    TyKind::Ref(..) => ControlFlow::Break(()),

                    // For non-phantom_data adts we check variants/fields as well as generic parameters
                    TyKind::Adt(adt_def, args)
                        if !is_phantom_data(self.interner.db(), adt_def.def_id().0) =>
                    {
                        let _variant_id_to_fields = |id: VariantId| {
                            let variant_data = &id.fields(self.interner.db());
                            if variant_data.fields().is_empty() {
                                vec![]
                            } else {
                                let field_types = self.interner.db().field_types(id);
                                variant_data
                                    .fields()
                                    .iter()
                                    .map(|(idx, _)| {
                                        field_types[idx].instantiate(self.interner, args)
                                    })
                                    .filter(|it| !it.references_non_lt_error())
                                    .collect()
                            }
                        };
                        let variant_id_to_fields = |_: VariantId| vec![];

                        let variants: Vec<Vec<Ty<'db>>> = match adt_def.def_id().0 {
                            AdtId::StructId(id) => {
                                vec![variant_id_to_fields(id.into())]
                            }
                            AdtId::EnumId(id) => id
                                .enum_variants(self.interner.db())
                                .variants
                                .iter()
                                .map(|&(variant_id, _, _)| variant_id_to_fields(variant_id.into()))
                                .collect(),
                            AdtId::UnionId(id) => {
                                vec![variant_id_to_fields(id.into())]
                            }
                        };

                        variants
                            .into_iter()
                            .flat_map(|variant| variant.into_iter())
                            .try_for_each(|ty| ty.visit_with(self))?;
                        args.visit_with(self)
                    }
                    // And for `PhantomData<T>`, we check `T`.
                    _ => ty.super_visit_with(self),
                }
            }
        }
    }

    pub fn as_reference(&self) -> Option<(Type<'db>, Mutability)> {
        let TyKind::Ref(_lt, ty, m) = self.ty.kind() else { return None };
        let m = Mutability::from_mutable(matches!(m, hir_ty::next_solver::Mutability::Mut));
        Some((self.derived(ty), m))
    }

    pub fn add_reference(&self, mutability: Mutability) -> Self {
        let interner = DbInterner::conjure();
        let ty_mutability = match mutability {
            Mutability::Shared => hir_ty::next_solver::Mutability::Not,
            Mutability::Mut => hir_ty::next_solver::Mutability::Mut,
        };
        self.derived(Ty::new_ref(interner, Region::error(interner), self.ty, ty_mutability))
    }

    pub fn is_slice(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Slice(..))
    }

    pub fn is_usize(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Uint(rustc_type_ir::UintTy::Usize))
    }

    pub fn is_float(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Float(_))
    }

    pub fn is_char(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Char)
    }

    pub fn is_int_or_uint(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Int(_) | TyKind::Uint(_))
    }

    pub fn is_scalar(&self) -> bool {
        matches!(
            self.ty.kind(),
            TyKind::Bool | TyKind::Char | TyKind::Int(_) | TyKind::Uint(_) | TyKind::Float(_)
        )
    }

    pub fn is_tuple(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Tuple(..))
    }

    pub fn remove_ref(&self) -> Option<Type<'db>> {
        match self.ty.kind() {
            TyKind::Ref(_, ty, _) => Some(self.derived(ty)),
            _ => None,
        }
    }

    pub fn as_slice(&self) -> Option<Type<'db>> {
        match self.ty.kind() {
            TyKind::Slice(ty) => Some(self.derived(ty)),
            _ => None,
        }
    }

    pub fn strip_references(&self) -> Self {
        self.derived(self.ty.strip_references())
    }

    // FIXME: This is the same as `remove_ref()`, remove one of these methods.
    pub fn strip_reference(&self) -> Self {
        self.derived(self.ty.strip_reference())
    }

    pub fn is_unknown(&self) -> bool {
        self.ty.is_ty_error()
    }

    /// Checks that particular type `ty` implements `std::future::IntoFuture` or
    /// `std::future::Future` and returns the `Output` associated type.
    /// This function is used in `.await` syntax completion.
    pub fn into_future_output(&self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
        let trait_ = LangItem::IntoFutureIntoFuture
            .resolve_function(db, self.env.krate)
            .and_then(|into_future_fn| {
                let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?;
                let into_future_trait = assoc_item.container_or_implemented_trait(db)?;
                Some(into_future_trait.id)
            })
            .or_else(|| LangItem::Future.resolve_trait(db, self.env.krate))?;

        if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) {
            return None;
        }

        let output_assoc_type =
            trait_.trait_items(db).associated_type_by_name(&Name::new_symbol_root(sym::Output))?;
        self.normalize_trait_assoc_type(db, &[], output_assoc_type.into())
    }

    /// This does **not** resolve `IntoFuture`, only `Future`.
    pub fn future_output(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
        let future_output = LangItem::FutureOutput.resolve_type_alias(db, self.env.krate)?;
        self.normalize_trait_assoc_type(db, &[], future_output.into())
    }

    /// This does **not** resolve `IntoIterator`, only `Iterator`.
    pub fn iterator_item(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
        let iterator_trait = LangItem::Iterator.resolve_trait(db, self.env.krate)?;
        let iterator_item = iterator_trait
            .trait_items(db)
            .associated_type_by_name(&Name::new_symbol_root(sym::Item))?;
        self.normalize_trait_assoc_type(db, &[], iterator_item.into())
    }

    pub fn impls_iterator(self, db: &'db dyn HirDatabase) -> bool {
        let Some(iterator_trait) = LangItem::Iterator.resolve_trait(db, self.env.krate) else {
            return false;
        };
        traits::implements_trait_unique(self.ty, db, self.env.clone(), iterator_trait)
    }

    /// Resolves the projection `<Self as IntoIterator>::IntoIter` and returns the resulting type
    pub fn into_iterator_iter(self, db: &'db dyn HirDatabase) -> Option<Type<'db>> {
        let trait_ = LangItem::IntoIterIntoIter.resolve_function(db, self.env.krate).and_then(
            |into_iter_fn| {
                let assoc_item = as_assoc_item(db, AssocItem::Function, into_iter_fn)?;
                let into_iter_trait = assoc_item.container_or_implemented_trait(db)?;
                Some(into_iter_trait.id)
            },
        )?;

        if !traits::implements_trait_unique(self.ty, db, self.env.clone(), trait_) {
            return None;
        }

        let into_iter_assoc_type = trait_
            .trait_items(db)
            .associated_type_by_name(&Name::new_symbol_root(sym::IntoIter))?;
        self.normalize_trait_assoc_type(db, &[], into_iter_assoc_type.into())
    }

    /// Checks that particular type `ty` implements `std::ops::FnOnce`.
    ///
    /// This function can be used to check if a particular type is callable, since FnOnce is a
    /// supertrait of Fn and FnMut, so all callable types implements at least FnOnce.
    pub fn impls_fnonce(&self, db: &'db dyn HirDatabase) -> bool {
        let fnonce_trait = match FnTrait::FnOnce.get_id(db, self.env.krate) {
            Some(it) => it,
            None => return false,
        };

        traits::implements_trait_unique(self.ty, db, self.env.clone(), fnonce_trait)
    }

    // FIXME: Find better API that also handles const generics
    pub fn impls_trait(&self, db: &'db dyn HirDatabase, trait_: Trait, args: &[Type<'db>]) -> bool {
        let interner = DbInterner::new_with(db, None, None);
        let args = generic_args_from_tys(
            interner,
            trait_.id.into(),
            std::iter::once(self.ty).chain(args.iter().map(|ty| ty.ty)),
        );
        traits::implements_trait_unique_with_args(db, self.env.clone(), trait_.id, args)
    }

    pub fn normalize_trait_assoc_type(
        &self,
        db: &'db dyn HirDatabase,
        args: &[Type<'db>],
        alias: TypeAlias,
    ) -> Option<Type<'db>> {
        let interner = DbInterner::new_with(db, Some(self.env.krate), self.env.block);
        let args = generic_args_from_tys(
            interner,
            alias.id.into(),
            std::iter::once(self.ty).chain(args.iter().map(|ty| ty.ty)),
        );
        // FIXME: We don't handle GATs yet.
        let projection = Ty::new_alias(
            interner,
            AliasTyKind::Projection,
            AliasTy::new(interner, alias.id.into(), args),
        );

        let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
        let ty = structurally_normalize_ty(&infcx, projection, self.env.clone());
        if ty.is_ty_error() { None } else { Some(self.derived(ty)) }
    }

    pub fn is_copy(&self, db: &'db dyn HirDatabase) -> bool {
        let Some(copy_trait) = LangItem::Copy.resolve_trait(db, self.env.krate) else {
            return false;
        };
        self.impls_trait(db, copy_trait.into(), &[])
    }

    pub fn as_callable(&self, db: &'db dyn HirDatabase) -> Option<Callable<'db>> {
        let interner = DbInterner::new_with(db, None, None);
        let callee = match self.ty.kind() {
            TyKind::Closure(id, subst) => Callee::Closure(id.0, subst),
            TyKind::CoroutineClosure(id, subst) => Callee::CoroutineClosure(id.0, subst),
            TyKind::FnPtr(..) => Callee::FnPtr,
            TyKind::FnDef(id, _) => Callee::Def(id.0),
            // This will happen when it implements fn or fn mut, since we add an autoborrow adjustment
            TyKind::Ref(_, inner_ty, _) => return self.derived(inner_ty).as_callable(db),
            _ => {
                let (fn_trait, sig) =
                    hir_ty::callable_sig_from_fn_trait(self.ty, self.env.clone(), db)?;
                return Some(Callable {
                    ty: self.clone(),
                    sig,
                    callee: Callee::FnImpl(fn_trait),
                    is_bound_method: false,
                });
            }
        };

        let sig = self.ty.callable_sig(interner)?;
        Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
    }

    pub fn is_closure(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Closure { .. })
    }

    pub fn as_closure(&self) -> Option<Closure<'db>> {
        match self.ty.kind() {
            TyKind::Closure(id, subst) => {
                Some(Closure { id: AnyClosureId::ClosureId(id.0), subst })
            }
            TyKind::CoroutineClosure(id, subst) => {
                Some(Closure { id: AnyClosureId::CoroutineClosureId(id.0), subst })
            }
            _ => None,
        }
    }

    pub fn is_fn(&self) -> bool {
        matches!(self.ty.kind(), TyKind::FnDef(..) | TyKind::FnPtr { .. })
    }

    pub fn is_array(&self) -> bool {
        matches!(self.ty.kind(), TyKind::Array(..))
    }

    pub fn is_packed(&self, db: &'db dyn HirDatabase) -> bool {
        let adt_id = match self.ty.kind() {
            TyKind::Adt(adt_def, ..) => adt_def.def_id().0,
            _ => return false,
        };

        let adt = adt_id.into();
        match adt {
            Adt::Struct(s) => s.repr(db).unwrap_or_default().pack.is_some(),
            _ => false,
        }
    }

    pub fn is_raw_ptr(&self) -> bool {
        matches!(self.ty.kind(), TyKind::RawPtr(..))
    }

    pub fn remove_raw_ptr(&self) -> Option<Type<'db>> {
        if let TyKind::RawPtr(ty, _) = self.ty.kind() { Some(self.derived(ty)) } else { None }
    }

    pub fn contains_unknown(&self) -> bool {
        self.ty.references_non_lt_error()
    }

    pub fn fields(&self, db: &'db dyn HirDatabase) -> Vec<(Field, Self)> {
        let interner = DbInterner::new_with(db, None, None);
        let (variant_id, substs) = match self.ty.kind() {
            TyKind::Adt(adt_def, substs) => {
                let id = match adt_def.def_id().0 {
                    AdtId::StructId(id) => id.into(),
                    AdtId::UnionId(id) => id.into(),
                    AdtId::EnumId(_) => return Vec::new(),
                };
                (id, substs)
            }
            _ => return Vec::new(),
        };

        db.field_types(variant_id)
            .iter()
            .map(|(local_id, ty)| {
                let def = Field { parent: variant_id.into(), id: local_id };
                let ty = ty.instantiate(interner, substs);
                (def, self.derived(ty))
            })
            .collect()
    }

    pub fn tuple_fields(&self, _db: &'db dyn HirDatabase) -> Vec<Self> {
        if let TyKind::Tuple(substs) = self.ty.kind() {
            substs.iter().map(|ty| self.derived(ty)).collect()
        } else {
            Vec::new()
        }
    }

    pub fn as_array(&self, db: &'db dyn HirDatabase) -> Option<(Self, usize)> {
        if let TyKind::Array(ty, len) = self.ty.kind() {
            try_const_usize(db, len).map(|it| (self.derived(ty), it as usize))
        } else {
            None
        }
    }

    pub fn fingerprint_for_trait_impl(&self) -> Option<SimplifiedType> {
        fast_reject::simplify_type(
            DbInterner::conjure(),
            self.ty,
            fast_reject::TreatParams::AsRigid,
        )
    }

    /// Returns types that this type dereferences to (including this type itself). The returned
    /// iterator won't yield the same type more than once even if the deref chain contains a cycle.
    pub fn autoderef(
        &self,
        db: &'db dyn HirDatabase,
    ) -> impl Iterator<Item = Type<'db>> + use<'_, 'db> {
        self.autoderef_(db).map(move |ty| self.derived(ty))
    }

    fn autoderef_(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Ty<'db>> {
        let interner = DbInterner::new_with(db, None, None);
        // There should be no inference vars in types passed here
        let canonical = hir_ty::replace_errors_with_variables(interner, &self.ty);
        autoderef(db, self.env.clone(), canonical)
    }

    // This would be nicer if it just returned an iterator, but that runs into
    // lifetime problems, because we need to borrow temp `CrateImplDefs`.
    pub fn iterate_assoc_items<T>(
        &self,
        db: &'db dyn HirDatabase,
        mut callback: impl FnMut(AssocItem) -> Option<T>,
    ) -> Option<T> {
        let mut slot = None;
        self.iterate_assoc_items_dyn(db, &mut |assoc_item_id| {
            slot = callback(assoc_item_id.into());
            slot.is_some()
        });
        slot
    }

    fn iterate_assoc_items_dyn(
        &self,
        db: &'db dyn HirDatabase,
        callback: &mut dyn FnMut(AssocItemId) -> bool,
    ) {
        let mut handle_impls = |impls: &[ImplId]| {
            for &impl_def in impls {
                for &(_, item) in impl_def.impl_items(db).items.iter() {
                    if callback(item) {
                        return;
                    }
                }
            }
        };

        let interner = DbInterner::new_with(db, None, None);
        let Some(simplified_type) =
            fast_reject::simplify_type(interner, self.ty, fast_reject::TreatParams::AsRigid)
        else {
            return;
        };

        handle_impls(method_resolution::incoherent_inherent_impls(db, simplified_type));

        if let Some(module) = method_resolution::simplified_type_module(db, &simplified_type) {
            InherentImpls::for_each_crate_and_block(
                db,
                module.krate(),
                module.containing_block(),
                &mut |impls| {
                    handle_impls(impls.for_self_ty(&simplified_type));
                },
            );
        }
    }

    /// Iterates its type arguments
    ///
    /// It iterates the actual type arguments when concrete types are used
    /// and otherwise the generic names.
    /// It does not include `const` arguments.
    ///
    /// For code, such as:
    /// ```text
    /// struct Foo<T, U>
    ///
    /// impl<U> Foo<String, U>
    /// ```
    ///
    /// It iterates:
    /// ```text
    /// - "String"
    /// - "U"
    /// ```
    pub fn type_arguments(&self) -> impl Iterator<Item = Type<'db>> + '_ {
        match self.ty.strip_references().kind() {
            TyKind::Adt(_, substs) => Either::Left(substs.types().map(move |ty| self.derived(ty))),
            TyKind::Tuple(substs) => {
                Either::Right(Either::Left(substs.iter().map(move |ty| self.derived(ty))))
            }
            _ => Either::Right(Either::Right(std::iter::empty())),
        }
    }

    /// Iterates its type and const arguments
    ///
    /// It iterates the actual type and const arguments when concrete types
    /// are used and otherwise the generic names.
    ///
    /// For code, such as:
    /// ```text
    /// struct Foo<T, const U: usize, const X: usize>
    ///
    /// impl<U> Foo<String, U, 12>
    /// ```
    ///
    /// It iterates:
    /// ```text
    /// - "String"
    /// - "U"
    /// - "12"
    /// ```
    pub fn type_and_const_arguments<'a>(
        &'a self,
        db: &'a dyn HirDatabase,
        display_target: DisplayTarget,
    ) -> impl Iterator<Item = SmolStr> + 'a {
        self.ty
            .strip_references()
            .as_adt()
            .into_iter()
            .flat_map(|(_, substs)| substs.iter())
            .filter_map(move |arg| match arg {
                GenericArg::Ty(ty) => Some(format_smolstr!("{}", ty.display(db, display_target))),
                GenericArg::Const(const_) => {
                    Some(format_smolstr!("{}", const_.display(db, display_target)))
                }
                GenericArg::Lifetime(_) => None,
            })
    }

    /// Combines lifetime indicators, type and constant parameters into a single `Iterator`
    pub fn generic_parameters<'a>(
        &'a self,
        db: &'a dyn HirDatabase,
        display_target: DisplayTarget,
    ) -> impl Iterator<Item = SmolStr> + 'a {
        // iterate the lifetime
        self.as_adt()
            .and_then(|a| {
                // Lifetimes do not need edition-specific handling as they cannot be escaped.
                a.lifetime(db).map(|lt| lt.name.display_no_db(Edition::Edition2015).to_smolstr())
            })
            .into_iter()
            // add the type and const parameters
            .chain(self.type_and_const_arguments(db, display_target))
    }

    pub fn iterate_method_candidates_with_traits<T>(
        &self,
        db: &'db dyn HirDatabase,
        scope: &SemanticsScope<'_>,
        traits_in_scope: &FxHashSet<TraitId>,
        name: Option<&Name>,
        mut callback: impl FnMut(Function) -> Option<T>,
    ) -> Option<T> {
        let _p = tracing::info_span!("iterate_method_candidates_with_traits").entered();
        let mut slot = None;
        self.iterate_method_candidates_split_inherent(db, scope, traits_in_scope, name, |f| {
            match callback(f) {
                it @ Some(_) => {
                    slot = it;
                    ControlFlow::Break(())
                }
                None => ControlFlow::Continue(()),
            }
        });
        slot
    }

    pub fn iterate_method_candidates<T>(
        &self,
        db: &'db dyn HirDatabase,
        scope: &SemanticsScope<'_>,
        name: Option<&Name>,
        callback: impl FnMut(Function) -> Option<T>,
    ) -> Option<T> {
        self.iterate_method_candidates_with_traits(
            db,
            scope,
            &scope.visible_traits().0,
            name,
            callback,
        )
    }

    fn with_method_resolution<R>(
        &self,
        db: &'db dyn HirDatabase,
        resolver: &Resolver<'db>,
        traits_in_scope: &FxHashSet<TraitId>,
        f: impl FnOnce(&MethodResolutionContext<'_, 'db>) -> R,
    ) -> R {
        let module = resolver.module();
        let interner = DbInterner::new_with(db, Some(module.krate()), module.containing_block());
        let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
        let unstable_features =
            MethodResolutionUnstableFeatures::from_def_map(resolver.top_level_def_map());
        let environment = resolver
            .generic_def()
            .map_or_else(|| TraitEnvironment::empty(module.krate()), |d| db.trait_environment(d));
        let ctx = MethodResolutionContext {
            infcx: &infcx,
            resolver,
            env: &environment,
            traits_in_scope,
            edition: resolver.krate().data(db).edition,
            unstable_features: &unstable_features,
        };
        f(&ctx)
    }

    /// Allows you to treat inherent and non-inherent methods differently.
    ///
    /// Note that inherent methods may actually be trait methods! For example, in `dyn Trait`, the trait's methods
    /// are considered inherent methods.
    pub fn iterate_method_candidates_split_inherent(
        &self,
        db: &'db dyn HirDatabase,
        scope: &SemanticsScope<'_>,
        traits_in_scope: &FxHashSet<TraitId>,
        name: Option<&Name>,
        mut callback: impl MethodCandidateCallback,
    ) {
        let _p = tracing::info_span!(
            "iterate_method_candidates_split_inherent",
            traits_in_scope = traits_in_scope.len(),
            ?name,
        )
        .entered();

        self.with_method_resolution(db, scope.resolver(), traits_in_scope, |ctx| {
            // There should be no inference vars in types passed here
            let canonical = hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty);
            let (self_ty, _) = ctx.infcx.instantiate_canonical(&canonical);

            match name {
                Some(name) => {
                    match ctx.probe_for_name(
                        method_resolution::Mode::MethodCall,
                        name.clone(),
                        self_ty,
                    ) {
                        Ok(candidate)
                        | Err(method_resolution::MethodError::PrivateMatch(candidate)) => {
                            let method_resolution::CandidateId::FunctionId(id) = candidate.item
                            else {
                                unreachable!("`Mode::MethodCall` can only return functions");
                            };
                            let id = Function { id };
                            match candidate.kind {
                                method_resolution::PickKind::InherentImplPick(_)
                                | method_resolution::PickKind::ObjectPick(..)
                                | method_resolution::PickKind::WhereClausePick(..) => {
                                    // Candidates from where clauses and trait objects are considered inherent.
                                    _ = callback.on_inherent_method(id);
                                }
                                method_resolution::PickKind::TraitPick(..) => {
                                    _ = callback.on_trait_method(id);
                                }
                            }
                        }
                        Err(_) => {}
                    };
                }
                None => {
                    _ = ctx.probe_all(method_resolution::Mode::MethodCall, self_ty).try_for_each(
                        |candidate| {
                            let method_resolution::CandidateId::FunctionId(id) =
                                candidate.candidate.item
                            else {
                                unreachable!("`Mode::MethodCall` can only return functions");
                            };
                            let id = Function { id };
                            match candidate.candidate.kind {
                                method_resolution::CandidateKind::InherentImplCandidate {
                                    ..
                                }
                                | method_resolution::CandidateKind::ObjectCandidate(..)
                                | method_resolution::CandidateKind::WhereClauseCandidate(..) => {
                                    // Candidates from where clauses and trait objects are considered inherent.
                                    callback.on_inherent_method(id)
                                }
                                method_resolution::CandidateKind::TraitCandidate(..) => {
                                    callback.on_trait_method(id)
                                }
                            }
                        },
                    );
                }
            }
        })
    }

    #[tracing::instrument(skip_all, fields(name = ?name))]
    pub fn iterate_path_candidates<T>(
        &self,
        db: &'db dyn HirDatabase,
        scope: &SemanticsScope<'_>,
        traits_in_scope: &FxHashSet<TraitId>,
        name: Option<&Name>,
        mut callback: impl FnMut(AssocItem) -> Option<T>,
    ) -> Option<T> {
        let _p = tracing::info_span!("iterate_path_candidates").entered();
        let mut slot = None;

        self.iterate_path_candidates_split_inherent(db, scope, traits_in_scope, name, |item| {
            match callback(item) {
                it @ Some(_) => {
                    slot = it;
                    ControlFlow::Break(())
                }
                None => ControlFlow::Continue(()),
            }
        });
        slot
    }

    /// Iterates over inherent methods.
    ///
    /// In some circumstances, inherent methods methods may actually be trait methods!
    /// For example, when `dyn Trait` is a receiver, _trait_'s methods would be considered
    /// to be inherent methods.
    #[tracing::instrument(skip_all, fields(name = ?name))]
    pub fn iterate_path_candidates_split_inherent(
        &self,
        db: &'db dyn HirDatabase,
        scope: &SemanticsScope<'_>,
        traits_in_scope: &FxHashSet<TraitId>,
        name: Option<&Name>,
        mut callback: impl PathCandidateCallback,
    ) {
        let _p = tracing::info_span!(
            "iterate_path_candidates_split_inherent",
            traits_in_scope = traits_in_scope.len(),
            ?name,
        )
        .entered();

        self.with_method_resolution(db, scope.resolver(), traits_in_scope, |ctx| {
            // There should be no inference vars in types passed here
            let canonical = hir_ty::replace_errors_with_variables(ctx.infcx.interner, &self.ty);
            let (self_ty, _) = ctx.infcx.instantiate_canonical(&canonical);

            match name {
                Some(name) => {
                    match ctx.probe_for_name(
                        method_resolution::Mode::MethodCall,
                        name.clone(),
                        self_ty,
                    ) {
                        Ok(candidate)
                        | Err(method_resolution::MethodError::PrivateMatch(candidate)) => {
                            let id = candidate.item.into();
                            match candidate.kind {
                                method_resolution::PickKind::InherentImplPick(_)
                                | method_resolution::PickKind::ObjectPick(..)
                                | method_resolution::PickKind::WhereClausePick(..) => {
                                    // Candidates from where clauses and trait objects are considered inherent.
                                    _ = callback.on_inherent_item(id);
                                }
                                method_resolution::PickKind::TraitPick(..) => {
                                    _ = callback.on_trait_item(id);
                                }
                            }
                        }
                        Err(_) => {}
                    };
                }
                None => {
                    _ = ctx.probe_all(method_resolution::Mode::Path, self_ty).try_for_each(
                        |candidate| {
                            let id = candidate.candidate.item.into();
                            match candidate.candidate.kind {
                                method_resolution::CandidateKind::InherentImplCandidate {
                                    ..
                                }
                                | method_resolution::CandidateKind::ObjectCandidate(..)
                                | method_resolution::CandidateKind::WhereClauseCandidate(..) => {
                                    // Candidates from where clauses and trait objects are considered inherent.
                                    callback.on_inherent_item(id)
                                }
                                method_resolution::CandidateKind::TraitCandidate(..) => {
                                    callback.on_trait_item(id)
                                }
                            }
                        },
                    );
                }
            }
        })
    }

    pub fn as_adt(&self) -> Option<Adt> {
        let (adt, _subst) = self.ty.as_adt()?;
        Some(adt.into())
    }

    pub fn as_builtin(&self) -> Option<BuiltinType> {
        self.ty.as_builtin().map(|inner| BuiltinType { inner })
    }

    pub fn as_dyn_trait(&self) -> Option<Trait> {
        self.ty.dyn_trait().map(Into::into)
    }

    /// If a type can be represented as `dyn Trait`, returns all traits accessible via this type,
    /// or an empty iterator otherwise.
    pub fn applicable_inherent_traits(
        &self,
        db: &'db dyn HirDatabase,
    ) -> impl Iterator<Item = Trait> {
        let _p = tracing::info_span!("applicable_inherent_traits").entered();
        self.autoderef_(db)
            .filter_map(|ty| ty.dyn_trait())
            .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db, dyn_trait_id))
            .map(Trait::from)
    }

    pub fn env_traits(&self, db: &'db dyn HirDatabase) -> impl Iterator<Item = Trait> {
        let _p = tracing::info_span!("env_traits").entered();
        self.autoderef_(db)
            .filter(|ty| matches!(ty.kind(), TyKind::Param(_)))
            .flat_map(|ty| {
                self.env
                    .traits_in_scope_from_clauses(ty)
                    .flat_map(|t| hir_ty::all_super_traits(db, t))
            })
            .map(Trait::from)
    }

    pub fn as_impl_traits(&self, db: &'db dyn HirDatabase) -> Option<impl Iterator<Item = Trait>> {
        self.ty.impl_trait_bounds(db).map(|it| {
            it.into_iter().filter_map(|pred| match pred.kind().skip_binder() {
                ClauseKind::Trait(trait_ref) => Some(Trait::from(trait_ref.def_id().0)),
                _ => None,
            })
        })
    }

    pub fn as_associated_type_parent_trait(&self, db: &'db dyn HirDatabase) -> Option<Trait> {
        let TyKind::Alias(AliasTyKind::Projection, alias) = self.ty.kind() else { return None };
        match alias.def_id.expect_type_alias().loc(db).container {
            ItemContainerId::TraitId(id) => Some(Trait { id }),
            _ => None,
        }
    }

    fn derived(&self, ty: Ty<'db>) -> Self {
        Type { env: self.env.clone(), ty }
    }

    /// Visits every type, including generic arguments, in this type. `callback` is called with type
    /// itself first, and then with its generic arguments.
    pub fn walk(&self, db: &'db dyn HirDatabase, callback: impl FnMut(Type<'db>)) {
        struct Visitor<'db, F> {
            db: &'db dyn HirDatabase,
            env: Arc<TraitEnvironment<'db>>,
            callback: F,
            visited: FxHashSet<Ty<'db>>,
        }
        impl<'db, F> TypeVisitor<DbInterner<'db>> for Visitor<'db, F>
        where
            F: FnMut(Type<'db>),
        {
            type Result = ();

            fn visit_ty(&mut self, ty: Ty<'db>) -> Self::Result {
                if !self.visited.insert(ty) {
                    return;
                }

                (self.callback)(Type { env: self.env.clone(), ty });

                if let Some(bounds) = ty.impl_trait_bounds(self.db) {
                    bounds.visit_with(self);
                }

                ty.super_visit_with(self);
            }
        }

        let mut visitor =
            Visitor { db, env: self.env.clone(), callback, visited: FxHashSet::default() };
        self.ty.visit_with(&mut visitor);
    }
    /// Check if type unifies with another type.
    ///
    /// Note that we consider placeholder types to unify with everything.
    /// For example `Option<T>` and `Option<U>` unify although there is unresolved goal `T = U`.
    pub fn could_unify_with(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool {
        let interner = DbInterner::new_with(db, None, None);
        let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty));
        hir_ty::could_unify(db, self.env.clone(), &tys)
    }

    /// Check if type unifies with another type eagerly making sure there are no unresolved goals.
    ///
    /// This means that placeholder types are not considered to unify if there are any bounds set on
    /// them. For example `Option<T>` and `Option<U>` do not unify as we cannot show that `T = U`
    pub fn could_unify_with_deeply(&self, db: &'db dyn HirDatabase, other: &Type<'db>) -> bool {
        let interner = DbInterner::new_with(db, None, None);
        let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, other.ty));
        hir_ty::could_unify_deeply(db, self.env.clone(), &tys)
    }

    pub fn could_coerce_to(&self, db: &'db dyn HirDatabase, to: &Type<'db>) -> bool {
        let interner = DbInterner::new_with(db, None, None);
        let tys = hir_ty::replace_errors_with_variables(interner, &(self.ty, to.ty));
        hir_ty::could_coerce(db, self.env.clone(), &tys)
    }

    pub fn as_type_param(&self, _db: &'db dyn HirDatabase) -> Option<TypeParam> {
        match self.ty.kind() {
            TyKind::Param(param) => Some(TypeParam { id: param.id }),
            _ => None,
        }
    }

    /// Returns unique `GenericParam`s contained in this type.
    pub fn generic_params(&self, db: &'db dyn HirDatabase) -> FxHashSet<GenericParam> {
        hir_ty::collect_params(&self.ty)
            .into_iter()
            .map(|id| TypeOrConstParam { id }.split(db).either_into())
            .collect()
    }

    pub fn layout(&self, db: &'db dyn HirDatabase) -> Result<Layout, LayoutError> {
        db.layout_of_ty(self.ty, self.env.clone())
            .map(|layout| Layout(layout, db.target_data_layout(self.env.krate).unwrap()))
    }

    pub fn drop_glue(&self, db: &'db dyn HirDatabase) -> DropGlue {
        let interner = DbInterner::new_with(db, Some(self.env.krate), self.env.block);
        let infcx = interner.infer_ctxt().build(TypingMode::PostAnalysis);
        hir_ty::drop::has_drop_glue(&infcx, self.ty, self.env.clone())
    }
}

#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct TypeNs<'db> {
    env: Arc<TraitEnvironment<'db>>,
    ty: Ty<'db>,
}

impl<'db> TypeNs<'db> {
    fn new(db: &'db dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty<'db>) -> Self {
        let resolver = lexical_env.resolver(db);
        let environment = resolver
            .generic_def()
            .map_or_else(|| TraitEnvironment::empty(resolver.krate()), |d| db.trait_environment(d));
        TypeNs { env: environment, ty }
    }

    pub fn to_type(&self, _db: &'db dyn HirDatabase) -> Type<'db> {
        Type { env: self.env.clone(), ty: self.ty }
    }

    // FIXME: Find better API that also handles const generics
    pub fn impls_trait(&self, infcx: InferCtxt<'db>, trait_: Trait, args: &[TypeNs<'db>]) -> bool {
        let args = GenericArgs::new_from_iter(
            infcx.interner,
            [self.ty].into_iter().chain(args.iter().map(|t| t.ty)).map(|t| t.into()),
        );
        let trait_ref = hir_ty::next_solver::TraitRef::new(infcx.interner, trait_.id.into(), args);

        let pred_kind = rustc_type_ir::Binder::dummy(rustc_type_ir::PredicateKind::Clause(
            rustc_type_ir::ClauseKind::Trait(rustc_type_ir::TraitPredicate {
                trait_ref,
                polarity: rustc_type_ir::PredicatePolarity::Positive,
            }),
        ));
        let predicate = hir_ty::next_solver::Predicate::new(infcx.interner, pred_kind);
        let goal = hir_ty::next_solver::Goal::new(
            infcx.interner,
            hir_ty::next_solver::ParamEnv::empty(),
            predicate,
        );
        let res = hir_ty::traits::next_trait_solve_in_ctxt(&infcx, goal);
        res.map_or(false, |res| matches!(res.1, rustc_type_ir::solve::Certainty::Yes))
    }

    pub fn is_bool(&self) -> bool {
        matches!(self.ty.kind(), rustc_type_ir::TyKind::Bool)
    }
}

#[derive(Debug, PartialEq, Eq, Copy, Clone, Hash)]
pub struct InlineAsmOperand {
    owner: DefWithBodyId,
    expr: ExprId,
    index: usize,
}

impl InlineAsmOperand {
    pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
        self.owner.into()
    }

    pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
        match &db.body(self.owner)[self.expr] {
            hir_def::hir::Expr::InlineAsm(e) => e.operands.get(self.index)?.0.clone(),
            _ => None,
        }
    }
}

// FIXME: Document this
#[derive(Debug)]
pub struct Callable<'db> {
    ty: Type<'db>,
    sig: PolyFnSig<'db>,
    callee: Callee<'db>,
    /// Whether this is a method that was called with method call syntax.
    is_bound_method: bool,
}

#[derive(Clone, PartialEq, Eq, Hash, Debug)]
enum Callee<'db> {
    Def(CallableDefId),
    Closure(InternedClosureId, GenericArgs<'db>),
    CoroutineClosure(InternedCoroutineId, GenericArgs<'db>),
    FnPtr,
    FnImpl(FnTrait),
}

pub enum CallableKind<'db> {
    Function(Function),
    TupleStruct(Struct),
    TupleEnumVariant(Variant),
    Closure(Closure<'db>),
    FnPtr,
    FnImpl(FnTrait),
}

impl<'db> Callable<'db> {
    pub fn kind(&self) -> CallableKind<'db> {
        match self.callee {
            Callee::Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
            Callee::Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
            Callee::Def(CallableDefId::EnumVariantId(it)) => {
                CallableKind::TupleEnumVariant(it.into())
            }
            Callee::Closure(id, subst) => {
                CallableKind::Closure(Closure { id: AnyClosureId::ClosureId(id), subst })
            }
            Callee::CoroutineClosure(id, subst) => {
                CallableKind::Closure(Closure { id: AnyClosureId::CoroutineClosureId(id), subst })
            }
            Callee::FnPtr => CallableKind::FnPtr,
            Callee::FnImpl(fn_) => CallableKind::FnImpl(fn_),
        }
    }
    pub fn receiver_param(&self, db: &'db dyn HirDatabase) -> Option<(SelfParam, Type<'db>)> {
        let func = match self.callee {
            Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
            _ => return None,
        };
        let func = Function { id: func };
        Some((
            func.self_param(db)?,
            self.ty.derived(self.sig.skip_binder().inputs_and_output.inputs()[0]),
        ))
    }
    pub fn n_params(&self) -> usize {
        self.sig.skip_binder().inputs_and_output.inputs().len()
            - if self.is_bound_method { 1 } else { 0 }
    }
    pub fn params(&self) -> Vec<Param<'db>> {
        self.sig
            .skip_binder()
            .inputs_and_output
            .inputs()
            .iter()
            .enumerate()
            .skip(if self.is_bound_method { 1 } else { 0 })
            .map(|(idx, ty)| (idx, self.ty.derived(*ty)))
            .map(|(idx, ty)| Param { func: self.callee.clone(), idx, ty })
            .collect()
    }
    pub fn return_type(&self) -> Type<'db> {
        self.ty.derived(self.sig.skip_binder().output())
    }
    pub fn sig(&self) -> impl Eq {
        &self.sig
    }

    pub fn ty(&self) -> &Type<'db> {
        &self.ty
    }
}

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Layout(Arc<TyLayout>, Arc<TargetDataLayout>);

impl Layout {
    pub fn size(&self) -> u64 {
        self.0.size.bytes()
    }

    pub fn align(&self) -> u64 {
        self.0.align.bytes()
    }

    pub fn niches(&self) -> Option<u128> {
        Some(self.0.largest_niche?.available(&*self.1))
    }

    pub fn field_offset(&self, field: Field) -> Option<u64> {
        match self.0.fields {
            layout::FieldsShape::Primitive => None,
            layout::FieldsShape::Union(_) => Some(0),
            layout::FieldsShape::Array { stride, count } => {
                let i = u64::try_from(field.index()).ok()?;
                (i < count).then_some((stride * i).bytes())
            }
            layout::FieldsShape::Arbitrary { ref offsets, .. } => {
                Some(offsets.get(RustcFieldIdx(field.id))?.bytes())
            }
        }
    }

    pub fn tuple_field_offset(&self, field: usize) -> Option<u64> {
        match self.0.fields {
            layout::FieldsShape::Primitive => None,
            layout::FieldsShape::Union(_) => Some(0),
            layout::FieldsShape::Array { stride, count } => {
                let i = u64::try_from(field).ok()?;
                (i < count).then_some((stride * i).bytes())
            }
            layout::FieldsShape::Arbitrary { ref offsets, .. } => {
                Some(offsets.get(RustcFieldIdx::new(field))?.bytes())
            }
        }
    }

    pub fn tail_padding(&self, field_size: &mut impl FnMut(usize) -> Option<u64>) -> Option<u64> {
        match self.0.fields {
            layout::FieldsShape::Primitive => None,
            layout::FieldsShape::Union(_) => None,
            layout::FieldsShape::Array { stride, count } => count.checked_sub(1).and_then(|tail| {
                let tail_field_size = field_size(tail as usize)?;
                let offset = stride.bytes() * tail;
                self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size)
            }),
            layout::FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
                let tail = memory_index.last_index()?;
                let tail_field_size = field_size(tail.0.into_raw().into_u32() as usize)?;
                let offset = offsets.get(tail)?.bytes();
                self.0.size.bytes().checked_sub(offset)?.checked_sub(tail_field_size)
            }
        }
    }

    pub fn largest_padding(
        &self,
        field_size: &mut impl FnMut(usize) -> Option<u64>,
    ) -> Option<u64> {
        match self.0.fields {
            layout::FieldsShape::Primitive => None,
            layout::FieldsShape::Union(_) => None,
            layout::FieldsShape::Array { stride: _, count: 0 } => None,
            layout::FieldsShape::Array { stride, .. } => {
                let size = field_size(0)?;
                stride.bytes().checked_sub(size)
            }
            layout::FieldsShape::Arbitrary { ref offsets, ref memory_index } => {
                let mut reverse_index = vec![None; memory_index.len()];
                for (src, (mem, offset)) in memory_index.iter().zip(offsets.iter()).enumerate() {
                    reverse_index[*mem as usize] = Some((src, offset.bytes()));
                }
                if reverse_index.iter().any(|it| it.is_none()) {
                    stdx::never!();
                    return None;
                }
                reverse_index
                    .into_iter()
                    .flatten()
                    .chain(std::iter::once((0, self.0.size.bytes())))
                    .tuple_windows()
                    .filter_map(|((i, start), (_, end))| {
                        let size = field_size(i)?;
                        end.checked_sub(start)?.checked_sub(size)
                    })
                    .max()
            }
        }
    }

    pub fn enum_tag_size(&self) -> Option<usize> {
        let tag_size =
            if let layout::Variants::Multiple { tag, tag_encoding, .. } = &self.0.variants {
                match tag_encoding {
                    TagEncoding::Direct => tag.size(&*self.1).bytes_usize(),
                    TagEncoding::Niche { .. } => 0,
                }
            } else {
                return None;
            };
        Some(tag_size)
    }
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum BindingMode {
    Move,
    Ref(Mutability),
}

/// For IDE only
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ScopeDef {
    ModuleDef(ModuleDef),
    GenericParam(GenericParam),
    ImplSelfType(Impl),
    AdtSelfType(Adt),
    Local(Local),
    Label(Label),
    Unknown,
}

impl ScopeDef {
    pub fn all_items(def: PerNs) -> ArrayVec<Self, 3> {
        let mut items = ArrayVec::new();

        match (def.take_types(), def.take_values()) {
            (Some(m1), None) => items.push(ScopeDef::ModuleDef(m1.into())),
            (None, Some(m2)) => items.push(ScopeDef::ModuleDef(m2.into())),
            (Some(m1), Some(m2)) => {
                // Some items, like unit structs and enum variants, are
                // returned as both a type and a value. Here we want
                // to de-duplicate them.
                if m1 != m2 {
                    items.push(ScopeDef::ModuleDef(m1.into()));
                    items.push(ScopeDef::ModuleDef(m2.into()));
                } else {
                    items.push(ScopeDef::ModuleDef(m1.into()));
                }
            }
            (None, None) => {}
        };

        if let Some(macro_def_id) = def.take_macros() {
            items.push(ScopeDef::ModuleDef(ModuleDef::Macro(macro_def_id.into())));
        }

        if items.is_empty() {
            items.push(ScopeDef::Unknown);
        }

        items
    }

    pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
        match self {
            ScopeDef::ModuleDef(it) => it.attrs(db),
            ScopeDef::GenericParam(it) => Some(it.attrs(db)),
            ScopeDef::ImplSelfType(_)
            | ScopeDef::AdtSelfType(_)
            | ScopeDef::Local(_)
            | ScopeDef::Label(_)
            | ScopeDef::Unknown => None,
        }
    }

    pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
        match self {
            ScopeDef::ModuleDef(it) => it.module(db).map(|m| m.krate()),
            ScopeDef::GenericParam(it) => Some(it.module(db).krate()),
            ScopeDef::ImplSelfType(_) => None,
            ScopeDef::AdtSelfType(it) => Some(it.module(db).krate()),
            ScopeDef::Local(it) => Some(it.module(db).krate()),
            ScopeDef::Label(it) => Some(it.module(db).krate()),
            ScopeDef::Unknown => None,
        }
    }
}

impl From<ItemInNs> for ScopeDef {
    fn from(item: ItemInNs) -> Self {
        match item {
            ItemInNs::Types(id) => ScopeDef::ModuleDef(id),
            ItemInNs::Values(id) => ScopeDef::ModuleDef(id),
            ItemInNs::Macros(id) => ScopeDef::ModuleDef(ModuleDef::Macro(id)),
        }
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Adjustment<'db> {
    pub source: Type<'db>,
    pub target: Type<'db>,
    pub kind: Adjust,
}

#[derive(Clone, Copy, 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),
}

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

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct OverloadedDeref(pub Mutability);

pub trait HasVisibility {
    fn visibility(&self, db: &dyn HirDatabase) -> Visibility;
    fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool {
        let vis = self.visibility(db);
        vis.is_visible_from(db, module.id)
    }
}

/// Trait for obtaining the defining crate of an item.
pub trait HasCrate {
    fn krate(&self, db: &dyn HirDatabase) -> Crate;
}

impl<T: hir_def::HasModule> HasCrate for T {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate().into()
    }
}

impl HasCrate for AssocItem {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for Struct {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for Union {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for Enum {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for Field {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.parent_def(db).module(db).krate()
    }
}

impl HasCrate for Variant {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for Function {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for Const {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for TypeAlias {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for Type<'_> {
    fn krate(&self, _db: &dyn HirDatabase) -> Crate {
        self.env.krate.into()
    }
}

impl HasCrate for Macro {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for Trait {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for Static {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for Adt {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for Impl {
    fn krate(&self, db: &dyn HirDatabase) -> Crate {
        self.module(db).krate()
    }
}

impl HasCrate for Module {
    fn krate(&self, _: &dyn HirDatabase) -> Crate {
        Module::krate(*self)
    }
}

pub trait HasContainer {
    fn container(&self, db: &dyn HirDatabase) -> ItemContainer;
}

impl HasContainer for ExternCrateDecl {
    fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
        container_id_to_hir(self.id.lookup(db).container.into())
    }
}

impl HasContainer for Module {
    fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
        // FIXME: handle block expressions as modules (their parent is in a different DefMap)
        let def_map = self.id.def_map(db);
        match def_map[self.id.local_id].parent {
            Some(parent_id) => ItemContainer::Module(Module { id: def_map.module_id(parent_id) }),
            None => ItemContainer::Crate(def_map.krate().into()),
        }
    }
}

impl HasContainer for Function {
    fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
        container_id_to_hir(self.id.lookup(db).container)
    }
}

impl HasContainer for Struct {
    fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
        ItemContainer::Module(Module { id: self.id.lookup(db).container })
    }
}

impl HasContainer for Union {
    fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
        ItemContainer::Module(Module { id: self.id.lookup(db).container })
    }
}

impl HasContainer for Enum {
    fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
        ItemContainer::Module(Module { id: self.id.lookup(db).container })
    }
}

impl HasContainer for TypeAlias {
    fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
        container_id_to_hir(self.id.lookup(db).container)
    }
}

impl HasContainer for Const {
    fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
        container_id_to_hir(self.id.lookup(db).container)
    }
}

impl HasContainer for Static {
    fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
        container_id_to_hir(self.id.lookup(db).container)
    }
}

impl HasContainer for Trait {
    fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
        ItemContainer::Module(Module { id: self.id.lookup(db).container })
    }
}

impl HasContainer for ExternBlock {
    fn container(&self, db: &dyn HirDatabase) -> ItemContainer {
        ItemContainer::Module(Module { id: self.id.lookup(db).container })
    }
}

fn container_id_to_hir(c: ItemContainerId) -> ItemContainer {
    match c {
        ItemContainerId::ExternBlockId(id) => ItemContainer::ExternBlock(ExternBlock { id }),
        ItemContainerId::ModuleId(id) => ItemContainer::Module(Module { id }),
        ItemContainerId::ImplId(id) => ItemContainer::Impl(Impl { id }),
        ItemContainerId::TraitId(id) => ItemContainer::Trait(Trait { id }),
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ItemContainer {
    Trait(Trait),
    Impl(Impl),
    Module(Module),
    ExternBlock(ExternBlock),
    Crate(Crate),
}

/// Subset of `ide_db::Definition` that doc links can resolve to.
pub enum DocLinkDef {
    ModuleDef(ModuleDef),
    Field(Field),
    SelfType(Trait),
}

fn push_ty_diagnostics<'db>(
    db: &'db dyn HirDatabase,
    acc: &mut Vec<AnyDiagnostic<'db>>,
    diagnostics: Option<ThinArc<(), TyLoweringDiagnostic>>,
    source_map: &ExpressionStoreSourceMap,
) {
    if let Some(diagnostics) = diagnostics {
        acc.extend(
            diagnostics
                .slice
                .iter()
                .filter_map(|diagnostic| AnyDiagnostic::ty_diagnostic(diagnostic, source_map, db)),
        );
    }
}

pub trait MethodCandidateCallback {
    fn on_inherent_method(&mut self, f: Function) -> ControlFlow<()>;

    fn on_trait_method(&mut self, f: Function) -> ControlFlow<()>;
}

impl<F> MethodCandidateCallback for F
where
    F: FnMut(Function) -> ControlFlow<()>,
{
    fn on_inherent_method(&mut self, f: Function) -> ControlFlow<()> {
        self(f)
    }

    fn on_trait_method(&mut self, f: Function) -> ControlFlow<()> {
        self(f)
    }
}

pub trait PathCandidateCallback {
    fn on_inherent_item(&mut self, item: AssocItem) -> ControlFlow<()>;

    fn on_trait_item(&mut self, item: AssocItem) -> ControlFlow<()>;
}

impl<F> PathCandidateCallback for F
where
    F: FnMut(AssocItem) -> ControlFlow<()>,
{
    fn on_inherent_item(&mut self, item: AssocItem) -> ControlFlow<()> {
        self(item)
    }

    fn on_trait_item(&mut self, item: AssocItem) -> ControlFlow<()> {
        self(item)
    }
}

pub fn resolve_absolute_path<'a, I: Iterator<Item = Symbol> + Clone + 'a>(
    db: &'a dyn HirDatabase,
    mut segments: I,
) -> impl Iterator<Item = ItemInNs> + use<'a, I> {
    segments
        .next()
        .into_iter()
        .flat_map(move |crate_name| {
            db.all_crates()
                .iter()
                .filter(|&krate| {
                    krate
                        .extra_data(db)
                        .display_name
                        .as_ref()
                        .is_some_and(|name| *name.crate_name().symbol() == crate_name)
                })
                .filter_map(|&krate| {
                    let segments = segments.clone();
                    let mut def_map = crate_def_map(db, krate);
                    let mut module = &def_map[DefMap::ROOT];
                    let mut segments = segments.with_position().peekable();
                    while let Some((_, segment)) = segments.next_if(|&(position, _)| {
                        !matches!(position, itertools::Position::Last | itertools::Position::Only)
                    }) {
                        let res = module
                            .scope
                            .get(&Name::new_symbol_root(segment))
                            .take_types()
                            .and_then(|res| match res {
                                ModuleDefId::ModuleId(it) => Some(it),
                                _ => None,
                            })?;
                        def_map = res.def_map(db);
                        module = &def_map[res.local_id];
                    }
                    let (_, item_name) = segments.next()?;
                    let res = module.scope.get(&Name::new_symbol_root(item_name));
                    Some(res.iter_items().map(|(item, _)| item.into()))
                })
                .collect::<Vec<_>>()
        })
        .flatten()
}

fn as_name_opt(name: Option<impl AsName>) -> Name {
    name.map_or_else(Name::missing, |name| name.as_name())
}

fn generic_args_from_tys<'db>(
    interner: DbInterner<'db>,
    def_id: SolverDefId,
    args: impl IntoIterator<Item = Ty<'db>>,
) -> GenericArgs<'db> {
    let mut args = args.into_iter();
    GenericArgs::for_item(interner, def_id, |_, id, _| {
        if matches!(id, GenericParamId::TypeParamId(_))
            && let Some(arg) = args.next()
        {
            arg.into()
        } else {
            next_solver::GenericArg::error_from_id(interner, id)
        }
    })
}

fn has_non_default_type_params(db: &dyn HirDatabase, generic_def: GenericDefId) -> bool {
    let params = db.generic_params(generic_def);
    let defaults = db.generic_defaults(generic_def);
    params
        .iter_type_or_consts()
        .filter(|(_, param)| matches!(param, TypeOrConstParamData::TypeParamData(_)))
        .map(|(local_id, _)| TypeOrConstParamId { parent: generic_def, local_id })
        .any(|param| {
            let Some(param) = hir_ty::param_idx(db, param) else {
                return false;
            };
            defaults.get(param).is_none()
        })
}

pub use hir_ty::next_solver;
pub use hir_ty::setup_tracing;
