//! See `Semantics`.

mod child_by_source;
mod source_to_def;

use std::{
    cell::RefCell,
    convert::Infallible,
    fmt, iter, mem,
    ops::{self, ControlFlow, Not},
};

use either::Either;
use hir_def::{
    DefWithBodyId, FunctionId, MacroId, StructId, TraitId, VariantId,
    expr_store::{Body, ExprOrPatSource, path::Path},
    hir::{BindingId, Expr, ExprId, ExprOrPatId, Pat},
    nameres::{ModuleOrigin, crate_def_map},
    resolver::{self, HasResolver, Resolver, TypeNs},
    type_ref::Mutability,
};
use hir_expand::{
    EditionedFileId, ExpandResult, FileRange, HirFileId, InMacroFile, MacroCallId,
    attrs::collect_attrs,
    builtin::{BuiltinFnLikeExpander, EagerExpander},
    db::ExpandDatabase,
    files::{FileRangeWrapper, HirFileRange, InRealFile},
    mod_path::{ModPath, PathKind},
    name::AsName,
};
use hir_ty::diagnostics::{unsafe_operations, unsafe_operations_for_body};
use intern::{Interned, Symbol, sym};
use itertools::Itertools;
use rustc_hash::{FxHashMap, FxHashSet};
use smallvec::{SmallVec, smallvec};
use span::{Edition, FileId, SyntaxContext};
use stdx::{TupleExt, always};
use syntax::{
    AstNode, AstToken, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextRange,
    TextSize,
    algo::skip_trivia_token,
    ast::{self, HasAttrs as _, HasGenericParams},
};

use crate::{
    Adjust, Adjustment, Adt, AutoBorrow, BindingMode, BuiltinAttr, Callable, Const, ConstParam,
    Crate, DefWithBody, DeriveHelper, Enum, Field, Function, GenericSubstitution, HasSource, Impl,
    InFile, InlineAsmOperand, ItemInNs, Label, LifetimeParam, Local, Macro, Module, ModuleDef,
    Name, OverloadedDeref, ScopeDef, Static, Struct, ToolModule, Trait, TupleField, Type,
    TypeAlias, TypeParam, Union, Variant, VariantDef,
    db::HirDatabase,
    semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
    source_analyzer::{SourceAnalyzer, name_hygiene, resolve_hir_path},
};

const CONTINUE_NO_BREAKS: ControlFlow<Infallible, ()> = ControlFlow::Continue(());

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum PathResolution {
    /// An item
    Def(ModuleDef),
    /// A local binding (only value namespace)
    Local(Local),
    /// A type parameter
    TypeParam(TypeParam),
    /// A const parameter
    ConstParam(ConstParam),
    SelfType(Impl),
    BuiltinAttr(BuiltinAttr),
    ToolModule(ToolModule),
    DeriveHelper(DeriveHelper),
}

impl PathResolution {
    pub(crate) fn in_type_ns(&self) -> Option<TypeNs> {
        match self {
            PathResolution::Def(ModuleDef::Adt(adt)) => Some(TypeNs::AdtId((*adt).into())),
            PathResolution::Def(ModuleDef::BuiltinType(builtin)) => {
                Some(TypeNs::BuiltinType((*builtin).into()))
            }
            PathResolution::Def(
                ModuleDef::Const(_)
                | ModuleDef::Variant(_)
                | ModuleDef::Macro(_)
                | ModuleDef::Function(_)
                | ModuleDef::Module(_)
                | ModuleDef::Static(_)
                | ModuleDef::Trait(_),
            ) => None,
            PathResolution::Def(ModuleDef::TypeAlias(alias)) => {
                Some(TypeNs::TypeAliasId((*alias).into()))
            }
            PathResolution::BuiltinAttr(_)
            | PathResolution::ToolModule(_)
            | PathResolution::Local(_)
            | PathResolution::DeriveHelper(_)
            | PathResolution::ConstParam(_) => None,
            PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())),
            PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())),
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct PathResolutionPerNs {
    pub type_ns: Option<PathResolution>,
    pub value_ns: Option<PathResolution>,
    pub macro_ns: Option<PathResolution>,
}

impl PathResolutionPerNs {
    pub fn new(
        type_ns: Option<PathResolution>,
        value_ns: Option<PathResolution>,
        macro_ns: Option<PathResolution>,
    ) -> Self {
        PathResolutionPerNs { type_ns, value_ns, macro_ns }
    }
    pub fn any(&self) -> Option<PathResolution> {
        self.type_ns.or(self.value_ns).or(self.macro_ns)
    }
}

#[derive(Debug)]
pub struct TypeInfo<'db> {
    /// The original type of the expression or pattern.
    pub original: Type<'db>,
    /// The adjusted type, if an adjustment happened.
    pub adjusted: Option<Type<'db>>,
}

impl<'db> TypeInfo<'db> {
    pub fn original(self) -> Type<'db> {
        self.original
    }

    pub fn has_adjustment(&self) -> bool {
        self.adjusted.is_some()
    }

    /// The adjusted type, or the original in case no adjustments occurred.
    pub fn adjusted(self) -> Type<'db> {
        self.adjusted.unwrap_or(self.original)
    }
}

/// Primary API to get semantic information, like types, from syntax trees.
pub struct Semantics<'db, DB: ?Sized> {
    pub db: &'db DB,
    imp: SemanticsImpl<'db>,
}

pub struct SemanticsImpl<'db> {
    pub db: &'db dyn HirDatabase,
    s2d_cache: RefCell<SourceToDefCache>,
    /// MacroCall to its expansion's MacroCallId cache
    macro_call_cache: RefCell<FxHashMap<InFile<ast::MacroCall>, MacroCallId>>,
}

impl<DB: ?Sized> fmt::Debug for Semantics<'_, DB> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "Semantics {{ ... }}")
    }
}

impl<'db, DB: ?Sized> ops::Deref for Semantics<'db, DB> {
    type Target = SemanticsImpl<'db>;

    fn deref(&self) -> &Self::Target {
        &self.imp
    }
}

// Note: while this variant of `Semantics<'_, _>` might seem unused, as it does not
// find actual use within the rust-analyzer project itself, it exists to enable the use
// within e.g. tracked salsa functions in third-party crates that build upon `ra_ap_hir`.
impl Semantics<'_, dyn HirDatabase> {
    /// Creates an instance that's weakly coupled to its underlying database type.
    pub fn new_dyn(db: &'_ dyn HirDatabase) -> Semantics<'_, dyn HirDatabase> {
        let impl_ = SemanticsImpl::new(db);
        Semantics { db, imp: impl_ }
    }
}

impl<DB: HirDatabase> Semantics<'_, DB> {
    /// Creates an instance that's strongly coupled to its underlying database type.
    pub fn new(db: &DB) -> Semantics<'_, DB> {
        let impl_ = SemanticsImpl::new(db);
        Semantics { db, imp: impl_ }
    }
}

// Note: We take `DB` as `?Sized` here in order to support type-erased
// use of `Semantics` via `Semantics<'_, dyn HirDatabase>`:
impl<DB: HirDatabase + ?Sized> Semantics<'_, DB> {
    pub fn hir_file_for(&self, syntax_node: &SyntaxNode) -> HirFileId {
        self.imp.find_file(syntax_node).file_id
    }

    pub fn token_ancestors_with_macros(
        &self,
        token: SyntaxToken,
    ) -> impl Iterator<Item = SyntaxNode> + '_ {
        token.parent().into_iter().flat_map(move |it| self.ancestors_with_macros(it))
    }

    /// Find an AstNode by offset inside SyntaxNode, if it is inside *Macrofile*,
    /// search up until it is of the target AstNode type
    pub fn find_node_at_offset_with_macros<N: AstNode>(
        &self,
        node: &SyntaxNode,
        offset: TextSize,
    ) -> Option<N> {
        self.imp.ancestors_at_offset_with_macros(node, offset).find_map(N::cast)
    }

    /// Find an AstNode by offset inside SyntaxNode, if it is inside *MacroCall*,
    /// descend it and find again
    // FIXME: Rethink this API
    pub fn find_node_at_offset_with_descend<N: AstNode>(
        &self,
        node: &SyntaxNode,
        offset: TextSize,
    ) -> Option<N> {
        self.imp.descend_node_at_offset(node, offset).flatten().find_map(N::cast)
    }

    /// Find an AstNode by offset inside SyntaxNode, if it is inside an attribute macro call,
    /// descend it and find again
    // FIXME: Rethink this API
    pub fn find_nodes_at_offset_with_descend<'slf, N: AstNode + 'slf>(
        &'slf self,
        node: &SyntaxNode,
        offset: TextSize,
    ) -> impl Iterator<Item = N> + 'slf {
        self.imp.descend_node_at_offset(node, offset).filter_map(|mut it| it.find_map(N::cast))
    }

    // FIXME: Rethink this API
    pub fn find_namelike_at_offset_with_descend<'slf>(
        &'slf self,
        node: &SyntaxNode,
        offset: TextSize,
    ) -> impl Iterator<Item = ast::NameLike> + 'slf {
        node.token_at_offset(offset)
            .map(move |token| self.descend_into_macros_no_opaque(token, true))
            .map(|descendants| descendants.into_iter().filter_map(move |it| it.value.parent()))
            // re-order the tokens from token_at_offset by returning the ancestors with the smaller first nodes first
            // See algo::ancestors_at_offset, which uses the same approach
            .kmerge_by(|left, right| left.text_range().len().lt(&right.text_range().len()))
            .filter_map(ast::NameLike::cast)
    }

    pub fn resolve_range_pat(&self, range_pat: &ast::RangePat) -> Option<Struct> {
        self.imp.resolve_range_pat(range_pat).map(Struct::from)
    }

    pub fn resolve_range_expr(&self, range_expr: &ast::RangeExpr) -> Option<Struct> {
        self.imp.resolve_range_expr(range_expr).map(Struct::from)
    }

    pub fn resolve_await_to_poll(&self, await_expr: &ast::AwaitExpr) -> Option<Function> {
        self.imp.resolve_await_to_poll(await_expr).map(Function::from)
    }

    pub fn resolve_prefix_expr(&self, prefix_expr: &ast::PrefixExpr) -> Option<Function> {
        self.imp.resolve_prefix_expr(prefix_expr).map(Function::from)
    }

    pub fn resolve_index_expr(&self, index_expr: &ast::IndexExpr) -> Option<Function> {
        self.imp.resolve_index_expr(index_expr).map(Function::from)
    }

    pub fn resolve_bin_expr(&self, bin_expr: &ast::BinExpr) -> Option<Function> {
        self.imp.resolve_bin_expr(bin_expr).map(Function::from)
    }

    pub fn resolve_try_expr(&self, try_expr: &ast::TryExpr) -> Option<Function> {
        self.imp.resolve_try_expr(try_expr).map(Function::from)
    }

    pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> {
        self.imp.resolve_variant(record_lit).map(VariantDef::from)
    }

    pub fn file_to_module_def(&self, file: impl Into<FileId>) -> Option<Module> {
        self.imp.file_to_module_defs(file.into()).next()
    }

    pub fn file_to_module_defs(&self, file: impl Into<FileId>) -> impl Iterator<Item = Module> {
        self.imp.file_to_module_defs(file.into())
    }

    pub fn hir_file_to_module_def(&self, file: impl Into<HirFileId>) -> Option<Module> {
        self.imp.hir_file_to_module_defs(file.into()).next()
    }

    pub fn hir_file_to_module_defs(
        &self,
        file: impl Into<HirFileId>,
    ) -> impl Iterator<Item = Module> {
        self.imp.hir_file_to_module_defs(file.into())
    }

    pub fn to_adt_def(&self, a: &ast::Adt) -> Option<Adt> {
        self.imp.to_def(a)
    }

    pub fn to_const_def(&self, c: &ast::Const) -> Option<Const> {
        self.imp.to_def(c)
    }

    pub fn to_enum_def(&self, e: &ast::Enum) -> Option<Enum> {
        self.imp.to_def(e)
    }

    pub fn to_enum_variant_def(&self, v: &ast::Variant) -> Option<Variant> {
        self.imp.to_def(v)
    }

    pub fn to_fn_def(&self, f: &ast::Fn) -> Option<Function> {
        self.imp.to_def(f)
    }

    pub fn to_impl_def(&self, i: &ast::Impl) -> Option<Impl> {
        self.imp.to_def(i)
    }

    pub fn to_macro_def(&self, m: &ast::Macro) -> Option<Macro> {
        self.imp.to_def(m)
    }

    pub fn to_module_def(&self, m: &ast::Module) -> Option<Module> {
        self.imp.to_def(m)
    }

    pub fn to_static_def(&self, s: &ast::Static) -> Option<Static> {
        self.imp.to_def(s)
    }

    pub fn to_struct_def(&self, s: &ast::Struct) -> Option<Struct> {
        self.imp.to_def(s)
    }

    pub fn to_trait_def(&self, t: &ast::Trait) -> Option<Trait> {
        self.imp.to_def(t)
    }

    pub fn to_type_alias_def(&self, t: &ast::TypeAlias) -> Option<TypeAlias> {
        self.imp.to_def(t)
    }

    pub fn to_union_def(&self, u: &ast::Union) -> Option<Union> {
        self.imp.to_def(u)
    }
}

impl<'db> SemanticsImpl<'db> {
    fn new(db: &'db dyn HirDatabase) -> Self {
        SemanticsImpl { db, s2d_cache: Default::default(), macro_call_cache: Default::default() }
    }

    pub fn parse(&self, file_id: EditionedFileId) -> ast::SourceFile {
        let hir_file_id = file_id.into();
        let tree = self.db.parse(file_id).tree();
        self.cache(tree.syntax().clone(), hir_file_id);
        tree
    }

    /// If not crate is found for the file, try to return the last crate in topological order.
    pub fn first_crate(&self, file: FileId) -> Option<Crate> {
        match self.file_to_module_defs(file).next() {
            Some(module) => Some(module.krate()),
            None => self.db.all_crates().last().copied().map(Into::into),
        }
    }

    pub fn attach_first_edition(&self, file: FileId) -> Option<EditionedFileId> {
        Some(EditionedFileId::new(
            self.db,
            file,
            self.file_to_module_defs(file).next()?.krate().edition(self.db),
        ))
    }

    pub fn parse_guess_edition(&self, file_id: FileId) -> ast::SourceFile {
        let file_id = self
            .attach_first_edition(file_id)
            .unwrap_or_else(|| EditionedFileId::new(self.db, file_id, Edition::CURRENT));

        let tree = self.db.parse(file_id).tree();
        self.cache(tree.syntax().clone(), file_id.into());
        tree
    }

    pub fn adjust_edition(&self, file_id: HirFileId) -> HirFileId {
        if let Some(editioned_file_id) = file_id.file_id() {
            self.attach_first_edition(editioned_file_id.file_id(self.db))
                .map_or(file_id, Into::into)
        } else {
            file_id
        }
    }

    pub fn find_parent_file(&self, file_id: HirFileId) -> Option<InFile<SyntaxNode>> {
        match file_id {
            HirFileId::FileId(file_id) => {
                let module = self.file_to_module_defs(file_id.file_id(self.db)).next()?;
                let def_map = crate_def_map(self.db, module.krate().id);
                match def_map[module.id.local_id].origin {
                    ModuleOrigin::CrateRoot { .. } => None,
                    ModuleOrigin::File { declaration, declaration_tree_id, .. } => {
                        let file_id = declaration_tree_id.file_id();
                        let in_file = InFile::new(file_id, declaration);
                        let node = in_file.to_node(self.db);
                        let root = find_root(node.syntax());
                        self.cache(root, file_id);
                        Some(in_file.with_value(node.syntax().clone()))
                    }
                    _ => unreachable!("FileId can only belong to a file module"),
                }
            }
            HirFileId::MacroFile(macro_file) => {
                let node = self.db.lookup_intern_macro_call(macro_file).to_node(self.db);
                let root = find_root(&node.value);
                self.cache(root, node.file_id);
                Some(node)
            }
        }
    }

    /// Returns the `SyntaxNode` of the module. If this is a file module, returns
    /// the `SyntaxNode` of the *definition* file, not of the *declaration*.
    pub fn module_definition_node(&self, module: Module) -> InFile<SyntaxNode> {
        let def_map = module.id.def_map(self.db);
        let definition = def_map[module.id.local_id].origin.definition_source(self.db);
        let definition = definition.map(|it| it.node());
        let root_node = find_root(&definition.value);
        self.cache(root_node, definition.file_id);
        definition
    }

    pub fn parse_or_expand(&self, file_id: HirFileId) -> SyntaxNode {
        let node = self.db.parse_or_expand(file_id);
        self.cache(node.clone(), file_id);
        node
    }

    pub fn expand(&self, file_id: MacroCallId) -> ExpandResult<SyntaxNode> {
        let res = self.db.parse_macro_expansion(file_id).map(|it| it.0.syntax_node());
        self.cache(res.value.clone(), file_id.into());
        res
    }

    pub fn expand_macro_call(&self, macro_call: &ast::MacroCall) -> Option<InFile<SyntaxNode>> {
        let file_id = self.to_def(macro_call)?;
        let node = self.parse_or_expand(file_id.into());
        Some(InFile::new(file_id.into(), node))
    }

    pub fn check_cfg_attr(&self, attr: &ast::TokenTree) -> Option<bool> {
        let file_id = self.find_file(attr.syntax()).file_id;
        let krate = match file_id {
            HirFileId::FileId(file_id) => {
                self.file_to_module_defs(file_id.file_id(self.db)).next()?.krate().id
            }
            HirFileId::MacroFile(macro_file) => self.db.lookup_intern_macro_call(macro_file).krate,
        };
        hir_expand::check_cfg_attr_value(self.db, attr, krate)
    }

    /// Expands the macro if it isn't one of the built-in ones that expand to custom syntax or dummy
    /// expansions.
    pub fn expand_allowed_builtins(
        &self,
        macro_call: &ast::MacroCall,
    ) -> Option<ExpandResult<SyntaxNode>> {
        let file_id = self.to_def(macro_call)?;
        let macro_call = self.db.lookup_intern_macro_call(file_id);

        let skip = matches!(
            macro_call.def.kind,
            hir_expand::MacroDefKind::BuiltIn(
                _,
                BuiltinFnLikeExpander::Column
                    | BuiltinFnLikeExpander::File
                    | BuiltinFnLikeExpander::ModulePath
                    | BuiltinFnLikeExpander::Asm
                    | BuiltinFnLikeExpander::GlobalAsm
                    | BuiltinFnLikeExpander::NakedAsm
                    | BuiltinFnLikeExpander::LogSyntax
                    | BuiltinFnLikeExpander::TraceMacros
                    | BuiltinFnLikeExpander::FormatArgs
                    | BuiltinFnLikeExpander::FormatArgsNl
                    | BuiltinFnLikeExpander::ConstFormatArgs,
            ) | hir_expand::MacroDefKind::BuiltInEager(_, EagerExpander::CompileError)
        );
        if skip {
            // these macros expand to custom builtin syntax and/or dummy things, no point in
            // showing these to the user
            return None;
        }

        let node = self.expand(file_id);
        Some(node)
    }

    /// If `item` has an attribute macro attached to it, expands it.
    pub fn expand_attr_macro(&self, item: &ast::Item) -> Option<ExpandResult<InFile<SyntaxNode>>> {
        let src = self.wrap_node_infile(item.clone());
        let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(src.as_ref()))?;
        Some(self.expand(macro_call_id).map(|it| InFile::new(macro_call_id.into(), it)))
    }

    pub fn expand_derive_as_pseudo_attr_macro(&self, attr: &ast::Attr) -> Option<SyntaxNode> {
        let adt = attr.syntax().parent().and_then(ast::Adt::cast)?;
        let src = self.wrap_node_infile(attr.clone());
        let call_id = self.with_ctx(|ctx| {
            ctx.attr_to_derive_macro_call(src.with_value(&adt), src).map(|(_, it, _)| it)
        })?;
        Some(self.parse_or_expand(call_id.into()))
    }

    pub fn resolve_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<Option<Macro>>> {
        let calls = self.derive_macro_calls(attr)?;
        self.with_ctx(|ctx| {
            Some(
                calls
                    .into_iter()
                    .map(|call| macro_call_to_macro_id(ctx, call?).map(|id| Macro { id }))
                    .collect(),
            )
        })
    }

    pub fn expand_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<ExpandResult<SyntaxNode>>> {
        let res: Vec<_> = self
            .derive_macro_calls(attr)?
            .into_iter()
            .flat_map(|call| {
                let file_id = call?;
                let ExpandResult { value, err } = self.db.parse_macro_expansion(file_id);
                let root_node = value.0.syntax_node();
                self.cache(root_node.clone(), file_id.into());
                Some(ExpandResult { value: root_node, err })
            })
            .collect();
        Some(res)
    }

    fn derive_macro_calls(&self, attr: &ast::Attr) -> Option<Vec<Option<MacroCallId>>> {
        let adt = attr.syntax().parent().and_then(ast::Adt::cast)?;
        let file_id = self.find_file(adt.syntax()).file_id;
        let adt = InFile::new(file_id, &adt);
        let src = InFile::new(file_id, attr.clone());
        self.with_ctx(|ctx| {
            let (.., res) = ctx.attr_to_derive_macro_call(adt, src)?;
            Some(res.to_vec())
        })
    }

    pub fn is_derive_annotated(&self, adt: InFile<&ast::Adt>) -> bool {
        self.with_ctx(|ctx| ctx.file_of_adt_has_derives(adt))
    }

    pub fn derive_helpers_in_scope(&self, adt: &ast::Adt) -> Option<Vec<(Symbol, Symbol)>> {
        let sa = self.analyze_no_infer(adt.syntax())?;
        let id = self.db.ast_id_map(sa.file_id).ast_id(adt);
        let result = sa
            .resolver
            .def_map()
            .derive_helpers_in_scope(InFile::new(sa.file_id, id))?
            .iter()
            .map(|(name, macro_, _)| {
                let macro_name = Macro::from(*macro_).name(self.db).symbol().clone();
                (name.symbol().clone(), macro_name)
            })
            .collect();
        Some(result)
    }

    pub fn derive_helper(&self, attr: &ast::Attr) -> Option<Vec<(Macro, MacroCallId)>> {
        let adt = attr.syntax().ancestors().find_map(ast::Item::cast).and_then(|it| match it {
            ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
            ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
            ast::Item::Union(it) => Some(ast::Adt::Union(it)),
            _ => None,
        })?;
        let attr_name = attr.path().and_then(|it| it.as_single_name_ref())?.as_name();
        let sa = self.analyze_no_infer(adt.syntax())?;
        let id = self.db.ast_id_map(sa.file_id).ast_id(&adt);
        let res: Vec<_> = sa
            .resolver
            .def_map()
            .derive_helpers_in_scope(InFile::new(sa.file_id, id))?
            .iter()
            .filter(|&(name, _, _)| *name == attr_name)
            .map(|&(_, macro_, call)| (macro_.into(), call))
            .collect();
        res.is_empty().not().then_some(res)
    }

    pub fn is_attr_macro_call(&self, item: InFile<&ast::Item>) -> bool {
        self.with_ctx(|ctx| ctx.item_to_macro_call(item).is_some())
    }

    /// Expand the macro call with a different token tree, mapping the `token_to_map` down into the
    /// expansion. `token_to_map` should be a token from the `speculative args` node.
    pub fn speculative_expand_macro_call(
        &self,
        actual_macro_call: &ast::MacroCall,
        speculative_args: &ast::TokenTree,
        token_to_map: SyntaxToken,
    ) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> {
        let macro_file = self.to_def(actual_macro_call)?;
        hir_expand::db::expand_speculative(
            self.db,
            macro_file,
            speculative_args.syntax(),
            token_to_map,
        )
    }

    pub fn speculative_expand_raw(
        &self,
        macro_file: MacroCallId,
        speculative_args: &SyntaxNode,
        token_to_map: SyntaxToken,
    ) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> {
        hir_expand::db::expand_speculative(self.db, macro_file, speculative_args, token_to_map)
    }

    /// Expand the macro call with a different item as the input, mapping the `token_to_map` down into the
    /// expansion. `token_to_map` should be a token from the `speculative args` node.
    pub fn speculative_expand_attr_macro(
        &self,
        actual_macro_call: &ast::Item,
        speculative_args: &ast::Item,
        token_to_map: SyntaxToken,
    ) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> {
        let macro_call = self.wrap_node_infile(actual_macro_call.clone());
        let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(macro_call.as_ref()))?;
        hir_expand::db::expand_speculative(
            self.db,
            macro_call_id,
            speculative_args.syntax(),
            token_to_map,
        )
    }

    pub fn speculative_expand_derive_as_pseudo_attr_macro(
        &self,
        actual_macro_call: &ast::Attr,
        speculative_args: &ast::Attr,
        token_to_map: SyntaxToken,
    ) -> Option<(SyntaxNode, Vec<(SyntaxToken, u8)>)> {
        let attr = self.wrap_node_infile(actual_macro_call.clone());
        let adt = actual_macro_call.syntax().parent().and_then(ast::Adt::cast)?;
        let macro_call_id = self.with_ctx(|ctx| {
            ctx.attr_to_derive_macro_call(attr.with_value(&adt), attr).map(|(_, it, _)| it)
        })?;
        hir_expand::db::expand_speculative(
            self.db,
            macro_call_id,
            speculative_args.syntax(),
            token_to_map,
        )
    }

    /// Checks if renaming `renamed` to `new_name` may introduce conflicts with other locals,
    /// and returns the conflicting locals.
    pub fn rename_conflicts(&self, to_be_renamed: &Local, new_name: &Name) -> Vec<Local> {
        let body = self.db.body(to_be_renamed.parent);
        let resolver = to_be_renamed.parent.resolver(self.db);
        let starting_expr = body.binding_owner(to_be_renamed.binding_id).unwrap_or(body.body_expr);
        let mut visitor = RenameConflictsVisitor {
            body: &body,
            conflicts: FxHashSet::default(),
            db: self.db,
            new_name: new_name.symbol().clone(),
            old_name: to_be_renamed.name(self.db).symbol().clone(),
            owner: to_be_renamed.parent,
            to_be_renamed: to_be_renamed.binding_id,
            resolver,
        };
        visitor.rename_conflicts(starting_expr);
        visitor
            .conflicts
            .into_iter()
            .map(|binding_id| Local { parent: to_be_renamed.parent, binding_id })
            .collect()
    }

    /// Retrieves all the formatting parts of the format_args! (or `asm!`) template string.
    pub fn as_format_args_parts(
        &self,
        string: &ast::String,
    ) -> Option<Vec<(TextRange, Option<Either<PathResolution, InlineAsmOperand>>)>> {
        let string_start = string.syntax().text_range().start();
        let token = self.wrap_token_infile(string.syntax().clone());
        self.descend_into_macros_breakable(token, |token, _| {
            (|| {
                let token = token.value;
                let string = ast::String::cast(token)?;
                let literal =
                    string.syntax().parent().filter(|it| it.kind() == SyntaxKind::LITERAL)?;
                let parent = literal.parent()?;
                if let Some(format_args) = ast::FormatArgsExpr::cast(parent.clone()) {
                    let source_analyzer = self.analyze_no_infer(format_args.syntax())?;
                    let format_args = self.wrap_node_infile(format_args);
                    let res = source_analyzer
                        .as_format_args_parts(self.db, format_args.as_ref())?
                        .map(|(range, res)| (range + string_start, res.map(Either::Left)))
                        .collect();
                    Some(res)
                } else {
                    let asm = ast::AsmExpr::cast(parent)?;
                    let source_analyzer = self.analyze_no_infer(asm.syntax())?;
                    let line = asm.template().position(|it| *it.syntax() == literal)?;
                    let asm = self.wrap_node_infile(asm);
                    let (owner, (expr, asm_parts)) = source_analyzer.as_asm_parts(asm.as_ref())?;
                    let res = asm_parts
                        .get(line)?
                        .iter()
                        .map(|&(range, index)| {
                            (
                                range + string_start,
                                Some(Either::Right(InlineAsmOperand { owner, expr, index })),
                            )
                        })
                        .collect();
                    Some(res)
                }
            })()
            .map_or(ControlFlow::Continue(()), ControlFlow::Break)
        })
    }

    /// Retrieves the formatting part of the format_args! template string at the given offset.
    ///
    // FIXME: Type the return type
    /// Returns the range (pre-expansion) in the string literal corresponding to the resolution,
    /// absolute file range (post-expansion)
    /// of the part in the format string, the corresponding string token and the resolution if it
    /// exists.
    // FIXME: Remove this in favor of `check_for_format_args_template_with_file`
    pub fn check_for_format_args_template(
        &self,
        original_token: SyntaxToken,
        offset: TextSize,
    ) -> Option<(
        TextRange,
        HirFileRange,
        ast::String,
        Option<Either<PathResolution, InlineAsmOperand>>,
    )> {
        let original_token =
            self.wrap_token_infile(original_token).map(ast::String::cast).transpose()?;
        self.check_for_format_args_template_with_file(original_token, offset)
    }

    /// Retrieves the formatting part of the format_args! template string at the given offset.
    ///
    // FIXME: Type the return type
    /// Returns the range (pre-expansion) in the string literal corresponding to the resolution,
    /// absolute file range (post-expansion)
    /// of the part in the format string, the corresponding string token and the resolution if it
    /// exists.
    pub fn check_for_format_args_template_with_file(
        &self,
        original_token: InFile<ast::String>,
        offset: TextSize,
    ) -> Option<(
        TextRange,
        HirFileRange,
        ast::String,
        Option<Either<PathResolution, InlineAsmOperand>>,
    )> {
        let relative_offset =
            offset.checked_sub(original_token.value.syntax().text_range().start())?;
        self.descend_into_macros_breakable(
            original_token.as_ref().map(|it| it.syntax().clone()),
            |token, _| {
                (|| {
                    let token = token.map(ast::String::cast).transpose()?;
                    self.resolve_offset_in_format_args(token.as_ref(), relative_offset).map(
                        |(range, res)| {
                            (
                                range + original_token.value.syntax().text_range().start(),
                                HirFileRange {
                                    file_id: token.file_id,
                                    range: range + token.value.syntax().text_range().start(),
                                },
                                token.value,
                                res,
                            )
                        },
                    )
                })()
                .map_or(ControlFlow::Continue(()), ControlFlow::Break)
            },
        )
    }

    fn resolve_offset_in_format_args(
        &self,
        InFile { value: string, file_id }: InFile<&ast::String>,
        offset: TextSize,
    ) -> Option<(TextRange, Option<Either<PathResolution, InlineAsmOperand>>)> {
        debug_assert!(offset <= string.syntax().text_range().len());
        let literal = string.syntax().parent().filter(|it| it.kind() == SyntaxKind::LITERAL)?;
        let parent = literal.parent()?;
        if let Some(format_args) = ast::FormatArgsExpr::cast(parent.clone()) {
            let source_analyzer =
                &self.analyze_impl(InFile::new(file_id, format_args.syntax()), None, false)?;
            source_analyzer
                .resolve_offset_in_format_args(self.db, InFile::new(file_id, &format_args), offset)
                .map(|(range, res)| (range, res.map(Either::Left)))
        } else {
            let asm = ast::AsmExpr::cast(parent)?;
            let source_analyzer =
                self.analyze_impl(InFile::new(file_id, asm.syntax()), None, false)?;
            let line = asm.template().position(|it| *it.syntax() == literal)?;
            source_analyzer
                .resolve_offset_in_asm_template(InFile::new(file_id, &asm), line, offset)
                .map(|(owner, (expr, range, index))| {
                    (range, Some(Either::Right(InlineAsmOperand { owner, expr, index })))
                })
        }
    }

    pub fn debug_hir_at(&self, token: SyntaxToken) -> Option<String> {
        self.analyze_no_infer(&token.parent()?).and_then(|it| {
            Some(match it.body_or_sig.as_ref()? {
                crate::source_analyzer::BodyOrSig::Body { def, body, .. } => {
                    hir_def::expr_store::pretty::print_body_hir(
                        self.db,
                        body,
                        *def,
                        it.file_id.edition(self.db),
                    )
                }
                &crate::source_analyzer::BodyOrSig::VariantFields { def, .. } => {
                    hir_def::expr_store::pretty::print_variant_body_hir(
                        self.db,
                        def,
                        it.file_id.edition(self.db),
                    )
                }
                &crate::source_analyzer::BodyOrSig::Sig { def, .. } => {
                    hir_def::expr_store::pretty::print_signature(
                        self.db,
                        def,
                        it.file_id.edition(self.db),
                    )
                }
            })
        })
    }

    /// Descends the token into the include expansion, if its file is an included file.
    pub fn descend_token_into_include_expansion(
        &self,
        tok: InRealFile<SyntaxToken>,
    ) -> InFile<SyntaxToken> {
        let Some(include) =
            self.s2d_cache.borrow_mut().get_or_insert_include_for(self.db, tok.file_id)
        else {
            return tok.into();
        };
        let span = self.db.real_span_map(tok.file_id).span_for_range(tok.value.text_range());
        let Some(InMacroFile { file_id, value: mut mapped_tokens }) = self.with_ctx(|ctx| {
            Some(
                ctx.cache
                    .get_or_insert_expansion(ctx.db, include)
                    .map_range_down(span)?
                    .map(SmallVec::<[_; 2]>::from_iter),
            )
        }) else {
            return tok.into();
        };
        // We should only get one result at most
        mapped_tokens.pop().map_or_else(|| tok.into(), |(tok, _)| InFile::new(file_id.into(), tok))
    }

    /// Maps a node down by mapping its first and last token down.
    pub fn descend_node_into_attributes<N: AstNode>(&self, node: N) -> SmallVec<[N; 1]> {
        // This might not be the correct way to do this, but it works for now
        let mut res = smallvec![];
        let tokens = (|| {
            // FIXME: the trivia skipping should not be necessary
            let first = skip_trivia_token(node.syntax().first_token()?, Direction::Next)?;
            let last = skip_trivia_token(node.syntax().last_token()?, Direction::Prev)?;
            Some((first, last))
        })();
        let (first, last) = match tokens {
            Some(it) => it,
            None => return res,
        };
        let file = self.find_file(node.syntax());

        if first == last {
            // node is just the token, so descend the token
            self.descend_into_macros_all(
                InFile::new(file.file_id, first),
                false,
                &mut |InFile { value, .. }, _ctx| {
                    if let Some(node) = value
                        .parent_ancestors()
                        .take_while(|it| it.text_range() == value.text_range())
                        .find_map(N::cast)
                    {
                        res.push(node)
                    }
                },
            );
        } else {
            // Descend first and last token, then zip them to look for the node they belong to
            let mut scratch: SmallVec<[_; 1]> = smallvec![];
            self.descend_into_macros_all(
                InFile::new(file.file_id, first),
                false,
                &mut |token, _ctx| scratch.push(token),
            );

            let mut scratch = scratch.into_iter();
            self.descend_into_macros_all(
                InFile::new(file.file_id, last),
                false,
                &mut |InFile { value: last, file_id: last_fid }, _ctx| {
                    if let Some(InFile { value: first, file_id: first_fid }) = scratch.next()
                        && first_fid == last_fid
                        && let Some(p) = first.parent()
                    {
                        let range = first.text_range().cover(last.text_range());
                        let node = find_root(&p)
                            .covering_element(range)
                            .ancestors()
                            .take_while(|it| it.text_range() == range)
                            .find_map(N::cast);
                        if let Some(node) = node {
                            res.push(node);
                        }
                    }
                },
            );
        }
        res
    }

    /// Returns true if the given input is within a macro call.
    ///
    /// Note that if this token itself is within the context of a macro expansion does not matter.
    /// That is, we strictly check if it lies inside the input of a macro call.
    pub fn is_inside_macro_call(&self, token @ InFile { value, .. }: InFile<&SyntaxToken>) -> bool {
        value.parent_ancestors().any(|ancestor| {
            if ast::MacroCall::can_cast(ancestor.kind()) {
                return true;
            }

            let Some(item) = ast::Item::cast(ancestor) else {
                return false;
            };
            self.with_ctx(|ctx| {
                if ctx.item_to_macro_call(token.with_value(&item)).is_some() {
                    return true;
                }
                let adt = match item {
                    ast::Item::Struct(it) => it.into(),
                    ast::Item::Enum(it) => it.into(),
                    ast::Item::Union(it) => it.into(),
                    _ => return false,
                };
                ctx.file_of_adt_has_derives(token.with_value(&adt))
            })
        })
    }

    pub fn descend_into_macros_cb(
        &self,
        token: SyntaxToken,
        mut cb: impl FnMut(InFile<SyntaxToken>, SyntaxContext),
    ) {
        self.descend_into_macros_all(self.wrap_token_infile(token), false, &mut |t, ctx| {
            cb(t, ctx)
        });
    }

    pub fn descend_into_macros(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
        let mut res = smallvec![];
        self.descend_into_macros_all(
            self.wrap_token_infile(token.clone()),
            false,
            &mut |t, _ctx| res.push(t.value),
        );
        if res.is_empty() {
            res.push(token);
        }
        res
    }

    pub fn descend_into_macros_no_opaque(
        &self,
        token: SyntaxToken,
        always_descend_into_derives: bool,
    ) -> SmallVec<[InFile<SyntaxToken>; 1]> {
        let mut res = smallvec![];
        let token = self.wrap_token_infile(token);
        self.descend_into_macros_all(token.clone(), always_descend_into_derives, &mut |t, ctx| {
            if !ctx.is_opaque(self.db) {
                // Don't descend into opaque contexts
                res.push(t);
            }
        });
        if res.is_empty() {
            res.push(token);
        }
        res
    }

    pub fn descend_into_macros_breakable<T>(
        &self,
        token: InFile<SyntaxToken>,
        mut cb: impl FnMut(InFile<SyntaxToken>, SyntaxContext) -> ControlFlow<T>,
    ) -> Option<T> {
        self.descend_into_macros_impl(token, false, &mut cb)
    }

    /// Descends the token into expansions, returning the tokens that matches the input
    /// token's [`SyntaxKind`] and text.
    pub fn descend_into_macros_exact(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
        let mut r = smallvec![];
        let text = token.text();
        let kind = token.kind();

        self.descend_into_macros_cb(token.clone(), |InFile { value, file_id: _ }, ctx| {
            let mapped_kind = value.kind();
            let any_ident_match = || kind.is_any_identifier() && value.kind().is_any_identifier();
            let matches = (kind == mapped_kind || any_ident_match())
                && text == value.text()
                && !ctx.is_opaque(self.db);
            if matches {
                r.push(value);
            }
        });
        if r.is_empty() {
            r.push(token);
        }
        r
    }

    /// Descends the token into expansions, returning the tokens that matches the input
    /// token's [`SyntaxKind`] and text.
    pub fn descend_into_macros_exact_with_file(
        &self,
        token: SyntaxToken,
    ) -> SmallVec<[InFile<SyntaxToken>; 1]> {
        let mut r = smallvec![];
        let text = token.text();
        let kind = token.kind();

        self.descend_into_macros_cb(token.clone(), |InFile { value, file_id }, ctx| {
            let mapped_kind = value.kind();
            let any_ident_match = || kind.is_any_identifier() && value.kind().is_any_identifier();
            let matches = (kind == mapped_kind || any_ident_match())
                && text == value.text()
                && !ctx.is_opaque(self.db);
            if matches {
                r.push(InFile { value, file_id });
            }
        });
        if r.is_empty() {
            r.push(self.wrap_token_infile(token));
        }
        r
    }

    /// Descends the token into expansions, returning the first token that matches the input
    /// token's [`SyntaxKind`] and text.
    pub fn descend_into_macros_single_exact(&self, token: SyntaxToken) -> SyntaxToken {
        let text = token.text();
        let kind = token.kind();
        self.descend_into_macros_breakable(
            self.wrap_token_infile(token.clone()),
            |InFile { value, file_id: _ }, _ctx| {
                let mapped_kind = value.kind();
                let any_ident_match =
                    || kind.is_any_identifier() && value.kind().is_any_identifier();
                let matches = (kind == mapped_kind || any_ident_match()) && text == value.text();
                if matches { ControlFlow::Break(value) } else { ControlFlow::Continue(()) }
            },
        )
        .unwrap_or(token)
    }

    fn descend_into_macros_all(
        &self,
        token: InFile<SyntaxToken>,
        always_descend_into_derives: bool,
        f: &mut dyn FnMut(InFile<SyntaxToken>, SyntaxContext),
    ) {
        self.descend_into_macros_impl(token, always_descend_into_derives, &mut |tok, ctx| {
            f(tok, ctx);
            CONTINUE_NO_BREAKS
        });
    }

    fn descend_into_macros_impl<T>(
        &self,
        InFile { value: token, file_id }: InFile<SyntaxToken>,
        always_descend_into_derives: bool,
        f: &mut dyn FnMut(InFile<SyntaxToken>, SyntaxContext) -> ControlFlow<T>,
    ) -> Option<T> {
        let _p = tracing::info_span!("descend_into_macros_impl").entered();

        let db = self.db;
        let span = db.span_map(file_id).span_for_range(token.text_range());

        // Process the expansion of a call, pushing all tokens with our span in the expansion back onto our stack
        let process_expansion_for_token =
            |ctx: &mut SourceToDefCtx<'_, '_>, stack: &mut Vec<_>, macro_file| {
                let InMacroFile { file_id, value: mapped_tokens } = ctx
                    .cache
                    .get_or_insert_expansion(ctx.db, macro_file)
                    .map_range_down(span)?
                    .map(SmallVec::<[_; 2]>::from_iter);
                // we have found a mapping for the token if the vec is non-empty
                let res = mapped_tokens.is_empty().not().then_some(());
                // requeue the tokens we got from mapping our current token down
                stack.push((HirFileId::from(file_id), mapped_tokens));
                res
            };

        // A stack of tokens to process, along with the file they came from
        // These are tracked to know which macro calls we still have to look into
        // the tokens themselves aren't that interesting as the span that is being used to map
        // things down never changes.
        let mut stack: Vec<(_, SmallVec<[_; 2]>)> = vec![];
        let include = file_id
            .file_id()
            .and_then(|file_id| self.s2d_cache.borrow_mut().get_or_insert_include_for(db, file_id));
        match include {
            Some(include) => {
                // include! inputs are always from real files, so they only need to be handled once upfront
                self.with_ctx(|ctx| process_expansion_for_token(ctx, &mut stack, include))?;
            }
            None => {
                stack.push((file_id, smallvec![(token, span.ctx)]));
            }
        }

        let mut m_cache = self.macro_call_cache.borrow_mut();

        // Filters out all tokens that contain the given range (usually the macro call), any such
        // token is redundant as the corresponding macro call has already been processed
        let filter_duplicates = |tokens: &mut SmallVec<_>, range: TextRange| {
            tokens.retain(|(t, _): &mut (SyntaxToken, _)| !range.contains_range(t.text_range()))
        };

        while let Some((expansion, ref mut tokens)) = stack.pop() {
            // Reverse the tokens so we prefer first tokens (to accommodate for popping from the
            // back)
            // alternatively we could pop from the front but that would shift the content on every pop
            tokens.reverse();
            while let Some((token, ctx)) = tokens.pop() {
                let was_not_remapped = (|| {
                    // First expand into attribute invocations, this is required to be handled
                    // upfront as any other macro call within will not semantically resolve unless
                    // also descended.
                    let res = self.with_ctx(|ctx| {
                        token
                            .parent_ancestors()
                            .filter_map(ast::Item::cast)
                            // FIXME: This might work incorrectly when we have a derive, followed by
                            // an attribute on an item, like:
                            // ```
                            // #[derive(Debug$0)]
                            // #[my_attr]
                            // struct MyStruct;
                            // ```
                            // here we should not consider the attribute at all, as our cursor
                            // technically lies outside of its expansion
                            .find_map(|item| {
                                // Don't force populate the dyn cache for items that don't have an attribute anyways
                                item.attrs().next()?;
                                ctx.item_to_macro_call(InFile::new(expansion, &item))
                                    .zip(Some(item))
                            })
                            .map(|(call_id, item)| {
                                let attr_id = match db.lookup_intern_macro_call(call_id).kind {
                                    hir_expand::MacroCallKind::Attr {
                                        invoc_attr_index, ..
                                    } => invoc_attr_index.ast_index(),
                                    _ => 0,
                                };
                                // FIXME: here, the attribute's text range is used to strip away all
                                // entries from the start of the attribute "list" up the invoking
                                // attribute. But in
                                // ```
                                // mod foo {
                                //     #![inner]
                                // }
                                // ```
                                // we don't wanna strip away stuff in the `mod foo {` range, that is
                                // here if the id corresponds to an inner attribute we got strip all
                                // text ranges of the outer ones, and then all of the inner ones up
                                // to the invoking attribute so that the inbetween is ignored.
                                let text_range = item.syntax().text_range();
                                let start = collect_attrs(&item)
                                    .nth(attr_id)
                                    .map(|attr| match attr.1 {
                                        Either::Left(it) => it.syntax().text_range().start(),
                                        Either::Right(it) => it.syntax().text_range().start(),
                                    })
                                    .unwrap_or_else(|| text_range.start());
                                let text_range = TextRange::new(start, text_range.end());
                                filter_duplicates(tokens, text_range);
                                process_expansion_for_token(ctx, &mut stack, call_id)
                            })
                    });

                    if let Some(res) = res {
                        return res;
                    }

                    if always_descend_into_derives {
                        let res = self.with_ctx(|ctx| {
                            let (derives, adt) = token
                                .parent_ancestors()
                                .filter_map(ast::Adt::cast)
                                .find_map(|adt| {
                                    Some((
                                        ctx.derive_macro_calls(InFile::new(expansion, &adt))?
                                            .map(|(a, b, c)| (a, b, c.to_owned()))
                                            .collect::<SmallVec<[_; 2]>>(),
                                        adt,
                                    ))
                                })?;
                            for (_, derive_attr, derives) in derives {
                                // as there may be multiple derives registering the same helper
                                // name, we gotta make sure to call this for all of them!
                                // FIXME: We need to call `f` for all of them as well though!
                                process_expansion_for_token(ctx, &mut stack, derive_attr);
                                for derive in derives.into_iter().flatten() {
                                    process_expansion_for_token(ctx, &mut stack, derive);
                                }
                            }
                            // remove all tokens that are within the derives expansion
                            filter_duplicates(tokens, adt.syntax().text_range());
                            Some(())
                        });
                        // if we found derives, we can early exit. There is no way we can be in any
                        // macro call at this point given we are not in a token tree
                        if let Some(()) = res {
                            // Note: derives do not remap the original token. Furthermore, we want
                            // the original token to be before the derives in the list, because if they
                            // upmap to the same token and we deduplicate them (e.g. in rename), we
                            // want the original token to remain, not the derive.
                            return None;
                        }
                    }
                    // Then check for token trees, that means we are either in a function-like macro or
                    // secondary attribute inputs
                    let tt = token
                        .parent_ancestors()
                        .map_while(Either::<ast::TokenTree, ast::Meta>::cast)
                        .last()?;

                    match tt {
                        // function-like macro call
                        Either::Left(tt) => {
                            let macro_call = tt.syntax().parent().and_then(ast::MacroCall::cast)?;
                            if tt.left_delimiter_token().map_or(false, |it| it == token) {
                                return None;
                            }
                            if tt.right_delimiter_token().map_or(false, |it| it == token) {
                                return None;
                            }
                            let mcall = InFile::new(expansion, macro_call);
                            let file_id = match m_cache.get(&mcall) {
                                Some(&it) => it,
                                None => {
                                    let it = ast::MacroCall::to_def(self, mcall.as_ref())?;
                                    m_cache.insert(mcall, it);
                                    it
                                }
                            };
                            let text_range = tt.syntax().text_range();
                            filter_duplicates(tokens, text_range);

                            self.with_ctx(|ctx| {
                                process_expansion_for_token(ctx, &mut stack, file_id).or(file_id
                                    .eager_arg(db)
                                    .and_then(|arg| {
                                        // also descend into eager expansions
                                        process_expansion_for_token(ctx, &mut stack, arg)
                                    }))
                            })
                        }
                        Either::Right(_) if always_descend_into_derives => None,
                        // derive or derive helper
                        Either::Right(meta) => {
                            // attribute we failed expansion for earlier, this might be a derive invocation
                            // or derive helper attribute
                            let attr = meta.parent_attr()?;
                            let adt = match attr.syntax().parent().and_then(ast::Adt::cast) {
                                Some(adt) => {
                                    // this might be a derive on an ADT
                                    let res = self.with_ctx(|ctx| {
                                        // so try downmapping the token into the pseudo derive expansion
                                        // see [hir_expand::builtin_attr_macro] for how the pseudo derive expansion works
                                        let derive_call = ctx
                                            .attr_to_derive_macro_call(
                                                InFile::new(expansion, &adt),
                                                InFile::new(expansion, attr.clone()),
                                            )?
                                            .1;

                                        // resolved to a derive
                                        let text_range = attr.syntax().text_range();
                                        // remove any other token in this macro input, all their mappings are the
                                        // same as this
                                        tokens.retain(|(t, _)| {
                                            !text_range.contains_range(t.text_range())
                                        });
                                        Some(process_expansion_for_token(
                                            ctx,
                                            &mut stack,
                                            derive_call,
                                        ))
                                    });
                                    if let Some(res) = res {
                                        return res;
                                    }
                                    Some(adt)
                                }
                                None => {
                                    // Otherwise this could be a derive helper on a variant or field
                                    attr.syntax().ancestors().find_map(ast::Item::cast).and_then(
                                        |it| match it {
                                            ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
                                            ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
                                            ast::Item::Union(it) => Some(ast::Adt::Union(it)),
                                            _ => None,
                                        },
                                    )
                                }
                            }?;
                            let attr_name =
                                attr.path().and_then(|it| it.as_single_name_ref())?.as_name();
                            // Not an attribute, nor a derive, so it's either an inert attribute or a derive helper
                            // Try to resolve to a derive helper and downmap
                            let resolver = &token
                                .parent()
                                .and_then(|parent| {
                                    self.analyze_impl(InFile::new(expansion, &parent), None, false)
                                })?
                                .resolver;
                            let id = db.ast_id_map(expansion).ast_id(&adt);
                            let helpers = resolver
                                .def_map()
                                .derive_helpers_in_scope(InFile::new(expansion, id))?;

                            if !helpers.is_empty() {
                                let text_range = attr.syntax().text_range();
                                filter_duplicates(tokens, text_range);
                            }

                            let mut res = None;
                            self.with_ctx(|ctx| {
                                for (.., derive) in
                                    helpers.iter().filter(|(helper, ..)| *helper == attr_name)
                                {
                                    // as there may be multiple derives registering the same helper
                                    // name, we gotta make sure to call this for all of them!
                                    // FIXME: We need to call `f` for all of them as well though!
                                    res = res
                                        .or(process_expansion_for_token(ctx, &mut stack, *derive));
                                }
                                res
                            })
                        }
                    }
                })()
                .is_none();
                if was_not_remapped
                    && let ControlFlow::Break(b) = f(InFile::new(expansion, token), ctx)
                {
                    return Some(b);
                }
            }
        }
        None
    }

    // Note this return type is deliberate as [`find_nodes_at_offset_with_descend`] wants to stop
    // traversing the inner iterator when it finds a node.
    // The outer iterator is over the tokens descendants
    // The inner iterator is the ancestors of a descendant
    fn descend_node_at_offset(
        &self,
        node: &SyntaxNode,
        offset: TextSize,
    ) -> impl Iterator<Item = impl Iterator<Item = SyntaxNode> + '_> + '_ {
        node.token_at_offset(offset)
            .map(move |token| self.descend_into_macros_exact(token))
            .map(|descendants| {
                descendants.into_iter().map(move |it| self.token_ancestors_with_macros(it))
            })
            // re-order the tokens from token_at_offset by returning the ancestors with the smaller first nodes first
            // See algo::ancestors_at_offset, which uses the same approach
            .kmerge_by(|left, right| {
                left.clone()
                    .map(|node| node.text_range().len())
                    .lt(right.clone().map(|node| node.text_range().len()))
            })
    }

    /// Attempts to map the node out of macro expanded files returning the original file range.
    /// If upmapping is not possible, this will fall back to the range of the macro call of the
    /// macro file the node resides in.
    pub fn original_range(&self, node: &SyntaxNode) -> FileRange {
        let node = self.find_file(node);
        node.original_file_range_rooted(self.db)
    }

    /// Attempts to map the node out of macro expanded files returning the original file range.
    pub fn original_range_opt(&self, node: &SyntaxNode) -> Option<FileRange> {
        let node = self.find_file(node);
        node.original_file_range_opt(self.db).filter(|(_, ctx)| ctx.is_root()).map(TupleExt::head)
    }

    /// Attempts to map the node out of macro expanded files.
    /// This only work for attribute expansions, as other ones do not have nodes as input.
    pub fn original_ast_node<N: AstNode>(&self, node: N) -> Option<N> {
        self.wrap_node_infile(node).original_ast_node_rooted(self.db).map(
            |InRealFile { file_id, value }| {
                self.cache(find_root(value.syntax()), file_id.into());
                value
            },
        )
    }

    /// Attempts to map the node out of macro expanded files.
    /// This only work for attribute expansions, as other ones do not have nodes as input.
    pub fn original_syntax_node_rooted(&self, node: &SyntaxNode) -> Option<SyntaxNode> {
        let InFile { file_id, .. } = self.find_file(node);
        InFile::new(file_id, node).original_syntax_node_rooted(self.db).map(
            |InRealFile { file_id, value }| {
                self.cache(find_root(&value), file_id.into());
                value
            },
        )
    }

    pub fn diagnostics_display_range(
        &self,
        src: InFile<SyntaxNodePtr>,
    ) -> FileRangeWrapper<FileId> {
        let root = self.parse_or_expand(src.file_id);
        let node = src.map(|it| it.to_node(&root));
        let FileRange { file_id, range } = node.as_ref().original_file_range_rooted(self.db);
        FileRangeWrapper { file_id: file_id.file_id(self.db), range }
    }

    fn token_ancestors_with_macros(
        &self,
        token: SyntaxToken,
    ) -> impl Iterator<Item = SyntaxNode> + Clone + '_ {
        token.parent().into_iter().flat_map(move |parent| self.ancestors_with_macros(parent))
    }

    /// Iterates the ancestors of the given node, climbing up macro expansions while doing so.
    // FIXME: Replace with `ancestors_with_macros_file` when all usages are updated.
    pub fn ancestors_with_macros(
        &self,
        node: SyntaxNode,
    ) -> impl Iterator<Item = SyntaxNode> + Clone + '_ {
        let node = self.find_file(&node);
        self.ancestors_with_macros_file(node.cloned()).map(|it| it.value)
    }

    /// Iterates the ancestors of the given node, climbing up macro expansions while doing so.
    pub fn ancestors_with_macros_file(
        &self,
        node: InFile<SyntaxNode>,
    ) -> impl Iterator<Item = InFile<SyntaxNode>> + Clone + '_ {
        iter::successors(Some(node), move |&InFile { file_id, ref value }| match value.parent() {
            Some(parent) => Some(InFile::new(file_id, parent)),
            None => {
                let macro_file = file_id.macro_file()?;

                self.with_ctx(|ctx| {
                    let expansion_info = ctx.cache.get_or_insert_expansion(ctx.db, macro_file);
                    expansion_info.arg().map(|node| node?.parent()).transpose()
                })
            }
        })
    }

    pub fn ancestors_at_offset_with_macros(
        &self,
        node: &SyntaxNode,
        offset: TextSize,
    ) -> impl Iterator<Item = SyntaxNode> + '_ {
        node.token_at_offset(offset)
            .map(|token| self.token_ancestors_with_macros(token))
            .kmerge_by(|node1, node2| node1.text_range().len() < node2.text_range().len())
    }

    pub fn resolve_lifetime_param(&self, lifetime: &ast::Lifetime) -> Option<LifetimeParam> {
        let text = lifetime.text();
        let lifetime_param = lifetime.syntax().ancestors().find_map(|syn| {
            let gpl = ast::AnyHasGenericParams::cast(syn)?.generic_param_list()?;
            gpl.lifetime_params()
                .find(|tp| tp.lifetime().as_ref().map(|lt| lt.text()).as_ref() == Some(&text))
        })?;
        let src = self.wrap_node_infile(lifetime_param);
        ToDef::to_def(self, src.as_ref())
    }

    pub fn resolve_label(&self, label: &ast::Lifetime) -> Option<Label> {
        let src = self.wrap_node_infile(label.clone());
        let (parent, label_id) = self.with_ctx(|ctx| ctx.label_ref_to_def(src.as_ref()))?;
        Some(Label { parent, label_id })
    }

    pub fn resolve_type(&self, ty: &ast::Type) -> Option<Type<'db>> {
        let analyze = self.analyze(ty.syntax())?;
        analyze.type_of_type(self.db, ty)
    }

    pub fn resolve_trait(&self, path: &ast::Path) -> Option<Trait> {
        let parent_ty = path.syntax().parent().and_then(ast::Type::cast)?;
        let analyze = self.analyze(path.syntax())?;
        let ty = analyze.store_sm()?.node_type(InFile::new(analyze.file_id, &parent_ty))?;
        let path = match &analyze.store()?.types[ty] {
            hir_def::type_ref::TypeRef::Path(path) => path,
            _ => return None,
        };
        match analyze.resolver.resolve_path_in_type_ns_fully(self.db, path)? {
            TypeNs::TraitId(trait_id) => Some(trait_id.into()),
            _ => None,
        }
    }

    pub fn expr_adjustments(&self, expr: &ast::Expr) -> Option<Vec<Adjustment<'db>>> {
        let mutability = |m| match m {
            hir_ty::Mutability::Not => Mutability::Shared,
            hir_ty::Mutability::Mut => Mutability::Mut,
        };

        let analyzer = self.analyze(expr.syntax())?;

        let (mut source_ty, _) = analyzer.type_of_expr(self.db, expr)?;

        analyzer.expr_adjustments(expr).map(|it| {
            it.iter()
                .map(|adjust| {
                    let target =
                        Type::new_with_resolver(self.db, &analyzer.resolver, adjust.target.clone());
                    let kind = match adjust.kind {
                        hir_ty::Adjust::NeverToAny => Adjust::NeverToAny,
                        hir_ty::Adjust::Deref(Some(hir_ty::OverloadedDeref(m))) => {
                            // FIXME: Should we handle unknown mutability better?
                            Adjust::Deref(Some(OverloadedDeref(
                                m.map(mutability).unwrap_or(Mutability::Shared),
                            )))
                        }
                        hir_ty::Adjust::Deref(None) => Adjust::Deref(None),
                        hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::RawPtr(m)) => {
                            Adjust::Borrow(AutoBorrow::RawPtr(mutability(m)))
                        }
                        hir_ty::Adjust::Borrow(hir_ty::AutoBorrow::Ref(_, m)) => {
                            // FIXME: Handle lifetimes here
                            Adjust::Borrow(AutoBorrow::Ref(mutability(m)))
                        }
                        hir_ty::Adjust::Pointer(pc) => Adjust::Pointer(pc),
                    };

                    // Update `source_ty` for the next adjustment
                    let source = mem::replace(&mut source_ty, target.clone());

                    Adjustment { source, target, kind }
                })
                .collect()
        })
    }

    pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<TypeInfo<'db>> {
        self.analyze(expr.syntax())?
            .type_of_expr(self.db, expr)
            .map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced })
    }

    pub fn type_of_pat(&self, pat: &ast::Pat) -> Option<TypeInfo<'db>> {
        self.analyze(pat.syntax())?
            .type_of_pat(self.db, pat)
            .map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced })
    }

    /// It also includes the changes that binding mode makes in the type. For example in
    /// `let ref x @ Some(_) = None` the result of `type_of_pat` is `Option<T>` but the result
    /// of this function is `&mut Option<T>`
    pub fn type_of_binding_in_pat(&self, pat: &ast::IdentPat) -> Option<Type<'db>> {
        self.analyze(pat.syntax())?.type_of_binding_in_pat(self.db, pat)
    }

    pub fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type<'db>> {
        self.analyze(param.syntax())?.type_of_self(self.db, param)
    }

    pub fn pattern_adjustments(&self, pat: &ast::Pat) -> SmallVec<[Type<'db>; 1]> {
        self.analyze(pat.syntax())
            .and_then(|it| it.pattern_adjustments(self.db, pat))
            .unwrap_or_default()
    }

    pub fn binding_mode_of_pat(&self, pat: &ast::IdentPat) -> Option<BindingMode> {
        self.analyze(pat.syntax())?.binding_mode_of_pat(self.db, pat)
    }

    pub fn resolve_expr_as_callable(&self, call: &ast::Expr) -> Option<Callable<'db>> {
        self.analyze(call.syntax())?.resolve_expr_as_callable(self.db, call)
    }

    pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
        self.analyze(call.syntax())?.resolve_method_call(self.db, call)
    }

    /// Attempts to resolve this call expression as a method call falling back to resolving it as a field.
    pub fn resolve_method_call_fallback(
        &self,
        call: &ast::MethodCallExpr,
    ) -> Option<(Either<Function, Field>, Option<GenericSubstitution<'db>>)> {
        self.analyze(call.syntax())?.resolve_method_call_fallback(self.db, call)
    }

    /// Env is used to derive the trait environment
    // FIXME: better api for the trait environment
    pub fn resolve_trait_impl_method(
        &self,
        env: Type<'db>,
        trait_: Trait,
        func: Function,
        subst: impl IntoIterator<Item = Type<'db>>,
    ) -> Option<Function> {
        let mut substs = hir_ty::TyBuilder::subst_for_def(self.db, TraitId::from(trait_), None);
        for s in subst {
            substs = substs.push(s.ty);
        }
        Some(self.db.lookup_impl_method(env.env, func.into(), substs.build()).0.into())
    }

    fn resolve_range_pat(&self, range_pat: &ast::RangePat) -> Option<StructId> {
        self.analyze(range_pat.syntax())?.resolve_range_pat(self.db, range_pat)
    }

    fn resolve_range_expr(&self, range_expr: &ast::RangeExpr) -> Option<StructId> {
        self.analyze(range_expr.syntax())?.resolve_range_expr(self.db, range_expr)
    }

    fn resolve_await_to_poll(&self, await_expr: &ast::AwaitExpr) -> Option<FunctionId> {
        self.analyze(await_expr.syntax())?.resolve_await_to_poll(self.db, await_expr)
    }

    fn resolve_prefix_expr(&self, prefix_expr: &ast::PrefixExpr) -> Option<FunctionId> {
        self.analyze(prefix_expr.syntax())?.resolve_prefix_expr(self.db, prefix_expr)
    }

    fn resolve_index_expr(&self, index_expr: &ast::IndexExpr) -> Option<FunctionId> {
        self.analyze(index_expr.syntax())?.resolve_index_expr(self.db, index_expr)
    }

    fn resolve_bin_expr(&self, bin_expr: &ast::BinExpr) -> Option<FunctionId> {
        self.analyze(bin_expr.syntax())?.resolve_bin_expr(self.db, bin_expr)
    }

    fn resolve_try_expr(&self, try_expr: &ast::TryExpr) -> Option<FunctionId> {
        self.analyze(try_expr.syntax())?.resolve_try_expr(self.db, try_expr)
    }

    // This does not resolve the method call to the correct trait impl!
    // We should probably fix that.
    pub fn resolve_method_call_as_callable(
        &self,
        call: &ast::MethodCallExpr,
    ) -> Option<Callable<'db>> {
        self.analyze(call.syntax())?.resolve_method_call_as_callable(self.db, call)
    }

    pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Either<Field, TupleField>> {
        self.analyze(field.syntax())?.resolve_field(field)
    }

    pub fn resolve_field_fallback(
        &self,
        field: &ast::FieldExpr,
    ) -> Option<(Either<Either<Field, TupleField>, Function>, Option<GenericSubstitution<'db>>)>
    {
        self.analyze(field.syntax())?.resolve_field_fallback(self.db, field)
    }

    pub fn resolve_record_field(
        &self,
        field: &ast::RecordExprField,
    ) -> Option<(Field, Option<Local>, Type<'db>)> {
        self.resolve_record_field_with_substitution(field)
            .map(|(field, local, ty, _)| (field, local, ty))
    }

    pub fn resolve_record_field_with_substitution(
        &self,
        field: &ast::RecordExprField,
    ) -> Option<(Field, Option<Local>, Type<'db>, GenericSubstitution<'db>)> {
        self.analyze(field.syntax())?.resolve_record_field(self.db, field)
    }

    pub fn resolve_record_pat_field(
        &self,
        field: &ast::RecordPatField,
    ) -> Option<(Field, Type<'db>)> {
        self.resolve_record_pat_field_with_subst(field).map(|(field, ty, _)| (field, ty))
    }

    pub fn resolve_record_pat_field_with_subst(
        &self,
        field: &ast::RecordPatField,
    ) -> Option<(Field, Type<'db>, GenericSubstitution<'db>)> {
        self.analyze(field.syntax())?.resolve_record_pat_field(self.db, field)
    }

    // FIXME: Replace this with `resolve_macro_call2`
    pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<Macro> {
        let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
        self.resolve_macro_call2(macro_call)
    }

    pub fn resolve_macro_call2(&self, macro_call: InFile<&ast::MacroCall>) -> Option<Macro> {
        self.to_def2(macro_call)
            .and_then(|call| self.with_ctx(|ctx| macro_call_to_macro_id(ctx, call)))
            .map(Into::into)
    }

    pub fn is_proc_macro_call(&self, macro_call: InFile<&ast::MacroCall>) -> bool {
        self.resolve_macro_call2(macro_call)
            .is_some_and(|m| matches!(m.id, MacroId::ProcMacroId(..)))
    }

    pub fn resolve_macro_call_arm(&self, macro_call: &ast::MacroCall) -> Option<u32> {
        let file_id = self.to_def(macro_call)?;
        self.db.parse_macro_expansion(file_id).value.1.matched_arm
    }

    pub fn get_unsafe_ops(&self, def: DefWithBody) -> FxHashSet<ExprOrPatSource> {
        let def = DefWithBodyId::from(def);
        let (body, source_map) = self.db.body_with_source_map(def);
        let infer = self.db.infer(def);
        let mut res = FxHashSet::default();
        unsafe_operations_for_body(self.db, &infer, def, &body, &mut |node| {
            if let Ok(node) = source_map.expr_or_pat_syntax(node) {
                res.insert(node);
            }
        });
        res
    }

    pub fn get_unsafe_ops_for_unsafe_block(&self, block: ast::BlockExpr) -> Vec<ExprOrPatSource> {
        always!(block.unsafe_token().is_some());
        let block = self.wrap_node_infile(ast::Expr::from(block));
        let Some(def) = self.body_for(block.syntax()) else { return Vec::new() };
        let def = def.into();
        let (body, source_map) = self.db.body_with_source_map(def);
        let infer = self.db.infer(def);
        let Some(ExprOrPatId::ExprId(block)) = source_map.node_expr(block.as_ref()) else {
            return Vec::new();
        };
        let mut res = Vec::default();
        unsafe_operations(self.db, &infer, def, &body, block, &mut |node, _| {
            if let Ok(node) = source_map.expr_or_pat_syntax(node) {
                res.push(node);
            }
        });
        res
    }

    pub fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool {
        let Some(mac) = self.resolve_macro_call(macro_call) else { return false };
        if mac.is_asm_like(self.db) {
            return true;
        }

        let Some(sa) = self.analyze(macro_call.syntax()) else { return false };
        let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
        match macro_call.map(|it| it.syntax().parent().and_then(ast::MacroExpr::cast)).transpose() {
            Some(it) => sa.is_unsafe_macro_call_expr(self.db, it.as_ref()),
            None => false,
        }
    }

    pub fn resolve_attr_macro_call(&self, item: &ast::Item) -> Option<Macro> {
        let item_in_file = self.wrap_node_infile(item.clone());
        let id = self.with_ctx(|ctx| {
            let macro_call_id = ctx.item_to_macro_call(item_in_file.as_ref())?;
            macro_call_to_macro_id(ctx, macro_call_id)
        })?;
        Some(Macro { id })
    }

    pub fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> {
        self.resolve_path_with_subst(path).map(|(it, _)| it)
    }

    pub fn resolve_path_per_ns(&self, path: &ast::Path) -> Option<PathResolutionPerNs> {
        self.analyze(path.syntax())?.resolve_hir_path_per_ns(self.db, path)
    }

    pub fn resolve_path_with_subst(
        &self,
        path: &ast::Path,
    ) -> Option<(PathResolution, Option<GenericSubstitution<'db>>)> {
        self.analyze(path.syntax())?.resolve_path(self.db, path)
    }

    pub fn resolve_use_type_arg(&self, name: &ast::NameRef) -> Option<TypeParam> {
        self.analyze(name.syntax())?.resolve_use_type_arg(name)
    }

    pub fn resolve_offset_of_field(
        &self,
        name_ref: &ast::NameRef,
    ) -> Option<(Either<Variant, Field>, GenericSubstitution<'db>)> {
        self.analyze_no_infer(name_ref.syntax())?.resolve_offset_of_field(self.db, name_ref)
    }

    pub fn resolve_mod_path(
        &self,
        scope: &SyntaxNode,
        path: &ModPath,
    ) -> Option<impl Iterator<Item = ItemInNs>> {
        let analyze = self.analyze(scope)?;
        let items = analyze.resolver.resolve_module_path_in_items(self.db, path);
        Some(items.iter_items().map(|(item, _)| item.into()))
    }

    fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {
        self.analyze(record_lit.syntax())?.resolve_variant(record_lit)
    }

    pub fn resolve_bind_pat_to_const(&self, pat: &ast::IdentPat) -> Option<ModuleDef> {
        self.analyze(pat.syntax())?.resolve_bind_pat_to_const(self.db, pat)
    }

    pub fn record_literal_missing_fields(
        &self,
        literal: &ast::RecordExpr,
    ) -> Vec<(Field, Type<'db>)> {
        self.analyze(literal.syntax())
            .and_then(|it| it.record_literal_missing_fields(self.db, literal))
            .unwrap_or_default()
    }

    pub fn record_pattern_missing_fields(
        &self,
        pattern: &ast::RecordPat,
    ) -> Vec<(Field, Type<'db>)> {
        self.analyze(pattern.syntax())
            .and_then(|it| it.record_pattern_missing_fields(self.db, pattern))
            .unwrap_or_default()
    }

    fn with_ctx<F: FnOnce(&mut SourceToDefCtx<'_, '_>) -> T, T>(&self, f: F) -> T {
        let mut ctx = SourceToDefCtx { db: self.db, cache: &mut self.s2d_cache.borrow_mut() };
        f(&mut ctx)
    }

    pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> {
        let src = self.find_file(src.syntax()).with_value(src);
        T::to_def(self, src)
    }

    pub fn to_def2<T: ToDef>(&self, src: InFile<&T>) -> Option<T::Def> {
        T::to_def(self, src)
    }

    fn file_to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
        self.with_ctx(|ctx| ctx.file_to_def(file).to_owned()).into_iter().map(Module::from)
    }

    fn hir_file_to_module_defs(&self, file: HirFileId) -> impl Iterator<Item = Module> {
        // FIXME: Do we need to care about inline modules for macro expansions?
        self.file_to_module_defs(file.original_file_respecting_includes(self.db).file_id(self.db))
    }

    pub fn scope(&self, node: &SyntaxNode) -> Option<SemanticsScope<'db>> {
        self.analyze_no_infer(node).map(|SourceAnalyzer { file_id, resolver, .. }| SemanticsScope {
            db: self.db,
            file_id,
            resolver,
        })
    }

    pub fn scope_at_offset(
        &self,
        node: &SyntaxNode,
        offset: TextSize,
    ) -> Option<SemanticsScope<'db>> {
        self.analyze_with_offset_no_infer(node, offset).map(
            |SourceAnalyzer { file_id, resolver, .. }| SemanticsScope {
                db: self.db,
                file_id,
                resolver,
            },
        )
    }

    /// Search for a definition's source and cache its syntax tree
    pub fn source<Def: HasSource>(&self, def: Def) -> Option<InFile<Def::Ast>>
    where
        Def::Ast: AstNode,
    {
        // FIXME: source call should go through the parse cache
        let res = def.source(self.db)?;
        self.cache(find_root(res.value.syntax()), res.file_id);
        Some(res)
    }

    pub fn body_for(&self, node: InFile<&SyntaxNode>) -> Option<DefWithBody> {
        let container = self.with_ctx(|ctx| ctx.find_container(node))?;

        match container {
            ChildContainer::DefWithBodyId(def) => Some(def.into()),
            _ => None,
        }
    }

    /// Returns none if the file of the node is not part of a crate.
    fn analyze(&self, node: &SyntaxNode) -> Option<SourceAnalyzer<'db>> {
        let node = self.find_file(node);
        self.analyze_impl(node, None, true)
    }

    /// Returns none if the file of the node is not part of a crate.
    fn analyze_no_infer(&self, node: &SyntaxNode) -> Option<SourceAnalyzer<'db>> {
        let node = self.find_file(node);
        self.analyze_impl(node, None, false)
    }

    fn analyze_with_offset_no_infer(
        &self,
        node: &SyntaxNode,
        offset: TextSize,
    ) -> Option<SourceAnalyzer<'db>> {
        let node = self.find_file(node);
        self.analyze_impl(node, Some(offset), false)
    }

    fn analyze_impl(
        &self,
        node: InFile<&SyntaxNode>,
        offset: Option<TextSize>,
        // replace this, just make the inference result a `LazyCell`
        infer_body: bool,
    ) -> Option<SourceAnalyzer<'db>> {
        let _p = tracing::info_span!("SemanticsImpl::analyze_impl").entered();

        let container = self.with_ctx(|ctx| ctx.find_container(node))?;

        let resolver = match container {
            ChildContainer::DefWithBodyId(def) => {
                return Some(if infer_body {
                    SourceAnalyzer::new_for_body(self.db, def, node, offset)
                } else {
                    SourceAnalyzer::new_for_body_no_infer(self.db, def, node, offset)
                });
            }
            ChildContainer::VariantId(def) => {
                return Some(SourceAnalyzer::new_variant_body(self.db, def, node, offset));
            }
            ChildContainer::TraitId(it) => {
                return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset));
            }
            ChildContainer::ImplId(it) => {
                return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset));
            }
            ChildContainer::EnumId(it) => {
                return Some(SourceAnalyzer::new_generic_def(self.db, it.into(), node, offset));
            }
            ChildContainer::GenericDefId(it) => {
                return Some(SourceAnalyzer::new_generic_def(self.db, it, node, offset));
            }
            ChildContainer::ModuleId(it) => it.resolver(self.db),
        };
        Some(SourceAnalyzer::new_for_resolver(resolver, node))
    }

    fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
        SourceToDefCache::cache(
            &mut self.s2d_cache.borrow_mut().root_to_file_cache,
            root_node,
            file_id,
        );
    }

    pub fn assert_contains_node(&self, node: &SyntaxNode) {
        self.find_file(node);
    }

    fn lookup(&self, root_node: &SyntaxNode) -> Option<HirFileId> {
        let cache = self.s2d_cache.borrow();
        cache.root_to_file_cache.get(root_node).copied()
    }

    fn wrap_node_infile<N: AstNode>(&self, node: N) -> InFile<N> {
        let InFile { file_id, .. } = self.find_file(node.syntax());
        InFile::new(file_id, node)
    }

    fn wrap_token_infile(&self, token: SyntaxToken) -> InFile<SyntaxToken> {
        let InFile { file_id, .. } = self.find_file(&token.parent().unwrap());
        InFile::new(file_id, token)
    }

    /// Wraps the node in a [`InFile`] with the file id it belongs to.
    fn find_file<'node>(&self, node: &'node SyntaxNode) -> InFile<&'node SyntaxNode> {
        let root_node = find_root(node);
        let file_id = self.lookup(&root_node).unwrap_or_else(|| {
            panic!(
                "\n\nFailed to lookup {:?} in this Semantics.\n\
                 Make sure to only query nodes derived from this instance of Semantics.\n\
                 root node:   {:?}\n\
                 known nodes: {}\n\n",
                node,
                root_node,
                self.s2d_cache
                    .borrow()
                    .root_to_file_cache
                    .keys()
                    .map(|it| format!("{it:?}"))
                    .collect::<Vec<_>>()
                    .join(", ")
            )
        });
        InFile::new(file_id, node)
    }

    /// Returns `true` if the `node` is inside an `unsafe` context.
    pub fn is_inside_unsafe(&self, expr: &ast::Expr) -> bool {
        let Some(enclosing_item) =
            expr.syntax().ancestors().find_map(Either::<ast::Item, ast::Variant>::cast)
        else {
            return false;
        };

        let def = match &enclosing_item {
            Either::Left(ast::Item::Fn(it)) if it.unsafe_token().is_some() => return true,
            Either::Left(ast::Item::Fn(it)) => {
                self.to_def(it).map(<_>::into).map(DefWithBodyId::FunctionId)
            }
            Either::Left(ast::Item::Const(it)) => {
                self.to_def(it).map(<_>::into).map(DefWithBodyId::ConstId)
            }
            Either::Left(ast::Item::Static(it)) => {
                self.to_def(it).map(<_>::into).map(DefWithBodyId::StaticId)
            }
            Either::Left(_) => None,
            Either::Right(it) => self.to_def(it).map(<_>::into).map(DefWithBodyId::VariantId),
        };
        let Some(def) = def else { return false };
        let enclosing_node = enclosing_item.as_ref().either(|i| i.syntax(), |v| v.syntax());

        let (body, source_map) = self.db.body_with_source_map(def);

        let file_id = self.find_file(expr.syntax()).file_id;

        let Some(mut parent) = expr.syntax().parent() else { return false };
        loop {
            if &parent == enclosing_node {
                break false;
            }

            if let Some(parent) = ast::Expr::cast(parent.clone())
                && let Some(ExprOrPatId::ExprId(expr_id)) =
                    source_map.node_expr(InFile { file_id, value: &parent })
                && let Expr::Unsafe { .. } = body[expr_id]
            {
                break true;
            }

            let Some(parent_) = parent.parent() else { break false };
            parent = parent_;
        }
    }
}

// FIXME This can't be the best way to do this
fn macro_call_to_macro_id(
    ctx: &mut SourceToDefCtx<'_, '_>,
    macro_call_id: MacroCallId,
) -> Option<MacroId> {
    let db: &dyn ExpandDatabase = ctx.db;
    let loc = db.lookup_intern_macro_call(macro_call_id);

    match loc.def.ast_id() {
        Either::Left(it) => {
            let node = match it.file_id {
                HirFileId::FileId(file_id) => {
                    it.to_ptr(db).to_node(&db.parse(file_id).syntax_node())
                }
                HirFileId::MacroFile(macro_file) => {
                    let expansion_info = ctx.cache.get_or_insert_expansion(ctx.db, macro_file);
                    it.to_ptr(db).to_node(&expansion_info.expanded().value)
                }
            };
            ctx.macro_to_def(InFile::new(it.file_id, &node))
        }
        Either::Right(it) => {
            let node = match it.file_id {
                HirFileId::FileId(file_id) => {
                    it.to_ptr(db).to_node(&db.parse(file_id).syntax_node())
                }
                HirFileId::MacroFile(macro_file) => {
                    let expansion_info = ctx.cache.get_or_insert_expansion(ctx.db, macro_file);
                    it.to_ptr(db).to_node(&expansion_info.expanded().value)
                }
            };
            ctx.proc_macro_to_def(InFile::new(it.file_id, &node))
        }
    }
}

pub trait ToDef: AstNode + Clone {
    type Def;
    fn to_def(sema: &SemanticsImpl<'_>, src: InFile<&Self>) -> Option<Self::Def>;
}

macro_rules! to_def_impls {
    ($(($def:path, $ast:path, $meth:ident)),* ,) => {$(
        impl ToDef for $ast {
            type Def = $def;
            fn to_def(sema: &SemanticsImpl<'_>, src: InFile<&Self>) -> Option<Self::Def> {
                sema.with_ctx(|ctx| ctx.$meth(src)).map(<$def>::from)
            }
        }
    )*}
}

to_def_impls![
    (crate::Module, ast::Module, module_to_def),
    (crate::Module, ast::SourceFile, source_file_to_def),
    (crate::Struct, ast::Struct, struct_to_def),
    (crate::Enum, ast::Enum, enum_to_def),
    (crate::Union, ast::Union, union_to_def),
    (crate::Trait, ast::Trait, trait_to_def),
    (crate::Impl, ast::Impl, impl_to_def),
    (crate::TypeAlias, ast::TypeAlias, type_alias_to_def),
    (crate::Const, ast::Const, const_to_def),
    (crate::Static, ast::Static, static_to_def),
    (crate::Function, ast::Fn, fn_to_def),
    (crate::Field, ast::RecordField, record_field_to_def),
    (crate::Field, ast::TupleField, tuple_field_to_def),
    (crate::Variant, ast::Variant, enum_variant_to_def),
    (crate::TypeParam, ast::TypeParam, type_param_to_def),
    (crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
    (crate::ConstParam, ast::ConstParam, const_param_to_def),
    (crate::GenericParam, ast::GenericParam, generic_param_to_def),
    (crate::Macro, ast::Macro, macro_to_def),
    (crate::Local, ast::IdentPat, bind_pat_to_def),
    (crate::Local, ast::SelfParam, self_param_to_def),
    (crate::Label, ast::Label, label_to_def),
    (crate::Adt, ast::Adt, adt_to_def),
    (crate::ExternCrateDecl, ast::ExternCrate, extern_crate_to_def),
    (crate::InlineAsmOperand, ast::AsmOperandNamed, asm_operand_to_def),
    (crate::ExternBlock, ast::ExternBlock, extern_block_to_def),
    (MacroCallId, ast::MacroCall, macro_call_to_macro_call),
];

fn find_root(node: &SyntaxNode) -> SyntaxNode {
    node.ancestors().last().unwrap()
}

/// `SemanticsScope` encapsulates the notion of a scope (the set of visible
/// names) at a particular program point.
///
/// It is a bit tricky, as scopes do not really exist inside the compiler.
/// Rather, the compiler directly computes for each reference the definition it
/// refers to. It might transiently compute the explicit scope map while doing
/// so, but, generally, this is not something left after the analysis.
///
/// However, we do very much need explicit scopes for IDE purposes --
/// completion, at its core, lists the contents of the current scope. The notion
/// of scope is also useful to answer questions like "what would be the meaning
/// of this piece of code if we inserted it into this position?".
///
/// So `SemanticsScope` is constructed from a specific program point (a syntax
/// node or just a raw offset) and provides access to the set of visible names
/// on a somewhat best-effort basis.
///
/// Note that if you are wondering "what does this specific existing name mean?",
/// you'd better use the `resolve_` family of methods.
#[derive(Debug)]
pub struct SemanticsScope<'db> {
    pub db: &'db dyn HirDatabase,
    file_id: HirFileId,
    resolver: Resolver<'db>,
}

impl<'db> SemanticsScope<'db> {
    pub fn file_id(&self) -> HirFileId {
        self.file_id
    }

    pub fn module(&self) -> Module {
        Module { id: self.resolver.module() }
    }

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

    pub fn containing_function(&self) -> Option<Function> {
        self.resolver.body_owner().and_then(|owner| match owner {
            DefWithBodyId::FunctionId(id) => Some(id.into()),
            _ => None,
        })
    }

    pub(crate) fn resolver(&self) -> &Resolver<'db> {
        &self.resolver
    }

    /// Note: `VisibleTraits` should be treated as an opaque type, passed into `Type
    pub fn visible_traits(&self) -> VisibleTraits {
        let resolver = &self.resolver;
        VisibleTraits(resolver.traits_in_scope(self.db))
    }

    /// Calls the passed closure `f` on all names in scope.
    pub fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
        let scope = self.resolver.names_in_scope(self.db);
        for (name, entries) in scope {
            for entry in entries {
                let def = match entry {
                    resolver::ScopeDef::ModuleDef(it) => ScopeDef::ModuleDef(it.into()),
                    resolver::ScopeDef::Unknown => ScopeDef::Unknown,
                    resolver::ScopeDef::ImplSelfType(it) => ScopeDef::ImplSelfType(it.into()),
                    resolver::ScopeDef::AdtSelfType(it) => ScopeDef::AdtSelfType(it.into()),
                    resolver::ScopeDef::GenericParam(id) => ScopeDef::GenericParam(id.into()),
                    resolver::ScopeDef::Local(binding_id) => match self.resolver.body_owner() {
                        Some(parent) => ScopeDef::Local(Local { parent, binding_id }),
                        None => continue,
                    },
                    resolver::ScopeDef::Label(label_id) => match self.resolver.body_owner() {
                        Some(parent) => ScopeDef::Label(Label { parent, label_id }),
                        None => continue,
                    },
                };
                f(name.clone(), def)
            }
        }
    }

    /// Checks if a trait is in scope, either because of an import or because we're in an impl of it.
    pub fn can_use_trait_methods(&self, t: Trait) -> bool {
        self.resolver.traits_in_scope(self.db).contains(&t.id)
    }

    /// Resolve a path as-if it was written at the given scope. This is
    /// necessary a heuristic, as it doesn't take hygiene into account.
    pub fn speculative_resolve(&self, ast_path: &ast::Path) -> Option<PathResolution> {
        let mut kind = PathKind::Plain;
        let mut segments = vec![];
        let mut first = true;
        for segment in ast_path.segments() {
            if first {
                first = false;
                if segment.coloncolon_token().is_some() {
                    kind = PathKind::Abs;
                }
            }

            let Some(k) = segment.kind() else { continue };
            match k {
                ast::PathSegmentKind::Name(name_ref) => segments.push(name_ref.as_name()),
                ast::PathSegmentKind::Type { .. } => continue,
                ast::PathSegmentKind::SelfTypeKw => {
                    segments.push(Name::new_symbol_root(sym::Self_))
                }
                ast::PathSegmentKind::SelfKw => kind = PathKind::Super(0),
                ast::PathSegmentKind::SuperKw => match kind {
                    PathKind::Super(s) => kind = PathKind::Super(s + 1),
                    PathKind::Plain => kind = PathKind::Super(1),
                    PathKind::Crate | PathKind::Abs | PathKind::DollarCrate(_) => continue,
                },
                ast::PathSegmentKind::CrateKw => kind = PathKind::Crate,
            }
        }

        resolve_hir_path(
            self.db,
            &self.resolver,
            &Path::BarePath(Interned::new(ModPath::from_segments(kind, segments))),
            name_hygiene(self.db, InFile::new(self.file_id, ast_path.syntax())),
            None,
        )
    }

    pub fn resolve_mod_path(&self, path: &ModPath) -> impl Iterator<Item = ItemInNs> + use<> {
        let items = self.resolver.resolve_module_path_in_items(self.db, path);
        items.iter_items().map(|(item, _)| item.into())
    }

    /// Iterates over associated types that may be specified after the given path (using
    /// `Ty::Assoc` syntax).
    pub fn assoc_type_shorthand_candidates(
        &self,
        resolution: &PathResolution,
        mut cb: impl FnMut(TypeAlias),
    ) {
        let (Some(def), Some(resolution)) = (self.resolver.generic_def(), resolution.in_type_ns())
        else {
            return;
        };
        hir_ty::associated_type_shorthand_candidates(self.db, def, resolution, |_, id| {
            cb(id.into());
            false
        });
    }

    pub fn generic_def(&self) -> Option<crate::GenericDef> {
        self.resolver.generic_def().map(|id| id.into())
    }

    pub fn extern_crates(&self) -> impl Iterator<Item = (Name, Module)> + '_ {
        self.resolver.extern_crates_in_scope().map(|(name, id)| (name, Module { id }))
    }

    pub fn extern_crate_decls(&self) -> impl Iterator<Item = Name> + '_ {
        self.resolver.extern_crate_decls_in_scope(self.db)
    }

    pub fn has_same_self_type(&self, other: &SemanticsScope<'_>) -> bool {
        self.resolver.impl_def() == other.resolver.impl_def()
    }
}

#[derive(Debug)]
pub struct VisibleTraits(pub FxHashSet<TraitId>);

impl ops::Deref for VisibleTraits {
    type Target = FxHashSet<TraitId>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

struct RenameConflictsVisitor<'a> {
    db: &'a dyn HirDatabase,
    owner: DefWithBodyId,
    resolver: Resolver<'a>,
    body: &'a Body,
    to_be_renamed: BindingId,
    new_name: Symbol,
    old_name: Symbol,
    conflicts: FxHashSet<BindingId>,
}

impl RenameConflictsVisitor<'_> {
    fn resolve_path(&mut self, node: ExprOrPatId, path: &Path) {
        if let Path::BarePath(path) = path
            && let Some(name) = path.as_ident()
        {
            if *name.symbol() == self.new_name {
                if let Some(conflicting) = self.resolver.rename_will_conflict_with_renamed(
                    self.db,
                    name,
                    path,
                    self.body.expr_or_pat_path_hygiene(node),
                    self.to_be_renamed,
                ) {
                    self.conflicts.insert(conflicting);
                }
            } else if *name.symbol() == self.old_name
                && let Some(conflicting) = self.resolver.rename_will_conflict_with_another_variable(
                    self.db,
                    name,
                    path,
                    self.body.expr_or_pat_path_hygiene(node),
                    &self.new_name,
                    self.to_be_renamed,
                )
            {
                self.conflicts.insert(conflicting);
            }
        }
    }

    fn rename_conflicts(&mut self, expr: ExprId) {
        match &self.body[expr] {
            Expr::Path(path) => {
                let guard = self.resolver.update_to_inner_scope(self.db, self.owner, expr);
                self.resolve_path(expr.into(), path);
                self.resolver.reset_to_guard(guard);
            }
            &Expr::Assignment { target, .. } => {
                let guard = self.resolver.update_to_inner_scope(self.db, self.owner, expr);
                self.body.walk_pats(target, &mut |pat| {
                    if let Pat::Path(path) = &self.body[pat] {
                        self.resolve_path(pat.into(), path);
                    }
                });
                self.resolver.reset_to_guard(guard);
            }
            _ => {}
        }

        self.body.walk_child_exprs(expr, |expr| self.rename_conflicts(expr));
    }
}
