]> git.lizzy.rs Git - rust.git/commitdiff
:arrow_up: rust-analyzer
authorLaurențiu Nicola <lnicola@dend.ro>
Tue, 2 Aug 2022 06:05:16 +0000 (09:05 +0300)
committerLaurențiu Nicola <lnicola@dend.ro>
Tue, 2 Aug 2022 06:05:16 +0000 (09:05 +0300)
45 files changed:
1  2 
src/tools/rust-analyzer/.github/workflows/publish.yml
src/tools/rust-analyzer/crates/hir-def/src/attr.rs
src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
src/tools/rust-analyzer/crates/hir-ty/src/chalk_ext.rs
src/tools/rust-analyzer/crates/hir/src/lib.rs
src/tools/rust-analyzer/crates/hir/src/semantics.rs
src/tools/rust-analyzer/crates/ide-assists/src/handlers/expand_glob_import.rs
src/tools/rust-analyzer/crates/ide-assists/src/handlers/inline_call.rs
src/tools/rust-analyzer/crates/ide-assists/src/tests/generated.rs
src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute.rs
src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/derive.rs
src/tools/rust-analyzer/crates/ide-completion/src/completions/expr.rs
src/tools/rust-analyzer/crates/ide-completion/src/completions/item_list.rs
src/tools/rust-analyzer/crates/ide-completion/src/completions/pattern.rs
src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs
src/tools/rust-analyzer/crates/ide-completion/src/completions/use_.rs
src/tools/rust-analyzer/crates/ide-completion/src/completions/vis.rs
src/tools/rust-analyzer/crates/ide-completion/src/context.rs
src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
src/tools/rust-analyzer/crates/ide-completion/src/context/tests.rs
src/tools/rust-analyzer/crates/ide-completion/src/render.rs
src/tools/rust-analyzer/crates/ide-completion/src/render/function.rs
src/tools/rust-analyzer/crates/ide-completion/src/render/pattern.rs
src/tools/rust-analyzer/crates/ide-completion/src/tests.rs
src/tools/rust-analyzer/crates/ide-completion/src/tests/expression.rs
src/tools/rust-analyzer/crates/ide-completion/src/tests/pattern.rs
src/tools/rust-analyzer/crates/ide-completion/src/tests/record.rs
src/tools/rust-analyzer/crates/ide-completion/src/tests/special.rs
src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/inject.rs
src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_inline.html
src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/test_data/highlight_module_docs_outline.html
src/tools/rust-analyzer/crates/ide/src/syntax_highlighting/tests.rs
src/tools/rust-analyzer/crates/limit/src/lib.rs
src/tools/rust-analyzer/crates/parser/src/grammar/paths.rs
src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs
src/tools/rust-analyzer/crates/rust-analyzer/src/cli/load_cargo.rs
src/tools/rust-analyzer/crates/rust-analyzer/src/reload.rs
src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
src/tools/rust-analyzer/crates/syntax/src/tests/sourcegen_ast.rs
src/tools/rust-analyzer/docs/dev/README.md
src/tools/rust-analyzer/xtask/src/release.rs

index 927996c1bef21d7f8a5c631a13577c3ee6fcaeb7,0000000000000000000000000000000000000000..a4497f49e3c2f8c5193aea300b044251ec262463
mode 100644,000000..100644
--- /dev/null
@@@ -1,41 -1,0 +1,54 @@@
-           # Fix names for crates that were published before switch to kebab-case.
-           find crates -name 'Cargo.toml' -exec sed -i "s/ra_ap_base-db/ra_ap_base_db/g; s/ra_ap_hir-def/ra_ap_hir_def/g; s/ra_ap_hir-expand/ra_ap_hir_expand/g; s/ra_ap_hir-ty/ra_ap_hir_ty/g; s/ra_ap_ide-assists/ra_ap_ide_assists/g; s/ra_ap_ide-completion/ra_ap_ide_completion/g; s/ra_ap_ide-db/ra_ap_ide_db/g; s/ra_ap_ide-diagnostics/ra_ap_ide_diagnostics/g; s/ra_ap_ide-ssr/ra_ap_ide_ssr/g; s/ra_ap_proc-macro-api/ra_ap_proc_macro_api/g; s/ra_ap_proc-macro-srv/ra_ap_proc_macro_srv/g; s/ra_ap_project-model/ra_ap_project_model/g; s/ra_ap_test-utils/ra_ap_test_utils/g; s/ra_ap_text-edit/ra_ap_text_edit/g" {} +
 +name: publish
 +on:
 +  workflow_dispatch: # We can add version input when 1.0 is released and scheduled releases are removed
 +
 +#   schedule:
 +#     - cron: "0 0 * * *" # midnight UTC
 +
 +  push:
 +    branches:
 +      - release
 +
 +jobs:
 +  publish:
 +    name: publish
 +    runs-on: ubuntu-latest
 +    steps:
 +      - name: Checkout repository
 +        uses: actions/checkout@v3
 +        with:
 +          fetch-depth: 0
 +
 +      - name: Install Rust toolchain
 +        run: rustup update --no-self-update stable
 +
 +      - name: Install cargo-workspaces
 +        run: cargo install cargo-workspaces
 +
 +      - name: Release
 +        env:
 +          CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
 +          PATCH: ${{ github.run_number }}
 +        shell: bash
 +        run: |
 +          git config --global user.email "runner@gha.local"
 +          git config --global user.name "Github Action"
 +          rm Cargo.lock
++          # Fix names for crates that were published before switch to kebab-case.
++          cargo workspaces rename --from base-db base_db
++          cargo workspaces rename --from hir-def hir_def
++          cargo workspaces rename --from hir-expand hir_expand
++          cargo workspaces rename --from hir-ty hir_ty
++          cargo workspaces rename --from ide-assists ide_assists
++          cargo workspaces rename --from ide-completion ide_completion
++          cargo workspaces rename --from ide-db ide_db
++          cargo workspaces rename --from ide-diagnostics ide_diagnostics
++          cargo workspaces rename --from ide-ssr ide_ssr
++          cargo workspaces rename --from proc-macro-api proc_macro_api
++          cargo workspaces rename --from proc-macro-srv proc_macro_srv
++          cargo workspaces rename --from project-model project_model
++          cargo workspaces rename --from test-utils test_utils
++          cargo workspaces rename --from text-edit text_edit
 +          cargo workspaces rename ra_ap_%n
 +          find crates/rust-analyzer -type f -name '*.rs' -exec sed -i 's/rust_analyzer/ra_ap_rust_analyzer/g' {} +
 +          cargo workspaces publish --yes --force '*' --exact --no-git-commit --allow-dirty --skip-published custom 0.0.$PATCH
index 8a6b6f3effd2ed33e6f121a79f8bf816688b8125,0000000000000000000000000000000000000000..2b39c6f8da86bee737371f8fd86547d5ed281d11
mode 100644,000000..100644
--- /dev/null
@@@ -1,991 -1,0 +1,1002 @@@
-         match (&self.entries, &other.entries) {
 +//! A higher level attributes based on TokenTree, with also some shortcuts.
 +
 +use std::{fmt, hash::Hash, ops, sync::Arc};
 +
 +use base_db::CrateId;
 +use cfg::{CfgExpr, CfgOptions};
 +use either::Either;
 +use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
 +use itertools::Itertools;
 +use la_arena::{ArenaMap, Idx, RawIdx};
 +use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
 +use smallvec::{smallvec, SmallVec};
 +use syntax::{
 +    ast::{self, AstNode, HasAttrs, IsString},
 +    match_ast, AstPtr, AstToken, SmolStr, SyntaxNode, TextRange, TextSize,
 +};
 +use tt::Subtree;
 +
 +use crate::{
 +    db::DefDatabase,
 +    intern::Interned,
 +    item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode},
 +    nameres::{ModuleOrigin, ModuleSource},
 +    path::{ModPath, PathKind},
 +    src::{HasChildSource, HasSource},
 +    AdtId, AttrDefId, EnumId, GenericParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroId,
 +    VariantId,
 +};
 +
 +/// Holds documentation
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Documentation(String);
 +
 +impl Documentation {
 +    pub fn new(s: String) -> Self {
 +        Documentation(s)
 +    }
 +
 +    pub fn as_str(&self) -> &str {
 +        &self.0
 +    }
 +}
 +
 +impl From<Documentation> for String {
 +    fn from(Documentation(string): Documentation) -> Self {
 +        string
 +    }
 +}
 +
 +/// Syntactical attributes, without filtering of `cfg_attr`s.
 +#[derive(Default, Debug, Clone, PartialEq, Eq)]
 +pub(crate) struct RawAttrs {
 +    entries: Option<Arc<[Attr]>>,
 +}
 +
 +#[derive(Default, Debug, Clone, PartialEq, Eq)]
 +pub struct Attrs(RawAttrs);
 +
 +#[derive(Debug, Clone, PartialEq, Eq)]
 +pub struct AttrsWithOwner {
 +    attrs: Attrs,
 +    owner: AttrDefId,
 +}
 +
 +impl ops::Deref for RawAttrs {
 +    type Target = [Attr];
 +
 +    fn deref(&self) -> &[Attr] {
 +        match &self.entries {
 +            Some(it) => &*it,
 +            None => &[],
 +        }
 +    }
 +}
 +impl Attrs {
 +    pub fn get(&self, id: AttrId) -> Option<&Attr> {
 +        (**self).iter().find(|attr| attr.id == id)
 +    }
 +}
 +
 +impl ops::Deref for Attrs {
 +    type Target = [Attr];
 +
 +    fn deref(&self) -> &[Attr] {
 +        match &self.0.entries {
 +            Some(it) => &*it,
 +            None => &[],
 +        }
 +    }
 +}
 +
 +impl ops::Deref for AttrsWithOwner {
 +    type Target = Attrs;
 +
 +    fn deref(&self) -> &Attrs {
 +        &self.attrs
 +    }
 +}
 +
 +impl RawAttrs {
 +    pub(crate) const EMPTY: Self = Self { entries: None };
 +
 +    pub(crate) fn new(db: &dyn DefDatabase, owner: &dyn ast::HasAttrs, hygiene: &Hygiene) -> Self {
 +        let entries = collect_attrs(owner)
 +            .filter_map(|(id, attr)| match attr {
 +                Either::Left(attr) => {
 +                    attr.meta().and_then(|meta| Attr::from_src(db, meta, hygiene, id))
 +                }
 +                Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
 +                    id,
 +                    input: Some(Interned::new(AttrInput::Literal(SmolStr::new(doc)))),
 +                    path: Interned::new(ModPath::from(hir_expand::name!(doc))),
 +                }),
 +            })
 +            .collect::<Arc<_>>();
 +
 +        Self { entries: if entries.is_empty() { None } else { Some(entries) } }
 +    }
 +
 +    fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn ast::HasAttrs>) -> Self {
 +        let hygiene = Hygiene::new(db.upcast(), owner.file_id);
 +        Self::new(db, owner.value, &hygiene)
 +    }
 +
 +    pub(crate) fn merge(&self, other: Self) -> Self {
 +        // FIXME: This needs to fixup `AttrId`s
-             (Some(entries), None) | (None, Some(entries)) => {
-                 Self { entries: Some(entries.clone()) }
-             }
++        match (&self.entries, other.entries) {
 +            (None, None) => Self::EMPTY,
-                 Self { entries: Some(a.iter().chain(b.iter()).cloned().collect()) }
++            (None, entries @ Some(_)) => Self { entries },
++            (Some(entries), None) => Self { entries: Some(entries.clone()) },
 +            (Some(a), Some(b)) => {
++                let last_ast_index = a.last().map_or(0, |it| it.id.ast_index + 1);
++                Self {
++                    entries: Some(
++                        a.iter()
++                            .cloned()
++                            .chain(b.iter().map(|it| {
++                                let mut it = it.clone();
++                                it.id.ast_index += last_ast_index;
++                                it
++                            }))
++                            .collect(),
++                    ),
++                }
 +            }
 +        }
 +    }
 +
 +    /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
 +    pub(crate) fn filter(self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
 +        let has_cfg_attrs = self.iter().any(|attr| {
 +            attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr])
 +        });
 +        if !has_cfg_attrs {
 +            return Attrs(self);
 +        }
 +
 +        let crate_graph = db.crate_graph();
 +        let new_attrs = self
 +            .iter()
 +            .flat_map(|attr| -> SmallVec<[_; 1]> {
 +                let is_cfg_attr =
 +                    attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]);
 +                if !is_cfg_attr {
 +                    return smallvec![attr.clone()];
 +                }
 +
 +                let subtree = match attr.token_tree_value() {
 +                    Some(it) => it,
 +                    _ => return smallvec![attr.clone()],
 +                };
 +
 +                // Input subtree is: `(cfg, $(attr),+)`
 +                // Split it up into a `cfg` subtree and the `attr` subtrees.
 +                // FIXME: There should be a common API for this.
 +                let mut parts = subtree.token_trees.split(|tt| {
 +                    matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. })))
 +                });
 +                let cfg = match parts.next() {
 +                    Some(it) => it,
 +                    None => return smallvec![],
 +                };
 +                let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
 +                let cfg = CfgExpr::parse(&cfg);
 +                let index = attr.id;
 +                let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
 +                    let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
 +                    // FIXME hygiene
 +                    let hygiene = Hygiene::new_unhygienic();
 +                    Attr::from_tt(db, &tree, &hygiene, index)
 +                });
 +
 +                let cfg_options = &crate_graph[krate].cfg_options;
 +                if cfg_options.check(&cfg) == Some(false) {
 +                    smallvec![]
 +                } else {
 +                    cov_mark::hit!(cfg_attr_active);
 +
 +                    attrs.collect()
 +                }
 +            })
 +            .collect();
 +
 +        Attrs(RawAttrs { entries: Some(new_attrs) })
 +    }
 +}
 +
 +impl Attrs {
 +    pub const EMPTY: Self = Self(RawAttrs::EMPTY);
 +
 +    pub(crate) fn variants_attrs_query(
 +        db: &dyn DefDatabase,
 +        e: EnumId,
 +    ) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>> {
 +        // FIXME: There should be some proper form of mapping between item tree enum variant ids and hir enum variant ids
 +        let mut res = ArenaMap::default();
 +
 +        let loc = e.lookup(db);
 +        let krate = loc.container.krate;
 +        let item_tree = loc.id.item_tree(db);
 +        let enum_ = &item_tree[loc.id.value];
 +        let crate_graph = db.crate_graph();
 +        let cfg_options = &crate_graph[krate].cfg_options;
 +
 +        let mut idx = 0;
 +        for variant in enum_.variants.clone() {
 +            let attrs = item_tree.attrs(db, krate, variant.into());
 +            if attrs.is_cfg_enabled(cfg_options) {
 +                res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);
 +                idx += 1;
 +            }
 +        }
 +
 +        Arc::new(res)
 +    }
 +
 +    pub(crate) fn fields_attrs_query(
 +        db: &dyn DefDatabase,
 +        v: VariantId,
 +    ) -> Arc<ArenaMap<LocalFieldId, Attrs>> {
 +        // FIXME: There should be some proper form of mapping between item tree field ids and hir field ids
 +        let mut res = ArenaMap::default();
 +
 +        let crate_graph = db.crate_graph();
 +        let (fields, item_tree, krate) = match v {
 +            VariantId::EnumVariantId(it) => {
 +                let e = it.parent;
 +                let loc = e.lookup(db);
 +                let krate = loc.container.krate;
 +                let item_tree = loc.id.item_tree(db);
 +                let enum_ = &item_tree[loc.id.value];
 +
 +                let cfg_options = &crate_graph[krate].cfg_options;
 +                let variant = 'tri: loop {
 +                    let mut idx = 0;
 +                    for variant in enum_.variants.clone() {
 +                        let attrs = item_tree.attrs(db, krate, variant.into());
 +                        if attrs.is_cfg_enabled(cfg_options) {
 +                            if it.local_id == Idx::from_raw(RawIdx::from(idx)) {
 +                                break 'tri variant;
 +                            }
 +                            idx += 1;
 +                        }
 +                    }
 +                    return Arc::new(res);
 +                };
 +                (item_tree[variant].fields.clone(), item_tree, krate)
 +            }
 +            VariantId::StructId(it) => {
 +                let loc = it.lookup(db);
 +                let krate = loc.container.krate;
 +                let item_tree = loc.id.item_tree(db);
 +                let struct_ = &item_tree[loc.id.value];
 +                (struct_.fields.clone(), item_tree, krate)
 +            }
 +            VariantId::UnionId(it) => {
 +                let loc = it.lookup(db);
 +                let krate = loc.container.krate;
 +                let item_tree = loc.id.item_tree(db);
 +                let union_ = &item_tree[loc.id.value];
 +                (union_.fields.clone(), item_tree, krate)
 +            }
 +        };
 +
 +        let fields = match fields {
 +            Fields::Record(fields) | Fields::Tuple(fields) => fields,
 +            Fields::Unit => return Arc::new(res),
 +        };
 +
 +        let cfg_options = &crate_graph[krate].cfg_options;
 +
 +        let mut idx = 0;
 +        for field in fields {
 +            let attrs = item_tree.attrs(db, krate, field.into());
 +            if attrs.is_cfg_enabled(cfg_options) {
 +                res.insert(Idx::from_raw(RawIdx::from(idx)), attrs);
 +                idx += 1;
 +            }
 +        }
 +
 +        Arc::new(res)
 +    }
 +
 +    pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
 +        AttrQuery { attrs: self, key }
 +    }
 +}
 +
 +impl Attrs {
 +    pub fn cfg(&self) -> Option<CfgExpr> {
 +        let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse);
 +        let first = cfgs.next()?;
 +        match cfgs.next() {
 +            Some(second) => {
 +                let cfgs = [first, second].into_iter().chain(cfgs);
 +                Some(CfgExpr::All(cfgs.collect()))
 +            }
 +            None => Some(first),
 +        }
 +    }
 +    pub(crate) fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> bool {
 +        match self.cfg() {
 +            None => true,
 +            Some(cfg) => cfg_options.check(&cfg) != Some(false),
 +        }
 +    }
 +
 +    pub fn lang(&self) -> Option<&SmolStr> {
 +        self.by_key("lang").string_value()
 +    }
 +
 +    pub fn docs(&self) -> Option<Documentation> {
 +        let docs = self.by_key("doc").attrs().filter_map(|attr| attr.string_value());
 +        let indent = doc_indent(self);
 +        let mut buf = String::new();
 +        for doc in docs {
 +            // str::lines doesn't yield anything for the empty string
 +            if !doc.is_empty() {
 +                buf.extend(Itertools::intersperse(
 +                    doc.lines().map(|line| {
 +                        line.char_indices()
 +                            .nth(indent)
 +                            .map_or(line, |(offset, _)| &line[offset..])
 +                            .trim_end()
 +                    }),
 +                    "\n",
 +                ));
 +            }
 +            buf.push('\n');
 +        }
 +        buf.pop();
 +        if buf.is_empty() {
 +            None
 +        } else {
 +            Some(Documentation(buf))
 +        }
 +    }
 +
 +    pub fn has_doc_hidden(&self) -> bool {
 +        self.by_key("doc").tt_values().any(|tt| {
 +            tt.delimiter_kind() == Some(DelimiterKind::Parenthesis) &&
 +                matches!(&*tt.token_trees, [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] if ident.text == "hidden")
 +        })
 +    }
 +
 +    pub fn is_proc_macro(&self) -> bool {
 +        self.by_key("proc_macro").exists()
 +    }
 +
 +    pub fn is_proc_macro_attribute(&self) -> bool {
 +        self.by_key("proc_macro_attribute").exists()
 +    }
 +
 +    pub fn is_proc_macro_derive(&self) -> bool {
 +        self.by_key("proc_macro_derive").exists()
 +    }
 +}
 +
 +impl AttrsWithOwner {
 +    pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Self {
 +        // FIXME: this should use `Trace` to avoid duplication in `source_map` below
 +        let raw_attrs = match def {
 +            AttrDefId::ModuleId(module) => {
 +                let def_map = module.def_map(db);
 +                let mod_data = &def_map[module.local_id];
 +
 +                match mod_data.origin {
 +                    ModuleOrigin::File { definition, declaration_tree_id, .. } => {
 +                        let decl_attrs = declaration_tree_id
 +                            .item_tree(db)
 +                            .raw_attrs(AttrOwner::ModItem(declaration_tree_id.value.into()))
 +                            .clone();
 +                        let tree = db.file_item_tree(definition.into());
 +                        let def_attrs = tree.raw_attrs(AttrOwner::TopLevel).clone();
 +                        decl_attrs.merge(def_attrs)
 +                    }
 +                    ModuleOrigin::CrateRoot { definition } => {
 +                        let tree = db.file_item_tree(definition.into());
 +                        tree.raw_attrs(AttrOwner::TopLevel).clone()
 +                    }
 +                    ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id
 +                        .item_tree(db)
 +                        .raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
 +                        .clone(),
 +                    ModuleOrigin::BlockExpr { block } => RawAttrs::from_attrs_owner(
 +                        db,
 +                        InFile::new(block.file_id, block.to_node(db.upcast()))
 +                            .as_ref()
 +                            .map(|it| it as &dyn ast::HasAttrs),
 +                    ),
 +                }
 +            }
 +            AttrDefId::FieldId(it) => {
 +                return Self { attrs: db.fields_attrs(it.parent)[it.local_id].clone(), owner: def };
 +            }
 +            AttrDefId::EnumVariantId(it) => {
 +                return Self {
 +                    attrs: db.variants_attrs(it.parent)[it.local_id].clone(),
 +                    owner: def,
 +                };
 +            }
 +            AttrDefId::AdtId(it) => match it {
 +                AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +                AdtId::EnumId(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +                AdtId::UnionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +            },
 +            AttrDefId::TraitId(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +            AttrDefId::MacroId(it) => match it {
 +                MacroId::Macro2Id(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +                MacroId::MacroRulesId(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +                MacroId::ProcMacroId(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +            },
 +            AttrDefId::ImplId(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +            AttrDefId::ConstId(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +            AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +            AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +            AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +            AttrDefId::GenericParamId(it) => match it {
 +                GenericParamId::ConstParamId(it) => {
 +                    let src = it.parent().child_source(db);
 +                    RawAttrs::from_attrs_owner(
 +                        db,
 +                        src.with_value(src.value[it.local_id()].as_ref().either(
 +                            |it| match it {
 +                                ast::TypeOrConstParam::Type(it) => it as _,
 +                                ast::TypeOrConstParam::Const(it) => it as _,
 +                            },
 +                            |it| it as _,
 +                        )),
 +                    )
 +                }
 +                GenericParamId::TypeParamId(it) => {
 +                    let src = it.parent().child_source(db);
 +                    RawAttrs::from_attrs_owner(
 +                        db,
 +                        src.with_value(src.value[it.local_id()].as_ref().either(
 +                            |it| match it {
 +                                ast::TypeOrConstParam::Type(it) => it as _,
 +                                ast::TypeOrConstParam::Const(it) => it as _,
 +                            },
 +                            |it| it as _,
 +                        )),
 +                    )
 +                }
 +                GenericParamId::LifetimeParamId(it) => {
 +                    let src = it.parent.child_source(db);
 +                    RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id]))
 +                }
 +            },
 +            AttrDefId::ExternBlockId(it) => attrs_from_item_tree(it.lookup(db).id, db),
 +        };
 +
 +        let attrs = raw_attrs.filter(db, def.krate(db));
 +        Self { attrs, owner: def }
 +    }
 +
 +    pub fn source_map(&self, db: &dyn DefDatabase) -> AttrSourceMap {
 +        let owner = match self.owner {
 +            AttrDefId::ModuleId(module) => {
 +                // Modules can have 2 attribute owners (the `mod x;` item, and the module file itself).
 +
 +                let def_map = module.def_map(db);
 +                let mod_data = &def_map[module.local_id];
 +                match mod_data.declaration_source(db) {
 +                    Some(it) => {
 +                        let mut map = AttrSourceMap::new(InFile::new(it.file_id, &it.value));
 +                        if let InFile { file_id, value: ModuleSource::SourceFile(file) } =
 +                            mod_data.definition_source(db)
 +                        {
 +                            map.append_module_inline_attrs(AttrSourceMap::new(InFile::new(
 +                                file_id, &file,
 +                            )));
 +                        }
 +                        return map;
 +                    }
 +                    None => {
 +                        let InFile { file_id, value } = mod_data.definition_source(db);
 +                        let attrs_owner = match &value {
 +                            ModuleSource::SourceFile(file) => file as &dyn ast::HasAttrs,
 +                            ModuleSource::Module(module) => module as &dyn ast::HasAttrs,
 +                            ModuleSource::BlockExpr(block) => block as &dyn ast::HasAttrs,
 +                        };
 +                        return AttrSourceMap::new(InFile::new(file_id, attrs_owner));
 +                    }
 +                }
 +            }
 +            AttrDefId::FieldId(id) => {
 +                let map = db.fields_attrs_source_map(id.parent);
 +                let file_id = id.parent.file_id(db);
 +                let root = db.parse_or_expand(file_id).unwrap();
 +                let owner = match &map[id.local_id] {
 +                    Either::Left(it) => ast::AnyHasAttrs::new(it.to_node(&root)),
 +                    Either::Right(it) => ast::AnyHasAttrs::new(it.to_node(&root)),
 +                };
 +                InFile::new(file_id, owner)
 +            }
 +            AttrDefId::AdtId(adt) => match adt {
 +                AdtId::StructId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +                AdtId::UnionId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +                AdtId::EnumId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +            },
 +            AttrDefId::FunctionId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +            AttrDefId::EnumVariantId(id) => {
 +                let map = db.variants_attrs_source_map(id.parent);
 +                let file_id = id.parent.lookup(db).id.file_id();
 +                let root = db.parse_or_expand(file_id).unwrap();
 +                InFile::new(file_id, ast::AnyHasAttrs::new(map[id.local_id].to_node(&root)))
 +            }
 +            AttrDefId::StaticId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +            AttrDefId::ConstId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +            AttrDefId::TraitId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +            AttrDefId::TypeAliasId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +            AttrDefId::MacroId(id) => match id {
 +                MacroId::Macro2Id(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +                MacroId::MacroRulesId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +                MacroId::ProcMacroId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +            },
 +            AttrDefId::ImplId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +            AttrDefId::GenericParamId(id) => match id {
 +                GenericParamId::ConstParamId(id) => {
 +                    id.parent().child_source(db).map(|source| match &source[id.local_id()] {
 +                        Either::Left(ast::TypeOrConstParam::Type(id)) => {
 +                            ast::AnyHasAttrs::new(id.clone())
 +                        }
 +                        Either::Left(ast::TypeOrConstParam::Const(id)) => {
 +                            ast::AnyHasAttrs::new(id.clone())
 +                        }
 +                        Either::Right(id) => ast::AnyHasAttrs::new(id.clone()),
 +                    })
 +                }
 +                GenericParamId::TypeParamId(id) => {
 +                    id.parent().child_source(db).map(|source| match &source[id.local_id()] {
 +                        Either::Left(ast::TypeOrConstParam::Type(id)) => {
 +                            ast::AnyHasAttrs::new(id.clone())
 +                        }
 +                        Either::Left(ast::TypeOrConstParam::Const(id)) => {
 +                            ast::AnyHasAttrs::new(id.clone())
 +                        }
 +                        Either::Right(id) => ast::AnyHasAttrs::new(id.clone()),
 +                    })
 +                }
 +                GenericParamId::LifetimeParamId(id) => id
 +                    .parent
 +                    .child_source(db)
 +                    .map(|source| ast::AnyHasAttrs::new(source[id.local_id].clone())),
 +            },
 +            AttrDefId::ExternBlockId(id) => id.lookup(db).source(db).map(ast::AnyHasAttrs::new),
 +        };
 +
 +        AttrSourceMap::new(owner.as_ref().map(|node| node as &dyn HasAttrs))
 +    }
 +
 +    pub fn docs_with_rangemap(
 +        &self,
 +        db: &dyn DefDatabase,
 +    ) -> Option<(Documentation, DocsRangeMap)> {
 +        let docs =
 +            self.by_key("doc").attrs().filter_map(|attr| attr.string_value().map(|s| (s, attr.id)));
 +        let indent = doc_indent(self);
 +        let mut buf = String::new();
 +        let mut mapping = Vec::new();
 +        for (doc, idx) in docs {
 +            if !doc.is_empty() {
 +                let mut base_offset = 0;
 +                for raw_line in doc.split('\n') {
 +                    let line = raw_line.trim_end();
 +                    let line_len = line.len();
 +                    let (offset, line) = match line.char_indices().nth(indent) {
 +                        Some((offset, _)) => (offset, &line[offset..]),
 +                        None => (0, line),
 +                    };
 +                    let buf_offset = buf.len();
 +                    buf.push_str(line);
 +                    mapping.push((
 +                        TextRange::new(buf_offset.try_into().ok()?, buf.len().try_into().ok()?),
 +                        idx,
 +                        TextRange::at(
 +                            (base_offset + offset).try_into().ok()?,
 +                            line_len.try_into().ok()?,
 +                        ),
 +                    ));
 +                    buf.push('\n');
 +                    base_offset += raw_line.len() + 1;
 +                }
 +            } else {
 +                buf.push('\n');
 +            }
 +        }
 +        buf.pop();
 +        if buf.is_empty() {
 +            None
 +        } else {
 +            Some((Documentation(buf), DocsRangeMap { mapping, source_map: self.source_map(db) }))
 +        }
 +    }
 +}
 +
 +fn doc_indent(attrs: &Attrs) -> usize {
 +    attrs
 +        .by_key("doc")
 +        .attrs()
 +        .filter_map(|attr| attr.string_value())
 +        .flat_map(|s| s.lines())
 +        .filter(|line| !line.chars().all(|c| c.is_whitespace()))
 +        .map(|line| line.chars().take_while(|c| c.is_whitespace()).count())
 +        .min()
 +        .unwrap_or(0)
 +}
 +
 +fn inner_attributes(
 +    syntax: &SyntaxNode,
 +) -> Option<impl Iterator<Item = Either<ast::Attr, ast::Comment>>> {
 +    let node = match_ast! {
 +        match syntax {
 +            ast::SourceFile(_) => syntax.clone(),
 +            ast::ExternBlock(it) => it.extern_item_list()?.syntax().clone(),
 +            ast::Fn(it) => it.body()?.stmt_list()?.syntax().clone(),
 +            ast::Impl(it) => it.assoc_item_list()?.syntax().clone(),
 +            ast::Module(it) => it.item_list()?.syntax().clone(),
 +            ast::BlockExpr(it) => {
 +                use syntax::SyntaxKind::{BLOCK_EXPR , EXPR_STMT};
 +                // Block expressions accept outer and inner attributes, but only when they are the outer
 +                // expression of an expression statement or the final expression of another block expression.
 +                let may_carry_attributes = matches!(
 +                    it.syntax().parent().map(|it| it.kind()),
 +                     Some(BLOCK_EXPR | EXPR_STMT)
 +                );
 +                if !may_carry_attributes {
 +                    return None
 +                }
 +                syntax.clone()
 +            },
 +            _ => return None,
 +        }
 +    };
 +
 +    let attrs = ast::AttrDocCommentIter::from_syntax_node(&node).filter(|el| match el {
 +        Either::Left(attr) => attr.kind().is_inner(),
 +        Either::Right(comment) => comment.is_inner(),
 +    });
 +    Some(attrs)
 +}
 +
 +#[derive(Debug)]
 +pub struct AttrSourceMap {
 +    source: Vec<Either<ast::Attr, ast::Comment>>,
 +    file_id: HirFileId,
 +    /// If this map is for a module, this will be the [`HirFileId`] of the module's definition site,
 +    /// while `file_id` will be the one of the module declaration site.
 +    /// The usize is the index into `source` from which point on the entries reside in the def site
 +    /// file.
 +    mod_def_site_file_id: Option<(HirFileId, usize)>,
 +}
 +
 +impl AttrSourceMap {
 +    fn new(owner: InFile<&dyn ast::HasAttrs>) -> Self {
 +        Self {
 +            source: collect_attrs(owner.value).map(|(_, it)| it).collect(),
 +            file_id: owner.file_id,
 +            mod_def_site_file_id: None,
 +        }
 +    }
 +
 +    /// Append a second source map to this one, this is required for modules, whose outline and inline
 +    /// attributes can reside in different files
 +    fn append_module_inline_attrs(&mut self, other: Self) {
 +        assert!(self.mod_def_site_file_id.is_none() && other.mod_def_site_file_id.is_none());
 +        let len = self.source.len();
 +        self.source.extend(other.source);
 +        if other.file_id != self.file_id {
 +            self.mod_def_site_file_id = Some((other.file_id, len));
 +        }
 +    }
 +
 +    /// Maps the lowered `Attr` back to its original syntax node.
 +    ///
 +    /// `attr` must come from the `owner` used for AttrSourceMap
 +    ///
 +    /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of
 +    /// the attribute represented by `Attr`.
 +    pub fn source_of(&self, attr: &Attr) -> InFile<&Either<ast::Attr, ast::Comment>> {
 +        self.source_of_id(attr.id)
 +    }
 +
 +    fn source_of_id(&self, id: AttrId) -> InFile<&Either<ast::Attr, ast::Comment>> {
 +        let ast_idx = id.ast_index as usize;
 +        let file_id = match self.mod_def_site_file_id {
 +            Some((file_id, def_site_cut)) if def_site_cut <= ast_idx => file_id,
 +            _ => self.file_id,
 +        };
 +
 +        self.source
 +            .get(ast_idx)
 +            .map(|it| InFile::new(file_id, it))
 +            .unwrap_or_else(|| panic!("cannot find attr at index {:?}", id))
 +    }
 +}
 +
 +/// A struct to map text ranges from [`Documentation`] back to TextRanges in the syntax tree.
 +#[derive(Debug)]
 +pub struct DocsRangeMap {
 +    source_map: AttrSourceMap,
 +    // (docstring-line-range, attr_index, attr-string-range)
 +    // a mapping from the text range of a line of the [`Documentation`] to the attribute index and
 +    // the original (untrimmed) syntax doc line
 +    mapping: Vec<(TextRange, AttrId, TextRange)>,
 +}
 +
 +impl DocsRangeMap {
 +    /// Maps a [`TextRange`] relative to the documentation string back to its AST range
 +    pub fn map(&self, range: TextRange) -> Option<InFile<TextRange>> {
 +        let found = self.mapping.binary_search_by(|(probe, ..)| probe.ordering(range)).ok()?;
 +        let (line_docs_range, idx, original_line_src_range) = self.mapping[found];
 +        if !line_docs_range.contains_range(range) {
 +            return None;
 +        }
 +
 +        let relative_range = range - line_docs_range.start();
 +
 +        let InFile { file_id, value: source } = self.source_map.source_of_id(idx);
 +        match source {
 +            Either::Left(attr) => {
 +                let string = get_doc_string_in_attr(attr)?;
 +                let text_range = string.open_quote_text_range()?;
 +                let range = TextRange::at(
 +                    text_range.end() + original_line_src_range.start() + relative_range.start(),
 +                    string.syntax().text_range().len().min(range.len()),
 +                );
 +                Some(InFile { file_id, value: range })
 +            }
 +            Either::Right(comment) => {
 +                let text_range = comment.syntax().text_range();
 +                let range = TextRange::at(
 +                    text_range.start()
 +                        + TextSize::try_from(comment.prefix().len()).ok()?
 +                        + original_line_src_range.start()
 +                        + relative_range.start(),
 +                    text_range.len().min(range.len()),
 +                );
 +                Some(InFile { file_id, value: range })
 +            }
 +        }
 +    }
 +}
 +
 +fn get_doc_string_in_attr(it: &ast::Attr) -> Option<ast::String> {
 +    match it.expr() {
 +        // #[doc = lit]
 +        Some(ast::Expr::Literal(lit)) => match lit.kind() {
 +            ast::LiteralKind::String(it) => Some(it),
 +            _ => None,
 +        },
 +        // #[cfg_attr(..., doc = "", ...)]
 +        None => {
 +            // FIXME: See highlight injection for what to do here
 +            None
 +        }
 +        _ => None,
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct AttrId {
 +    pub(crate) ast_index: u32,
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq)]
 +pub struct Attr {
 +    pub(crate) id: AttrId,
 +    pub(crate) path: Interned<ModPath>,
 +    pub(crate) input: Option<Interned<AttrInput>>,
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub enum AttrInput {
 +    /// `#[attr = "string"]`
 +    Literal(SmolStr),
 +    /// `#[attr(subtree)]`
 +    TokenTree(tt::Subtree, mbe::TokenMap),
 +}
 +
 +impl fmt::Display for AttrInput {
 +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 +        match self {
 +            AttrInput::Literal(lit) => write!(f, " = \"{}\"", lit.escape_debug()),
 +            AttrInput::TokenTree(subtree, _) => subtree.fmt(f),
 +        }
 +    }
 +}
 +
 +impl Attr {
 +    fn from_src(
 +        db: &dyn DefDatabase,
 +        ast: ast::Meta,
 +        hygiene: &Hygiene,
 +        id: AttrId,
 +    ) -> Option<Attr> {
 +        let path = Interned::new(ModPath::from_src(db.upcast(), ast.path()?, hygiene)?);
 +        let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
 +            let value = match lit.kind() {
 +                ast::LiteralKind::String(string) => string.value()?.into(),
 +                _ => lit.syntax().first_token()?.text().trim_matches('"').into(),
 +            };
 +            Some(Interned::new(AttrInput::Literal(value)))
 +        } else if let Some(tt) = ast.token_tree() {
 +            let (tree, map) = syntax_node_to_token_tree(tt.syntax());
 +            Some(Interned::new(AttrInput::TokenTree(tree, map)))
 +        } else {
 +            None
 +        };
 +        Some(Attr { id, path, input })
 +    }
 +
 +    fn from_tt(
 +        db: &dyn DefDatabase,
 +        tt: &tt::Subtree,
 +        hygiene: &Hygiene,
 +        id: AttrId,
 +    ) -> Option<Attr> {
 +        let (parse, _) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MetaItem);
 +        let ast = ast::Meta::cast(parse.syntax_node())?;
 +
 +        Self::from_src(db, ast, hygiene, id)
 +    }
 +
 +    pub fn path(&self) -> &ModPath {
 +        &self.path
 +    }
 +}
 +
 +impl Attr {
 +    /// #[path = "string"]
 +    pub fn string_value(&self) -> Option<&SmolStr> {
 +        match self.input.as_deref()? {
 +            AttrInput::Literal(it) => Some(it),
 +            _ => None,
 +        }
 +    }
 +
 +    /// #[path(ident)]
 +    pub fn single_ident_value(&self) -> Option<&tt::Ident> {
 +        match self.input.as_deref()? {
 +            AttrInput::TokenTree(subtree, _) => match &*subtree.token_trees {
 +                [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] => Some(ident),
 +                _ => None,
 +            },
 +            _ => None,
 +        }
 +    }
 +
 +    /// #[path TokenTree]
 +    pub fn token_tree_value(&self) -> Option<&Subtree> {
 +        match self.input.as_deref()? {
 +            AttrInput::TokenTree(subtree, _) => Some(subtree),
 +            _ => None,
 +        }
 +    }
 +
 +    /// Parses this attribute as a token tree consisting of comma separated paths.
 +    pub fn parse_path_comma_token_tree(&self) -> Option<impl Iterator<Item = ModPath> + '_> {
 +        let args = self.token_tree_value()?;
 +
 +        if args.delimiter_kind() != Some(DelimiterKind::Parenthesis) {
 +            return None;
 +        }
 +        let paths = args
 +            .token_trees
 +            .split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))))
 +            .filter_map(|tts| {
 +                if tts.is_empty() {
 +                    return None;
 +                }
 +                let segments = tts.iter().filter_map(|tt| match tt {
 +                    tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
 +                    _ => None,
 +                });
 +                Some(ModPath::from_segments(PathKind::Plain, segments))
 +            });
 +
 +        Some(paths)
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy)]
 +pub struct AttrQuery<'attr> {
 +    attrs: &'attr Attrs,
 +    key: &'static str,
 +}
 +
 +impl<'attr> AttrQuery<'attr> {
 +    pub fn tt_values(self) -> impl Iterator<Item = &'attr Subtree> {
 +        self.attrs().filter_map(|attr| attr.token_tree_value())
 +    }
 +
 +    pub fn string_value(self) -> Option<&'attr SmolStr> {
 +        self.attrs().find_map(|attr| attr.string_value())
 +    }
 +
 +    pub fn exists(self) -> bool {
 +        self.attrs().next().is_some()
 +    }
 +
 +    pub fn attrs(self) -> impl Iterator<Item = &'attr Attr> + Clone {
 +        let key = self.key;
 +        self.attrs
 +            .iter()
 +            .filter(move |attr| attr.path.as_ident().map_or(false, |s| s.to_smol_str() == key))
 +    }
 +
 +    /// Find string value for a specific key inside token tree
 +    ///
 +    /// ```ignore
 +    /// #[doc(html_root_url = "url")]
 +    ///       ^^^^^^^^^^^^^ key
 +    /// ```
 +    pub fn find_string_value_in_tt(self, key: &'attr str) -> Option<&SmolStr> {
 +        self.tt_values().find_map(|tt| {
 +            let name = tt.token_trees.iter()
 +                .skip_while(|tt| !matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Ident(tt::Ident { text, ..} )) if text == key))
 +                .nth(2);
 +
 +            match name {
 +                Some(tt::TokenTree::Leaf(tt::Leaf::Literal(tt::Literal{ref text, ..}))) => Some(text),
 +                _ => None
 +            }
 +        })
 +    }
 +}
 +
 +fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> RawAttrs {
 +    let tree = id.item_tree(db);
 +    let mod_item = N::id_to_mod_item(id.value);
 +    tree.raw_attrs(mod_item.into()).clone()
 +}
 +
 +fn collect_attrs(
 +    owner: &dyn ast::HasAttrs,
 +) -> impl Iterator<Item = (AttrId, Either<ast::Attr, ast::Comment>)> {
 +    let inner_attrs = inner_attributes(owner.syntax()).into_iter().flatten();
 +    let outer_attrs =
 +        ast::AttrDocCommentIter::from_syntax_node(owner.syntax()).filter(|el| match el {
 +            Either::Left(attr) => attr.kind().is_outer(),
 +            Either::Right(comment) => comment.is_outer(),
 +        });
 +    outer_attrs
 +        .chain(inner_attrs)
 +        .enumerate()
 +        .map(|(id, attr)| (AttrId { ast_index: id as u32 }, attr))
 +}
 +
 +pub(crate) fn variants_attrs_source_map(
 +    db: &dyn DefDatabase,
 +    def: EnumId,
 +) -> Arc<ArenaMap<LocalEnumVariantId, AstPtr<ast::Variant>>> {
 +    let mut res = ArenaMap::default();
 +    let child_source = def.child_source(db);
 +
 +    for (idx, variant) in child_source.value.iter() {
 +        res.insert(idx, AstPtr::new(variant));
 +    }
 +
 +    Arc::new(res)
 +}
 +
 +pub(crate) fn fields_attrs_source_map(
 +    db: &dyn DefDatabase,
 +    def: VariantId,
 +) -> Arc<ArenaMap<LocalFieldId, Either<AstPtr<ast::TupleField>, AstPtr<ast::RecordField>>>> {
 +    let mut res = ArenaMap::default();
 +    let child_source = def.child_source(db);
 +
 +    for (idx, variant) in child_source.value.iter() {
 +        res.insert(
 +            idx,
 +            variant
 +                .as_ref()
 +                .either(|l| Either::Left(AstPtr::new(l)), |r| Either::Right(AstPtr::new(r))),
 +        );
 +    }
 +
 +    Arc::new(res)
 +}
index 579f803ea193ac94b3f4f998955e9cbf5a44ccc2,0000000000000000000000000000000000000000..a11a92204c15c29c788a4d134e71e681595e466c
mode 100644,000000..100644
--- /dev/null
@@@ -1,464 -1,0 +1,464 @@@
-         let keys: FxHashSet<_> = self
-             .types
 +//! Describes items defined or visible (ie, imported) in a certain scope.
 +//! This is shared between modules and blocks.
 +
 +use std::collections::hash_map::Entry;
 +
 +use base_db::CrateId;
 +use hir_expand::{name::Name, AstId, MacroCallId};
++use itertools::Itertools;
 +use once_cell::sync::Lazy;
 +use profile::Count;
 +use rustc_hash::{FxHashMap, FxHashSet};
 +use smallvec::{smallvec, SmallVec};
 +use stdx::format_to;
 +use syntax::ast;
 +
 +use crate::{
 +    attr::AttrId, db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType,
 +    ConstId, HasModule, ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId,
 +};
 +
 +#[derive(Copy, Clone)]
 +pub(crate) enum ImportType {
 +    Glob,
 +    Named,
 +}
 +
 +#[derive(Debug, Default)]
 +pub struct PerNsGlobImports {
 +    types: FxHashSet<(LocalModuleId, Name)>,
 +    values: FxHashSet<(LocalModuleId, Name)>,
 +    macros: FxHashSet<(LocalModuleId, Name)>,
 +}
 +
 +#[derive(Debug, Default, PartialEq, Eq)]
 +pub struct ItemScope {
 +    _c: Count<Self>,
 +
 +    /// Defs visible in this scope. This includes `declarations`, but also
 +    /// imports.
 +    types: FxHashMap<Name, (ModuleDefId, Visibility)>,
 +    values: FxHashMap<Name, (ModuleDefId, Visibility)>,
 +    macros: FxHashMap<Name, (MacroId, Visibility)>,
 +    unresolved: FxHashSet<Name>,
 +
 +    /// The defs declared in this scope. Each def has a single scope where it is
 +    /// declared.
 +    declarations: Vec<ModuleDefId>,
 +
 +    impls: Vec<ImplId>,
 +    unnamed_consts: Vec<ConstId>,
 +    /// Traits imported via `use Trait as _;`.
 +    unnamed_trait_imports: FxHashMap<TraitId, Visibility>,
 +    /// Macros visible in current module in legacy textual scope
 +    ///
 +    /// For macros invoked by an unqualified identifier like `bar!()`, `legacy_macros` will be searched in first.
 +    /// If it yields no result, then it turns to module scoped `macros`.
 +    /// It macros with name qualified with a path like `crate::foo::bar!()`, `legacy_macros` will be skipped,
 +    /// and only normal scoped `macros` will be searched in.
 +    ///
 +    /// Note that this automatically inherit macros defined textually before the definition of module itself.
 +    ///
 +    /// Module scoped macros will be inserted into `items` instead of here.
 +    // FIXME: Macro shadowing in one module is not properly handled. Non-item place macros will
 +    // be all resolved to the last one defined if shadowing happens.
 +    legacy_macros: FxHashMap<Name, SmallVec<[MacroId; 1]>>,
 +    /// The derive macro invocations in this scope.
 +    attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
 +    /// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
 +    /// paired with the derive macro invocations for the specific attribute.
 +    derive_macros: FxHashMap<AstId<ast::Adt>, SmallVec<[DeriveMacroInvocation; 1]>>,
 +}
 +
 +#[derive(Debug, PartialEq, Eq)]
 +struct DeriveMacroInvocation {
 +    attr_id: AttrId,
 +    attr_call_id: MacroCallId,
 +    derive_call_ids: SmallVec<[Option<MacroCallId>; 1]>,
 +}
 +
 +pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
 +    BuiltinType::ALL
 +        .iter()
 +        .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public)))
 +        .collect()
 +});
 +
 +/// Shadow mode for builtin type which can be shadowed by module.
 +#[derive(Debug, Copy, Clone, PartialEq, Eq)]
 +pub(crate) enum BuiltinShadowMode {
 +    /// Prefer user-defined modules (or other types) over builtins.
 +    Module,
 +    /// Prefer builtins over user-defined modules (but not other types).
 +    Other,
 +}
 +
 +/// Legacy macros can only be accessed through special methods like `get_legacy_macros`.
 +/// Other methods will only resolve values, types and module scoped macros only.
 +impl ItemScope {
 +    pub fn entries<'a>(&'a self) -> impl Iterator<Item = (&'a Name, PerNs)> + 'a {
 +        // FIXME: shadowing
-             .collect();
-         keys.into_iter().map(move |name| (name, self.get(name)))
++        self.types
 +            .keys()
 +            .chain(self.values.keys())
 +            .chain(self.macros.keys())
 +            .chain(self.unresolved.iter())
++            .sorted()
++            .unique()
++            .map(move |name| (name, self.get(name)))
 +    }
 +
 +    pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
 +        self.declarations.iter().copied()
 +    }
 +
 +    pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
 +        self.impls.iter().copied()
 +    }
 +
 +    pub fn values(
 +        &self,
 +    ) -> impl Iterator<Item = (ModuleDefId, Visibility)> + ExactSizeIterator + '_ {
 +        self.values.values().copied()
 +    }
 +
 +    pub fn types(
 +        &self,
 +    ) -> impl Iterator<Item = (ModuleDefId, Visibility)> + ExactSizeIterator + '_ {
 +        self.types.values().copied()
 +    }
 +
 +    pub fn unnamed_consts(&self) -> impl Iterator<Item = ConstId> + '_ {
 +        self.unnamed_consts.iter().copied()
 +    }
 +
 +    /// Iterate over all module scoped macros
 +    pub(crate) fn macros(&self) -> impl Iterator<Item = (&Name, MacroId)> + '_ {
 +        self.entries().filter_map(|(name, def)| def.take_macros().map(|macro_| (name, macro_)))
 +    }
 +
 +    /// Iterate over all legacy textual scoped macros visible at the end of the module
 +    pub fn legacy_macros(&self) -> impl Iterator<Item = (&Name, &[MacroId])> + '_ {
 +        self.legacy_macros.iter().map(|(name, def)| (name, &**def))
 +    }
 +
 +    /// Get a name from current module scope, legacy macros are not included
 +    pub(crate) fn get(&self, name: &Name) -> PerNs {
 +        PerNs {
 +            types: self.types.get(name).copied(),
 +            values: self.values.get(name).copied(),
 +            macros: self.macros.get(name).copied(),
 +        }
 +    }
 +
 +    pub(crate) fn type_(&self, name: &Name) -> Option<(ModuleDefId, Visibility)> {
 +        self.types.get(name).copied()
 +    }
 +
 +    /// XXX: this is O(N) rather than O(1), try to not introduce new usages.
 +    pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> {
 +        let (def, mut iter) = match item {
 +            ItemInNs::Macros(def) => {
 +                return self
 +                    .macros
 +                    .iter()
 +                    .find_map(|(name, &(other_def, vis))| (other_def == def).then(|| (name, vis)));
 +            }
 +            ItemInNs::Types(def) => (def, self.types.iter()),
 +            ItemInNs::Values(def) => (def, self.values.iter()),
 +        };
 +        iter.find_map(|(name, &(other_def, vis))| (other_def == def).then(|| (name, vis)))
 +    }
 +
 +    pub(crate) fn traits<'a>(&'a self) -> impl Iterator<Item = TraitId> + 'a {
 +        self.types
 +            .values()
 +            .filter_map(|&(def, _)| match def {
 +                ModuleDefId::TraitId(t) => Some(t),
 +                _ => None,
 +            })
 +            .chain(self.unnamed_trait_imports.keys().copied())
 +    }
 +
 +    pub(crate) fn declare(&mut self, def: ModuleDefId) {
 +        self.declarations.push(def)
 +    }
 +
 +    pub(crate) fn get_legacy_macro(&self, name: &Name) -> Option<&[MacroId]> {
 +        self.legacy_macros.get(name).map(|it| &**it)
 +    }
 +
 +    pub(crate) fn define_impl(&mut self, imp: ImplId) {
 +        self.impls.push(imp)
 +    }
 +
 +    pub(crate) fn define_unnamed_const(&mut self, konst: ConstId) {
 +        self.unnamed_consts.push(konst);
 +    }
 +
 +    pub(crate) fn define_legacy_macro(&mut self, name: Name, mac: MacroId) {
 +        self.legacy_macros.entry(name).or_default().push(mac);
 +    }
 +
 +    pub(crate) fn add_attr_macro_invoc(&mut self, item: AstId<ast::Item>, call: MacroCallId) {
 +        self.attr_macros.insert(item, call);
 +    }
 +
 +    pub(crate) fn attr_macro_invocs(
 +        &self,
 +    ) -> impl Iterator<Item = (AstId<ast::Item>, MacroCallId)> + '_ {
 +        self.attr_macros.iter().map(|(k, v)| (*k, *v))
 +    }
 +
 +    pub(crate) fn set_derive_macro_invoc(
 +        &mut self,
 +        adt: AstId<ast::Adt>,
 +        call: MacroCallId,
 +        id: AttrId,
 +        idx: usize,
 +    ) {
 +        if let Some(derives) = self.derive_macros.get_mut(&adt) {
 +            if let Some(DeriveMacroInvocation { derive_call_ids, .. }) =
 +                derives.iter_mut().find(|&&mut DeriveMacroInvocation { attr_id, .. }| id == attr_id)
 +            {
 +                derive_call_ids[idx] = Some(call);
 +            }
 +        }
 +    }
 +
 +    /// We are required to set this up front as derive invocation recording happens out of order
 +    /// due to the fixed pointer iteration loop being able to record some derives later than others
 +    /// independent of their indices.
 +    pub(crate) fn init_derive_attribute(
 +        &mut self,
 +        adt: AstId<ast::Adt>,
 +        attr_id: AttrId,
 +        attr_call_id: MacroCallId,
 +        len: usize,
 +    ) {
 +        self.derive_macros.entry(adt).or_default().push(DeriveMacroInvocation {
 +            attr_id,
 +            attr_call_id,
 +            derive_call_ids: smallvec![None; len],
 +        });
 +    }
 +
 +    pub(crate) fn derive_macro_invocs(
 +        &self,
 +    ) -> impl Iterator<
 +        Item = (
 +            AstId<ast::Adt>,
 +            impl Iterator<Item = (AttrId, MacroCallId, &[Option<MacroCallId>])>,
 +        ),
 +    > + '_ {
 +        self.derive_macros.iter().map(|(k, v)| {
 +            (
 +                *k,
 +                v.iter().map(|DeriveMacroInvocation { attr_id, attr_call_id, derive_call_ids }| {
 +                    (*attr_id, *attr_call_id, &**derive_call_ids)
 +                }),
 +            )
 +        })
 +    }
 +
 +    pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {
 +        self.unnamed_trait_imports.get(&tr).copied()
 +    }
 +
 +    pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) {
 +        self.unnamed_trait_imports.insert(tr, vis);
 +    }
 +
 +    pub(crate) fn push_res_with_import(
 +        &mut self,
 +        glob_imports: &mut PerNsGlobImports,
 +        lookup: (LocalModuleId, Name),
 +        def: PerNs,
 +        def_import_type: ImportType,
 +    ) -> bool {
 +        let mut changed = false;
 +
 +        macro_rules! check_changed {
 +            (
 +                $changed:ident,
 +                ( $this:ident / $def:ident ) . $field:ident,
 +                $glob_imports:ident [ $lookup:ident ],
 +                $def_import_type:ident
 +            ) => {{
 +                if let Some(fld) = $def.$field {
 +                    let existing = $this.$field.entry($lookup.1.clone());
 +                    match existing {
 +                        Entry::Vacant(entry) => {
 +                            match $def_import_type {
 +                                ImportType::Glob => {
 +                                    $glob_imports.$field.insert($lookup.clone());
 +                                }
 +                                ImportType::Named => {
 +                                    $glob_imports.$field.remove(&$lookup);
 +                                }
 +                            }
 +
 +                            entry.insert(fld);
 +                            $changed = true;
 +                        }
 +                        Entry::Occupied(mut entry)
 +                            if $glob_imports.$field.contains(&$lookup)
 +                                && matches!($def_import_type, ImportType::Named) =>
 +                        {
 +                            cov_mark::hit!(import_shadowed);
 +                            $glob_imports.$field.remove(&$lookup);
 +                            entry.insert(fld);
 +                            $changed = true;
 +                        }
 +                        _ => {}
 +                    }
 +                }
 +            }};
 +        }
 +
 +        check_changed!(changed, (self / def).types, glob_imports[lookup], def_import_type);
 +        check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type);
 +        check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type);
 +
 +        if def.is_none() && self.unresolved.insert(lookup.1) {
 +            changed = true;
 +        }
 +
 +        changed
 +    }
 +
 +    pub(crate) fn resolutions<'a>(&'a self) -> impl Iterator<Item = (Option<Name>, PerNs)> + 'a {
 +        self.entries().map(|(name, res)| (Some(name.clone()), res)).chain(
 +            self.unnamed_trait_imports
 +                .iter()
 +                .map(|(tr, vis)| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))),
 +        )
 +    }
 +
 +    pub(crate) fn collect_legacy_macros(&self) -> FxHashMap<Name, SmallVec<[MacroId; 1]>> {
 +        self.legacy_macros.clone()
 +    }
 +
 +    /// Marks everything that is not a procedural macro as private to `this_module`.
 +    pub(crate) fn censor_non_proc_macros(&mut self, this_module: ModuleId) {
 +        self.types
 +            .values_mut()
 +            .chain(self.values.values_mut())
 +            .map(|(_, v)| v)
 +            .chain(self.unnamed_trait_imports.values_mut())
 +            .for_each(|vis| *vis = Visibility::Module(this_module));
 +
 +        for (mac, vis) in self.macros.values_mut() {
 +            if let MacroId::ProcMacroId(_) = mac {
 +                // FIXME: Technically this is insufficient since reexports of proc macros are also
 +                // forbidden. Practically nobody does that.
 +                continue;
 +            }
 +
 +            *vis = Visibility::Module(this_module);
 +        }
 +    }
 +
 +    pub(crate) fn dump(&self, buf: &mut String) {
 +        let mut entries: Vec<_> = self.resolutions().collect();
 +        entries.sort_by_key(|(name, _)| name.clone());
 +
 +        for (name, def) in entries {
 +            format_to!(buf, "{}:", name.map_or("_".to_string(), |name| name.to_string()));
 +
 +            if def.types.is_some() {
 +                buf.push_str(" t");
 +            }
 +            if def.values.is_some() {
 +                buf.push_str(" v");
 +            }
 +            if def.macros.is_some() {
 +                buf.push_str(" m");
 +            }
 +            if def.is_none() {
 +                buf.push_str(" _");
 +            }
 +
 +            buf.push('\n');
 +        }
 +    }
 +
 +    pub(crate) fn shrink_to_fit(&mut self) {
 +        // Exhaustive match to require handling new fields.
 +        let Self {
 +            _c: _,
 +            types,
 +            values,
 +            macros,
 +            unresolved,
 +            declarations,
 +            impls,
 +            unnamed_consts,
 +            unnamed_trait_imports,
 +            legacy_macros,
 +            attr_macros,
 +            derive_macros,
 +        } = self;
 +        types.shrink_to_fit();
 +        values.shrink_to_fit();
 +        macros.shrink_to_fit();
 +        unresolved.shrink_to_fit();
 +        declarations.shrink_to_fit();
 +        impls.shrink_to_fit();
 +        unnamed_consts.shrink_to_fit();
 +        unnamed_trait_imports.shrink_to_fit();
 +        legacy_macros.shrink_to_fit();
 +        attr_macros.shrink_to_fit();
 +        derive_macros.shrink_to_fit();
 +    }
 +}
 +
 +impl PerNs {
 +    pub(crate) fn from_def(def: ModuleDefId, v: Visibility, has_constructor: bool) -> PerNs {
 +        match def {
 +            ModuleDefId::ModuleId(_) => PerNs::types(def, v),
 +            ModuleDefId::FunctionId(_) => PerNs::values(def, v),
 +            ModuleDefId::AdtId(adt) => match adt {
 +                AdtId::UnionId(_) => PerNs::types(def, v),
 +                AdtId::EnumId(_) => PerNs::types(def, v),
 +                AdtId::StructId(_) => {
 +                    if has_constructor {
 +                        PerNs::both(def, def, v)
 +                    } else {
 +                        PerNs::types(def, v)
 +                    }
 +                }
 +            },
 +            ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v),
 +            ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v),
 +            ModuleDefId::TraitId(_) => PerNs::types(def, v),
 +            ModuleDefId::TypeAliasId(_) => PerNs::types(def, v),
 +            ModuleDefId::BuiltinType(_) => PerNs::types(def, v),
 +            ModuleDefId::MacroId(mac) => PerNs::macros(mac, v),
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
 +pub enum ItemInNs {
 +    Types(ModuleDefId),
 +    Values(ModuleDefId),
 +    Macros(MacroId),
 +}
 +
 +impl ItemInNs {
 +    pub fn as_module_def_id(self) -> Option<ModuleDefId> {
 +        match self {
 +            ItemInNs::Types(id) | ItemInNs::Values(id) => Some(id),
 +            ItemInNs::Macros(_) => None,
 +        }
 +    }
 +
 +    /// Returns the crate defining this item (or `None` if `self` is built-in).
 +    pub fn krate(&self, db: &dyn DefDatabase) -> Option<CrateId> {
 +        match self {
 +            ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate),
 +            ItemInNs::Macros(id) => Some(id.module(db).krate),
 +        }
 +    }
 +}
index f394c541719f323a42f20bc7765b6a300de8b900,0000000000000000000000000000000000000000..8a6bb929c3df7bd660e2fcd5995b8e38b61bcfc0
mode 100644,000000..100644
--- /dev/null
@@@ -1,2201 -1,0 +1,2202 @@@
-             let resolver2 = |path| {
 +//! The core of the module-level name resolution algorithm.
 +//!
 +//! `DefCollector::collect` contains the fixed-point iteration loop which
 +//! resolves imports and expands macros.
 +
 +use std::{iter, mem};
 +
 +use base_db::{CrateId, Edition, FileId};
 +use cfg::{CfgExpr, CfgOptions};
 +use either::Either;
 +use hir_expand::{
 +    ast_id_map::FileAstId,
 +    builtin_attr_macro::find_builtin_attr,
 +    builtin_derive_macro::find_builtin_derive,
 +    builtin_fn_macro::find_builtin_macro,
 +    name::{name, AsName, Name},
 +    proc_macro::ProcMacroExpander,
 +    ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroCallLoc, MacroDefId,
 +    MacroDefKind,
 +};
 +use itertools::{izip, Itertools};
 +use la_arena::Idx;
 +use limit::Limit;
 +use rustc_hash::{FxHashMap, FxHashSet};
 +use stdx::always;
 +use syntax::{ast, SmolStr};
 +
 +use crate::{
 +    attr::{Attr, AttrId, Attrs},
 +    attr_macro_as_call_id,
 +    db::DefDatabase,
 +    derive_macro_as_call_id,
 +    item_scope::{ImportType, PerNsGlobImports},
 +    item_tree::{
 +        self, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, MacroCall,
 +        MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
 +    },
 +    macro_call_as_call_id, macro_id_to_def_id,
 +    nameres::{
 +        diagnostics::DefDiagnostic,
 +        mod_resolution::ModDir,
 +        path_resolution::ReachedFixedPoint,
 +        proc_macro::{ProcMacroDef, ProcMacroKind},
 +        BuiltinShadowMode, DefMap, ModuleData, ModuleOrigin, ResolveMode,
 +    },
 +    path::{ImportAlias, ModPath, PathKind},
 +    per_ns::PerNs,
 +    visibility::{RawVisibility, Visibility},
 +    AdtId, AstId, AstIdWithPath, ConstLoc, EnumLoc, EnumVariantId, ExternBlockLoc, FunctionId,
 +    FunctionLoc, ImplLoc, Intern, ItemContainerId, LocalModuleId, Macro2Id, Macro2Loc,
 +    MacroExpander, MacroId, MacroRulesId, MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId,
 +    ProcMacroLoc, StaticLoc, StructLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro,
 +};
 +
 +static GLOB_RECURSION_LIMIT: Limit = Limit::new(100);
 +static EXPANSION_DEPTH_LIMIT: Limit = Limit::new(128);
 +static FIXED_POINT_LIMIT: Limit = Limit::new(8192);
 +
 +pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: DefMap, tree_id: TreeId) -> DefMap {
 +    let crate_graph = db.crate_graph();
 +
 +    let mut deps = FxHashMap::default();
 +    // populate external prelude and dependency list
 +    let krate = &crate_graph[def_map.krate];
 +    for dep in &krate.dependencies {
 +        tracing::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
 +        let dep_def_map = db.crate_def_map(dep.crate_id);
 +        let dep_root = dep_def_map.module_id(dep_def_map.root);
 +
 +        deps.insert(dep.as_name(), dep_root.into());
 +
 +        if dep.is_prelude() && !tree_id.is_block() {
 +            def_map.extern_prelude.insert(dep.as_name(), dep_root);
 +        }
 +    }
 +
 +    let cfg_options = &krate.cfg_options;
 +    let proc_macros = match &krate.proc_macro {
 +        Ok(proc_macros) => {
 +            proc_macros
 +                .iter()
 +                .enumerate()
 +                .map(|(idx, it)| {
 +                    // FIXME: a hacky way to create a Name from string.
 +                    let name = tt::Ident { text: it.name.clone(), id: tt::TokenId::unspecified() };
 +                    (
 +                        name.as_name(),
 +                        ProcMacroExpander::new(def_map.krate, base_db::ProcMacroId(idx as u32)),
 +                    )
 +                })
 +                .collect()
 +        }
 +        Err(e) => {
 +            def_map.proc_macro_loading_error = Some(e.clone().into_boxed_str());
 +            Vec::new()
 +        }
 +    };
 +    let is_proc_macro = krate.is_proc_macro;
 +
 +    let mut collector = DefCollector {
 +        db,
 +        def_map,
 +        deps,
 +        glob_imports: FxHashMap::default(),
 +        unresolved_imports: Vec::new(),
 +        indeterminate_imports: Vec::new(),
 +        unresolved_macros: Vec::new(),
 +        mod_dirs: FxHashMap::default(),
 +        cfg_options,
 +        proc_macros,
 +        from_glob_import: Default::default(),
 +        skip_attrs: Default::default(),
 +        is_proc_macro,
 +    };
 +    if tree_id.is_block() {
 +        collector.seed_with_inner(tree_id);
 +    } else {
 +        collector.seed_with_top_level();
 +    }
 +    collector.collect();
 +    let mut def_map = collector.finish();
 +    def_map.shrink_to_fit();
 +    def_map
 +}
 +
 +#[derive(Copy, Clone, Debug, Eq, PartialEq)]
 +enum PartialResolvedImport {
 +    /// None of any namespaces is resolved
 +    Unresolved,
 +    /// One of namespaces is resolved
 +    Indeterminate(PerNs),
 +    /// All namespaces are resolved, OR it comes from other crate
 +    Resolved(PerNs),
 +}
 +
 +impl PartialResolvedImport {
 +    fn namespaces(self) -> PerNs {
 +        match self {
 +            PartialResolvedImport::Unresolved => PerNs::none(),
 +            PartialResolvedImport::Indeterminate(ns) | PartialResolvedImport::Resolved(ns) => ns,
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Debug, Eq, PartialEq)]
 +enum ImportSource {
 +    Import { id: ItemTreeId<item_tree::Import>, use_tree: Idx<ast::UseTree> },
 +    ExternCrate(ItemTreeId<item_tree::ExternCrate>),
 +}
 +
 +#[derive(Debug, Eq, PartialEq)]
 +struct Import {
 +    path: ModPath,
 +    alias: Option<ImportAlias>,
 +    visibility: RawVisibility,
 +    kind: ImportKind,
 +    is_prelude: bool,
 +    is_extern_crate: bool,
 +    is_macro_use: bool,
 +    source: ImportSource,
 +}
 +
 +impl Import {
 +    fn from_use(
 +        db: &dyn DefDatabase,
 +        krate: CrateId,
 +        tree: &ItemTree,
 +        id: ItemTreeId<item_tree::Import>,
 +    ) -> Vec<Self> {
 +        let it = &tree[id.value];
 +        let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
 +        let visibility = &tree[it.visibility];
 +        let is_prelude = attrs.by_key("prelude_import").exists();
 +
 +        let mut res = Vec::new();
 +        it.use_tree.expand(|idx, path, kind, alias| {
 +            res.push(Self {
 +                path,
 +                alias,
 +                visibility: visibility.clone(),
 +                kind,
 +                is_prelude,
 +                is_extern_crate: false,
 +                is_macro_use: false,
 +                source: ImportSource::Import { id, use_tree: idx },
 +            });
 +        });
 +        res
 +    }
 +
 +    fn from_extern_crate(
 +        db: &dyn DefDatabase,
 +        krate: CrateId,
 +        tree: &ItemTree,
 +        id: ItemTreeId<item_tree::ExternCrate>,
 +    ) -> Self {
 +        let it = &tree[id.value];
 +        let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
 +        let visibility = &tree[it.visibility];
 +        Self {
 +            path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())),
 +            alias: it.alias.clone(),
 +            visibility: visibility.clone(),
 +            kind: ImportKind::Plain,
 +            is_prelude: false,
 +            is_extern_crate: true,
 +            is_macro_use: attrs.by_key("macro_use").exists(),
 +            source: ImportSource::ExternCrate(id),
 +        }
 +    }
 +}
 +
 +#[derive(Debug, Eq, PartialEq)]
 +struct ImportDirective {
 +    module_id: LocalModuleId,
 +    import: Import,
 +    status: PartialResolvedImport,
 +}
 +
 +#[derive(Clone, Debug, Eq, PartialEq)]
 +struct MacroDirective {
 +    module_id: LocalModuleId,
 +    depth: usize,
 +    kind: MacroDirectiveKind,
 +    container: ItemContainerId,
 +}
 +
 +#[derive(Clone, Debug, Eq, PartialEq)]
 +enum MacroDirectiveKind {
 +    FnLike { ast_id: AstIdWithPath<ast::MacroCall>, expand_to: ExpandTo },
 +    Derive { ast_id: AstIdWithPath<ast::Adt>, derive_attr: AttrId, derive_pos: usize },
 +    Attr { ast_id: AstIdWithPath<ast::Item>, attr: Attr, mod_item: ModItem, tree: TreeId },
 +}
 +
 +/// Walks the tree of module recursively
 +struct DefCollector<'a> {
 +    db: &'a dyn DefDatabase,
 +    def_map: DefMap,
 +    deps: FxHashMap<Name, ModuleId>,
 +    glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>,
 +    unresolved_imports: Vec<ImportDirective>,
 +    indeterminate_imports: Vec<ImportDirective>,
 +    unresolved_macros: Vec<MacroDirective>,
 +    mod_dirs: FxHashMap<LocalModuleId, ModDir>,
 +    cfg_options: &'a CfgOptions,
 +    /// List of procedural macros defined by this crate. This is read from the dynamic library
 +    /// built by the build system, and is the list of proc. macros we can actually expand. It is
 +    /// empty when proc. macro support is disabled (in which case we still do name resolution for
 +    /// them).
 +    proc_macros: Vec<(Name, ProcMacroExpander)>,
 +    is_proc_macro: bool,
 +    from_glob_import: PerNsGlobImports,
 +    /// If we fail to resolve an attribute on a `ModItem`, we fall back to ignoring the attribute.
 +    /// This map is used to skip all attributes up to and including the one that failed to resolve,
 +    /// in order to not expand them twice.
 +    ///
 +    /// This also stores the attributes to skip when we resolve derive helpers and non-macro
 +    /// non-builtin attributes in general.
 +    skip_attrs: FxHashMap<InFile<ModItem>, AttrId>,
 +}
 +
 +impl DefCollector<'_> {
 +    fn seed_with_top_level(&mut self) {
 +        let _p = profile::span("seed_with_top_level");
 +
 +        let file_id = self.db.crate_graph()[self.def_map.krate].root_file_id;
 +        let item_tree = self.db.file_item_tree(file_id.into());
 +        let module_id = self.def_map.root;
 +
 +        let attrs = item_tree.top_level_attrs(self.db, self.def_map.krate);
 +        if attrs.cfg().map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) {
 +            self.inject_prelude(&attrs);
 +
 +            // Process other crate-level attributes.
 +            for attr in &*attrs {
 +                let attr_name = match attr.path.as_ident() {
 +                    Some(name) => name,
 +                    None => continue,
 +                };
 +
 +                if *attr_name == hir_expand::name![recursion_limit] {
 +                    if let Some(limit) = attr.string_value() {
 +                        if let Ok(limit) = limit.parse() {
 +                            self.def_map.recursion_limit = Some(limit);
 +                        }
 +                    }
 +                    continue;
 +                }
 +
 +                if *attr_name == hir_expand::name![crate_type] {
 +                    if let Some("proc-macro") = attr.string_value().map(SmolStr::as_str) {
 +                        self.is_proc_macro = true;
 +                    }
 +                    continue;
 +                }
 +
 +                let attr_is_register_like = *attr_name == hir_expand::name![register_attr]
 +                    || *attr_name == hir_expand::name![register_tool];
 +                if !attr_is_register_like {
 +                    continue;
 +                }
 +
 +                let registered_name = match attr.single_ident_value() {
 +                    Some(ident) => ident.as_name(),
 +                    _ => continue,
 +                };
 +
 +                if *attr_name == hir_expand::name![register_attr] {
 +                    self.def_map.registered_attrs.push(registered_name.to_smol_str());
 +                    cov_mark::hit!(register_attr);
 +                } else {
 +                    self.def_map.registered_tools.push(registered_name.to_smol_str());
 +                    cov_mark::hit!(register_tool);
 +                }
 +            }
 +
 +            ModCollector {
 +                def_collector: self,
 +                macro_depth: 0,
 +                module_id,
 +                tree_id: TreeId::new(file_id.into(), None),
 +                item_tree: &item_tree,
 +                mod_dir: ModDir::root(),
 +            }
 +            .collect_in_top_module(item_tree.top_level_items());
 +        }
 +    }
 +
 +    fn seed_with_inner(&mut self, tree_id: TreeId) {
 +        let item_tree = tree_id.item_tree(self.db);
 +        let module_id = self.def_map.root;
 +
 +        let is_cfg_enabled = item_tree
 +            .top_level_attrs(self.db, self.def_map.krate)
 +            .cfg()
 +            .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false));
 +        if is_cfg_enabled {
 +            ModCollector {
 +                def_collector: self,
 +                macro_depth: 0,
 +                module_id,
 +                tree_id,
 +                item_tree: &item_tree,
 +                mod_dir: ModDir::root(),
 +            }
 +            .collect_in_top_module(item_tree.top_level_items());
 +        }
 +    }
 +
 +    fn resolution_loop(&mut self) {
 +        let _p = profile::span("DefCollector::resolution_loop");
 +
 +        // main name resolution fixed-point loop.
 +        let mut i = 0;
 +        'resolve_attr: loop {
 +            'resolve_macros: loop {
 +                self.db.unwind_if_cancelled();
 +
 +                {
 +                    let _p = profile::span("resolve_imports loop");
 +
 +                    'resolve_imports: loop {
 +                        if self.resolve_imports() == ReachedFixedPoint::Yes {
 +                            break 'resolve_imports;
 +                        }
 +                    }
 +                }
 +                if self.resolve_macros() == ReachedFixedPoint::Yes {
 +                    break 'resolve_macros;
 +                }
 +
 +                i += 1;
 +                if FIXED_POINT_LIMIT.check(i).is_err() {
 +                    tracing::error!("name resolution is stuck");
 +                    break 'resolve_attr;
 +                }
 +            }
 +
 +            if self.reseed_with_unresolved_attribute() == ReachedFixedPoint::Yes {
 +                break 'resolve_attr;
 +            }
 +        }
 +    }
 +
 +    fn collect(&mut self) {
 +        let _p = profile::span("DefCollector::collect");
 +
 +        self.resolution_loop();
 +
 +        // Resolve all indeterminate resolved imports again
 +        // As some of the macros will expand newly import shadowing partial resolved imports
 +        // FIXME: We maybe could skip this, if we handle the indeterminate imports in `resolve_imports`
 +        // correctly
 +        let partial_resolved = self.indeterminate_imports.drain(..).map(|directive| {
 +            ImportDirective { status: PartialResolvedImport::Unresolved, ..directive }
 +        });
 +        self.unresolved_imports.extend(partial_resolved);
 +        self.resolve_imports();
 +
 +        let unresolved_imports = mem::take(&mut self.unresolved_imports);
 +        // show unresolved imports in completion, etc
 +        for directive in &unresolved_imports {
 +            self.record_resolved_import(directive);
 +        }
 +        self.unresolved_imports = unresolved_imports;
 +
 +        if self.is_proc_macro {
 +            // A crate exporting procedural macros is not allowed to export anything else.
 +            //
 +            // Additionally, while the proc macro entry points must be `pub`, they are not publicly
 +            // exported in type/value namespace. This function reduces the visibility of all items
 +            // in the crate root that aren't proc macros.
 +            let root = self.def_map.root;
 +            let module_id = self.def_map.module_id(root);
 +            let root = &mut self.def_map.modules[root];
 +            root.scope.censor_non_proc_macros(module_id);
 +        }
 +    }
 +
 +    /// When the fixed-point loop reaches a stable state, we might still have
 +    /// some unresolved attributes left over. This takes one of them, and feeds
 +    /// the item it's applied to back into name resolution.
 +    ///
 +    /// This effectively ignores the fact that the macro is there and just treats the items as
 +    /// normal code.
 +    ///
 +    /// This improves UX for unresolved attributes, and replicates the
 +    /// behavior before we supported proc. attribute macros.
 +    fn reseed_with_unresolved_attribute(&mut self) -> ReachedFixedPoint {
 +        cov_mark::hit!(unresolved_attribute_fallback);
 +
 +        let unresolved_attr =
 +            self.unresolved_macros.iter().enumerate().find_map(|(idx, directive)| match &directive
 +                .kind
 +            {
 +                MacroDirectiveKind::Attr { ast_id, mod_item, attr, tree } => {
 +                    self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
 +                        directive.module_id,
 +                        MacroCallKind::Attr {
 +                            ast_id: ast_id.ast_id,
 +                            attr_args: Default::default(),
 +                            invoc_attr_index: attr.id.ast_index,
 +                            is_derive: false,
 +                        },
 +                        attr.path().clone(),
 +                    ));
 +
 +                    self.skip_attrs.insert(ast_id.ast_id.with_value(*mod_item), attr.id);
 +
 +                    Some((idx, directive, *mod_item, *tree))
 +                }
 +                _ => None,
 +            });
 +
 +        match unresolved_attr {
 +            Some((pos, &MacroDirective { module_id, depth, container, .. }, mod_item, tree_id)) => {
 +                let item_tree = &tree_id.item_tree(self.db);
 +                let mod_dir = self.mod_dirs[&module_id].clone();
 +                ModCollector {
 +                    def_collector: self,
 +                    macro_depth: depth,
 +                    module_id,
 +                    tree_id,
 +                    item_tree,
 +                    mod_dir,
 +                }
 +                .collect(&[mod_item], container);
 +
 +                self.unresolved_macros.swap_remove(pos);
 +                // Continue name resolution with the new data.
 +                ReachedFixedPoint::No
 +            }
 +            None => ReachedFixedPoint::Yes,
 +        }
 +    }
 +
 +    fn inject_prelude(&mut self, crate_attrs: &Attrs) {
 +        // See compiler/rustc_builtin_macros/src/standard_library_imports.rs
 +
 +        if crate_attrs.by_key("no_core").exists() {
 +            // libcore does not get a prelude.
 +            return;
 +        }
 +
 +        let krate = if crate_attrs.by_key("no_std").exists() {
 +            name![core]
 +        } else {
 +            let std = name![std];
 +            if self.def_map.extern_prelude().any(|(name, _)| *name == std) {
 +                std
 +            } else {
 +                // If `std` does not exist for some reason, fall back to core. This mostly helps
 +                // keep r-a's own tests minimal.
 +                name![core]
 +            }
 +        };
 +
 +        let edition = match self.def_map.edition {
 +            Edition::Edition2015 => name![rust_2015],
 +            Edition::Edition2018 => name![rust_2018],
 +            Edition::Edition2021 => name![rust_2021],
 +        };
 +
 +        let path_kind = if self.def_map.edition == Edition::Edition2015 {
 +            PathKind::Plain
 +        } else {
 +            PathKind::Abs
 +        };
 +        let path =
 +            ModPath::from_segments(path_kind, [krate.clone(), name![prelude], edition].into_iter());
 +        // Fall back to the older `std::prelude::v1` for compatibility with Rust <1.52.0
 +        // FIXME remove this fallback
 +        let fallback_path =
 +            ModPath::from_segments(path_kind, [krate, name![prelude], name![v1]].into_iter());
 +
 +        for path in &[path, fallback_path] {
 +            let (per_ns, _) = self.def_map.resolve_path(
 +                self.db,
 +                self.def_map.root,
 +                path,
 +                BuiltinShadowMode::Other,
 +            );
 +
 +            match per_ns.types {
 +                Some((ModuleDefId::ModuleId(m), _)) => {
 +                    self.def_map.prelude = Some(m);
 +                    return;
 +                }
 +                types => {
 +                    tracing::debug!(
 +                        "could not resolve prelude path `{}` to module (resolved to {:?})",
 +                        path,
 +                        types
 +                    );
 +                }
 +            }
 +        }
 +    }
 +
 +    /// Adds a definition of procedural macro `name` to the root module.
 +    ///
 +    /// # Notes on procedural macro resolution
 +    ///
 +    /// Procedural macro functionality is provided by the build system: It has to build the proc
 +    /// macro and pass the resulting dynamic library to rust-analyzer.
 +    ///
 +    /// When procedural macro support is enabled, the list of proc macros exported by a crate is
 +    /// known before we resolve names in the crate. This list is stored in `self.proc_macros` and is
 +    /// derived from the dynamic library.
 +    ///
 +    /// However, we *also* would like to be able to at least *resolve* macros on our own, without
 +    /// help by the build system. So, when the macro isn't found in `self.proc_macros`, we instead
 +    /// use a dummy expander that always errors. This comes with the drawback of macros potentially
 +    /// going out of sync with what the build system sees (since we resolve using VFS state, but
 +    /// Cargo builds only on-disk files). We could and probably should add diagnostics for that.
 +    fn export_proc_macro(
 +        &mut self,
 +        def: ProcMacroDef,
 +        id: ItemTreeId<item_tree::Function>,
 +        fn_id: FunctionId,
 +        module_id: ModuleId,
 +    ) {
 +        let kind = def.kind.to_basedb_kind();
 +        let (expander, kind) = match self.proc_macros.iter().find(|(n, _)| n == &def.name) {
 +            Some(&(_, expander)) => (expander, kind),
 +            None => (ProcMacroExpander::dummy(self.def_map.krate), kind),
 +        };
 +
 +        let proc_macro_id =
 +            ProcMacroLoc { container: module_id, id, expander, kind }.intern(self.db);
 +        self.define_proc_macro(def.name.clone(), proc_macro_id);
 +        if let ProcMacroKind::CustomDerive { helpers } = def.kind {
 +            self.def_map
 +                .exported_derives
 +                .insert(macro_id_to_def_id(self.db, proc_macro_id.into()), helpers);
 +        }
 +        self.def_map.fn_proc_macro_mapping.insert(fn_id, proc_macro_id);
 +    }
 +
 +    /// Define a macro with `macro_rules`.
 +    ///
 +    /// It will define the macro in legacy textual scope, and if it has `#[macro_export]`,
 +    /// then it is also defined in the root module scope.
 +    /// You can `use` or invoke it by `crate::macro_name` anywhere, before or after the definition.
 +    ///
 +    /// It is surprising that the macro will never be in the current module scope.
 +    /// These code fails with "unresolved import/macro",
 +    /// ```rust,compile_fail
 +    /// mod m { macro_rules! foo { () => {} } }
 +    /// use m::foo as bar;
 +    /// ```
 +    ///
 +    /// ```rust,compile_fail
 +    /// macro_rules! foo { () => {} }
 +    /// self::foo!();
 +    /// crate::foo!();
 +    /// ```
 +    ///
 +    /// Well, this code compiles, because the plain path `foo` in `use` is searched
 +    /// in the legacy textual scope only.
 +    /// ```rust
 +    /// macro_rules! foo { () => {} }
 +    /// use foo as bar;
 +    /// ```
 +    fn define_macro_rules(
 +        &mut self,
 +        module_id: LocalModuleId,
 +        name: Name,
 +        macro_: MacroRulesId,
 +        export: bool,
 +    ) {
 +        // Textual scoping
 +        self.define_legacy_macro(module_id, name.clone(), macro_.into());
 +
 +        // Module scoping
 +        // In Rust, `#[macro_export]` macros are unconditionally visible at the
 +        // crate root, even if the parent modules is **not** visible.
 +        if export {
 +            let module_id = self.def_map.root;
 +            self.def_map.modules[module_id].scope.declare(macro_.into());
 +            self.update(
 +                module_id,
 +                &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
 +                Visibility::Public,
 +                ImportType::Named,
 +            );
 +        }
 +    }
 +
 +    /// Define a legacy textual scoped macro in module
 +    ///
 +    /// We use a map `legacy_macros` to store all legacy textual scoped macros visible per module.
 +    /// It will clone all macros from parent legacy scope, whose definition is prior to
 +    /// the definition of current module.
 +    /// And also, `macro_use` on a module will import all legacy macros visible inside to
 +    /// current legacy scope, with possible shadowing.
 +    fn define_legacy_macro(&mut self, module_id: LocalModuleId, name: Name, mac: MacroId) {
 +        // Always shadowing
 +        self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
 +    }
 +
 +    /// Define a macro 2.0 macro
 +    ///
 +    /// The scoped of macro 2.0 macro is equal to normal function
 +    fn define_macro_def(
 +        &mut self,
 +        module_id: LocalModuleId,
 +        name: Name,
 +        macro_: Macro2Id,
 +        vis: &RawVisibility,
 +    ) {
 +        let vis =
 +            self.def_map.resolve_visibility(self.db, module_id, vis).unwrap_or(Visibility::Public);
 +        self.def_map.modules[module_id].scope.declare(macro_.into());
 +        self.update(
 +            module_id,
 +            &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
 +            vis,
 +            ImportType::Named,
 +        );
 +    }
 +
 +    /// Define a proc macro
 +    ///
 +    /// A proc macro is similar to normal macro scope, but it would not visible in legacy textual scoped.
 +    /// And unconditionally exported.
 +    fn define_proc_macro(&mut self, name: Name, macro_: ProcMacroId) {
 +        let module_id = self.def_map.root;
 +        self.def_map.modules[module_id].scope.declare(macro_.into());
 +        self.update(
 +            module_id,
 +            &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
 +            Visibility::Public,
 +            ImportType::Named,
 +        );
 +    }
 +
 +    /// Import macros from `#[macro_use] extern crate`.
 +    fn import_macros_from_extern_crate(
 +        &mut self,
 +        current_module_id: LocalModuleId,
 +        extern_crate: &item_tree::ExternCrate,
 +    ) {
 +        tracing::debug!(
 +            "importing macros from extern crate: {:?} ({:?})",
 +            extern_crate,
 +            self.def_map.edition,
 +        );
 +
 +        if let Some(m) = self.resolve_extern_crate(&extern_crate.name) {
 +            if m == self.def_map.module_id(current_module_id) {
 +                cov_mark::hit!(ignore_macro_use_extern_crate_self);
 +                return;
 +            }
 +
 +            cov_mark::hit!(macro_rules_from_other_crates_are_visible_with_macro_use);
 +            self.import_all_macros_exported(current_module_id, m.krate);
 +        }
 +    }
 +
 +    /// Import all exported macros from another crate
 +    ///
 +    /// Exported macros are just all macros in the root module scope.
 +    /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
 +    /// created by `use` in the root module, ignoring the visibility of `use`.
 +    fn import_all_macros_exported(&mut self, current_module_id: LocalModuleId, krate: CrateId) {
 +        let def_map = self.db.crate_def_map(krate);
 +        for (name, def) in def_map[def_map.root].scope.macros() {
 +            // `#[macro_use]` brings macros into legacy scope. Yes, even non-`macro_rules!` macros.
 +            self.define_legacy_macro(current_module_id, name.clone(), def);
 +        }
 +    }
 +
 +    /// Tries to resolve every currently unresolved import.
 +    fn resolve_imports(&mut self) -> ReachedFixedPoint {
 +        let mut res = ReachedFixedPoint::Yes;
 +        let imports = mem::take(&mut self.unresolved_imports);
 +
 +        self.unresolved_imports = imports
 +            .into_iter()
 +            .filter_map(|mut directive| {
 +                directive.status = self.resolve_import(directive.module_id, &directive.import);
 +                match directive.status {
 +                    PartialResolvedImport::Indeterminate(_) => {
 +                        self.record_resolved_import(&directive);
 +                        self.indeterminate_imports.push(directive);
 +                        res = ReachedFixedPoint::No;
 +                        None
 +                    }
 +                    PartialResolvedImport::Resolved(_) => {
 +                        self.record_resolved_import(&directive);
 +                        res = ReachedFixedPoint::No;
 +                        None
 +                    }
 +                    PartialResolvedImport::Unresolved => Some(directive),
 +                }
 +            })
 +            .collect();
 +        res
 +    }
 +
 +    fn resolve_import(&self, module_id: LocalModuleId, import: &Import) -> PartialResolvedImport {
 +        let _p = profile::span("resolve_import").detail(|| format!("{}", import.path));
 +        tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.edition);
 +        if import.is_extern_crate {
 +            let name = import
 +                .path
 +                .as_ident()
 +                .expect("extern crate should have been desugared to one-element path");
 +
 +            let res = self.resolve_extern_crate(name);
 +
 +            match res {
 +                Some(res) => {
 +                    PartialResolvedImport::Resolved(PerNs::types(res.into(), Visibility::Public))
 +                }
 +                None => PartialResolvedImport::Unresolved,
 +            }
 +        } else {
 +            let res = self.def_map.resolve_path_fp_with_macro(
 +                self.db,
 +                ResolveMode::Import,
 +                module_id,
 +                &import.path,
 +                BuiltinShadowMode::Module,
 +            );
 +
 +            let def = res.resolved_def;
 +            if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() {
 +                return PartialResolvedImport::Unresolved;
 +            }
 +
 +            if let Some(krate) = res.krate {
 +                if krate != self.def_map.krate {
 +                    return PartialResolvedImport::Resolved(
 +                        def.filter_visibility(|v| matches!(v, Visibility::Public)),
 +                    );
 +                }
 +            }
 +
 +            // Check whether all namespace is resolved
 +            if def.take_types().is_some()
 +                && def.take_values().is_some()
 +                && def.take_macros().is_some()
 +            {
 +                PartialResolvedImport::Resolved(def)
 +            } else {
 +                PartialResolvedImport::Indeterminate(def)
 +            }
 +        }
 +    }
 +
 +    fn resolve_extern_crate(&self, name: &Name) -> Option<ModuleId> {
 +        if *name == name!(self) {
 +            cov_mark::hit!(extern_crate_self_as);
 +            let root = match self.def_map.block {
 +                Some(_) => {
 +                    let def_map = self.def_map.crate_root(self.db).def_map(self.db);
 +                    def_map.module_id(def_map.root())
 +                }
 +                None => self.def_map.module_id(self.def_map.root()),
 +            };
 +            Some(root)
 +        } else {
 +            self.deps.get(name).copied()
 +        }
 +    }
 +
 +    fn record_resolved_import(&mut self, directive: &ImportDirective) {
 +        let _p = profile::span("record_resolved_import");
 +
 +        let module_id = directive.module_id;
 +        let import = &directive.import;
 +        let mut def = directive.status.namespaces();
 +        let vis = self
 +            .def_map
 +            .resolve_visibility(self.db, module_id, &directive.import.visibility)
 +            .unwrap_or(Visibility::Public);
 +
 +        match import.kind {
 +            ImportKind::Plain | ImportKind::TypeOnly => {
 +                let name = match &import.alias {
 +                    Some(ImportAlias::Alias(name)) => Some(name),
 +                    Some(ImportAlias::Underscore) => None,
 +                    None => match import.path.segments().last() {
 +                        Some(last_segment) => Some(last_segment),
 +                        None => {
 +                            cov_mark::hit!(bogus_paths);
 +                            return;
 +                        }
 +                    },
 +                };
 +
 +                if import.kind == ImportKind::TypeOnly {
 +                    def.values = None;
 +                    def.macros = None;
 +                }
 +
 +                tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
 +
 +                // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
 +                if import.is_extern_crate && module_id == self.def_map.root {
 +                    if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = (def.take_types(), name)
 +                    {
 +                        self.def_map.extern_prelude.insert(name.clone(), def);
 +                    }
 +                }
 +
 +                self.update(module_id, &[(name.cloned(), def)], vis, ImportType::Named);
 +            }
 +            ImportKind::Glob => {
 +                tracing::debug!("glob import: {:?}", import);
 +                match def.take_types() {
 +                    Some(ModuleDefId::ModuleId(m)) => {
 +                        if import.is_prelude {
 +                            // Note: This dodgily overrides the injected prelude. The rustc
 +                            // implementation seems to work the same though.
 +                            cov_mark::hit!(std_prelude);
 +                            self.def_map.prelude = Some(m);
 +                        } else if m.krate != self.def_map.krate {
 +                            cov_mark::hit!(glob_across_crates);
 +                            // glob import from other crate => we can just import everything once
 +                            let item_map = m.def_map(self.db);
 +                            let scope = &item_map[m.local_id].scope;
 +
 +                            // Module scoped macros is included
 +                            let items = scope
 +                                .resolutions()
 +                                // only keep visible names...
 +                                .map(|(n, res)| {
 +                                    (n, res.filter_visibility(|v| v.is_visible_from_other_crate()))
 +                                })
 +                                .filter(|(_, res)| !res.is_none())
 +                                .collect::<Vec<_>>();
 +
 +                            self.update(module_id, &items, vis, ImportType::Glob);
 +                        } else {
 +                            // glob import from same crate => we do an initial
 +                            // import, and then need to propagate any further
 +                            // additions
 +                            let def_map;
 +                            let scope = if m.block == self.def_map.block_id() {
 +                                &self.def_map[m.local_id].scope
 +                            } else {
 +                                def_map = m.def_map(self.db);
 +                                &def_map[m.local_id].scope
 +                            };
 +
 +                            // Module scoped macros is included
 +                            let items = scope
 +                                .resolutions()
 +                                // only keep visible names...
 +                                .map(|(n, res)| {
 +                                    (
 +                                        n,
 +                                        res.filter_visibility(|v| {
 +                                            v.is_visible_from_def_map(
 +                                                self.db,
 +                                                &self.def_map,
 +                                                module_id,
 +                                            )
 +                                        }),
 +                                    )
 +                                })
 +                                .filter(|(_, res)| !res.is_none())
 +                                .collect::<Vec<_>>();
 +
 +                            self.update(module_id, &items, vis, ImportType::Glob);
 +                            // record the glob import in case we add further items
 +                            let glob = self.glob_imports.entry(m.local_id).or_default();
 +                            if !glob.iter().any(|(mid, _)| *mid == module_id) {
 +                                glob.push((module_id, vis));
 +                            }
 +                        }
 +                    }
 +                    Some(ModuleDefId::AdtId(AdtId::EnumId(e))) => {
 +                        cov_mark::hit!(glob_enum);
 +                        // glob import from enum => just import all the variants
 +
 +                        // XXX: urgh, so this works by accident! Here, we look at
 +                        // the enum data, and, in theory, this might require us to
 +                        // look back at the crate_def_map, creating a cycle. For
 +                        // example, `enum E { crate::some_macro!(); }`. Luckily, the
 +                        // only kind of macro that is allowed inside enum is a
 +                        // `cfg_macro`, and we don't need to run name resolution for
 +                        // it, but this is sheer luck!
 +                        let enum_data = self.db.enum_data(e);
 +                        let resolutions = enum_data
 +                            .variants
 +                            .iter()
 +                            .map(|(local_id, variant_data)| {
 +                                let name = variant_data.name.clone();
 +                                let variant = EnumVariantId { parent: e, local_id };
 +                                let res = PerNs::both(variant.into(), variant.into(), vis);
 +                                (Some(name), res)
 +                            })
 +                            .collect::<Vec<_>>();
 +                        self.update(module_id, &resolutions, vis, ImportType::Glob);
 +                    }
 +                    Some(d) => {
 +                        tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d);
 +                    }
 +                    None => {
 +                        tracing::debug!("glob import {:?} didn't resolve as type", import);
 +                    }
 +                }
 +            }
 +        }
 +    }
 +
 +    fn update(
 +        &mut self,
 +        module_id: LocalModuleId,
 +        resolutions: &[(Option<Name>, PerNs)],
 +        vis: Visibility,
 +        import_type: ImportType,
 +    ) {
 +        self.db.unwind_if_cancelled();
 +        self.update_recursive(module_id, resolutions, vis, import_type, 0)
 +    }
 +
 +    fn update_recursive(
 +        &mut self,
 +        module_id: LocalModuleId,
 +        resolutions: &[(Option<Name>, PerNs)],
 +        // All resolutions are imported with this visibility; the visibilities in
 +        // the `PerNs` values are ignored and overwritten
 +        vis: Visibility,
 +        import_type: ImportType,
 +        depth: usize,
 +    ) {
 +        if GLOB_RECURSION_LIMIT.check(depth).is_err() {
 +            // prevent stack overflows (but this shouldn't be possible)
 +            panic!("infinite recursion in glob imports!");
 +        }
 +        let mut changed = false;
 +
 +        for (name, res) in resolutions {
 +            match name {
 +                Some(name) => {
 +                    let scope = &mut self.def_map.modules[module_id].scope;
 +                    changed |= scope.push_res_with_import(
 +                        &mut self.from_glob_import,
 +                        (module_id, name.clone()),
 +                        res.with_visibility(vis),
 +                        import_type,
 +                    );
 +                }
 +                None => {
 +                    let tr = match res.take_types() {
 +                        Some(ModuleDefId::TraitId(tr)) => tr,
 +                        Some(other) => {
 +                            tracing::debug!("non-trait `_` import of {:?}", other);
 +                            continue;
 +                        }
 +                        None => continue,
 +                    };
 +                    let old_vis = self.def_map.modules[module_id].scope.unnamed_trait_vis(tr);
 +                    let should_update = match old_vis {
 +                        None => true,
 +                        Some(old_vis) => {
 +                            let max_vis = old_vis.max(vis, &self.def_map).unwrap_or_else(|| {
 +                                panic!("`Tr as _` imports with unrelated visibilities {:?} and {:?} (trait {:?})", old_vis, vis, tr);
 +                            });
 +
 +                            if max_vis == old_vis {
 +                                false
 +                            } else {
 +                                cov_mark::hit!(upgrade_underscore_visibility);
 +                                true
 +                            }
 +                        }
 +                    };
 +
 +                    if should_update {
 +                        changed = true;
 +                        self.def_map.modules[module_id].scope.push_unnamed_trait(tr, vis);
 +                    }
 +                }
 +            }
 +        }
 +
 +        if !changed {
 +            return;
 +        }
 +        let glob_imports = self
 +            .glob_imports
 +            .get(&module_id)
 +            .into_iter()
 +            .flatten()
 +            .filter(|(glob_importing_module, _)| {
 +                // we know all resolutions have the same visibility (`vis`), so we
 +                // just need to check that once
 +                vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
 +            })
 +            .cloned()
 +            .collect::<Vec<_>>();
 +
 +        for (glob_importing_module, glob_import_vis) in glob_imports {
 +            self.update_recursive(
 +                glob_importing_module,
 +                resolutions,
 +                glob_import_vis,
 +                ImportType::Glob,
 +                depth + 1,
 +            );
 +        }
 +    }
 +
 +    fn resolve_macros(&mut self) -> ReachedFixedPoint {
 +        let mut macros = mem::take(&mut self.unresolved_macros);
 +        let mut resolved = Vec::new();
 +        let mut push_resolved = |directive: &MacroDirective, call_id| {
 +            resolved.push((directive.module_id, directive.depth, directive.container, call_id));
 +        };
 +        let mut res = ReachedFixedPoint::Yes;
 +        macros.retain(|directive| {
-             let resolver = |path| resolver2(path).map(|(_, it)| it);
++            let resolver = |path| {
 +                let resolved_res = self.def_map.resolve_path_fp_with_macro(
 +                    self.db,
 +                    ResolveMode::Other,
 +                    directive.module_id,
 +                    &path,
 +                    BuiltinShadowMode::Module,
 +                );
 +                resolved_res
 +                    .resolved_def
 +                    .take_macros()
 +                    .map(|it| (it, macro_id_to_def_id(self.db, it)))
 +            };
-                         &resolver,
++            let resolver_def_id = |path| resolver(path).map(|(_, it)| it);
 +
 +            match &directive.kind {
 +                MacroDirectiveKind::FnLike { ast_id, expand_to } => {
 +                    let call_id = macro_call_as_call_id(
 +                        self.db,
 +                        ast_id,
 +                        *expand_to,
 +                        self.def_map.krate,
-                         &resolver2,
++                        &resolver_def_id,
 +                        &mut |_err| (),
 +                    );
 +                    if let Ok(Ok(call_id)) = call_id {
 +                        push_resolved(directive, call_id);
 +                        res = ReachedFixedPoint::No;
 +                        return false;
 +                    }
 +                }
 +                MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
 +                    let id = derive_macro_as_call_id(
 +                        self.db,
 +                        ast_id,
 +                        *derive_attr,
 +                        *derive_pos as u32,
 +                        self.def_map.krate,
-                     let def = match resolver(path.clone()) {
++                        &resolver,
 +                    );
 +
 +                    if let Ok((macro_id, def_id, call_id)) = id {
 +                        self.def_map.modules[directive.module_id].scope.set_derive_macro_invoc(
 +                            ast_id.ast_id,
 +                            call_id,
 +                            *derive_attr,
 +                            *derive_pos,
 +                        );
 +                        // Record its helper attributes.
 +                        if def_id.krate != self.def_map.krate {
 +                            let def_map = self.db.crate_def_map(def_id.krate);
 +                            if let Some(helpers) = def_map.exported_derives.get(&def_id) {
 +                                self.def_map
 +                                    .derive_helpers_in_scope
 +                                    .entry(ast_id.ast_id.map(|it| it.upcast()))
 +                                    .or_default()
 +                                    .extend(izip!(
 +                                        helpers.iter().cloned(),
 +                                        iter::repeat(macro_id),
 +                                        iter::repeat(call_id),
 +                                    ));
 +                            }
 +                        }
 +
 +                        push_resolved(directive, call_id);
 +                        res = ReachedFixedPoint::No;
 +                        return false;
 +                    }
 +                }
 +                MacroDirectiveKind::Attr { ast_id: file_ast_id, mod_item, attr, tree } => {
 +                    let &AstIdWithPath { ast_id, ref path } = file_ast_id;
 +                    let file_id = ast_id.file_id;
 +
 +                    let mut recollect_without = |collector: &mut Self| {
 +                        // Remove the original directive since we resolved it.
 +                        let mod_dir = collector.mod_dirs[&directive.module_id].clone();
 +                        collector.skip_attrs.insert(InFile::new(file_id, *mod_item), attr.id);
 +
 +                        let item_tree = tree.item_tree(self.db);
 +                        ModCollector {
 +                            def_collector: collector,
 +                            macro_depth: directive.depth,
 +                            module_id: directive.module_id,
 +                            tree_id: *tree,
 +                            item_tree: &item_tree,
 +                            mod_dir,
 +                        }
 +                        .collect(&[*mod_item], directive.container);
 +                        res = ReachedFixedPoint::No;
 +                        false
 +                    };
 +
 +                    if let Some(ident) = path.as_ident() {
 +                        if let Some(helpers) = self.def_map.derive_helpers_in_scope.get(&ast_id) {
 +                            if helpers.iter().any(|(it, ..)| it == ident) {
 +                                cov_mark::hit!(resolved_derive_helper);
 +                                // Resolved to derive helper. Collect the item's attributes again,
 +                                // starting after the derive helper.
 +                                return recollect_without(self);
 +                            }
 +                        }
 +                    }
 +
-         self.unresolved_macros.extend(macros);
++                    let def = match resolver_def_id(path.clone()) {
 +                        Some(def) if def.is_attribute() => def,
 +                        _ => return true,
 +                    };
 +                    if matches!(
 +                        def,
 +                        MacroDefId { kind:MacroDefKind::BuiltInAttr(expander, _),.. }
 +                        if expander.is_derive()
 +                    ) {
 +                        // Resolved to `#[derive]`
 +
 +                        let item_tree = tree.item_tree(self.db);
 +                        let ast_adt_id: FileAstId<ast::Adt> = match *mod_item {
 +                            ModItem::Struct(strukt) => item_tree[strukt].ast_id().upcast(),
 +                            ModItem::Union(union) => item_tree[union].ast_id().upcast(),
 +                            ModItem::Enum(enum_) => item_tree[enum_].ast_id().upcast(),
 +                            _ => {
 +                                let diag = DefDiagnostic::invalid_derive_target(
 +                                    directive.module_id,
 +                                    ast_id,
 +                                    attr.id,
 +                                );
 +                                self.def_map.diagnostics.push(diag);
 +                                return recollect_without(self);
 +                            }
 +                        };
 +                        let ast_id = ast_id.with_value(ast_adt_id);
 +
 +                        match attr.parse_path_comma_token_tree() {
 +                            Some(derive_macros) => {
 +                                let mut len = 0;
 +                                for (idx, path) in derive_macros.enumerate() {
 +                                    let ast_id = AstIdWithPath::new(file_id, ast_id.value, path);
 +                                    self.unresolved_macros.push(MacroDirective {
 +                                        module_id: directive.module_id,
 +                                        depth: directive.depth + 1,
 +                                        kind: MacroDirectiveKind::Derive {
 +                                            ast_id,
 +                                            derive_attr: attr.id,
 +                                            derive_pos: idx,
 +                                        },
 +                                        container: directive.container,
 +                                    });
 +                                    len = idx;
 +                                }
 +
 +                                // We treat the #[derive] macro as an attribute call, but we do not resolve it for nameres collection.
 +                                // This is just a trick to be able to resolve the input to derives as proper paths.
 +                                // Check the comment in [`builtin_attr_macro`].
 +                                let call_id = attr_macro_as_call_id(
 +                                    self.db,
 +                                    file_ast_id,
 +                                    attr,
 +                                    self.def_map.krate,
 +                                    def,
 +                                    true,
 +                                );
 +                                self.def_map.modules[directive.module_id]
 +                                    .scope
 +                                    .init_derive_attribute(ast_id, attr.id, call_id, len + 1);
 +                            }
 +                            None => {
 +                                let diag = DefDiagnostic::malformed_derive(
 +                                    directive.module_id,
 +                                    ast_id,
 +                                    attr.id,
 +                                );
 +                                self.def_map.diagnostics.push(diag);
 +                            }
 +                        }
 +
 +                        return recollect_without(self);
 +                    }
 +
 +                    // Not resolved to a derive helper or the derive attribute, so try to treat as a normal attribute.
 +                    let call_id = attr_macro_as_call_id(
 +                        self.db,
 +                        file_ast_id,
 +                        attr,
 +                        self.def_map.krate,
 +                        def,
 +                        false,
 +                    );
 +                    let loc: MacroCallLoc = self.db.lookup_intern_macro_call(call_id);
 +
 +                    // If proc attribute macro expansion is disabled, skip expanding it here
 +                    if !self.db.enable_proc_attr_macros() {
 +                        self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
 +                            directive.module_id,
 +                            loc.kind,
 +                            loc.def.krate,
 +                        ));
 +                        return recollect_without(self);
 +                    }
 +
 +                    // Skip #[test]/#[bench] expansion, which would merely result in more memory usage
 +                    // due to duplicating functions into macro expansions
 +                    if matches!(
 +                        loc.def.kind,
 +                        MacroDefKind::BuiltInAttr(expander, _)
 +                        if expander.is_test() || expander.is_bench()
 +                    ) {
 +                        return recollect_without(self);
 +                    }
 +
 +                    if let MacroDefKind::ProcMacro(exp, ..) = loc.def.kind {
 +                        if exp.is_dummy() {
 +                            // If there's no expander for the proc macro (e.g.
 +                            // because proc macros are disabled, or building the
 +                            // proc macro crate failed), report this and skip
 +                            // expansion like we would if it was disabled
 +                            self.def_map.diagnostics.push(DefDiagnostic::unresolved_proc_macro(
 +                                directive.module_id,
 +                                loc.kind,
 +                                loc.def.krate,
 +                            ));
 +
 +                            return recollect_without(self);
 +                        }
 +                    }
 +
 +                    self.def_map.modules[directive.module_id]
 +                        .scope
 +                        .add_attr_macro_invoc(ast_id, call_id);
 +
 +                    push_resolved(directive, call_id);
 +                    res = ReachedFixedPoint::No;
 +                    return false;
 +                }
 +            }
 +
 +            true
 +        });
 +        // Attribute resolution can add unresolved macro invocations, so concatenate the lists.
++        macros.extend(mem::take(&mut self.unresolved_macros));
++        self.unresolved_macros = macros;
 +
 +        for (module_id, depth, container, macro_call_id) in resolved {
 +            self.collect_macro_expansion(module_id, macro_call_id, depth, container);
 +        }
 +
 +        res
 +    }
 +
 +    fn collect_macro_expansion(
 +        &mut self,
 +        module_id: LocalModuleId,
 +        macro_call_id: MacroCallId,
 +        depth: usize,
 +        container: ItemContainerId,
 +    ) {
 +        if EXPANSION_DEPTH_LIMIT.check(depth).is_err() {
 +            cov_mark::hit!(macro_expansion_overflow);
 +            tracing::warn!("macro expansion is too deep");
 +            return;
 +        }
 +        let file_id = macro_call_id.as_file();
 +
 +        // First, fetch the raw expansion result for purposes of error reporting. This goes through
 +        // `macro_expand_error` to avoid depending on the full expansion result (to improve
 +        // incrementality).
 +        let loc: MacroCallLoc = self.db.lookup_intern_macro_call(macro_call_id);
 +        let err = self.db.macro_expand_error(macro_call_id);
 +        if let Some(err) = err {
 +            let diag = match err {
 +                hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
 +                    always!(krate == loc.def.krate);
 +                    // Missing proc macros are non-fatal, so they are handled specially.
 +                    DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone(), loc.def.krate)
 +                }
 +                _ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()),
 +            };
 +
 +            self.def_map.diagnostics.push(diag);
 +        }
 +
 +        // Then, fetch and process the item tree. This will reuse the expansion result from above.
 +        let item_tree = self.db.file_item_tree(file_id);
 +        let mod_dir = self.mod_dirs[&module_id].clone();
 +        ModCollector {
 +            def_collector: &mut *self,
 +            macro_depth: depth,
 +            tree_id: TreeId::new(file_id, None),
 +            module_id,
 +            item_tree: &item_tree,
 +            mod_dir,
 +        }
 +        .collect(item_tree.top_level_items(), container);
 +    }
 +
 +    fn finish(mut self) -> DefMap {
 +        // Emit diagnostics for all remaining unexpanded macros.
 +
 +        let _p = profile::span("DefCollector::finish");
 +
 +        for directive in &self.unresolved_macros {
 +            match &directive.kind {
 +                MacroDirectiveKind::FnLike { ast_id, expand_to } => {
 +                    let macro_call_as_call_id = macro_call_as_call_id(
 +                        self.db,
 +                        ast_id,
 +                        *expand_to,
 +                        self.def_map.krate,
 +                        |path| {
 +                            let resolved_res = self.def_map.resolve_path_fp_with_macro(
 +                                self.db,
 +                                ResolveMode::Other,
 +                                directive.module_id,
 +                                &path,
 +                                BuiltinShadowMode::Module,
 +                            );
 +                            resolved_res
 +                                .resolved_def
 +                                .take_macros()
 +                                .map(|it| macro_id_to_def_id(self.db, it))
 +                        },
 +                        &mut |_| (),
 +                    );
 +                    if let Err(UnresolvedMacro { path }) = macro_call_as_call_id {
 +                        self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
 +                            directive.module_id,
 +                            MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: *expand_to },
 +                            path,
 +                        ));
 +                    }
 +                }
 +                MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
 +                    self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
 +                        directive.module_id,
 +                        MacroCallKind::Derive {
 +                            ast_id: ast_id.ast_id,
 +                            derive_attr_index: derive_attr.ast_index,
 +                            derive_index: *derive_pos as u32,
 +                        },
 +                        ast_id.path.clone(),
 +                    ));
 +                }
 +                // These are diagnosed by `reseed_with_unresolved_attribute`, as that function consumes them
 +                MacroDirectiveKind::Attr { .. } => {}
 +            }
 +        }
 +
 +        // Emit diagnostics for all remaining unresolved imports.
 +
 +        // We'd like to avoid emitting a diagnostics avalanche when some `extern crate` doesn't
 +        // resolve. We first emit diagnostics for unresolved extern crates and collect the missing
 +        // crate names. Then we emit diagnostics for unresolved imports, but only if the import
 +        // doesn't start with an unresolved crate's name. Due to renaming and reexports, this is a
 +        // heuristic, but it works in practice.
 +        let mut diagnosed_extern_crates = FxHashSet::default();
 +        for directive in &self.unresolved_imports {
 +            if let ImportSource::ExternCrate(krate) = directive.import.source {
 +                let item_tree = krate.item_tree(self.db);
 +                let extern_crate = &item_tree[krate.value];
 +
 +                diagnosed_extern_crates.insert(extern_crate.name.clone());
 +
 +                self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
 +                    directive.module_id,
 +                    InFile::new(krate.file_id(), extern_crate.ast_id),
 +                ));
 +            }
 +        }
 +
 +        for directive in &self.unresolved_imports {
 +            if let ImportSource::Import { id: import, use_tree } = directive.import.source {
 +                if matches!(
 +                    (directive.import.path.segments().first(), &directive.import.path.kind),
 +                    (Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate)
 +                ) {
 +                    continue;
 +                }
 +
 +                self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
 +                    directive.module_id,
 +                    import,
 +                    use_tree,
 +                ));
 +            }
 +        }
 +
 +        self.def_map
 +    }
 +}
 +
 +/// Walks a single module, populating defs, imports and macros
 +struct ModCollector<'a, 'b> {
 +    def_collector: &'a mut DefCollector<'b>,
 +    macro_depth: usize,
 +    module_id: LocalModuleId,
 +    tree_id: TreeId,
 +    item_tree: &'a ItemTree,
 +    mod_dir: ModDir,
 +}
 +
 +impl ModCollector<'_, '_> {
 +    fn collect_in_top_module(&mut self, items: &[ModItem]) {
 +        let module = self.def_collector.def_map.module_id(self.module_id);
 +        self.collect(items, module.into())
 +    }
 +
 +    fn collect(&mut self, items: &[ModItem], container: ItemContainerId) {
 +        let krate = self.def_collector.def_map.krate;
 +
 +        // Note: don't assert that inserted value is fresh: it's simply not true
 +        // for macros.
 +        self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
 +
 +        // Prelude module is always considered to be `#[macro_use]`.
 +        if let Some(prelude_module) = self.def_collector.def_map.prelude {
 +            if prelude_module.krate != krate {
 +                cov_mark::hit!(prelude_is_macro_use);
 +                self.def_collector.import_all_macros_exported(self.module_id, prelude_module.krate);
 +            }
 +        }
 +
 +        // This should be processed eagerly instead of deferred to resolving.
 +        // `#[macro_use] extern crate` is hoisted to imports macros before collecting
 +        // any other items.
 +        for &item in items {
 +            let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
 +            if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) {
 +                if let ModItem::ExternCrate(id) = item {
 +                    let import = &self.item_tree[id];
 +                    let attrs = self.item_tree.attrs(
 +                        self.def_collector.db,
 +                        krate,
 +                        ModItem::from(id).into(),
 +                    );
 +                    if attrs.by_key("macro_use").exists() {
 +                        self.def_collector.import_macros_from_extern_crate(self.module_id, import);
 +                    }
 +                }
 +            }
 +        }
 +
 +        for &item in items {
 +            let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
 +            if let Some(cfg) = attrs.cfg() {
 +                if !self.is_cfg_enabled(&cfg) {
 +                    self.emit_unconfigured_diagnostic(item, &cfg);
 +                    continue;
 +                }
 +            }
 +
 +            if let Err(()) = self.resolve_attributes(&attrs, item, container) {
 +                // Do not process the item. It has at least one non-builtin attribute, so the
 +                // fixed-point algorithm is required to resolve the rest of them.
 +                continue;
 +            }
 +
 +            let db = self.def_collector.db;
 +            let module = self.def_collector.def_map.module_id(self.module_id);
 +            let def_map = &mut self.def_collector.def_map;
 +            let update_def =
 +                |def_collector: &mut DefCollector<'_>, id, name: &Name, vis, has_constructor| {
 +                    def_collector.def_map.modules[self.module_id].scope.declare(id);
 +                    def_collector.update(
 +                        self.module_id,
 +                        &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
 +                        vis,
 +                        ImportType::Named,
 +                    )
 +                };
 +            let resolve_vis = |def_map: &DefMap, visibility| {
 +                def_map
 +                    .resolve_visibility(db, self.module_id, visibility)
 +                    .unwrap_or(Visibility::Public)
 +            };
 +
 +            match item {
 +                ModItem::Mod(m) => self.collect_module(m, &attrs),
 +                ModItem::Import(import_id) => {
 +                    let imports = Import::from_use(
 +                        db,
 +                        krate,
 +                        self.item_tree,
 +                        ItemTreeId::new(self.tree_id, import_id),
 +                    );
 +                    self.def_collector.unresolved_imports.extend(imports.into_iter().map(
 +                        |import| ImportDirective {
 +                            module_id: self.module_id,
 +                            import,
 +                            status: PartialResolvedImport::Unresolved,
 +                        },
 +                    ));
 +                }
 +                ModItem::ExternCrate(import_id) => {
 +                    self.def_collector.unresolved_imports.push(ImportDirective {
 +                        module_id: self.module_id,
 +                        import: Import::from_extern_crate(
 +                            db,
 +                            krate,
 +                            self.item_tree,
 +                            ItemTreeId::new(self.tree_id, import_id),
 +                        ),
 +                        status: PartialResolvedImport::Unresolved,
 +                    })
 +                }
 +                ModItem::ExternBlock(block) => self.collect(
 +                    &self.item_tree[block].children,
 +                    ItemContainerId::ExternBlockId(
 +                        ExternBlockLoc {
 +                            container: module,
 +                            id: ItemTreeId::new(self.tree_id, block),
 +                        }
 +                        .intern(db),
 +                    ),
 +                ),
 +                ModItem::MacroCall(mac) => self.collect_macro_call(&self.item_tree[mac], container),
 +                ModItem::MacroRules(id) => self.collect_macro_rules(id, module),
 +                ModItem::MacroDef(id) => self.collect_macro_def(id, module),
 +                ModItem::Impl(imp) => {
 +                    let impl_id =
 +                        ImplLoc { container: module, id: ItemTreeId::new(self.tree_id, imp) }
 +                            .intern(db);
 +                    self.def_collector.def_map.modules[self.module_id].scope.define_impl(impl_id)
 +                }
 +                ModItem::Function(id) => {
 +                    let it = &self.item_tree[id];
 +                    let fn_id =
 +                        FunctionLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
 +
 +                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
 +                    if self.def_collector.is_proc_macro {
 +                        if self.module_id == def_map.root {
 +                            if let Some(proc_macro) = attrs.parse_proc_macro_decl(&it.name) {
 +                                let crate_root = def_map.module_id(def_map.root);
 +                                self.def_collector.export_proc_macro(
 +                                    proc_macro,
 +                                    ItemTreeId::new(self.tree_id, id),
 +                                    fn_id,
 +                                    crate_root,
 +                                );
 +                            }
 +                        }
 +                    }
 +
 +                    update_def(self.def_collector, fn_id.into(), &it.name, vis, false);
 +                }
 +                ModItem::Struct(id) => {
 +                    let it = &self.item_tree[id];
 +
 +                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
 +                    update_def(
 +                        self.def_collector,
 +                        StructLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
 +                            .intern(db)
 +                            .into(),
 +                        &it.name,
 +                        vis,
 +                        !matches!(it.fields, Fields::Record(_)),
 +                    );
 +                }
 +                ModItem::Union(id) => {
 +                    let it = &self.item_tree[id];
 +
 +                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
 +                    update_def(
 +                        self.def_collector,
 +                        UnionLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
 +                            .intern(db)
 +                            .into(),
 +                        &it.name,
 +                        vis,
 +                        false,
 +                    );
 +                }
 +                ModItem::Enum(id) => {
 +                    let it = &self.item_tree[id];
 +
 +                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
 +                    update_def(
 +                        self.def_collector,
 +                        EnumLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
 +                            .intern(db)
 +                            .into(),
 +                        &it.name,
 +                        vis,
 +                        false,
 +                    );
 +                }
 +                ModItem::Const(id) => {
 +                    let it = &self.item_tree[id];
 +                    let const_id =
 +                        ConstLoc { container, id: ItemTreeId::new(self.tree_id, id) }.intern(db);
 +
 +                    match &it.name {
 +                        Some(name) => {
 +                            let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
 +                            update_def(self.def_collector, const_id.into(), name, vis, false);
 +                        }
 +                        None => {
 +                            // const _: T = ...;
 +                            self.def_collector.def_map.modules[self.module_id]
 +                                .scope
 +                                .define_unnamed_const(const_id);
 +                        }
 +                    }
 +                }
 +                ModItem::Static(id) => {
 +                    let it = &self.item_tree[id];
 +
 +                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
 +                    update_def(
 +                        self.def_collector,
 +                        StaticLoc { container, id: ItemTreeId::new(self.tree_id, id) }
 +                            .intern(db)
 +                            .into(),
 +                        &it.name,
 +                        vis,
 +                        false,
 +                    );
 +                }
 +                ModItem::Trait(id) => {
 +                    let it = &self.item_tree[id];
 +
 +                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
 +                    update_def(
 +                        self.def_collector,
 +                        TraitLoc { container: module, id: ItemTreeId::new(self.tree_id, id) }
 +                            .intern(db)
 +                            .into(),
 +                        &it.name,
 +                        vis,
 +                        false,
 +                    );
 +                }
 +                ModItem::TypeAlias(id) => {
 +                    let it = &self.item_tree[id];
 +
 +                    let vis = resolve_vis(def_map, &self.item_tree[it.visibility]);
 +                    update_def(
 +                        self.def_collector,
 +                        TypeAliasLoc { container, id: ItemTreeId::new(self.tree_id, id) }
 +                            .intern(db)
 +                            .into(),
 +                        &it.name,
 +                        vis,
 +                        false,
 +                    );
 +                }
 +            }
 +        }
 +    }
 +
 +    fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
 +        let path_attr = attrs.by_key("path").string_value();
 +        let is_macro_use = attrs.by_key("macro_use").exists();
 +        let module = &self.item_tree[module_id];
 +        match &module.kind {
 +            // inline module, just recurse
 +            ModKind::Inline { items } => {
 +                let module_id = self.push_child_module(
 +                    module.name.clone(),
 +                    AstId::new(self.file_id(), module.ast_id),
 +                    None,
 +                    &self.item_tree[module.visibility],
 +                    module_id,
 +                );
 +
 +                if let Some(mod_dir) = self.mod_dir.descend_into_definition(&module.name, path_attr)
 +                {
 +                    ModCollector {
 +                        def_collector: &mut *self.def_collector,
 +                        macro_depth: self.macro_depth,
 +                        module_id,
 +                        tree_id: self.tree_id,
 +                        item_tree: self.item_tree,
 +                        mod_dir,
 +                    }
 +                    .collect_in_top_module(&*items);
 +                    if is_macro_use {
 +                        self.import_all_legacy_macros(module_id);
 +                    }
 +                }
 +            }
 +            // out of line module, resolve, parse and recurse
 +            ModKind::Outline => {
 +                let ast_id = AstId::new(self.tree_id.file_id(), module.ast_id);
 +                let db = self.def_collector.db;
 +                match self.mod_dir.resolve_declaration(db, self.file_id(), &module.name, path_attr)
 +                {
 +                    Ok((file_id, is_mod_rs, mod_dir)) => {
 +                        let item_tree = db.file_item_tree(file_id.into());
 +                        let krate = self.def_collector.def_map.krate;
 +                        let is_enabled = item_tree
 +                            .top_level_attrs(db, krate)
 +                            .cfg()
 +                            .map_or(true, |cfg| self.is_cfg_enabled(&cfg));
 +                        if is_enabled {
 +                            let module_id = self.push_child_module(
 +                                module.name.clone(),
 +                                ast_id,
 +                                Some((file_id, is_mod_rs)),
 +                                &self.item_tree[module.visibility],
 +                                module_id,
 +                            );
 +                            ModCollector {
 +                                def_collector: self.def_collector,
 +                                macro_depth: self.macro_depth,
 +                                module_id,
 +                                tree_id: TreeId::new(file_id.into(), None),
 +                                item_tree: &item_tree,
 +                                mod_dir,
 +                            }
 +                            .collect_in_top_module(item_tree.top_level_items());
 +                            let is_macro_use = is_macro_use
 +                                || item_tree
 +                                    .top_level_attrs(db, krate)
 +                                    .by_key("macro_use")
 +                                    .exists();
 +                            if is_macro_use {
 +                                self.import_all_legacy_macros(module_id);
 +                            }
 +                        }
 +                    }
 +                    Err(candidates) => {
 +                        self.push_child_module(
 +                            module.name.clone(),
 +                            ast_id,
 +                            None,
 +                            &self.item_tree[module.visibility],
 +                            module_id,
 +                        );
 +                        self.def_collector.def_map.diagnostics.push(
 +                            DefDiagnostic::unresolved_module(self.module_id, ast_id, candidates),
 +                        );
 +                    }
 +                };
 +            }
 +        }
 +    }
 +
 +    fn push_child_module(
 +        &mut self,
 +        name: Name,
 +        declaration: AstId<ast::Module>,
 +        definition: Option<(FileId, bool)>,
 +        visibility: &crate::visibility::RawVisibility,
 +        mod_tree_id: FileItemTreeId<Mod>,
 +    ) -> LocalModuleId {
 +        let def_map = &mut self.def_collector.def_map;
 +        let vis = def_map
 +            .resolve_visibility(self.def_collector.db, self.module_id, visibility)
 +            .unwrap_or(Visibility::Public);
 +        let modules = &mut def_map.modules;
 +        let origin = match definition {
 +            None => ModuleOrigin::Inline {
 +                definition: declaration,
 +                definition_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id),
 +            },
 +            Some((definition, is_mod_rs)) => ModuleOrigin::File {
 +                declaration,
 +                definition,
 +                is_mod_rs,
 +                declaration_tree_id: ItemTreeId::new(self.tree_id, mod_tree_id),
 +            },
 +        };
 +
 +        let res = modules.alloc(ModuleData::new(origin, vis));
 +        modules[res].parent = Some(self.module_id);
 +        for (name, mac) in modules[self.module_id].scope.collect_legacy_macros() {
 +            for &mac in &mac {
 +                modules[res].scope.define_legacy_macro(name.clone(), mac);
 +            }
 +        }
 +        modules[self.module_id].children.insert(name.clone(), res);
 +
 +        let module = def_map.module_id(res);
 +        let def = ModuleDefId::from(module);
 +
 +        def_map.modules[self.module_id].scope.declare(def);
 +        self.def_collector.update(
 +            self.module_id,
 +            &[(Some(name), PerNs::from_def(def, vis, false))],
 +            vis,
 +            ImportType::Named,
 +        );
 +        res
 +    }
 +
 +    /// Resolves attributes on an item.
 +    ///
 +    /// Returns `Err` when some attributes could not be resolved to builtins and have been
 +    /// registered as unresolved.
 +    ///
 +    /// If `ignore_up_to` is `Some`, attributes preceding and including that attribute will be
 +    /// assumed to be resolved already.
 +    fn resolve_attributes(
 +        &mut self,
 +        attrs: &Attrs,
 +        mod_item: ModItem,
 +        container: ItemContainerId,
 +    ) -> Result<(), ()> {
 +        let mut ignore_up_to =
 +            self.def_collector.skip_attrs.get(&InFile::new(self.file_id(), mod_item)).copied();
 +        let iter = attrs
 +            .iter()
 +            .dedup_by(|a, b| {
 +                // FIXME: this should not be required, all attributes on an item should have a
 +                // unique ID!
 +                // Still, this occurs because `#[cfg_attr]` can "expand" to multiple attributes:
 +                //     #[cfg_attr(not(off), unresolved, unresolved)]
 +                //     struct S;
 +                // We should come up with a different way to ID attributes.
 +                a.id == b.id
 +            })
 +            .skip_while(|attr| match ignore_up_to {
 +                Some(id) if attr.id == id => {
 +                    ignore_up_to = None;
 +                    true
 +                }
 +                Some(_) => true,
 +                None => false,
 +            });
 +
 +        for attr in iter {
 +            if self.def_collector.def_map.is_builtin_or_registered_attr(&attr.path) {
 +                continue;
 +            }
 +            tracing::debug!("non-builtin attribute {}", attr.path);
 +
 +            let ast_id = AstIdWithPath::new(
 +                self.file_id(),
 +                mod_item.ast_id(self.item_tree),
 +                attr.path.as_ref().clone(),
 +            );
 +            self.def_collector.unresolved_macros.push(MacroDirective {
 +                module_id: self.module_id,
 +                depth: self.macro_depth + 1,
 +                kind: MacroDirectiveKind::Attr {
 +                    ast_id,
 +                    attr: attr.clone(),
 +                    mod_item,
 +                    tree: self.tree_id,
 +                },
 +                container,
 +            });
 +
 +            return Err(());
 +        }
 +
 +        Ok(())
 +    }
 +
 +    fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>, module: ModuleId) {
 +        let krate = self.def_collector.def_map.krate;
 +        let mac = &self.item_tree[id];
 +        let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
 +        let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast());
 +
 +        let export_attr = attrs.by_key("macro_export");
 +
 +        let is_export = export_attr.exists();
 +        let local_inner = if is_export {
 +            export_attr.tt_values().flat_map(|it| &it.token_trees).any(|it| match it {
 +                tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
 +                    ident.text.contains("local_inner_macros")
 +                }
 +                _ => false,
 +            })
 +        } else {
 +            false
 +        };
 +
 +        // Case 1: builtin macros
 +        let expander = if attrs.by_key("rustc_builtin_macro").exists() {
 +            // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
 +            let name;
 +            let name = match attrs.by_key("rustc_builtin_macro").string_value() {
 +                Some(it) => {
 +                    // FIXME: a hacky way to create a Name from string.
 +                    name = tt::Ident { text: it.clone(), id: tt::TokenId::unspecified() }.as_name();
 +                    &name
 +                }
 +                None => {
 +                    let explicit_name =
 +                        attrs.by_key("rustc_builtin_macro").tt_values().next().and_then(|tt| {
 +                            match tt.token_trees.first() {
 +                                Some(tt::TokenTree::Leaf(tt::Leaf::Ident(name))) => Some(name),
 +                                _ => None,
 +                            }
 +                        });
 +                    match explicit_name {
 +                        Some(ident) => {
 +                            name = ident.as_name();
 +                            &name
 +                        }
 +                        None => &mac.name,
 +                    }
 +                }
 +            };
 +            match find_builtin_macro(name) {
 +                Some(Either::Left(it)) => MacroExpander::BuiltIn(it),
 +                Some(Either::Right(it)) => MacroExpander::BuiltInEager(it),
 +                None => {
 +                    self.def_collector
 +                        .def_map
 +                        .diagnostics
 +                        .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
 +                    return;
 +                }
 +            }
 +        } else {
 +            // Case 2: normal `macro_rules!` macro
 +            MacroExpander::Declarative
 +        };
 +
 +        let macro_id = MacroRulesLoc {
 +            container: module,
 +            id: ItemTreeId::new(self.tree_id, id),
 +            local_inner,
 +            expander,
 +        }
 +        .intern(self.def_collector.db);
 +        self.def_collector.define_macro_rules(
 +            self.module_id,
 +            mac.name.clone(),
 +            macro_id,
 +            is_export,
 +        );
 +    }
 +
 +    fn collect_macro_def(&mut self, id: FileItemTreeId<MacroDef>, module: ModuleId) {
 +        let krate = self.def_collector.def_map.krate;
 +        let mac = &self.item_tree[id];
 +        let ast_id = InFile::new(self.file_id(), mac.ast_id.upcast());
 +
 +        // Case 1: builtin macros
 +        let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
 +        let expander = if attrs.by_key("rustc_builtin_macro").exists() {
 +            if let Some(expander) = find_builtin_macro(&mac.name) {
 +                match expander {
 +                    Either::Left(it) => MacroExpander::BuiltIn(it),
 +                    Either::Right(it) => MacroExpander::BuiltInEager(it),
 +                }
 +            } else if let Some(expander) = find_builtin_derive(&mac.name) {
 +                MacroExpander::BuiltInDerive(expander)
 +            } else if let Some(expander) = find_builtin_attr(&mac.name) {
 +                MacroExpander::BuiltInAttr(expander)
 +            } else {
 +                self.def_collector
 +                    .def_map
 +                    .diagnostics
 +                    .push(DefDiagnostic::unimplemented_builtin_macro(self.module_id, ast_id));
 +                return;
 +            }
 +        } else {
 +            // Case 2: normal `macro`
 +            MacroExpander::Declarative
 +        };
 +
 +        let macro_id =
 +            Macro2Loc { container: module, id: ItemTreeId::new(self.tree_id, id), expander }
 +                .intern(self.def_collector.db);
 +        self.def_collector.define_macro_def(
 +            self.module_id,
 +            mac.name.clone(),
 +            macro_id,
 +            &self.item_tree[mac.visibility],
 +        );
 +    }
 +
 +    fn collect_macro_call(&mut self, mac: &MacroCall, container: ItemContainerId) {
 +        let ast_id = AstIdWithPath::new(self.file_id(), mac.ast_id, ModPath::clone(&mac.path));
 +
 +        // Case 1: try to resolve in legacy scope and expand macro_rules
 +        let mut error = None;
 +        match macro_call_as_call_id(
 +            self.def_collector.db,
 +            &ast_id,
 +            mac.expand_to,
 +            self.def_collector.def_map.krate,
 +            |path| {
 +                path.as_ident().and_then(|name| {
 +                    self.def_collector.def_map.with_ancestor_maps(
 +                        self.def_collector.db,
 +                        self.module_id,
 +                        &mut |map, module| {
 +                            map[module]
 +                                .scope
 +                                .get_legacy_macro(name)
 +                                .and_then(|it| it.last())
 +                                .map(|&it| macro_id_to_def_id(self.def_collector.db, it.into()))
 +                        },
 +                    )
 +                })
 +            },
 +            &mut |err| {
 +                error.get_or_insert(err);
 +            },
 +        ) {
 +            Ok(Ok(macro_call_id)) => {
 +                // Legacy macros need to be expanded immediately, so that any macros they produce
 +                // are in scope.
 +                self.def_collector.collect_macro_expansion(
 +                    self.module_id,
 +                    macro_call_id,
 +                    self.macro_depth + 1,
 +                    container,
 +                );
 +
 +                if let Some(err) = error {
 +                    self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
 +                        self.module_id,
 +                        MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: mac.expand_to },
 +                        err.to_string(),
 +                    ));
 +                }
 +
 +                return;
 +            }
 +            Ok(Err(_)) => {
 +                // Built-in macro failed eager expansion.
 +
 +                self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
 +                    self.module_id,
 +                    MacroCallKind::FnLike { ast_id: ast_id.ast_id, expand_to: mac.expand_to },
 +                    error.unwrap().to_string(),
 +                ));
 +                return;
 +            }
 +            Err(UnresolvedMacro { .. }) => (),
 +        }
 +
 +        // Case 2: resolve in module scope, expand during name resolution.
 +        self.def_collector.unresolved_macros.push(MacroDirective {
 +            module_id: self.module_id,
 +            depth: self.macro_depth + 1,
 +            kind: MacroDirectiveKind::FnLike { ast_id, expand_to: mac.expand_to },
 +            container,
 +        });
 +    }
 +
 +    fn import_all_legacy_macros(&mut self, module_id: LocalModuleId) {
 +        let macros = self.def_collector.def_map[module_id].scope.collect_legacy_macros();
 +        for (name, macs) in macros {
 +            macs.last().map(|&mac| {
 +                self.def_collector.define_legacy_macro(self.module_id, name.clone(), mac)
 +            });
 +        }
 +    }
 +
 +    fn is_cfg_enabled(&self, cfg: &CfgExpr) -> bool {
 +        self.def_collector.cfg_options.check(cfg) != Some(false)
 +    }
 +
 +    fn emit_unconfigured_diagnostic(&mut self, item: ModItem, cfg: &CfgExpr) {
 +        let ast_id = item.ast_id(self.item_tree);
 +
 +        let ast_id = InFile::new(self.file_id(), ast_id);
 +        self.def_collector.def_map.diagnostics.push(DefDiagnostic::unconfigured_code(
 +            self.module_id,
 +            ast_id,
 +            cfg.clone(),
 +            self.def_collector.cfg_options.clone(),
 +        ));
 +    }
 +
 +    fn file_id(&self) -> HirFileId {
 +        self.tree_id.file_id()
 +    }
 +}
 +
 +#[cfg(test)]
 +mod tests {
 +    use crate::{db::DefDatabase, test_db::TestDB};
 +    use base_db::{fixture::WithFixture, SourceDatabase};
 +
 +    use super::*;
 +
 +    fn do_collect_defs(db: &dyn DefDatabase, def_map: DefMap) -> DefMap {
 +        let mut collector = DefCollector {
 +            db,
 +            def_map,
 +            deps: FxHashMap::default(),
 +            glob_imports: FxHashMap::default(),
 +            unresolved_imports: Vec::new(),
 +            indeterminate_imports: Vec::new(),
 +            unresolved_macros: Vec::new(),
 +            mod_dirs: FxHashMap::default(),
 +            cfg_options: &CfgOptions::default(),
 +            proc_macros: Default::default(),
 +            from_glob_import: Default::default(),
 +            skip_attrs: Default::default(),
 +            is_proc_macro: false,
 +        };
 +        collector.seed_with_top_level();
 +        collector.collect();
 +        collector.def_map
 +    }
 +
 +    fn do_resolve(not_ra_fixture: &str) -> DefMap {
 +        let (db, file_id) = TestDB::with_single_file(not_ra_fixture);
 +        let krate = db.test_crate();
 +
 +        let edition = db.crate_graph()[krate].edition;
 +        let module_origin = ModuleOrigin::CrateRoot { definition: file_id };
 +        let def_map =
 +            DefMap::empty(krate, edition, ModuleData::new(module_origin, Visibility::Public));
 +        do_collect_defs(&db, def_map)
 +    }
 +
 +    #[test]
 +    fn test_macro_expand_will_stop_1() {
 +        do_resolve(
 +            r#"
 +macro_rules! foo {
 +    ($($ty:ty)*) => { foo!($($ty)*); }
 +}
 +foo!(KABOOM);
 +"#,
 +        );
 +        do_resolve(
 +            r#"
 +macro_rules! foo {
 +    ($($ty:ty)*) => { foo!(() $($ty)*); }
 +}
 +foo!(KABOOM);
 +"#,
 +        );
 +    }
 +
 +    #[ignore]
 +    #[test]
 +    fn test_macro_expand_will_stop_2() {
 +        // FIXME: this test does succeed, but takes quite a while: 90 seconds in
 +        // the release mode. That's why the argument is not an ra_fixture --
 +        // otherwise injection highlighting gets stuck.
 +        //
 +        // We need to find a way to fail this faster.
 +        do_resolve(
 +            r#"
 +macro_rules! foo {
 +    ($($ty:ty)*) => { foo!($($ty)* $($ty)*); }
 +}
 +foo!(KABOOM);
 +"#,
 +        );
 +    }
 +}
index b0885ab003f71317db3669607aaf5515673a81f1,0000000000000000000000000000000000000000..a9c124b42dc2c112b3a04718f4c0d161fcb00afc
mode 100644,000000..100644
--- /dev/null
@@@ -1,353 -1,0 +1,358 @@@
 +//! Various extensions traits for Chalk types.
 +
 +use chalk_ir::{FloatTy, IntTy, Mutability, Scalar, UintTy};
 +use hir_def::{
 +    builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType, BuiltinUint},
 +    generics::TypeOrConstParamData,
 +    type_ref::Rawness,
 +    FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId,
 +};
 +use syntax::SmolStr;
 +
 +use crate::{
 +    db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
 +    from_placeholder_idx, to_chalk_trait_id, AdtId, AliasEq, AliasTy, Binders, CallableDefId,
 +    CallableSig, FnPointer, ImplTraitId, Interner, Lifetime, ProjectionTy, QuantifiedWhereClause,
 +    Substitution, TraitRef, Ty, TyBuilder, TyKind, WhereClause,
 +};
 +
 +pub trait TyExt {
 +    fn is_unit(&self) -> bool;
 +    fn is_never(&self) -> bool;
 +    fn is_unknown(&self) -> bool;
 +    fn is_ty_var(&self) -> bool;
 +
 +    fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>;
 +    fn as_builtin(&self) -> Option<BuiltinType>;
 +    fn as_tuple(&self) -> Option<&Substitution>;
 +    fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId>;
 +    fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>;
 +    fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)>;
 +    fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId>;
 +
 +    fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId>;
 +    fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig>;
 +
 +    fn strip_references(&self) -> &Ty;
++    fn strip_reference(&self) -> &Ty;
 +
 +    /// If this is a `dyn Trait`, returns that trait.
 +    fn dyn_trait(&self) -> Option<TraitId>;
 +
 +    fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>>;
 +    fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId>;
 +
 +    /// FIXME: Get rid of this, it's not a good abstraction
 +    fn equals_ctor(&self, other: &Ty) -> bool;
 +}
 +
 +impl TyExt for Ty {
 +    fn is_unit(&self) -> bool {
 +        matches!(self.kind(Interner), TyKind::Tuple(0, _))
 +    }
 +
 +    fn is_never(&self) -> bool {
 +        matches!(self.kind(Interner), TyKind::Never)
 +    }
 +
 +    fn is_unknown(&self) -> bool {
 +        matches!(self.kind(Interner), TyKind::Error)
 +    }
 +
 +    fn is_ty_var(&self) -> bool {
 +        matches!(self.kind(Interner), TyKind::InferenceVar(_, _))
 +    }
 +
 +    fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> {
 +        match self.kind(Interner) {
 +            TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
 +            _ => None,
 +        }
 +    }
 +
 +    fn as_builtin(&self) -> Option<BuiltinType> {
 +        match self.kind(Interner) {
 +            TyKind::Str => Some(BuiltinType::Str),
 +            TyKind::Scalar(Scalar::Bool) => Some(BuiltinType::Bool),
 +            TyKind::Scalar(Scalar::Char) => Some(BuiltinType::Char),
 +            TyKind::Scalar(Scalar::Float(fty)) => Some(BuiltinType::Float(match fty {
 +                FloatTy::F64 => BuiltinFloat::F64,
 +                FloatTy::F32 => BuiltinFloat::F32,
 +            })),
 +            TyKind::Scalar(Scalar::Int(ity)) => Some(BuiltinType::Int(match ity {
 +                IntTy::Isize => BuiltinInt::Isize,
 +                IntTy::I8 => BuiltinInt::I8,
 +                IntTy::I16 => BuiltinInt::I16,
 +                IntTy::I32 => BuiltinInt::I32,
 +                IntTy::I64 => BuiltinInt::I64,
 +                IntTy::I128 => BuiltinInt::I128,
 +            })),
 +            TyKind::Scalar(Scalar::Uint(ity)) => Some(BuiltinType::Uint(match ity {
 +                UintTy::Usize => BuiltinUint::Usize,
 +                UintTy::U8 => BuiltinUint::U8,
 +                UintTy::U16 => BuiltinUint::U16,
 +                UintTy::U32 => BuiltinUint::U32,
 +                UintTy::U64 => BuiltinUint::U64,
 +                UintTy::U128 => BuiltinUint::U128,
 +            })),
 +            _ => None,
 +        }
 +    }
 +
 +    fn as_tuple(&self) -> Option<&Substitution> {
 +        match self.kind(Interner) {
 +            TyKind::Tuple(_, substs) => Some(substs),
 +            _ => None,
 +        }
 +    }
 +
 +    fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> {
 +        match self.callable_def(db) {
 +            Some(CallableDefId::FunctionId(func)) => Some(func),
 +            Some(CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_)) | None => None,
 +        }
 +    }
 +    fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
 +        match self.kind(Interner) {
 +            TyKind::Ref(mutability, lifetime, ty) => Some((ty, lifetime.clone(), *mutability)),
 +            _ => None,
 +        }
 +    }
 +
 +    fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
 +        match self.kind(Interner) {
 +            TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)),
 +            TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
 +            _ => None,
 +        }
 +    }
 +
 +    fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
 +        match *self.kind(Interner) {
 +            TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
 +            TyKind::FnDef(callable, ..) => {
 +                Some(db.lookup_intern_callable_def(callable.into()).into())
 +            }
 +            TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()),
 +            TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()),
 +            _ => None,
 +        }
 +    }
 +
 +    fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> {
 +        match self.kind(Interner) {
 +            &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())),
 +            _ => None,
 +        }
 +    }
 +
 +    fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
 +        match self.kind(Interner) {
 +            TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
 +            TyKind::FnDef(def, parameters) => {
 +                let callable_def = db.lookup_intern_callable_def((*def).into());
 +                let sig = db.callable_item_signature(callable_def);
 +                Some(sig.substitute(Interner, &parameters))
 +            }
 +            TyKind::Closure(.., substs) => {
 +                let sig_param = substs.at(Interner, 0).assert_ty_ref(Interner);
 +                sig_param.callable_sig(db)
 +            }
 +            _ => None,
 +        }
 +    }
 +
 +    fn dyn_trait(&self) -> Option<TraitId> {
 +        let trait_ref = match self.kind(Interner) {
 +            TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| {
 +                match b.skip_binders() {
 +                    WhereClause::Implemented(trait_ref) => Some(trait_ref),
 +                    _ => None,
 +                }
 +            }),
 +            _ => None,
 +        }?;
 +        Some(from_chalk_trait_id(trait_ref.trait_id))
 +    }
 +
 +    fn strip_references(&self) -> &Ty {
 +        let mut t: &Ty = self;
 +        while let TyKind::Ref(_mutability, _lifetime, ty) = t.kind(Interner) {
 +            t = ty;
 +        }
 +        t
 +    }
 +
++    fn strip_reference(&self) -> &Ty {
++        self.as_reference().map_or(self, |(ty, _, _)| ty)
++    }
++
 +    fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
 +        match self.kind(Interner) {
 +            TyKind::OpaqueType(opaque_ty_id, subst) => {
 +                match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
 +                    ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
 +                        let krate = def.module(db.upcast()).krate();
 +                        if let Some(future_trait) = db
 +                            .lang_item(krate, SmolStr::new_inline("future_trait"))
 +                            .and_then(|item| item.as_trait())
 +                        {
 +                            // This is only used by type walking.
 +                            // Parameters will be walked outside, and projection predicate is not used.
 +                            // So just provide the Future trait.
 +                            let impl_bound = Binders::empty(
 +                                Interner,
 +                                WhereClause::Implemented(TraitRef {
 +                                    trait_id: to_chalk_trait_id(future_trait),
 +                                    substitution: Substitution::empty(Interner),
 +                                }),
 +                            );
 +                            Some(vec![impl_bound])
 +                        } else {
 +                            None
 +                        }
 +                    }
 +                    ImplTraitId::ReturnTypeImplTrait(func, idx) => {
 +                        db.return_type_impl_traits(func).map(|it| {
 +                            let data = (*it)
 +                                .as_ref()
 +                                .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
 +                            data.substitute(Interner, &subst).into_value_and_skipped_binders().0
 +                        })
 +                    }
 +                }
 +            }
 +            TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
 +                let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into())
 +                {
 +                    ImplTraitId::ReturnTypeImplTrait(func, idx) => {
 +                        db.return_type_impl_traits(func).map(|it| {
 +                            let data = (*it)
 +                                .as_ref()
 +                                .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
 +                            data.substitute(Interner, &opaque_ty.substitution)
 +                        })
 +                    }
 +                    // It always has an parameter for Future::Output type.
 +                    ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
 +                };
 +
 +                predicates.map(|it| it.into_value_and_skipped_binders().0)
 +            }
 +            TyKind::Placeholder(idx) => {
 +                let id = from_placeholder_idx(db, *idx);
 +                let generic_params = db.generic_params(id.parent);
 +                let param_data = &generic_params.type_or_consts[id.local_id];
 +                match param_data {
 +                    TypeOrConstParamData::TypeParamData(p) => match p.provenance {
 +                        hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
 +                            let substs = TyBuilder::placeholder_subst(db, id.parent);
 +                            let predicates = db
 +                                .generic_predicates(id.parent)
 +                                .iter()
 +                                .map(|pred| pred.clone().substitute(Interner, &substs))
 +                                .filter(|wc| match &wc.skip_binders() {
 +                                    WhereClause::Implemented(tr) => {
 +                                        &tr.self_type_parameter(Interner) == self
 +                                    }
 +                                    WhereClause::AliasEq(AliasEq {
 +                                        alias: AliasTy::Projection(proj),
 +                                        ty: _,
 +                                    }) => &proj.self_type_parameter(Interner) == self,
 +                                    _ => false,
 +                                })
 +                                .collect::<Vec<_>>();
 +
 +                            Some(predicates)
 +                        }
 +                        _ => None,
 +                    },
 +                    _ => None,
 +                }
 +            }
 +            _ => None,
 +        }
 +    }
 +
 +    fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
 +        match self.kind(Interner) {
 +            TyKind::AssociatedType(id, ..) => {
 +                match from_assoc_type_id(*id).lookup(db.upcast()).container {
 +                    ItemContainerId::TraitId(trait_id) => Some(trait_id),
 +                    _ => None,
 +                }
 +            }
 +            TyKind::Alias(AliasTy::Projection(projection_ty)) => {
 +                match from_assoc_type_id(projection_ty.associated_ty_id)
 +                    .lookup(db.upcast())
 +                    .container
 +                {
 +                    ItemContainerId::TraitId(trait_id) => Some(trait_id),
 +                    _ => None,
 +                }
 +            }
 +            _ => None,
 +        }
 +    }
 +
 +    fn equals_ctor(&self, other: &Ty) -> bool {
 +        match (self.kind(Interner), other.kind(Interner)) {
 +            (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2,
 +            (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_, _), TyKind::Array(_, _)) => {
 +                true
 +            }
 +            (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
 +            (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
 +            (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => {
 +                ty_id == ty_id2
 +            }
 +            (TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2,
 +            (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2,
 +            (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..))
 +            | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => {
 +                mutability == mutability2
 +            }
 +            (
 +                TyKind::Function(FnPointer { num_binders, sig, .. }),
 +                TyKind::Function(FnPointer { num_binders: num_binders2, sig: sig2, .. }),
 +            ) => num_binders == num_binders2 && sig == sig2,
 +            (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => {
 +                cardinality == cardinality2
 +            }
 +            (TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true,
 +            (TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2,
 +            _ => false,
 +        }
 +    }
 +}
 +
 +pub trait ProjectionTyExt {
 +    fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef;
 +    fn trait_(&self, db: &dyn HirDatabase) -> TraitId;
 +}
 +
 +impl ProjectionTyExt for ProjectionTy {
 +    fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
 +        TraitRef {
 +            trait_id: to_chalk_trait_id(self.trait_(db)),
 +            substitution: self.substitution.clone(),
 +        }
 +    }
 +
 +    fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
 +        match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container {
 +            ItemContainerId::TraitId(it) => it,
 +            _ => panic!("projection ty without parent trait"),
 +        }
 +    }
 +}
 +
 +pub trait TraitRefExt {
 +    fn hir_trait_id(&self) -> TraitId;
 +}
 +
 +impl TraitRefExt for TraitRef {
 +    fn hir_trait_id(&self) -> TraitId {
 +        from_chalk_trait_id(self.trait_id)
 +    }
 +}
index d4925455d7bd2dcf4c7d90df5a0d2d6bfb41e9bc,0000000000000000000000000000000000000000..8f984210e1176702c1ce23c865ed8aca631a4c82
mode 100644,000000..100644
--- /dev/null
@@@ -1,3635 -1,0 +1,3639 @@@
 +//! HIR (previously known as descriptors) provides a high-level object oriented
 +//! access to Rust code.
 +//!
 +//! The principal difference between HIR and syntax trees is that HIR is bound
 +//! to a particular crate instance. That is, it has cfg flags and features
 +//! applied. So, the relation between syntax and HIR is many-to-one.
 +//!
 +//! HIR is the public API of the all of the compiler logic above syntax trees.
 +//! It is written in "OO" style. Each type is self contained (as in, it knows it's
 +//! parents and full context). It should be "clean code".
 +//!
 +//! `hir_*` crates are the implementation of the compiler logic.
 +//! They are written in "ECS" style, with relatively little abstractions.
 +//! Many types are not self-contained, and explicitly use local indexes, arenas, etc.
 +//!
 +//! `hir` is what insulates the "we don't know how to actually write an incremental compiler"
 +//! from the ide with completions, hovers, etc. It is a (soft, internal) boundary:
 +//! <https://www.tedinski.com/2018/02/06/system-boundaries.html>.
 +
 +#![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
 +#![recursion_limit = "512"]
 +
 +mod semantics;
 +mod source_analyzer;
 +
 +mod from_id;
 +mod attrs;
 +mod has_source;
 +
 +pub mod diagnostics;
 +pub mod db;
 +pub mod symbols;
 +
 +mod display;
 +
 +use std::{iter, ops::ControlFlow, sync::Arc};
 +
 +use arrayvec::ArrayVec;
 +use base_db::{CrateDisplayName, CrateId, CrateOrigin, Edition, FileId, ProcMacroKind};
 +use either::Either;
 +use hir_def::{
 +    adt::{ReprKind, VariantData},
 +    body::{BodyDiagnostic, SyntheticSyntax},
 +    expr::{BindingAnnotation, LabelId, Pat, PatId},
 +    generics::{TypeOrConstParamData, TypeParamProvenance},
 +    item_tree::ItemTreeNode,
 +    lang_item::LangItemTarget,
 +    nameres::{self, diagnostics::DefDiagnostic},
 +    per_ns::PerNs,
 +    resolver::{HasResolver, Resolver},
 +    src::HasSource as _,
 +    AdtId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, DefWithBodyId, EnumId,
 +    FunctionId, GenericDefId, HasModule, ImplId, ItemContainerId, LifetimeParamId,
 +    LocalEnumVariantId, LocalFieldId, Lookup, MacroExpander, MacroId, ModuleId, StaticId, StructId,
 +    TraitId, TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId,
 +};
 +use hir_expand::{name::name, MacroCallKind};
 +use hir_ty::{
 +    all_super_traits, autoderef,
 +    consteval::{unknown_const_as_generic, ComputedExpr, ConstEvalError, ConstExt},
 +    diagnostics::BodyValidationDiagnostic,
 +    method_resolution::{self, TyFingerprint},
 +    primitive::UintTy,
 +    subst_prefix,
 +    traits::FnTrait,
 +    AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
 +    ClosureId, DebruijnIndex, GenericArgData, InEnvironment, Interner, ParamKind,
 +    QuantifiedWhereClause, Scalar, Solution, Substitution, TraitEnvironment, TraitRefExt, Ty,
 +    TyBuilder, TyDefId, TyExt, TyKind, TyVariableKind, WhereClause,
 +};
 +use itertools::Itertools;
 +use nameres::diagnostics::DefDiagnosticKind;
 +use once_cell::unsync::Lazy;
 +use rustc_hash::FxHashSet;
 +use stdx::{format_to, impl_from, never};
 +use syntax::{
 +    ast::{self, HasAttrs as _, HasDocComments, HasName},
 +    AstNode, AstPtr, SmolStr, SyntaxNodePtr, TextRange, T,
 +};
 +
 +use crate::db::{DefDatabase, HirDatabase};
 +
 +pub use crate::{
 +    attrs::{HasAttrs, Namespace},
 +    diagnostics::{
 +        AnyDiagnostic, BreakOutsideOfLoop, InactiveCode, IncorrectCase, InvalidDeriveTarget,
 +        MacroError, MalformedDerive, MismatchedArgCount, MissingFields, MissingMatchArms,
 +        MissingUnsafe, NoSuchField, ReplaceFilterMapNextWithFindMap, TypeMismatch,
 +        UnimplementedBuiltinMacro, UnresolvedExternCrate, UnresolvedImport, UnresolvedMacroCall,
 +        UnresolvedModule, UnresolvedProcMacro,
 +    },
 +    has_source::HasSource,
 +    semantics::{PathResolution, Semantics, SemanticsScope, TypeInfo, VisibleTraits},
 +};
 +
 +// Be careful with these re-exports.
 +//
 +// `hir` is the boundary between the compiler and the IDE. It should try hard to
 +// isolate the compiler from the ide, to allow the two to be refactored
 +// independently. Re-exporting something from the compiler is the sure way to
 +// breach the boundary.
 +//
 +// Generally, a refactoring which *removes* a name from this list is a good
 +// idea!
 +pub use {
 +    cfg::{CfgAtom, CfgExpr, CfgOptions},
 +    hir_def::{
 +        adt::StructKind,
 +        attr::{Attr, Attrs, AttrsWithOwner, Documentation},
 +        builtin_attr::AttributeTemplate,
 +        find_path::PrefixKind,
 +        import_map,
 +        nameres::ModuleSource,
 +        path::{ModPath, PathKind},
 +        type_ref::{Mutability, TypeRef},
 +        visibility::Visibility,
 +    },
 +    hir_expand::{
 +        name::{known, Name},
 +        ExpandResult, HirFileId, InFile, MacroFile, Origin,
 +    },
 +    hir_ty::display::HirDisplay,
 +};
 +
 +// These are negative re-exports: pub using these names is forbidden, they
 +// should remain private to hir internals.
 +#[allow(unused)]
 +use {
 +    hir_def::path::Path,
 +    hir_expand::{hygiene::Hygiene, name::AsName},
 +};
 +
 +/// hir::Crate describes a single crate. It's the main interface with which
 +/// a crate's dependencies interact. Mostly, it should be just a proxy for the
 +/// root module.
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Crate {
 +    pub(crate) id: CrateId,
 +}
 +
 +#[derive(Debug)]
 +pub struct CrateDependency {
 +    pub krate: Crate,
 +    pub name: Name,
 +}
 +
 +impl Crate {
 +    pub fn origin(self, db: &dyn HirDatabase) -> CrateOrigin {
 +        db.crate_graph()[self.id].origin.clone()
 +    }
 +
 +    pub fn is_builtin(self, db: &dyn HirDatabase) -> bool {
 +        matches!(self.origin(db), CrateOrigin::Lang(_))
 +    }
 +
 +    pub fn dependencies(self, db: &dyn HirDatabase) -> Vec<CrateDependency> {
 +        db.crate_graph()[self.id]
 +            .dependencies
 +            .iter()
 +            .map(|dep| {
 +                let krate = Crate { id: dep.crate_id };
 +                let name = dep.as_name();
 +                CrateDependency { krate, name }
 +            })
 +            .collect()
 +    }
 +
 +    pub fn reverse_dependencies(self, db: &dyn HirDatabase) -> Vec<Crate> {
 +        let crate_graph = db.crate_graph();
 +        crate_graph
 +            .iter()
 +            .filter(|&krate| {
 +                crate_graph[krate].dependencies.iter().any(|it| it.crate_id == self.id)
 +            })
 +            .map(|id| Crate { id })
 +            .collect()
 +    }
 +
 +    pub fn transitive_reverse_dependencies(
 +        self,
 +        db: &dyn HirDatabase,
 +    ) -> impl Iterator<Item = Crate> {
 +        db.crate_graph().transitive_rev_deps(self.id).map(|id| Crate { id })
 +    }
 +
 +    pub fn root_module(self, db: &dyn HirDatabase) -> Module {
 +        let def_map = db.crate_def_map(self.id);
 +        Module { id: def_map.module_id(def_map.root()) }
 +    }
 +
 +    pub fn modules(self, db: &dyn HirDatabase) -> Vec<Module> {
 +        let def_map = db.crate_def_map(self.id);
 +        def_map.modules().map(|(id, _)| def_map.module_id(id).into()).collect()
 +    }
 +
 +    pub fn root_file(self, db: &dyn HirDatabase) -> FileId {
 +        db.crate_graph()[self.id].root_file_id
 +    }
 +
 +    pub fn edition(self, db: &dyn HirDatabase) -> Edition {
 +        db.crate_graph()[self.id].edition
 +    }
 +
 +    pub fn version(self, db: &dyn HirDatabase) -> Option<String> {
 +        db.crate_graph()[self.id].version.clone()
 +    }
 +
 +    pub fn display_name(self, db: &dyn HirDatabase) -> Option<CrateDisplayName> {
 +        db.crate_graph()[self.id].display_name.clone()
 +    }
 +
 +    pub fn query_external_importables(
 +        self,
 +        db: &dyn DefDatabase,
 +        query: import_map::Query,
 +    ) -> impl Iterator<Item = Either<ModuleDef, Macro>> {
 +        let _p = profile::span("query_external_importables");
 +        import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| {
 +            match ItemInNs::from(item) {
 +                ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id),
 +                ItemInNs::Macros(mac_id) => Either::Right(mac_id),
 +            }
 +        })
 +    }
 +
 +    pub fn all(db: &dyn HirDatabase) -> Vec<Crate> {
 +        db.crate_graph().iter().map(|id| Crate { id }).collect()
 +    }
 +
 +    /// Try to get the root URL of the documentation of a crate.
 +    pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
 +        // Look for #![doc(html_root_url = "...")]
 +        let attrs = db.attrs(AttrDefId::ModuleId(self.root_module(db).into()));
 +        let doc_url = attrs.by_key("doc").find_string_value_in_tt("html_root_url");
 +        doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
 +    }
 +
 +    pub fn cfg(&self, db: &dyn HirDatabase) -> CfgOptions {
 +        db.crate_graph()[self.id].cfg_options.clone()
 +    }
 +
 +    pub fn potential_cfg(&self, db: &dyn HirDatabase) -> CfgOptions {
 +        db.crate_graph()[self.id].potential_cfg_options.clone()
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Module {
 +    pub(crate) id: ModuleId,
 +}
 +
 +/// The defs which can be visible in the module.
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub enum ModuleDef {
 +    Module(Module),
 +    Function(Function),
 +    Adt(Adt),
 +    // Can't be directly declared, but can be imported.
 +    Variant(Variant),
 +    Const(Const),
 +    Static(Static),
 +    Trait(Trait),
 +    TypeAlias(TypeAlias),
 +    BuiltinType(BuiltinType),
 +    Macro(Macro),
 +}
 +impl_from!(
 +    Module,
 +    Function,
 +    Adt(Struct, Enum, Union),
 +    Variant,
 +    Const,
 +    Static,
 +    Trait,
 +    TypeAlias,
 +    BuiltinType,
 +    Macro
 +    for ModuleDef
 +);
 +
 +impl From<VariantDef> for ModuleDef {
 +    fn from(var: VariantDef) -> Self {
 +        match var {
 +            VariantDef::Struct(t) => Adt::from(t).into(),
 +            VariantDef::Union(t) => Adt::from(t).into(),
 +            VariantDef::Variant(t) => t.into(),
 +        }
 +    }
 +}
 +
 +impl ModuleDef {
 +    pub fn module(self, db: &dyn HirDatabase) -> Option<Module> {
 +        match self {
 +            ModuleDef::Module(it) => it.parent(db),
 +            ModuleDef::Function(it) => Some(it.module(db)),
 +            ModuleDef::Adt(it) => Some(it.module(db)),
 +            ModuleDef::Variant(it) => Some(it.module(db)),
 +            ModuleDef::Const(it) => Some(it.module(db)),
 +            ModuleDef::Static(it) => Some(it.module(db)),
 +            ModuleDef::Trait(it) => Some(it.module(db)),
 +            ModuleDef::TypeAlias(it) => Some(it.module(db)),
 +            ModuleDef::Macro(it) => Some(it.module(db)),
 +            ModuleDef::BuiltinType(_) => None,
 +        }
 +    }
 +
 +    pub fn canonical_path(&self, db: &dyn HirDatabase) -> Option<String> {
 +        let mut segments = vec![self.name(db)?];
 +        for m in self.module(db)?.path_to_root(db) {
 +            segments.extend(m.name(db))
 +        }
 +        segments.reverse();
 +        Some(segments.into_iter().join("::"))
 +    }
 +
 +    pub fn canonical_module_path(
 +        &self,
 +        db: &dyn HirDatabase,
 +    ) -> Option<impl Iterator<Item = Module>> {
 +        self.module(db).map(|it| it.path_to_root(db).into_iter().rev())
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
 +        let name = match self {
 +            ModuleDef::Module(it) => it.name(db)?,
 +            ModuleDef::Const(it) => it.name(db)?,
 +            ModuleDef::Adt(it) => it.name(db),
 +            ModuleDef::Trait(it) => it.name(db),
 +            ModuleDef::Function(it) => it.name(db),
 +            ModuleDef::Variant(it) => it.name(db),
 +            ModuleDef::TypeAlias(it) => it.name(db),
 +            ModuleDef::Static(it) => it.name(db),
 +            ModuleDef::Macro(it) => it.name(db),
 +            ModuleDef::BuiltinType(it) => it.name(),
 +        };
 +        Some(name)
 +    }
 +
 +    pub fn diagnostics(self, db: &dyn HirDatabase) -> Vec<AnyDiagnostic> {
 +        let id = match self {
 +            ModuleDef::Adt(it) => match it {
 +                Adt::Struct(it) => it.id.into(),
 +                Adt::Enum(it) => it.id.into(),
 +                Adt::Union(it) => it.id.into(),
 +            },
 +            ModuleDef::Trait(it) => it.id.into(),
 +            ModuleDef::Function(it) => it.id.into(),
 +            ModuleDef::TypeAlias(it) => it.id.into(),
 +            ModuleDef::Module(it) => it.id.into(),
 +            ModuleDef::Const(it) => it.id.into(),
 +            ModuleDef::Static(it) => it.id.into(),
 +            _ => return Vec::new(),
 +        };
 +
 +        let module = match self.module(db) {
 +            Some(it) => it,
 +            None => return Vec::new(),
 +        };
 +
 +        let mut acc = Vec::new();
 +
 +        match self.as_def_with_body() {
 +            Some(def) => {
 +                def.diagnostics(db, &mut acc);
 +            }
 +            None => {
 +                for diag in hir_ty::diagnostics::incorrect_case(db, module.id.krate(), id) {
 +                    acc.push(diag.into())
 +                }
 +            }
 +        }
 +
 +        acc
 +    }
 +
 +    pub fn as_def_with_body(self) -> Option<DefWithBody> {
 +        match self {
 +            ModuleDef::Function(it) => Some(it.into()),
 +            ModuleDef::Const(it) => Some(it.into()),
 +            ModuleDef::Static(it) => Some(it.into()),
 +
 +            ModuleDef::Module(_)
 +            | ModuleDef::Adt(_)
 +            | ModuleDef::Variant(_)
 +            | ModuleDef::Trait(_)
 +            | ModuleDef::TypeAlias(_)
 +            | ModuleDef::Macro(_)
 +            | ModuleDef::BuiltinType(_) => None,
 +        }
 +    }
 +
 +    pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
 +        Some(match self {
 +            ModuleDef::Module(it) => it.attrs(db),
 +            ModuleDef::Function(it) => it.attrs(db),
 +            ModuleDef::Adt(it) => it.attrs(db),
 +            ModuleDef::Variant(it) => it.attrs(db),
 +            ModuleDef::Const(it) => it.attrs(db),
 +            ModuleDef::Static(it) => it.attrs(db),
 +            ModuleDef::Trait(it) => it.attrs(db),
 +            ModuleDef::TypeAlias(it) => it.attrs(db),
 +            ModuleDef::Macro(it) => it.attrs(db),
 +            ModuleDef::BuiltinType(_) => return None,
 +        })
 +    }
 +}
 +
 +impl HasVisibility for ModuleDef {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        match *self {
 +            ModuleDef::Module(it) => it.visibility(db),
 +            ModuleDef::Function(it) => it.visibility(db),
 +            ModuleDef::Adt(it) => it.visibility(db),
 +            ModuleDef::Const(it) => it.visibility(db),
 +            ModuleDef::Static(it) => it.visibility(db),
 +            ModuleDef::Trait(it) => it.visibility(db),
 +            ModuleDef::TypeAlias(it) => it.visibility(db),
 +            ModuleDef::Variant(it) => it.visibility(db),
 +            ModuleDef::Macro(it) => it.visibility(db),
 +            ModuleDef::BuiltinType(_) => Visibility::Public,
 +        }
 +    }
 +}
 +
 +impl Module {
 +    /// Name of this module.
 +    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
 +        let def_map = self.id.def_map(db.upcast());
 +        let parent = def_map[self.id.local_id].parent?;
 +        def_map[parent].children.iter().find_map(|(name, module_id)| {
 +            if *module_id == self.id.local_id {
 +                Some(name.clone())
 +            } else {
 +                None
 +            }
 +        })
 +    }
 +
 +    /// Returns the crate this module is part of.
 +    pub fn krate(self) -> Crate {
 +        Crate { id: self.id.krate() }
 +    }
 +
 +    /// Topmost parent of this module. Every module has a `crate_root`, but some
 +    /// might be missing `krate`. This can happen if a module's file is not included
 +    /// in the module tree of any target in `Cargo.toml`.
 +    pub fn crate_root(self, db: &dyn HirDatabase) -> Module {
 +        let def_map = db.crate_def_map(self.id.krate());
 +        Module { id: def_map.module_id(def_map.root()) }
 +    }
 +
 +    pub fn is_crate_root(self, db: &dyn HirDatabase) -> bool {
 +        let def_map = db.crate_def_map(self.id.krate());
 +        def_map.root() == self.id.local_id
 +    }
 +
 +    /// Iterates over all child modules.
 +    pub fn children(self, db: &dyn HirDatabase) -> impl Iterator<Item = Module> {
 +        let def_map = self.id.def_map(db.upcast());
 +        let children = def_map[self.id.local_id]
 +            .children
 +            .iter()
 +            .map(|(_, module_id)| Module { id: def_map.module_id(*module_id) })
 +            .collect::<Vec<_>>();
 +        children.into_iter()
 +    }
 +
 +    /// Finds a parent module.
 +    pub fn parent(self, db: &dyn HirDatabase) -> Option<Module> {
 +        // FIXME: handle block expressions as modules (their parent is in a different DefMap)
 +        let def_map = self.id.def_map(db.upcast());
 +        let parent_id = def_map[self.id.local_id].parent?;
 +        Some(Module { id: def_map.module_id(parent_id) })
 +    }
 +
 +    pub fn path_to_root(self, db: &dyn HirDatabase) -> Vec<Module> {
 +        let mut res = vec![self];
 +        let mut curr = self;
 +        while let Some(next) = curr.parent(db) {
 +            res.push(next);
 +            curr = next
 +        }
 +        res
 +    }
 +
 +    /// Returns a `ModuleScope`: a set of items, visible in this module.
 +    pub fn scope(
 +        self,
 +        db: &dyn HirDatabase,
 +        visible_from: Option<Module>,
 +    ) -> Vec<(Name, ScopeDef)> {
 +        self.id.def_map(db.upcast())[self.id.local_id]
 +            .scope
 +            .entries()
 +            .filter_map(|(name, def)| {
 +                if let Some(m) = visible_from {
 +                    let filtered =
 +                        def.filter_visibility(|vis| vis.is_visible_from(db.upcast(), m.id));
 +                    if filtered.is_none() && !def.is_none() {
 +                        None
 +                    } else {
 +                        Some((name, filtered))
 +                    }
 +                } else {
 +                    Some((name, def))
 +                }
 +            })
 +            .flat_map(|(name, def)| {
 +                ScopeDef::all_items(def).into_iter().map(move |item| (name.clone(), item))
 +            })
 +            .collect()
 +    }
 +
 +    pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
 +        let _p = profile::span("Module::diagnostics").detail(|| {
 +            format!("{:?}", self.name(db).map_or("<unknown>".into(), |name| name.to_string()))
 +        });
 +        let def_map = self.id.def_map(db.upcast());
 +        for diag in def_map.diagnostics() {
 +            if diag.in_module != self.id.local_id {
 +                // FIXME: This is accidentally quadratic.
 +                continue;
 +            }
 +            emit_def_diagnostic(db, acc, diag);
 +        }
 +        for decl in self.declarations(db) {
 +            match decl {
 +                ModuleDef::Module(m) => {
 +                    // Only add diagnostics from inline modules
 +                    if def_map[m.id.local_id].origin.is_inline() {
 +                        m.diagnostics(db, acc)
 +                    }
 +                }
 +                _ => acc.extend(decl.diagnostics(db)),
 +            }
 +        }
 +
 +        for impl_def in self.impl_defs(db) {
 +            for item in impl_def.items(db) {
 +                let def: DefWithBody = match item {
 +                    AssocItem::Function(it) => it.into(),
 +                    AssocItem::Const(it) => it.into(),
 +                    AssocItem::TypeAlias(_) => continue,
 +                };
 +
 +                def.diagnostics(db, acc);
 +            }
 +        }
 +    }
 +
 +    pub fn declarations(self, db: &dyn HirDatabase) -> Vec<ModuleDef> {
 +        let def_map = self.id.def_map(db.upcast());
 +        let scope = &def_map[self.id.local_id].scope;
 +        scope
 +            .declarations()
 +            .map(ModuleDef::from)
 +            .chain(scope.unnamed_consts().map(|id| ModuleDef::Const(Const::from(id))))
 +            .collect()
 +    }
 +
 +    pub fn legacy_macros(self, db: &dyn HirDatabase) -> Vec<Macro> {
 +        let def_map = self.id.def_map(db.upcast());
 +        let scope = &def_map[self.id.local_id].scope;
 +        scope.legacy_macros().flat_map(|(_, it)| it).map(|&it| MacroId::from(it).into()).collect()
 +    }
 +
 +    pub fn impl_defs(self, db: &dyn HirDatabase) -> Vec<Impl> {
 +        let def_map = self.id.def_map(db.upcast());
 +        def_map[self.id.local_id].scope.impls().map(Impl::from).collect()
 +    }
 +
 +    /// Finds a path that can be used to refer to the given item from within
 +    /// this module, if possible.
 +    pub fn find_use_path(self, db: &dyn DefDatabase, item: impl Into<ItemInNs>) -> Option<ModPath> {
 +        hir_def::find_path::find_path(db, item.into().into(), self.into())
 +    }
 +
 +    /// Finds a path that can be used to refer to the given item from within
 +    /// this module, if possible. This is used for returning import paths for use-statements.
 +    pub fn find_use_path_prefixed(
 +        self,
 +        db: &dyn DefDatabase,
 +        item: impl Into<ItemInNs>,
 +        prefix_kind: PrefixKind,
 +    ) -> Option<ModPath> {
 +        hir_def::find_path::find_path_prefixed(db, item.into().into(), self.into(), prefix_kind)
 +    }
 +}
 +
 +fn emit_def_diagnostic(db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>, diag: &DefDiagnostic) {
 +    match &diag.kind {
 +        DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => {
 +            let decl = declaration.to_node(db.upcast());
 +            acc.push(
 +                UnresolvedModule {
 +                    decl: InFile::new(declaration.file_id, AstPtr::new(&decl)),
 +                    candidates: candidates.clone(),
 +                }
 +                .into(),
 +            )
 +        }
 +        DefDiagnosticKind::UnresolvedExternCrate { ast } => {
 +            let item = ast.to_node(db.upcast());
 +            acc.push(
 +                UnresolvedExternCrate { decl: InFile::new(ast.file_id, AstPtr::new(&item)) }.into(),
 +            );
 +        }
 +
 +        DefDiagnosticKind::UnresolvedImport { id, index } => {
 +            let file_id = id.file_id();
 +            let item_tree = id.item_tree(db.upcast());
 +            let import = &item_tree[id.value];
 +
 +            let use_tree = import.use_tree_to_ast(db.upcast(), file_id, *index);
 +            acc.push(
 +                UnresolvedImport { decl: InFile::new(file_id, AstPtr::new(&use_tree)) }.into(),
 +            );
 +        }
 +
 +        DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
 +            let item = ast.to_node(db.upcast());
 +            acc.push(
 +                InactiveCode {
 +                    node: ast.with_value(AstPtr::new(&item).into()),
 +                    cfg: cfg.clone(),
 +                    opts: opts.clone(),
 +                }
 +                .into(),
 +            );
 +        }
 +
 +        DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {
 +            let (node, precise_location, macro_name, kind) = precise_macro_call_location(ast, db);
 +            acc.push(
 +                UnresolvedProcMacro { node, precise_location, macro_name, kind, krate: *krate }
 +                    .into(),
 +            );
 +        }
 +
 +        DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
 +            let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
 +            acc.push(
 +                UnresolvedMacroCall {
 +                    macro_call: node,
 +                    precise_location,
 +                    path: path.clone(),
 +                    is_bang: matches!(ast, MacroCallKind::FnLike { .. }),
 +                }
 +                .into(),
 +            );
 +        }
 +
 +        DefDiagnosticKind::MacroError { ast, message } => {
 +            let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
 +            acc.push(MacroError { node, precise_location, message: message.clone() }.into());
 +        }
 +
 +        DefDiagnosticKind::UnimplementedBuiltinMacro { ast } => {
 +            let node = ast.to_node(db.upcast());
 +            // Must have a name, otherwise we wouldn't emit it.
 +            let name = node.name().expect("unimplemented builtin macro with no name");
 +            acc.push(
 +                UnimplementedBuiltinMacro {
 +                    node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&name))),
 +                }
 +                .into(),
 +            );
 +        }
 +        DefDiagnosticKind::InvalidDeriveTarget { ast, id } => {
 +            let node = ast.to_node(db.upcast());
 +            let derive = node.attrs().nth(*id as usize);
 +            match derive {
 +                Some(derive) => {
 +                    acc.push(
 +                        InvalidDeriveTarget {
 +                            node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
 +                        }
 +                        .into(),
 +                    );
 +                }
 +                None => stdx::never!("derive diagnostic on item without derive attribute"),
 +            }
 +        }
 +        DefDiagnosticKind::MalformedDerive { ast, id } => {
 +            let node = ast.to_node(db.upcast());
 +            let derive = node.attrs().nth(*id as usize);
 +            match derive {
 +                Some(derive) => {
 +                    acc.push(
 +                        MalformedDerive {
 +                            node: ast.with_value(SyntaxNodePtr::from(AstPtr::new(&derive))),
 +                        }
 +                        .into(),
 +                    );
 +                }
 +                None => stdx::never!("derive diagnostic on item without derive attribute"),
 +            }
 +        }
 +    }
 +}
 +
 +fn precise_macro_call_location(
 +    ast: &MacroCallKind,
 +    db: &dyn HirDatabase,
 +) -> (InFile<SyntaxNodePtr>, Option<TextRange>, Option<String>, MacroKind) {
 +    // FIXME: maaybe we actually want slightly different ranges for the different macro diagnostics
 +    // - e.g. the full attribute for macro errors, but only the name for name resolution
 +    match ast {
 +        MacroCallKind::FnLike { ast_id, .. } => {
 +            let node = ast_id.to_node(db.upcast());
 +            (
 +                ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
 +                node.path()
 +                    .and_then(|it| it.segment())
 +                    .and_then(|it| it.name_ref())
 +                    .map(|it| it.syntax().text_range()),
 +                node.path().and_then(|it| it.segment()).map(|it| it.to_string()),
 +                MacroKind::ProcMacro,
 +            )
 +        }
 +        MacroCallKind::Derive { ast_id, derive_attr_index, derive_index } => {
 +            let node = ast_id.to_node(db.upcast());
 +            // Compute the precise location of the macro name's token in the derive
 +            // list.
 +            let token = (|| {
 +                let derive_attr = node
 +                    .doc_comments_and_attrs()
 +                    .nth(*derive_attr_index as usize)
 +                    .and_then(Either::left)?;
 +                let token_tree = derive_attr.meta()?.token_tree()?;
 +                let group_by = token_tree
 +                    .syntax()
 +                    .children_with_tokens()
 +                    .filter_map(|elem| match elem {
 +                        syntax::NodeOrToken::Token(tok) => Some(tok),
 +                        _ => None,
 +                    })
 +                    .group_by(|t| t.kind() == T![,]);
 +                let (_, mut group) = group_by
 +                    .into_iter()
 +                    .filter(|&(comma, _)| !comma)
 +                    .nth(*derive_index as usize)?;
 +                group.find(|t| t.kind() == T![ident])
 +            })();
 +            (
 +                ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
 +                token.as_ref().map(|tok| tok.text_range()),
 +                token.as_ref().map(ToString::to_string),
 +                MacroKind::Derive,
 +            )
 +        }
 +        MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
 +            let node = ast_id.to_node(db.upcast());
 +            let attr = node
 +                .doc_comments_and_attrs()
 +                .nth((*invoc_attr_index) as usize)
 +                .and_then(Either::left)
 +                .unwrap_or_else(|| panic!("cannot find attribute #{}", invoc_attr_index));
 +
 +            (
 +                ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
 +                Some(attr.syntax().text_range()),
 +                attr.path()
 +                    .and_then(|path| path.segment())
 +                    .and_then(|seg| seg.name_ref())
 +                    .as_ref()
 +                    .map(ToString::to_string),
 +                MacroKind::Attr,
 +            )
 +        }
 +    }
 +}
 +
 +impl HasVisibility for Module {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        let def_map = self.id.def_map(db.upcast());
 +        let module_data = &def_map[self.id.local_id];
 +        module_data.visibility
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Field {
 +    pub(crate) parent: VariantDef,
 +    pub(crate) id: LocalFieldId,
 +}
 +
 +#[derive(Debug, PartialEq, Eq)]
 +pub enum FieldSource {
 +    Named(ast::RecordField),
 +    Pos(ast::TupleField),
 +}
 +
 +impl Field {
 +    pub fn name(&self, db: &dyn HirDatabase) -> Name {
 +        self.parent.variant_data(db).fields()[self.id].name.clone()
 +    }
 +
 +    /// Returns the type as in the signature of the struct (i.e., with
 +    /// placeholder types for type parameters). Only use this in the context of
 +    /// the field definition.
 +    pub fn ty(&self, db: &dyn HirDatabase) -> Type {
 +        let var_id = self.parent.into();
 +        let generic_def_id: GenericDefId = match self.parent {
 +            VariantDef::Struct(it) => it.id.into(),
 +            VariantDef::Union(it) => it.id.into(),
 +            VariantDef::Variant(it) => it.parent.id.into(),
 +        };
 +        let substs = TyBuilder::placeholder_subst(db, generic_def_id);
 +        let ty = db.field_types(var_id)[self.id].clone().substitute(Interner, &substs);
 +        Type::new(db, var_id, ty)
 +    }
 +
 +    pub fn parent_def(&self, _db: &dyn HirDatabase) -> VariantDef {
 +        self.parent
 +    }
 +}
 +
 +impl HasVisibility for Field {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        let variant_data = self.parent.variant_data(db);
 +        let visibility = &variant_data.fields()[self.id].visibility;
 +        let parent_id: hir_def::VariantId = self.parent.into();
 +        visibility.resolve(db.upcast(), &parent_id.resolver(db.upcast()))
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Struct {
 +    pub(crate) id: StructId,
 +}
 +
 +impl Struct {
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        Module { id: self.id.lookup(db.upcast()).container }
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        db.struct_data(self.id).name.clone()
 +    }
 +
 +    pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
 +        db.struct_data(self.id)
 +            .variant_data
 +            .fields()
 +            .iter()
 +            .map(|(id, _)| Field { parent: self.into(), id })
 +            .collect()
 +    }
 +
 +    pub fn ty(self, db: &dyn HirDatabase) -> Type {
 +        Type::from_def(db, self.id)
 +    }
 +
 +    pub fn repr(self, db: &dyn HirDatabase) -> Option<ReprKind> {
 +        db.struct_data(self.id).repr.clone()
 +    }
 +
 +    pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
 +        self.variant_data(db).kind()
 +    }
 +
 +    fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
 +        db.struct_data(self.id).variant_data.clone()
 +    }
 +}
 +
 +impl HasVisibility for Struct {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        db.struct_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Union {
 +    pub(crate) id: UnionId,
 +}
 +
 +impl Union {
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        db.union_data(self.id).name.clone()
 +    }
 +
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        Module { id: self.id.lookup(db.upcast()).container }
 +    }
 +
 +    pub fn ty(self, db: &dyn HirDatabase) -> Type {
 +        Type::from_def(db, self.id)
 +    }
 +
 +    pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
 +        db.union_data(self.id)
 +            .variant_data
 +            .fields()
 +            .iter()
 +            .map(|(id, _)| Field { parent: self.into(), id })
 +            .collect()
 +    }
 +
 +    fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
 +        db.union_data(self.id).variant_data.clone()
 +    }
 +}
 +
 +impl HasVisibility for Union {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        db.union_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Enum {
 +    pub(crate) id: EnumId,
 +}
 +
 +impl Enum {
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        Module { id: self.id.lookup(db.upcast()).container }
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        db.enum_data(self.id).name.clone()
 +    }
 +
 +    pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> {
 +        db.enum_data(self.id).variants.iter().map(|(id, _)| Variant { parent: self, id }).collect()
 +    }
 +
 +    pub fn ty(self, db: &dyn HirDatabase) -> Type {
 +        Type::from_def(db, self.id)
 +    }
 +}
 +
 +impl HasVisibility for Enum {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        db.enum_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Variant {
 +    pub(crate) parent: Enum,
 +    pub(crate) id: LocalEnumVariantId,
 +}
 +
 +impl Variant {
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        self.parent.module(db)
 +    }
 +
 +    pub fn parent_enum(self, _db: &dyn HirDatabase) -> Enum {
 +        self.parent
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        db.enum_data(self.parent.id).variants[self.id].name.clone()
 +    }
 +
 +    pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
 +        self.variant_data(db)
 +            .fields()
 +            .iter()
 +            .map(|(id, _)| Field { parent: self.into(), id })
 +            .collect()
 +    }
 +
 +    pub fn kind(self, db: &dyn HirDatabase) -> StructKind {
 +        self.variant_data(db).kind()
 +    }
 +
 +    pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
 +        db.enum_data(self.parent.id).variants[self.id].variant_data.clone()
 +    }
 +}
 +
 +/// Variants inherit visibility from the parent enum.
 +impl HasVisibility for Variant {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        self.parent_enum(db).visibility(db)
 +    }
 +}
 +
 +/// A Data Type
 +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 +pub enum Adt {
 +    Struct(Struct),
 +    Union(Union),
 +    Enum(Enum),
 +}
 +impl_from!(Struct, Union, Enum for Adt);
 +
 +impl Adt {
 +    pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
 +        let subst = db.generic_defaults(self.into());
 +        subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
 +            GenericArgData::Ty(x) => x.is_unknown(),
 +            _ => false,
 +        })
 +    }
 +
 +    /// Turns this ADT into a type. Any type parameters of the ADT will be
 +    /// turned into unknown types, which is good for e.g. finding the most
 +    /// general set of completions, but will not look very nice when printed.
 +    pub fn ty(self, db: &dyn HirDatabase) -> Type {
 +        let id = AdtId::from(self);
 +        Type::from_def(db, id)
 +    }
 +
 +    /// Turns this ADT into a type with the given type parameters. This isn't
 +    /// the greatest API, FIXME find a better one.
 +    pub fn ty_with_args(self, db: &dyn HirDatabase, args: &[Type]) -> Type {
 +        let id = AdtId::from(self);
 +        let mut it = args.iter().map(|t| t.ty.clone());
 +        let ty = TyBuilder::def_ty(db, id.into())
 +            .fill(|x| {
 +                let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
 +                match x {
 +                    ParamKind::Type => GenericArgData::Ty(r).intern(Interner),
 +                    ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
 +                }
 +            })
 +            .build();
 +        Type::new(db, id, ty)
 +    }
 +
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        match self {
 +            Adt::Struct(s) => s.module(db),
 +            Adt::Union(s) => s.module(db),
 +            Adt::Enum(e) => e.module(db),
 +        }
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        match self {
 +            Adt::Struct(s) => s.name(db),
 +            Adt::Union(u) => u.name(db),
 +            Adt::Enum(e) => e.name(db),
 +        }
 +    }
 +
 +    pub fn as_enum(&self) -> Option<Enum> {
 +        if let Self::Enum(v) = self {
 +            Some(*v)
 +        } else {
 +            None
 +        }
 +    }
 +}
 +
 +impl HasVisibility for Adt {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        match self {
 +            Adt::Struct(it) => it.visibility(db),
 +            Adt::Union(it) => it.visibility(db),
 +            Adt::Enum(it) => it.visibility(db),
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 +pub enum VariantDef {
 +    Struct(Struct),
 +    Union(Union),
 +    Variant(Variant),
 +}
 +impl_from!(Struct, Union, Variant for VariantDef);
 +
 +impl VariantDef {
 +    pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
 +        match self {
 +            VariantDef::Struct(it) => it.fields(db),
 +            VariantDef::Union(it) => it.fields(db),
 +            VariantDef::Variant(it) => it.fields(db),
 +        }
 +    }
 +
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        match self {
 +            VariantDef::Struct(it) => it.module(db),
 +            VariantDef::Union(it) => it.module(db),
 +            VariantDef::Variant(it) => it.module(db),
 +        }
 +    }
 +
 +    pub fn name(&self, db: &dyn HirDatabase) -> Name {
 +        match self {
 +            VariantDef::Struct(s) => s.name(db),
 +            VariantDef::Union(u) => u.name(db),
 +            VariantDef::Variant(e) => e.name(db),
 +        }
 +    }
 +
 +    pub(crate) fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> {
 +        match self {
 +            VariantDef::Struct(it) => it.variant_data(db),
 +            VariantDef::Union(it) => it.variant_data(db),
 +            VariantDef::Variant(it) => it.variant_data(db),
 +        }
 +    }
 +}
 +
 +/// The defs which have a body.
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub enum DefWithBody {
 +    Function(Function),
 +    Static(Static),
 +    Const(Const),
 +}
 +impl_from!(Function, Const, Static for DefWithBody);
 +
 +impl DefWithBody {
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        match self {
 +            DefWithBody::Const(c) => c.module(db),
 +            DefWithBody::Function(f) => f.module(db),
 +            DefWithBody::Static(s) => s.module(db),
 +        }
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
 +        match self {
 +            DefWithBody::Function(f) => Some(f.name(db)),
 +            DefWithBody::Static(s) => Some(s.name(db)),
 +            DefWithBody::Const(c) => c.name(db),
 +        }
 +    }
 +
 +    /// Returns the type this def's body has to evaluate to.
 +    pub fn body_type(self, db: &dyn HirDatabase) -> Type {
 +        match self {
 +            DefWithBody::Function(it) => it.ret_type(db),
 +            DefWithBody::Static(it) => it.ty(db),
 +            DefWithBody::Const(it) => it.ty(db),
 +        }
 +    }
 +
 +    pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
 +        let krate = self.module(db).id.krate();
 +
 +        let (body, source_map) = db.body_with_source_map(self.into());
 +
 +        for (_, def_map) in body.blocks(db.upcast()) {
 +            for diag in def_map.diagnostics() {
 +                emit_def_diagnostic(db, acc, diag);
 +            }
 +        }
 +
 +        for diag in source_map.diagnostics() {
 +            match diag {
 +                BodyDiagnostic::InactiveCode { node, cfg, opts } => acc.push(
 +                    InactiveCode { node: node.clone(), cfg: cfg.clone(), opts: opts.clone() }
 +                        .into(),
 +                ),
 +                BodyDiagnostic::MacroError { node, message } => acc.push(
 +                    MacroError {
 +                        node: node.clone().map(|it| it.into()),
 +                        precise_location: None,
 +                        message: message.to_string(),
 +                    }
 +                    .into(),
 +                ),
 +                BodyDiagnostic::UnresolvedProcMacro { node, krate } => acc.push(
 +                    UnresolvedProcMacro {
 +                        node: node.clone().map(|it| it.into()),
 +                        precise_location: None,
 +                        macro_name: None,
 +                        kind: MacroKind::ProcMacro,
 +                        krate: *krate,
 +                    }
 +                    .into(),
 +                ),
 +                BodyDiagnostic::UnresolvedMacroCall { node, path } => acc.push(
 +                    UnresolvedMacroCall {
 +                        macro_call: node.clone().map(|ast_ptr| ast_ptr.into()),
 +                        precise_location: None,
 +                        path: path.clone(),
 +                        is_bang: true,
 +                    }
 +                    .into(),
 +                ),
 +            }
 +        }
 +
 +        let infer = db.infer(self.into());
 +        let source_map = Lazy::new(|| db.body_with_source_map(self.into()).1);
 +        for d in &infer.diagnostics {
 +            match d {
 +                hir_ty::InferenceDiagnostic::NoSuchField { expr } => {
 +                    let field = source_map.field_syntax(*expr);
 +                    acc.push(NoSuchField { field }.into())
 +                }
 +                hir_ty::InferenceDiagnostic::BreakOutsideOfLoop { expr } => {
 +                    let expr = source_map
 +                        .expr_syntax(*expr)
 +                        .expect("break outside of loop in synthetic syntax");
 +                    acc.push(BreakOutsideOfLoop { expr }.into())
 +                }
 +                hir_ty::InferenceDiagnostic::MismatchedArgCount { call_expr, expected, found } => {
 +                    match source_map.expr_syntax(*call_expr) {
 +                        Ok(source_ptr) => acc.push(
 +                            MismatchedArgCount {
 +                                call_expr: source_ptr,
 +                                expected: *expected,
 +                                found: *found,
 +                            }
 +                            .into(),
 +                        ),
 +                        Err(SyntheticSyntax) => (),
 +                    }
 +                }
 +            }
 +        }
 +        for (expr, mismatch) in infer.expr_type_mismatches() {
 +            let expr = match source_map.expr_syntax(expr) {
 +                Ok(expr) => expr,
 +                Err(SyntheticSyntax) => continue,
 +            };
 +            acc.push(
 +                TypeMismatch {
 +                    expr,
 +                    expected: Type::new(db, DefWithBodyId::from(self), mismatch.expected.clone()),
 +                    actual: Type::new(db, DefWithBodyId::from(self), mismatch.actual.clone()),
 +                }
 +                .into(),
 +            );
 +        }
 +
 +        for expr in hir_ty::diagnostics::missing_unsafe(db, self.into()) {
 +            match source_map.expr_syntax(expr) {
 +                Ok(expr) => acc.push(MissingUnsafe { expr }.into()),
 +                Err(SyntheticSyntax) => {
 +                    // FIXME: Here and eslwhere in this file, the `expr` was
 +                    // desugared, report or assert that this doesn't happen.
 +                }
 +            }
 +        }
 +
 +        for diagnostic in BodyValidationDiagnostic::collect(db, self.into()) {
 +            match diagnostic {
 +                BodyValidationDiagnostic::RecordMissingFields {
 +                    record,
 +                    variant,
 +                    missed_fields,
 +                } => {
 +                    let variant_data = variant.variant_data(db.upcast());
 +                    let missed_fields = missed_fields
 +                        .into_iter()
 +                        .map(|idx| variant_data.fields()[idx].name.clone())
 +                        .collect();
 +
 +                    match record {
 +                        Either::Left(record_expr) => match source_map.expr_syntax(record_expr) {
 +                            Ok(source_ptr) => {
 +                                let root = source_ptr.file_syntax(db.upcast());
 +                                if let ast::Expr::RecordExpr(record_expr) =
 +                                    &source_ptr.value.to_node(&root)
 +                                {
 +                                    if record_expr.record_expr_field_list().is_some() {
 +                                        acc.push(
 +                                            MissingFields {
 +                                                file: source_ptr.file_id,
 +                                                field_list_parent: Either::Left(AstPtr::new(
 +                                                    record_expr,
 +                                                )),
 +                                                field_list_parent_path: record_expr
 +                                                    .path()
 +                                                    .map(|path| AstPtr::new(&path)),
 +                                                missed_fields,
 +                                            }
 +                                            .into(),
 +                                        )
 +                                    }
 +                                }
 +                            }
 +                            Err(SyntheticSyntax) => (),
 +                        },
 +                        Either::Right(record_pat) => match source_map.pat_syntax(record_pat) {
 +                            Ok(source_ptr) => {
 +                                if let Some(expr) = source_ptr.value.as_ref().left() {
 +                                    let root = source_ptr.file_syntax(db.upcast());
 +                                    if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) {
 +                                        if record_pat.record_pat_field_list().is_some() {
 +                                            acc.push(
 +                                                MissingFields {
 +                                                    file: source_ptr.file_id,
 +                                                    field_list_parent: Either::Right(AstPtr::new(
 +                                                        &record_pat,
 +                                                    )),
 +                                                    field_list_parent_path: record_pat
 +                                                        .path()
 +                                                        .map(|path| AstPtr::new(&path)),
 +                                                    missed_fields,
 +                                                }
 +                                                .into(),
 +                                            )
 +                                        }
 +                                    }
 +                                }
 +                            }
 +                            Err(SyntheticSyntax) => (),
 +                        },
 +                    }
 +                }
 +                BodyValidationDiagnostic::ReplaceFilterMapNextWithFindMap { method_call_expr } => {
 +                    if let Ok(next_source_ptr) = source_map.expr_syntax(method_call_expr) {
 +                        acc.push(
 +                            ReplaceFilterMapNextWithFindMap {
 +                                file: next_source_ptr.file_id,
 +                                next_expr: next_source_ptr.value,
 +                            }
 +                            .into(),
 +                        );
 +                    }
 +                }
 +                BodyValidationDiagnostic::MissingMatchArms { match_expr, uncovered_patterns } => {
 +                    match source_map.expr_syntax(match_expr) {
 +                        Ok(source_ptr) => {
 +                            let root = source_ptr.file_syntax(db.upcast());
 +                            if let ast::Expr::MatchExpr(match_expr) =
 +                                &source_ptr.value.to_node(&root)
 +                            {
 +                                if let Some(match_expr) = match_expr.expr() {
 +                                    acc.push(
 +                                        MissingMatchArms {
 +                                            file: source_ptr.file_id,
 +                                            match_expr: AstPtr::new(&match_expr),
 +                                            uncovered_patterns,
 +                                        }
 +                                        .into(),
 +                                    );
 +                                }
 +                            }
 +                        }
 +                        Err(SyntheticSyntax) => (),
 +                    }
 +                }
 +            }
 +        }
 +
 +        let def: ModuleDef = match self {
 +            DefWithBody::Function(it) => it.into(),
 +            DefWithBody::Static(it) => it.into(),
 +            DefWithBody::Const(it) => it.into(),
 +        };
 +        for diag in hir_ty::diagnostics::incorrect_case(db, krate, def.into()) {
 +            acc.push(diag.into())
 +        }
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Function {
 +    pub(crate) id: FunctionId,
 +}
 +
 +impl Function {
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        self.id.lookup(db.upcast()).module(db.upcast()).into()
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        db.function_data(self.id).name.clone()
 +    }
 +
 +    /// Get this function's return type
 +    pub fn ret_type(self, db: &dyn HirDatabase) -> Type {
 +        let resolver = self.id.resolver(db.upcast());
 +        let substs = TyBuilder::placeholder_subst(db, self.id);
 +        let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
 +        let ty = callable_sig.ret().clone();
 +        Type::new_with_resolver_inner(db, &resolver, ty)
 +    }
 +
 +    pub fn async_ret_type(self, db: &dyn HirDatabase) -> Option<Type> {
 +        if !self.is_async(db) {
 +            return None;
 +        }
 +        let resolver = self.id.resolver(db.upcast());
 +        let substs = TyBuilder::placeholder_subst(db, self.id);
 +        let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
 +        let ret_ty = callable_sig.ret().clone();
 +        for pred in ret_ty.impl_trait_bounds(db).into_iter().flatten() {
 +            if let WhereClause::AliasEq(output_eq) = pred.into_value_and_skipped_binders().0 {
 +                return Type::new_with_resolver_inner(db, &resolver, output_eq.ty).into();
 +            }
 +        }
 +        never!("Async fn ret_type should be impl Future");
 +        None
 +    }
 +
 +    pub fn has_self_param(self, db: &dyn HirDatabase) -> bool {
 +        db.function_data(self.id).has_self_param()
 +    }
 +
 +    pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
 +        self.has_self_param(db).then(|| SelfParam { func: self.id })
 +    }
 +
 +    pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param> {
 +        let environment = db.trait_environment(self.id.into());
 +        let substs = TyBuilder::placeholder_subst(db, self.id);
 +        let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
 +        callable_sig
 +            .params()
 +            .iter()
 +            .enumerate()
 +            .map(|(idx, ty)| {
 +                let ty = Type { env: environment.clone(), ty: ty.clone() };
 +                Param { func: self, ty, idx }
 +            })
 +            .collect()
 +    }
 +
 +    pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> {
 +        if self.self_param(db).is_none() {
 +            return None;
 +        }
 +        Some(self.params_without_self(db))
 +    }
 +
 +    pub fn params_without_self(self, db: &dyn HirDatabase) -> Vec<Param> {
 +        let environment = db.trait_environment(self.id.into());
 +        let substs = TyBuilder::placeholder_subst(db, self.id);
 +        let callable_sig = db.callable_item_signature(self.id.into()).substitute(Interner, &substs);
 +        let skip = if db.function_data(self.id).has_self_param() { 1 } else { 0 };
 +        callable_sig
 +            .params()
 +            .iter()
 +            .enumerate()
 +            .skip(skip)
 +            .map(|(idx, ty)| {
 +                let ty = Type { env: environment.clone(), ty: ty.clone() };
 +                Param { func: self, ty, idx }
 +            })
 +            .collect()
 +    }
 +
 +    pub fn is_const(self, db: &dyn HirDatabase) -> bool {
 +        db.function_data(self.id).has_const_kw()
 +    }
 +
 +    pub fn is_async(self, db: &dyn HirDatabase) -> bool {
 +        db.function_data(self.id).has_async_kw()
 +    }
 +
 +    pub fn is_unsafe_to_call(self, db: &dyn HirDatabase) -> bool {
 +        hir_ty::is_fn_unsafe_to_call(db, self.id)
 +    }
 +
 +    /// Whether this function declaration has a definition.
 +    ///
 +    /// This is false in the case of required (not provided) trait methods.
 +    pub fn has_body(self, db: &dyn HirDatabase) -> bool {
 +        db.function_data(self.id).has_body()
 +    }
 +
 +    pub fn as_proc_macro(self, db: &dyn HirDatabase) -> Option<Macro> {
 +        let function_data = db.function_data(self.id);
 +        let attrs = &function_data.attrs;
 +        // FIXME: Store this in FunctionData flags?
 +        if !(attrs.is_proc_macro()
 +            || attrs.is_proc_macro_attribute()
 +            || attrs.is_proc_macro_derive())
 +        {
 +            return None;
 +        }
 +        let loc = self.id.lookup(db.upcast());
 +        let def_map = db.crate_def_map(loc.krate(db).into());
 +        def_map.fn_as_proc_macro(self.id).map(|id| Macro { id: id.into() })
 +    }
 +
 +    /// A textual representation of the HIR of this function for debugging purposes.
 +    pub fn debug_hir(self, db: &dyn HirDatabase) -> String {
 +        let body = db.body(self.id.into());
 +
 +        let mut result = String::new();
 +        format_to!(result, "HIR expressions in the body of `{}`:\n", self.name(db));
 +        for (id, expr) in body.exprs.iter() {
 +            format_to!(result, "{:?}: {:?}\n", id, expr);
 +        }
 +
 +        result
 +    }
 +}
 +
 +// Note: logically, this belongs to `hir_ty`, but we are not using it there yet.
 +#[derive(Clone, Copy, PartialEq, Eq)]
 +pub enum Access {
 +    Shared,
 +    Exclusive,
 +    Owned,
 +}
 +
 +impl From<hir_ty::Mutability> for Access {
 +    fn from(mutability: hir_ty::Mutability) -> Access {
 +        match mutability {
 +            hir_ty::Mutability::Not => Access::Shared,
 +            hir_ty::Mutability::Mut => Access::Exclusive,
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Debug)]
 +pub struct Param {
 +    func: Function,
 +    /// The index in parameter list, including self parameter.
 +    idx: usize,
 +    ty: Type,
 +}
 +
 +impl Param {
 +    pub fn ty(&self) -> &Type {
 +        &self.ty
 +    }
 +
 +    pub fn name(&self, db: &dyn HirDatabase) -> Option<Name> {
 +        db.function_data(self.func.id).params[self.idx].0.clone()
 +    }
 +
 +    pub fn as_local(&self, db: &dyn HirDatabase) -> Option<Local> {
 +        let parent = DefWithBodyId::FunctionId(self.func.into());
 +        let body = db.body(parent);
 +        let pat_id = body.params[self.idx];
 +        if let Pat::Bind { .. } = &body[pat_id] {
 +            Some(Local { parent, pat_id: body.params[self.idx] })
 +        } else {
 +            None
 +        }
 +    }
 +
 +    pub fn pattern_source(&self, db: &dyn HirDatabase) -> Option<ast::Pat> {
 +        self.source(db).and_then(|p| p.value.pat())
 +    }
 +
 +    pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::Param>> {
 +        let InFile { file_id, value } = self.func.source(db)?;
 +        let params = value.param_list()?;
 +        if params.self_param().is_some() {
 +            params.params().nth(self.idx.checked_sub(1)?)
 +        } else {
 +            params.params().nth(self.idx)
 +        }
 +        .map(|value| InFile { file_id, value })
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct SelfParam {
 +    func: FunctionId,
 +}
 +
 +impl SelfParam {
 +    pub fn access(self, db: &dyn HirDatabase) -> Access {
 +        let func_data = db.function_data(self.func);
 +        func_data
 +            .params
 +            .first()
 +            .map(|(_, param)| match &**param {
 +                TypeRef::Reference(.., mutability) => match mutability {
 +                    hir_def::type_ref::Mutability::Shared => Access::Shared,
 +                    hir_def::type_ref::Mutability::Mut => Access::Exclusive,
 +                },
 +                _ => Access::Owned,
 +            })
 +            .unwrap_or(Access::Owned)
 +    }
 +
 +    pub fn display(self, db: &dyn HirDatabase) -> &'static str {
 +        match self.access(db) {
 +            Access::Shared => "&self",
 +            Access::Exclusive => "&mut self",
 +            Access::Owned => "self",
 +        }
 +    }
 +
 +    pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::SelfParam>> {
 +        let InFile { file_id, value } = Function::from(self.func).source(db)?;
 +        value
 +            .param_list()
 +            .and_then(|params| params.self_param())
 +            .map(|value| InFile { file_id, value })
 +    }
 +
 +    pub fn ty(&self, db: &dyn HirDatabase) -> Type {
 +        let substs = TyBuilder::placeholder_subst(db, self.func);
 +        let callable_sig =
 +            db.callable_item_signature(self.func.into()).substitute(Interner, &substs);
 +        let environment = db.trait_environment(self.func.into());
 +        let ty = callable_sig.params()[0].clone();
 +        Type { env: environment, ty }
 +    }
 +}
 +
 +impl HasVisibility for Function {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        db.function_visibility(self.id)
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Const {
 +    pub(crate) id: ConstId,
 +}
 +
 +impl Const {
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
 +        db.const_data(self.id).name.clone()
 +    }
 +
 +    pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
 +        self.source(db)?.value.body()
 +    }
 +
 +    pub fn ty(self, db: &dyn HirDatabase) -> Type {
 +        let data = db.const_data(self.id);
 +        let resolver = self.id.resolver(db.upcast());
 +        let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
 +        let ty = ctx.lower_ty(&data.type_ref);
 +        Type::new_with_resolver_inner(db, &resolver, ty)
 +    }
 +
 +    pub fn eval(self, db: &dyn HirDatabase) -> Result<ComputedExpr, ConstEvalError> {
 +        db.const_eval(self.id)
 +    }
 +}
 +
 +impl HasVisibility for Const {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        db.const_visibility(self.id)
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Static {
 +    pub(crate) id: StaticId,
 +}
 +
 +impl Static {
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        db.static_data(self.id).name.clone()
 +    }
 +
 +    pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
 +        db.static_data(self.id).mutable
 +    }
 +
 +    pub fn value(self, db: &dyn HirDatabase) -> Option<ast::Expr> {
 +        self.source(db)?.value.body()
 +    }
 +
 +    pub fn ty(self, db: &dyn HirDatabase) -> Type {
 +        let data = db.static_data(self.id);
 +        let resolver = self.id.resolver(db.upcast());
 +        let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
 +        let ty = ctx.lower_ty(&data.type_ref);
 +        Type::new_with_resolver_inner(db, &resolver, ty)
 +    }
 +}
 +
 +impl HasVisibility for Static {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        db.static_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Trait {
 +    pub(crate) id: TraitId,
 +}
 +
 +impl Trait {
 +    pub fn lang(db: &dyn HirDatabase, krate: Crate, name: &Name) -> Option<Trait> {
 +        db.lang_item(krate.into(), name.to_smol_str())
 +            .and_then(LangItemTarget::as_trait)
 +            .map(Into::into)
 +    }
 +
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        Module { id: self.id.lookup(db.upcast()).container }
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        db.trait_data(self.id).name.clone()
 +    }
 +
 +    pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
 +        db.trait_data(self.id).items.iter().map(|(_name, it)| (*it).into()).collect()
 +    }
 +
 +    pub fn items_with_supertraits(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
 +        let traits = all_super_traits(db.upcast(), self.into());
 +        traits.iter().flat_map(|tr| Trait::from(*tr).items(db)).collect()
 +    }
 +
 +    pub fn is_auto(self, db: &dyn HirDatabase) -> bool {
 +        db.trait_data(self.id).is_auto
 +    }
 +
 +    pub fn is_unsafe(&self, db: &dyn HirDatabase) -> bool {
 +        db.trait_data(self.id).is_unsafe
 +    }
 +
 +    pub fn type_or_const_param_count(
 +        &self,
 +        db: &dyn HirDatabase,
 +        count_required_only: bool,
 +    ) -> usize {
 +        db.generic_params(GenericDefId::from(self.id))
 +            .type_or_consts
 +            .iter()
 +            .filter(|(_, ty)| match ty {
 +                TypeOrConstParamData::TypeParamData(ty)
 +                    if ty.provenance != TypeParamProvenance::TypeParamList =>
 +                {
 +                    false
 +                }
 +                _ => true,
 +            })
 +            .filter(|(_, ty)| !count_required_only || !ty.has_default())
 +            .count()
 +    }
 +}
 +
 +impl HasVisibility for Trait {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        db.trait_data(self.id).visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct TypeAlias {
 +    pub(crate) id: TypeAliasId,
 +}
 +
 +impl TypeAlias {
 +    pub fn has_non_default_type_params(self, db: &dyn HirDatabase) -> bool {
 +        let subst = db.generic_defaults(self.id.into());
 +        subst.iter().any(|ty| match ty.skip_binders().data(Interner) {
 +            GenericArgData::Ty(x) => x.is_unknown(),
 +            _ => false,
 +        })
 +    }
 +
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        Module { id: self.id.lookup(db.upcast()).module(db.upcast()) }
 +    }
 +
 +    pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
 +        db.type_alias_data(self.id).type_ref.as_deref().cloned()
 +    }
 +
 +    pub fn ty(self, db: &dyn HirDatabase) -> Type {
 +        Type::from_def(db, self.id)
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        db.type_alias_data(self.id).name.clone()
 +    }
 +}
 +
 +impl HasVisibility for TypeAlias {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        let function_data = db.type_alias_data(self.id);
 +        let visibility = &function_data.visibility;
 +        visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct BuiltinType {
 +    pub(crate) inner: hir_def::builtin_type::BuiltinType,
 +}
 +
 +impl BuiltinType {
 +    pub fn str() -> BuiltinType {
 +        BuiltinType { inner: hir_def::builtin_type::BuiltinType::Str }
 +    }
 +
 +    pub fn ty(self, db: &dyn HirDatabase) -> Type {
 +        Type::new_for_crate(db.crate_graph().iter().next().unwrap(), TyBuilder::builtin(self.inner))
 +    }
 +
 +    pub fn name(self) -> Name {
 +        self.inner.as_name()
 +    }
 +
 +    pub fn is_int(&self) -> bool {
 +        matches!(self.inner, hir_def::builtin_type::BuiltinType::Int(_))
 +    }
 +
 +    pub fn is_uint(&self) -> bool {
 +        matches!(self.inner, hir_def::builtin_type::BuiltinType::Uint(_))
 +    }
 +
 +    pub fn is_float(&self) -> bool {
 +        matches!(self.inner, hir_def::builtin_type::BuiltinType::Float(_))
 +    }
 +
 +    pub fn is_char(&self) -> bool {
 +        matches!(self.inner, hir_def::builtin_type::BuiltinType::Char)
 +    }
 +
 +    pub fn is_bool(&self) -> bool {
 +        matches!(self.inner, hir_def::builtin_type::BuiltinType::Bool)
 +    }
 +
 +    pub fn is_str(&self) -> bool {
 +        matches!(self.inner, hir_def::builtin_type::BuiltinType::Str)
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub enum MacroKind {
 +    /// `macro_rules!` or Macros 2.0 macro.
 +    Declarative,
 +    /// A built-in or custom derive.
 +    Derive,
 +    /// A built-in function-like macro.
 +    BuiltIn,
 +    /// A procedural attribute macro.
 +    Attr,
 +    /// A function-like procedural macro.
 +    ProcMacro,
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Macro {
 +    pub(crate) id: MacroId,
 +}
 +
 +impl Macro {
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        Module { id: self.id.module(db.upcast()) }
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        match self.id {
 +            MacroId::Macro2Id(id) => db.macro2_data(id).name.clone(),
 +            MacroId::MacroRulesId(id) => db.macro_rules_data(id).name.clone(),
 +            MacroId::ProcMacroId(id) => db.proc_macro_data(id).name.clone(),
 +        }
 +    }
 +
 +    pub fn is_macro_export(self, db: &dyn HirDatabase) -> bool {
 +        matches!(self.id, MacroId::MacroRulesId(id) if db.macro_rules_data(id).macro_export)
 +    }
 +
 +    pub fn kind(&self, db: &dyn HirDatabase) -> MacroKind {
 +        match self.id {
 +            MacroId::Macro2Id(it) => match it.lookup(db.upcast()).expander {
 +                MacroExpander::Declarative => MacroKind::Declarative,
 +                MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
 +                MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
 +                MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
 +            },
 +            MacroId::MacroRulesId(it) => match it.lookup(db.upcast()).expander {
 +                MacroExpander::Declarative => MacroKind::Declarative,
 +                MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroKind::BuiltIn,
 +                MacroExpander::BuiltInAttr(_) => MacroKind::Attr,
 +                MacroExpander::BuiltInDerive(_) => MacroKind::Derive,
 +            },
 +            MacroId::ProcMacroId(it) => match it.lookup(db.upcast()).kind {
 +                ProcMacroKind::CustomDerive => MacroKind::Derive,
 +                ProcMacroKind::FuncLike => MacroKind::ProcMacro,
 +                ProcMacroKind::Attr => MacroKind::Attr,
 +            },
 +        }
 +    }
 +
 +    pub fn is_fn_like(&self, db: &dyn HirDatabase) -> bool {
 +        match self.kind(db) {
 +            MacroKind::Declarative | MacroKind::BuiltIn | MacroKind::ProcMacro => true,
 +            MacroKind::Attr | MacroKind::Derive => false,
 +        }
 +    }
 +
 +    pub fn is_builtin_derive(&self, db: &dyn HirDatabase) -> bool {
 +        match self.id {
 +            MacroId::Macro2Id(it) => {
 +                matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInDerive(_))
 +            }
 +            MacroId::MacroRulesId(it) => {
 +                matches!(it.lookup(db.upcast()).expander, MacroExpander::BuiltInDerive(_))
 +            }
 +            MacroId::ProcMacroId(_) => false,
 +        }
 +    }
 +
 +    pub fn is_attr(&self, db: &dyn HirDatabase) -> bool {
 +        matches!(self.kind(db), MacroKind::Attr)
 +    }
 +
 +    pub fn is_derive(&self, db: &dyn HirDatabase) -> bool {
 +        matches!(self.kind(db), MacroKind::Derive)
 +    }
 +}
 +
 +impl HasVisibility for Macro {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        match self.id {
 +            MacroId::Macro2Id(id) => {
 +                let data = db.macro2_data(id);
 +                let visibility = &data.visibility;
 +                visibility.resolve(db.upcast(), &self.id.resolver(db.upcast()))
 +            }
 +            MacroId::MacroRulesId(_) => Visibility::Public,
 +            MacroId::ProcMacroId(_) => Visibility::Public,
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
 +pub enum ItemInNs {
 +    Types(ModuleDef),
 +    Values(ModuleDef),
 +    Macros(Macro),
 +}
 +
 +impl From<Macro> for ItemInNs {
 +    fn from(it: Macro) -> Self {
 +        Self::Macros(it)
 +    }
 +}
 +
 +impl From<ModuleDef> for ItemInNs {
 +    fn from(module_def: ModuleDef) -> Self {
 +        match module_def {
 +            ModuleDef::Static(_) | ModuleDef::Const(_) | ModuleDef::Function(_) => {
 +                ItemInNs::Values(module_def)
 +            }
 +            _ => ItemInNs::Types(module_def),
 +        }
 +    }
 +}
 +
 +impl ItemInNs {
 +    pub fn as_module_def(self) -> Option<ModuleDef> {
 +        match self {
 +            ItemInNs::Types(id) | ItemInNs::Values(id) => Some(id),
 +            ItemInNs::Macros(_) => None,
 +        }
 +    }
 +
 +    /// Returns the crate defining this item (or `None` if `self` is built-in).
 +    pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
 +        match self {
 +            ItemInNs::Types(did) | ItemInNs::Values(did) => did.module(db).map(|m| m.krate()),
 +            ItemInNs::Macros(id) => Some(id.module(db).krate()),
 +        }
 +    }
 +
 +    pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
 +        match self {
 +            ItemInNs::Types(it) | ItemInNs::Values(it) => it.attrs(db),
 +            ItemInNs::Macros(it) => Some(it.attrs(db)),
 +        }
 +    }
 +}
 +
 +/// Invariant: `inner.as_assoc_item(db).is_some()`
 +/// We do not actively enforce this invariant.
 +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 +pub enum AssocItem {
 +    Function(Function),
 +    Const(Const),
 +    TypeAlias(TypeAlias),
 +}
 +#[derive(Debug)]
 +pub enum AssocItemContainer {
 +    Trait(Trait),
 +    Impl(Impl),
 +}
 +pub trait AsAssocItem {
 +    fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem>;
 +}
 +
 +impl AsAssocItem for Function {
 +    fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
 +        as_assoc_item(db, AssocItem::Function, self.id)
 +    }
 +}
 +impl AsAssocItem for Const {
 +    fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
 +        as_assoc_item(db, AssocItem::Const, self.id)
 +    }
 +}
 +impl AsAssocItem for TypeAlias {
 +    fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
 +        as_assoc_item(db, AssocItem::TypeAlias, self.id)
 +    }
 +}
 +impl AsAssocItem for ModuleDef {
 +    fn as_assoc_item(self, db: &dyn HirDatabase) -> Option<AssocItem> {
 +        match self {
 +            ModuleDef::Function(it) => it.as_assoc_item(db),
 +            ModuleDef::Const(it) => it.as_assoc_item(db),
 +            ModuleDef::TypeAlias(it) => it.as_assoc_item(db),
 +            _ => None,
 +        }
 +    }
 +}
 +fn as_assoc_item<ID, DEF, CTOR, AST>(db: &dyn HirDatabase, ctor: CTOR, id: ID) -> Option<AssocItem>
 +where
 +    ID: Lookup<Data = AssocItemLoc<AST>>,
 +    DEF: From<ID>,
 +    CTOR: FnOnce(DEF) -> AssocItem,
 +    AST: ItemTreeNode,
 +{
 +    match id.lookup(db.upcast()).container {
 +        ItemContainerId::TraitId(_) | ItemContainerId::ImplId(_) => Some(ctor(DEF::from(id))),
 +        ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => None,
 +    }
 +}
 +
 +impl AssocItem {
 +    pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
 +        match self {
 +            AssocItem::Function(it) => Some(it.name(db)),
 +            AssocItem::Const(it) => it.name(db),
 +            AssocItem::TypeAlias(it) => Some(it.name(db)),
 +        }
 +    }
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        match self {
 +            AssocItem::Function(f) => f.module(db),
 +            AssocItem::Const(c) => c.module(db),
 +            AssocItem::TypeAlias(t) => t.module(db),
 +        }
 +    }
 +    pub fn container(self, db: &dyn HirDatabase) -> AssocItemContainer {
 +        let container = match self {
 +            AssocItem::Function(it) => it.id.lookup(db.upcast()).container,
 +            AssocItem::Const(it) => it.id.lookup(db.upcast()).container,
 +            AssocItem::TypeAlias(it) => it.id.lookup(db.upcast()).container,
 +        };
 +        match container {
 +            ItemContainerId::TraitId(id) => AssocItemContainer::Trait(id.into()),
 +            ItemContainerId::ImplId(id) => AssocItemContainer::Impl(id.into()),
 +            ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
 +                panic!("invalid AssocItem")
 +            }
 +        }
 +    }
 +
 +    pub fn containing_trait(self, db: &dyn HirDatabase) -> Option<Trait> {
 +        match self.container(db) {
 +            AssocItemContainer::Trait(t) => Some(t),
 +            _ => None,
 +        }
 +    }
 +
 +    pub fn containing_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait> {
 +        match self.container(db) {
 +            AssocItemContainer::Impl(i) => i.trait_(db),
 +            _ => None,
 +        }
 +    }
 +
 +    pub fn containing_trait_or_trait_impl(self, db: &dyn HirDatabase) -> Option<Trait> {
 +        match self.container(db) {
 +            AssocItemContainer::Trait(t) => Some(t),
 +            AssocItemContainer::Impl(i) => i.trait_(db),
 +        }
 +    }
 +}
 +
 +impl HasVisibility for AssocItem {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
 +        match self {
 +            AssocItem::Function(f) => f.visibility(db),
 +            AssocItem::Const(c) => c.visibility(db),
 +            AssocItem::TypeAlias(t) => t.visibility(db),
 +        }
 +    }
 +}
 +
 +impl From<AssocItem> for ModuleDef {
 +    fn from(assoc: AssocItem) -> Self {
 +        match assoc {
 +            AssocItem::Function(it) => ModuleDef::Function(it),
 +            AssocItem::Const(it) => ModuleDef::Const(it),
 +            AssocItem::TypeAlias(it) => ModuleDef::TypeAlias(it),
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
 +pub enum GenericDef {
 +    Function(Function),
 +    Adt(Adt),
 +    Trait(Trait),
 +    TypeAlias(TypeAlias),
 +    Impl(Impl),
 +    // enum variants cannot have generics themselves, but their parent enums
 +    // can, and this makes some code easier to write
 +    Variant(Variant),
 +    // consts can have type parameters from their parents (i.e. associated consts of traits)
 +    Const(Const),
 +}
 +impl_from!(
 +    Function,
 +    Adt(Struct, Enum, Union),
 +    Trait,
 +    TypeAlias,
 +    Impl,
 +    Variant,
 +    Const
 +    for GenericDef
 +);
 +
 +impl GenericDef {
 +    pub fn params(self, db: &dyn HirDatabase) -> Vec<GenericParam> {
 +        let generics = db.generic_params(self.into());
 +        let ty_params = generics.type_or_consts.iter().map(|(local_id, _)| {
 +            let toc = TypeOrConstParam { id: TypeOrConstParamId { parent: self.into(), local_id } };
 +            match toc.split(db) {
 +                Either::Left(x) => GenericParam::ConstParam(x),
 +                Either::Right(x) => GenericParam::TypeParam(x),
 +            }
 +        });
 +        let lt_params = generics
 +            .lifetimes
 +            .iter()
 +            .map(|(local_id, _)| LifetimeParam {
 +                id: LifetimeParamId { parent: self.into(), local_id },
 +            })
 +            .map(GenericParam::LifetimeParam);
 +        lt_params.chain(ty_params).collect()
 +    }
 +
 +    pub fn type_params(self, db: &dyn HirDatabase) -> Vec<TypeOrConstParam> {
 +        let generics = db.generic_params(self.into());
 +        generics
 +            .type_or_consts
 +            .iter()
 +            .map(|(local_id, _)| TypeOrConstParam {
 +                id: TypeOrConstParamId { parent: self.into(), local_id },
 +            })
 +            .collect()
 +    }
 +}
 +
 +/// A single local definition.
 +///
 +/// If the definition of this is part of a "MultiLocal", that is a local that has multiple declarations due to or-patterns
 +/// then this only references a single one of those.
 +/// To retrieve the other locals you should use [`Local::associated_locals`]
 +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 +pub struct Local {
 +    pub(crate) parent: DefWithBodyId,
 +    pub(crate) pat_id: PatId,
 +}
 +
 +impl Local {
 +    pub fn is_param(self, db: &dyn HirDatabase) -> bool {
 +        let src = self.source(db);
 +        match src.value {
 +            Either::Left(pat) => pat
 +                .syntax()
 +                .ancestors()
 +                .map(|it| it.kind())
 +                .take_while(|&kind| ast::Pat::can_cast(kind) || ast::Param::can_cast(kind))
 +                .any(ast::Param::can_cast),
 +            Either::Right(_) => true,
 +        }
 +    }
 +
 +    pub fn as_self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
 +        match self.parent {
 +            DefWithBodyId::FunctionId(func) if self.is_self(db) => Some(SelfParam { func }),
 +            _ => None,
 +        }
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        let body = db.body(self.parent);
 +        match &body[self.pat_id] {
 +            Pat::Bind { name, .. } => name.clone(),
 +            _ => {
 +                stdx::never!("hir::Local is missing a name!");
 +                Name::missing()
 +            }
 +        }
 +    }
 +
 +    pub fn is_self(self, db: &dyn HirDatabase) -> bool {
 +        self.name(db) == name![self]
 +    }
 +
 +    pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
 +        let body = db.body(self.parent);
 +        matches!(&body[self.pat_id], Pat::Bind { mode: BindingAnnotation::Mutable, .. })
 +    }
 +
 +    pub fn is_ref(self, db: &dyn HirDatabase) -> bool {
 +        let body = db.body(self.parent);
 +        matches!(
 +            &body[self.pat_id],
 +            Pat::Bind { mode: BindingAnnotation::Ref | BindingAnnotation::RefMut, .. }
 +        )
 +    }
 +
 +    pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
 +        self.parent.into()
 +    }
 +
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        self.parent(db).module(db)
 +    }
 +
 +    pub fn ty(self, db: &dyn HirDatabase) -> Type {
 +        let def = self.parent;
 +        let infer = db.infer(def);
 +        let ty = infer[self.pat_id].clone();
 +        Type::new(db, def, ty)
 +    }
 +
 +    pub fn associated_locals(self, db: &dyn HirDatabase) -> Box<[Local]> {
 +        let body = db.body(self.parent);
 +        body.ident_patterns_for(&self.pat_id)
 +            .iter()
 +            .map(|&pat_id| Local { parent: self.parent, pat_id })
 +            .collect()
 +    }
 +
 +    /// If this local is part of a multi-local, retrieve the representative local.
 +    /// That is the local that references are being resolved to.
 +    pub fn representative(self, db: &dyn HirDatabase) -> Local {
 +        let body = db.body(self.parent);
 +        Local { pat_id: body.pattern_representative(self.pat_id), ..self }
 +    }
 +
 +    pub fn source(self, db: &dyn HirDatabase) -> InFile<Either<ast::IdentPat, ast::SelfParam>> {
 +        let (_body, source_map) = db.body_with_source_map(self.parent);
 +        let src = source_map.pat_syntax(self.pat_id).unwrap(); // Hmm...
 +        let root = src.file_syntax(db.upcast());
 +        src.map(|ast| match ast {
 +            // Suspicious unwrap
 +            Either::Left(it) => Either::Left(it.cast().unwrap().to_node(&root)),
 +            Either::Right(it) => Either::Right(it.to_node(&root)),
 +        })
 +    }
 +}
 +
 +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 +pub struct DeriveHelper {
 +    pub(crate) derive: MacroId,
 +    pub(crate) idx: usize,
 +}
 +
 +impl DeriveHelper {
 +    pub fn derive(&self) -> Macro {
 +        Macro { id: self.derive.into() }
 +    }
 +
 +    pub fn name(&self, db: &dyn HirDatabase) -> Name {
 +        match self.derive {
 +            MacroId::Macro2Id(_) => None,
 +            MacroId::MacroRulesId(_) => None,
 +            MacroId::ProcMacroId(proc_macro) => db
 +                .proc_macro_data(proc_macro)
 +                .helpers
 +                .as_ref()
 +                .and_then(|it| it.get(self.idx))
 +                .cloned(),
 +        }
 +        .unwrap_or_else(|| Name::missing())
 +    }
 +}
 +
 +// FIXME: Wrong name? This is could also be a registered attribute
 +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 +pub struct BuiltinAttr {
 +    krate: Option<CrateId>,
 +    idx: usize,
 +}
 +
 +impl BuiltinAttr {
 +    // FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs?
 +    pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
 +        if let builtin @ Some(_) = Self::builtin(name) {
 +            return builtin;
 +        }
 +        let idx = db.crate_def_map(krate.id).registered_attrs().iter().position(|it| it == name)?;
 +        Some(BuiltinAttr { krate: Some(krate.id), idx })
 +    }
 +
 +    fn builtin(name: &str) -> Option<Self> {
 +        hir_def::builtin_attr::INERT_ATTRIBUTES
 +            .iter()
 +            .position(|tool| tool.name == name)
 +            .map(|idx| BuiltinAttr { krate: None, idx })
 +    }
 +
 +    pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
 +        // FIXME: Return a `Name` here
 +        match self.krate {
 +            Some(krate) => db.crate_def_map(krate).registered_attrs()[self.idx].clone(),
 +            None => SmolStr::new(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx].name),
 +        }
 +    }
 +
 +    pub fn template(&self, _: &dyn HirDatabase) -> Option<AttributeTemplate> {
 +        match self.krate {
 +            Some(_) => None,
 +            None => Some(hir_def::builtin_attr::INERT_ATTRIBUTES[self.idx].template),
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 +pub struct ToolModule {
 +    krate: Option<CrateId>,
 +    idx: usize,
 +}
 +
 +impl ToolModule {
 +    // FIXME: consider crates\hir_def\src\nameres\attr_resolution.rs?
 +    pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
 +        if let builtin @ Some(_) = Self::builtin(name) {
 +            return builtin;
 +        }
 +        let idx = db.crate_def_map(krate.id).registered_tools().iter().position(|it| it == name)?;
 +        Some(ToolModule { krate: Some(krate.id), idx })
 +    }
 +
 +    fn builtin(name: &str) -> Option<Self> {
 +        hir_def::builtin_attr::TOOL_MODULES
 +            .iter()
 +            .position(|&tool| tool == name)
 +            .map(|idx| ToolModule { krate: None, idx })
 +    }
 +
 +    pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
 +        // FIXME: Return a `Name` here
 +        match self.krate {
 +            Some(krate) => db.crate_def_map(krate).registered_tools()[self.idx].clone(),
 +            None => SmolStr::new(hir_def::builtin_attr::TOOL_MODULES[self.idx]),
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 +pub struct Label {
 +    pub(crate) parent: DefWithBodyId,
 +    pub(crate) label_id: LabelId,
 +}
 +
 +impl Label {
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        self.parent(db).module(db)
 +    }
 +
 +    pub fn parent(self, _db: &dyn HirDatabase) -> DefWithBody {
 +        self.parent.into()
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        let body = db.body(self.parent);
 +        body[self.label_id].name.clone()
 +    }
 +
 +    pub fn source(self, db: &dyn HirDatabase) -> InFile<ast::Label> {
 +        let (_body, source_map) = db.body_with_source_map(self.parent);
 +        let src = source_map.label_syntax(self.label_id);
 +        let root = src.file_syntax(db.upcast());
 +        src.map(|ast| ast.to_node(&root))
 +    }
 +}
 +
 +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 +pub enum GenericParam {
 +    TypeParam(TypeParam),
 +    ConstParam(ConstParam),
 +    LifetimeParam(LifetimeParam),
 +}
 +impl_from!(TypeParam, ConstParam, LifetimeParam for GenericParam);
 +
 +impl GenericParam {
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        match self {
 +            GenericParam::TypeParam(it) => it.module(db),
 +            GenericParam::ConstParam(it) => it.module(db),
 +            GenericParam::LifetimeParam(it) => it.module(db),
 +        }
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        match self {
 +            GenericParam::TypeParam(it) => it.name(db),
 +            GenericParam::ConstParam(it) => it.name(db),
 +            GenericParam::LifetimeParam(it) => it.name(db),
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 +pub struct TypeParam {
 +    pub(crate) id: TypeParamId,
 +}
 +
 +impl TypeParam {
 +    pub fn merge(self) -> TypeOrConstParam {
 +        TypeOrConstParam { id: self.id.into() }
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        self.merge().name(db)
 +    }
 +
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        self.id.parent().module(db.upcast()).into()
 +    }
 +
 +    /// Is this type parameter implicitly introduced (eg. `Self` in a trait or an `impl Trait`
 +    /// argument)?
 +    pub fn is_implicit(self, db: &dyn HirDatabase) -> bool {
 +        let params = db.generic_params(self.id.parent());
 +        let data = &params.type_or_consts[self.id.local_id()];
 +        match data.type_param().unwrap().provenance {
 +            hir_def::generics::TypeParamProvenance::TypeParamList => false,
 +            hir_def::generics::TypeParamProvenance::TraitSelf
 +            | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => true,
 +        }
 +    }
 +
 +    pub fn ty(self, db: &dyn HirDatabase) -> Type {
 +        let resolver = self.id.parent().resolver(db.upcast());
 +        let ty =
 +            TyKind::Placeholder(hir_ty::to_placeholder_idx(db, self.id.into())).intern(Interner);
 +        Type::new_with_resolver_inner(db, &resolver, ty)
 +    }
 +
 +    /// FIXME: this only lists trait bounds from the item defining the type
 +    /// parameter, not additional bounds that might be added e.g. by a method if
 +    /// the parameter comes from an impl!
 +    pub fn trait_bounds(self, db: &dyn HirDatabase) -> Vec<Trait> {
 +        db.generic_predicates_for_param(self.id.parent(), self.id.into(), None)
 +            .iter()
 +            .filter_map(|pred| match &pred.skip_binders().skip_binders() {
 +                hir_ty::WhereClause::Implemented(trait_ref) => {
 +                    Some(Trait::from(trait_ref.hir_trait_id()))
 +                }
 +                _ => None,
 +            })
 +            .collect()
 +    }
 +
 +    pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
 +        let params = db.generic_defaults(self.id.parent());
 +        let local_idx = hir_ty::param_idx(db, self.id.into())?;
 +        let resolver = self.id.parent().resolver(db.upcast());
 +        let ty = params.get(local_idx)?.clone();
 +        let subst = TyBuilder::placeholder_subst(db, self.id.parent());
 +        let ty = ty.substitute(Interner, &subst_prefix(&subst, local_idx));
 +        match ty.data(Interner) {
 +            GenericArgData::Ty(x) => Some(Type::new_with_resolver_inner(db, &resolver, x.clone())),
 +            _ => None,
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 +pub struct LifetimeParam {
 +    pub(crate) id: LifetimeParamId,
 +}
 +
 +impl LifetimeParam {
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        let params = db.generic_params(self.id.parent);
 +        params.lifetimes[self.id.local_id].name.clone()
 +    }
 +
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        self.id.parent.module(db.upcast()).into()
 +    }
 +
 +    pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
 +        self.id.parent.into()
 +    }
 +}
 +
 +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 +pub struct ConstParam {
 +    pub(crate) id: ConstParamId,
 +}
 +
 +impl ConstParam {
 +    pub fn merge(self) -> TypeOrConstParam {
 +        TypeOrConstParam { id: self.id.into() }
 +    }
 +
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        let params = db.generic_params(self.id.parent());
 +        match params.type_or_consts[self.id.local_id()].name() {
 +            Some(x) => x.clone(),
 +            None => {
 +                never!();
 +                Name::missing()
 +            }
 +        }
 +    }
 +
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        self.id.parent().module(db.upcast()).into()
 +    }
 +
 +    pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
 +        self.id.parent().into()
 +    }
 +
 +    pub fn ty(self, db: &dyn HirDatabase) -> Type {
 +        Type::new(db, self.id.parent(), db.const_param_ty(self.id))
 +    }
 +}
 +
 +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
 +pub struct TypeOrConstParam {
 +    pub(crate) id: TypeOrConstParamId,
 +}
 +
 +impl TypeOrConstParam {
 +    pub fn name(self, db: &dyn HirDatabase) -> Name {
 +        let params = db.generic_params(self.id.parent);
 +        match params.type_or_consts[self.id.local_id].name() {
 +            Some(n) => n.clone(),
 +            _ => Name::missing(),
 +        }
 +    }
 +
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        self.id.parent.module(db.upcast()).into()
 +    }
 +
 +    pub fn parent(self, _db: &dyn HirDatabase) -> GenericDef {
 +        self.id.parent.into()
 +    }
 +
 +    pub fn split(self, db: &dyn HirDatabase) -> Either<ConstParam, TypeParam> {
 +        let params = db.generic_params(self.id.parent);
 +        match &params.type_or_consts[self.id.local_id] {
 +            hir_def::generics::TypeOrConstParamData::TypeParamData(_) => {
 +                Either::Right(TypeParam { id: TypeParamId::from_unchecked(self.id) })
 +            }
 +            hir_def::generics::TypeOrConstParamData::ConstParamData(_) => {
 +                Either::Left(ConstParam { id: ConstParamId::from_unchecked(self.id) })
 +            }
 +        }
 +    }
 +
 +    pub fn ty(self, db: &dyn HirDatabase) -> Type {
 +        match self.split(db) {
 +            Either::Left(x) => x.ty(db),
 +            Either::Right(x) => x.ty(db),
 +        }
 +    }
 +}
 +
 +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 +pub struct Impl {
 +    pub(crate) id: ImplId,
 +}
 +
 +impl Impl {
 +    pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<Impl> {
 +        let inherent = db.inherent_impls_in_crate(krate.id);
 +        let trait_ = db.trait_impls_in_crate(krate.id);
 +
 +        inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect()
 +    }
 +
 +    pub fn all_for_type(db: &dyn HirDatabase, Type { ty, env }: Type) -> Vec<Impl> {
 +        let def_crates = match method_resolution::def_crates(db, &ty, env.krate) {
 +            Some(def_crates) => def_crates,
 +            None => return Vec::new(),
 +        };
 +
 +        let filter = |impl_def: &Impl| {
 +            let self_ty = impl_def.self_ty(db);
 +            let rref = self_ty.remove_ref();
 +            ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
 +        };
 +
 +        let fp = TyFingerprint::for_inherent_impl(&ty);
 +        let fp = match fp {
 +            Some(fp) => fp,
 +            None => return Vec::new(),
 +        };
 +
 +        let mut all = Vec::new();
 +        def_crates.iter().for_each(|&id| {
 +            all.extend(
 +                db.inherent_impls_in_crate(id)
 +                    .for_self_ty(&ty)
 +                    .iter()
 +                    .cloned()
 +                    .map(Self::from)
 +                    .filter(filter),
 +            )
 +        });
 +        for id in def_crates
 +            .iter()
 +            .flat_map(|&id| Crate { id }.transitive_reverse_dependencies(db))
 +            .map(|Crate { id }| id)
 +            .chain(def_crates.iter().copied())
 +            .unique()
 +        {
 +            all.extend(
 +                db.trait_impls_in_crate(id)
 +                    .for_self_ty_without_blanket_impls(fp)
 +                    .map(Self::from)
 +                    .filter(filter),
 +            );
 +        }
 +        all
 +    }
 +
 +    pub fn all_for_trait(db: &dyn HirDatabase, trait_: Trait) -> Vec<Impl> {
 +        let krate = trait_.module(db).krate();
 +        let mut all = Vec::new();
 +        for Crate { id } in krate.transitive_reverse_dependencies(db).into_iter() {
 +            let impls = db.trait_impls_in_crate(id);
 +            all.extend(impls.for_trait(trait_.id).map(Self::from))
 +        }
 +        all
 +    }
 +
 +    // FIXME: the return type is wrong. This should be a hir version of
 +    // `TraitRef` (to account for parameters and qualifiers)
 +    pub fn trait_(self, db: &dyn HirDatabase) -> Option<Trait> {
 +        let trait_ref = db.impl_trait(self.id)?.skip_binders().clone();
 +        let id = hir_ty::from_chalk_trait_id(trait_ref.trait_id);
 +        Some(Trait { id })
 +    }
 +
 +    pub fn self_ty(self, db: &dyn HirDatabase) -> Type {
 +        let resolver = self.id.resolver(db.upcast());
 +        let substs = TyBuilder::placeholder_subst(db, self.id);
 +        let ty = db.impl_self_ty(self.id).substitute(Interner, &substs);
 +        Type::new_with_resolver_inner(db, &resolver, ty)
 +    }
 +
 +    pub fn items(self, db: &dyn HirDatabase) -> Vec<AssocItem> {
 +        db.impl_data(self.id).items.iter().map(|it| (*it).into()).collect()
 +    }
 +
 +    pub fn is_negative(self, db: &dyn HirDatabase) -> bool {
 +        db.impl_data(self.id).is_negative
 +    }
 +
 +    pub fn module(self, db: &dyn HirDatabase) -> Module {
 +        self.id.lookup(db.upcast()).container.into()
 +    }
 +
 +    pub fn is_builtin_derive(self, db: &dyn HirDatabase) -> Option<InFile<ast::Attr>> {
 +        let src = self.source(db)?;
 +        src.file_id.is_builtin_derive(db.upcast())
 +    }
 +}
 +
 +#[derive(Clone, PartialEq, Eq, Debug)]
 +pub struct Type {
 +    env: Arc<TraitEnvironment>,
 +    ty: Ty,
 +}
 +
 +impl Type {
 +    pub(crate) fn new_with_resolver(db: &dyn HirDatabase, resolver: &Resolver, ty: Ty) -> Type {
 +        Type::new_with_resolver_inner(db, resolver, ty)
 +    }
 +
 +    pub(crate) fn new_with_resolver_inner(
 +        db: &dyn HirDatabase,
 +        resolver: &Resolver,
 +        ty: Ty,
 +    ) -> Type {
 +        let environment = resolver.generic_def().map_or_else(
 +            || Arc::new(TraitEnvironment::empty(resolver.krate())),
 +            |d| db.trait_environment(d),
 +        );
 +        Type { env: environment, ty }
 +    }
 +
 +    pub(crate) fn new_for_crate(krate: CrateId, ty: Ty) -> Type {
 +        Type { env: Arc::new(TraitEnvironment::empty(krate)), ty }
 +    }
 +
 +    pub fn reference(inner: &Type, m: Mutability) -> Type {
 +        inner.derived(
 +            TyKind::Ref(
 +                if m.is_mut() { hir_ty::Mutability::Mut } else { hir_ty::Mutability::Not },
 +                hir_ty::static_lifetime(),
 +                inner.ty.clone(),
 +            )
 +            .intern(Interner),
 +        )
 +    }
 +
 +    fn new(db: &dyn HirDatabase, lexical_env: impl HasResolver, ty: Ty) -> Type {
 +        let resolver = lexical_env.resolver(db.upcast());
 +        let environment = resolver.generic_def().map_or_else(
 +            || Arc::new(TraitEnvironment::empty(resolver.krate())),
 +            |d| db.trait_environment(d),
 +        );
 +        Type { env: environment, ty }
 +    }
 +
 +    fn from_def(db: &dyn HirDatabase, def: impl HasResolver + Into<TyDefId>) -> Type {
 +        let ty = TyBuilder::def_ty(db, def.into()).fill_with_unknown().build();
 +        Type::new(db, def, ty)
 +    }
 +
 +    pub fn new_slice(ty: Type) -> Type {
 +        Type { env: ty.env, ty: TyBuilder::slice(ty.ty) }
 +    }
 +
 +    pub fn is_unit(&self) -> bool {
 +        matches!(self.ty.kind(Interner), TyKind::Tuple(0, ..))
 +    }
 +
 +    pub fn is_bool(&self) -> bool {
 +        matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Bool))
 +    }
 +
 +    pub fn is_never(&self) -> bool {
 +        matches!(self.ty.kind(Interner), TyKind::Never)
 +    }
 +
 +    pub fn is_mutable_reference(&self) -> bool {
 +        matches!(self.ty.kind(Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
 +    }
 +
 +    pub fn is_reference(&self) -> bool {
 +        matches!(self.ty.kind(Interner), TyKind::Ref(..))
 +    }
 +
 +    pub fn as_reference(&self) -> Option<(Type, Mutability)> {
 +        let (ty, _lt, m) = self.ty.as_reference()?;
 +        let m = Mutability::from_mutable(matches!(m, hir_ty::Mutability::Mut));
 +        Some((self.derived(ty.clone()), m))
 +    }
 +
 +    pub fn is_slice(&self) -> bool {
 +        matches!(self.ty.kind(Interner), TyKind::Slice(..))
 +    }
 +
 +    pub fn is_usize(&self) -> bool {
 +        matches!(self.ty.kind(Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
 +    }
 +
 +    pub fn remove_ref(&self) -> Option<Type> {
 +        match &self.ty.kind(Interner) {
 +            TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
 +            _ => None,
 +        }
 +    }
 +
 +    pub fn strip_references(&self) -> Type {
 +        self.derived(self.ty.strip_references().clone())
 +    }
 +
++    pub fn strip_reference(&self) -> Type {
++        self.derived(self.ty.strip_reference().clone())
++    }
++
 +    pub fn is_unknown(&self) -> bool {
 +        self.ty.is_unknown()
 +    }
 +
 +    /// Checks that particular type `ty` implements `std::future::Future`.
 +    /// This function is used in `.await` syntax completion.
 +    pub fn impls_future(&self, db: &dyn HirDatabase) -> bool {
 +        let std_future_trait = db
 +            .lang_item(self.env.krate, SmolStr::new_inline("future_trait"))
 +            .and_then(|it| it.as_trait());
 +        let std_future_trait = match std_future_trait {
 +            Some(it) => it,
 +            None => return false,
 +        };
 +
 +        let canonical_ty =
 +            Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
 +        method_resolution::implements_trait(&canonical_ty, db, self.env.clone(), std_future_trait)
 +    }
 +
 +    /// Checks that particular type `ty` implements `std::ops::FnOnce`.
 +    ///
 +    /// This function can be used to check if a particular type is callable, since FnOnce is a
 +    /// supertrait of Fn and FnMut, so all callable types implements at least FnOnce.
 +    pub fn impls_fnonce(&self, db: &dyn HirDatabase) -> bool {
 +        let fnonce_trait = match FnTrait::FnOnce.get_id(db, self.env.krate) {
 +            Some(it) => it,
 +            None => return false,
 +        };
 +
 +        let canonical_ty =
 +            Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
 +        method_resolution::implements_trait_unique(
 +            &canonical_ty,
 +            db,
 +            self.env.clone(),
 +            fnonce_trait,
 +        )
 +    }
 +
 +    pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
 +        let mut it = args.iter().map(|t| t.ty.clone());
 +        let trait_ref = TyBuilder::trait_ref(db, trait_.id)
 +            .push(self.ty.clone())
 +            .fill(|x| {
 +                let r = it.next().unwrap();
 +                match x {
 +                    ParamKind::Type => GenericArgData::Ty(r).intern(Interner),
 +                    ParamKind::Const(ty) => {
 +                        // FIXME: this code is not covered in tests.
 +                        unknown_const_as_generic(ty.clone())
 +                    }
 +                }
 +            })
 +            .build();
 +
 +        let goal = Canonical {
 +            value: hir_ty::InEnvironment::new(&self.env.env, trait_ref.cast(Interner)),
 +            binders: CanonicalVarKinds::empty(Interner),
 +        };
 +
 +        db.trait_solve(self.env.krate, goal).is_some()
 +    }
 +
 +    pub fn normalize_trait_assoc_type(
 +        &self,
 +        db: &dyn HirDatabase,
 +        args: &[Type],
 +        alias: TypeAlias,
 +    ) -> Option<Type> {
 +        let mut args = args.iter();
 +        let projection = TyBuilder::assoc_type_projection(db, alias.id)
 +            .push(self.ty.clone())
 +            .fill(|x| {
 +                // FIXME: this code is not covered in tests.
 +                match x {
 +                    ParamKind::Type => {
 +                        GenericArgData::Ty(args.next().unwrap().ty.clone()).intern(Interner)
 +                    }
 +                    ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
 +                }
 +            })
 +            .build();
 +        let goal = hir_ty::make_canonical(
 +            InEnvironment::new(
 +                &self.env.env,
 +                AliasEq {
 +                    alias: AliasTy::Projection(projection),
 +                    ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
 +                        .intern(Interner),
 +                }
 +                .cast(Interner),
 +            ),
 +            [TyVariableKind::General].into_iter(),
 +        );
 +
 +        match db.trait_solve(self.env.krate, goal)? {
 +            Solution::Unique(s) => s
 +                .value
 +                .subst
 +                .as_slice(Interner)
 +                .first()
 +                .map(|ty| self.derived(ty.assert_ty_ref(Interner).clone())),
 +            Solution::Ambig(_) => None,
 +        }
 +    }
 +
 +    pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
 +        let lang_item = db.lang_item(self.env.krate, SmolStr::new_inline("copy"));
 +        let copy_trait = match lang_item {
 +            Some(LangItemTarget::TraitId(it)) => it,
 +            _ => return false,
 +        };
 +        self.impls_trait(db, copy_trait.into(), &[])
 +    }
 +
 +    pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
 +        let callee = match self.ty.kind(Interner) {
 +            TyKind::Closure(id, _) => Callee::Closure(*id),
 +            TyKind::Function(_) => Callee::FnPtr,
 +            _ => Callee::Def(self.ty.callable_def(db)?),
 +        };
 +
 +        let sig = self.ty.callable_sig(db)?;
 +        Some(Callable { ty: self.clone(), sig, callee, is_bound_method: false })
 +    }
 +
 +    pub fn is_closure(&self) -> bool {
 +        matches!(&self.ty.kind(Interner), TyKind::Closure { .. })
 +    }
 +
 +    pub fn is_fn(&self) -> bool {
 +        matches!(&self.ty.kind(Interner), TyKind::FnDef(..) | TyKind::Function { .. })
 +    }
 +
 +    pub fn is_array(&self) -> bool {
 +        matches!(&self.ty.kind(Interner), TyKind::Array(..))
 +    }
 +
 +    pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
 +        let adt_id = match *self.ty.kind(Interner) {
 +            TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
 +            _ => return false,
 +        };
 +
 +        let adt = adt_id.into();
 +        match adt {
 +            Adt::Struct(s) => matches!(s.repr(db), Some(ReprKind::Packed)),
 +            _ => false,
 +        }
 +    }
 +
 +    pub fn is_raw_ptr(&self) -> bool {
 +        matches!(&self.ty.kind(Interner), TyKind::Raw(..))
 +    }
 +
 +    pub fn contains_unknown(&self) -> bool {
 +        return go(&self.ty);
 +
 +        fn go(ty: &Ty) -> bool {
 +            match ty.kind(Interner) {
 +                TyKind::Error => true,
 +
 +                TyKind::Adt(_, substs)
 +                | TyKind::AssociatedType(_, substs)
 +                | TyKind::Tuple(_, substs)
 +                | TyKind::OpaqueType(_, substs)
 +                | TyKind::FnDef(_, substs)
 +                | TyKind::Closure(_, substs) => {
 +                    substs.iter(Interner).filter_map(|a| a.ty(Interner)).any(go)
 +                }
 +
 +                TyKind::Array(_ty, len) if len.is_unknown() => true,
 +                TyKind::Array(ty, _)
 +                | TyKind::Slice(ty)
 +                | TyKind::Raw(_, ty)
 +                | TyKind::Ref(_, _, ty) => go(ty),
 +
 +                TyKind::Scalar(_)
 +                | TyKind::Str
 +                | TyKind::Never
 +                | TyKind::Placeholder(_)
 +                | TyKind::BoundVar(_)
 +                | TyKind::InferenceVar(_, _)
 +                | TyKind::Dyn(_)
 +                | TyKind::Function(_)
 +                | TyKind::Alias(_)
 +                | TyKind::Foreign(_)
 +                | TyKind::Generator(..)
 +                | TyKind::GeneratorWitness(..) => false,
 +            }
 +        }
 +    }
 +
 +    pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
 +        let (variant_id, substs) = match self.ty.kind(Interner) {
 +            TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), substs) => ((*s).into(), substs),
 +            TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), substs) => ((*u).into(), substs),
 +            _ => return Vec::new(),
 +        };
 +
 +        db.field_types(variant_id)
 +            .iter()
 +            .map(|(local_id, ty)| {
 +                let def = Field { parent: variant_id.into(), id: local_id };
 +                let ty = ty.clone().substitute(Interner, substs);
 +                (def, self.derived(ty))
 +            })
 +            .collect()
 +    }
 +
 +    pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
 +        if let TyKind::Tuple(_, substs) = &self.ty.kind(Interner) {
 +            substs
 +                .iter(Interner)
 +                .map(|ty| self.derived(ty.assert_ty_ref(Interner).clone()))
 +                .collect()
 +        } else {
 +            Vec::new()
 +        }
 +    }
 +
 +    pub fn autoderef<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Type> + 'a {
 +        self.autoderef_(db).map(move |ty| self.derived(ty))
 +    }
 +
 +    fn autoderef_<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Ty> + 'a {
 +        // There should be no inference vars in types passed here
 +        let canonical = hir_ty::replace_errors_with_variables(&self.ty);
 +        let environment = self.env.clone();
 +        autoderef(db, environment, canonical).map(|canonical| canonical.value)
 +    }
 +
 +    // This would be nicer if it just returned an iterator, but that runs into
 +    // lifetime problems, because we need to borrow temp `CrateImplDefs`.
 +    pub fn iterate_assoc_items<T>(
 +        &self,
 +        db: &dyn HirDatabase,
 +        krate: Crate,
 +        mut callback: impl FnMut(AssocItem) -> Option<T>,
 +    ) -> Option<T> {
 +        let mut slot = None;
 +        self.iterate_assoc_items_dyn(db, krate, &mut |assoc_item_id| {
 +            slot = callback(assoc_item_id.into());
 +            slot.is_some()
 +        });
 +        slot
 +    }
 +
 +    fn iterate_assoc_items_dyn(
 +        &self,
 +        db: &dyn HirDatabase,
 +        krate: Crate,
 +        callback: &mut dyn FnMut(AssocItemId) -> bool,
 +    ) {
 +        let def_crates = match method_resolution::def_crates(db, &self.ty, krate.id) {
 +            Some(it) => it,
 +            None => return,
 +        };
 +        for krate in def_crates {
 +            let impls = db.inherent_impls_in_crate(krate);
 +
 +            for impl_def in impls.for_self_ty(&self.ty) {
 +                for &item in db.impl_data(*impl_def).items.iter() {
 +                    if callback(item) {
 +                        return;
 +                    }
 +                }
 +            }
 +        }
 +    }
 +
 +    pub fn type_arguments(&self) -> impl Iterator<Item = Type> + '_ {
 +        self.ty
 +            .strip_references()
 +            .as_adt()
 +            .into_iter()
 +            .flat_map(|(_, substs)| substs.iter(Interner))
 +            .filter_map(|arg| arg.ty(Interner).cloned())
 +            .map(move |ty| self.derived(ty))
 +    }
 +
 +    pub fn iterate_method_candidates<T>(
 +        &self,
 +        db: &dyn HirDatabase,
 +        scope: &SemanticsScope<'_>,
 +        // FIXME this can be retrieved from `scope`, except autoimport uses this
 +        // to specify a different set, so the method needs to be split
 +        traits_in_scope: &FxHashSet<TraitId>,
 +        with_local_impls: Option<Module>,
 +        name: Option<&Name>,
 +        mut callback: impl FnMut(Function) -> Option<T>,
 +    ) -> Option<T> {
 +        let _p = profile::span("iterate_method_candidates");
 +        let mut slot = None;
 +
 +        self.iterate_method_candidates_dyn(
 +            db,
 +            scope,
 +            traits_in_scope,
 +            with_local_impls,
 +            name,
 +            &mut |assoc_item_id| {
 +                if let AssocItemId::FunctionId(func) = assoc_item_id {
 +                    if let Some(res) = callback(func.into()) {
 +                        slot = Some(res);
 +                        return ControlFlow::Break(());
 +                    }
 +                }
 +                ControlFlow::Continue(())
 +            },
 +        );
 +        slot
 +    }
 +
 +    fn iterate_method_candidates_dyn(
 +        &self,
 +        db: &dyn HirDatabase,
 +        scope: &SemanticsScope<'_>,
 +        traits_in_scope: &FxHashSet<TraitId>,
 +        with_local_impls: Option<Module>,
 +        name: Option<&Name>,
 +        callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
 +    ) {
 +        // There should be no inference vars in types passed here
 +        let canonical = hir_ty::replace_errors_with_variables(&self.ty);
 +
 +        let krate = scope.krate();
 +        let environment = scope.resolver().generic_def().map_or_else(
 +            || Arc::new(TraitEnvironment::empty(krate.id)),
 +            |d| db.trait_environment(d),
 +        );
 +
 +        method_resolution::iterate_method_candidates_dyn(
 +            &canonical,
 +            db,
 +            environment,
 +            traits_in_scope,
 +            with_local_impls.and_then(|b| b.id.containing_block()).into(),
 +            name,
 +            method_resolution::LookupMode::MethodCall,
 +            &mut |_adj, id| callback(id),
 +        );
 +    }
 +
 +    pub fn iterate_path_candidates<T>(
 +        &self,
 +        db: &dyn HirDatabase,
 +        scope: &SemanticsScope<'_>,
 +        traits_in_scope: &FxHashSet<TraitId>,
 +        with_local_impls: Option<Module>,
 +        name: Option<&Name>,
 +        mut callback: impl FnMut(AssocItem) -> Option<T>,
 +    ) -> Option<T> {
 +        let _p = profile::span("iterate_path_candidates");
 +        let mut slot = None;
 +        self.iterate_path_candidates_dyn(
 +            db,
 +            scope,
 +            traits_in_scope,
 +            with_local_impls,
 +            name,
 +            &mut |assoc_item_id| {
 +                if let Some(res) = callback(assoc_item_id.into()) {
 +                    slot = Some(res);
 +                    return ControlFlow::Break(());
 +                }
 +                ControlFlow::Continue(())
 +            },
 +        );
 +        slot
 +    }
 +
 +    fn iterate_path_candidates_dyn(
 +        &self,
 +        db: &dyn HirDatabase,
 +        scope: &SemanticsScope<'_>,
 +        traits_in_scope: &FxHashSet<TraitId>,
 +        with_local_impls: Option<Module>,
 +        name: Option<&Name>,
 +        callback: &mut dyn FnMut(AssocItemId) -> ControlFlow<()>,
 +    ) {
 +        let canonical = hir_ty::replace_errors_with_variables(&self.ty);
 +
 +        let krate = scope.krate();
 +        let environment = scope.resolver().generic_def().map_or_else(
 +            || Arc::new(TraitEnvironment::empty(krate.id)),
 +            |d| db.trait_environment(d),
 +        );
 +
 +        method_resolution::iterate_path_candidates(
 +            &canonical,
 +            db,
 +            environment,
 +            traits_in_scope,
 +            with_local_impls.and_then(|b| b.id.containing_block()).into(),
 +            name,
 +            &mut |id| callback(id),
 +        );
 +    }
 +
 +    pub fn as_adt(&self) -> Option<Adt> {
 +        let (adt, _subst) = self.ty.as_adt()?;
 +        Some(adt.into())
 +    }
 +
 +    pub fn as_builtin(&self) -> Option<BuiltinType> {
 +        self.ty.as_builtin().map(|inner| BuiltinType { inner })
 +    }
 +
 +    pub fn as_dyn_trait(&self) -> Option<Trait> {
 +        self.ty.dyn_trait().map(Into::into)
 +    }
 +
 +    /// If a type can be represented as `dyn Trait`, returns all traits accessible via this type,
 +    /// or an empty iterator otherwise.
 +    pub fn applicable_inherent_traits<'a>(
 +        &'a self,
 +        db: &'a dyn HirDatabase,
 +    ) -> impl Iterator<Item = Trait> + 'a {
 +        let _p = profile::span("applicable_inherent_traits");
 +        self.autoderef_(db)
 +            .filter_map(|ty| ty.dyn_trait())
 +            .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
 +            .map(Trait::from)
 +    }
 +
 +    pub fn env_traits<'a>(&'a self, db: &'a dyn HirDatabase) -> impl Iterator<Item = Trait> + 'a {
 +        let _p = profile::span("env_traits");
 +        self.autoderef_(db)
 +            .filter(|ty| matches!(ty.kind(Interner), TyKind::Placeholder(_)))
 +            .flat_map(|ty| {
 +                self.env
 +                    .traits_in_scope_from_clauses(ty)
 +                    .flat_map(|t| hir_ty::all_super_traits(db.upcast(), t))
 +            })
 +            .map(Trait::from)
 +    }
 +
 +    pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<impl Iterator<Item = Trait>> {
 +        self.ty.impl_trait_bounds(db).map(|it| {
 +            it.into_iter().filter_map(|pred| match pred.skip_binders() {
 +                hir_ty::WhereClause::Implemented(trait_ref) => {
 +                    Some(Trait::from(trait_ref.hir_trait_id()))
 +                }
 +                _ => None,
 +            })
 +        })
 +    }
 +
 +    pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> {
 +        self.ty.associated_type_parent_trait(db).map(Into::into)
 +    }
 +
 +    fn derived(&self, ty: Ty) -> Type {
 +        Type { env: self.env.clone(), ty }
 +    }
 +
 +    pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
 +        // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself.
 +        // We need a different order here.
 +
 +        fn walk_substs(
 +            db: &dyn HirDatabase,
 +            type_: &Type,
 +            substs: &Substitution,
 +            cb: &mut impl FnMut(Type),
 +        ) {
 +            for ty in substs.iter(Interner).filter_map(|a| a.ty(Interner)) {
 +                walk_type(db, &type_.derived(ty.clone()), cb);
 +            }
 +        }
 +
 +        fn walk_bounds(
 +            db: &dyn HirDatabase,
 +            type_: &Type,
 +            bounds: &[QuantifiedWhereClause],
 +            cb: &mut impl FnMut(Type),
 +        ) {
 +            for pred in bounds {
 +                if let WhereClause::Implemented(trait_ref) = pred.skip_binders() {
 +                    cb(type_.clone());
 +                    // skip the self type. it's likely the type we just got the bounds from
 +                    for ty in
 +                        trait_ref.substitution.iter(Interner).skip(1).filter_map(|a| a.ty(Interner))
 +                    {
 +                        walk_type(db, &type_.derived(ty.clone()), cb);
 +                    }
 +                }
 +            }
 +        }
 +
 +        fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
 +            let ty = type_.ty.strip_references();
 +            match ty.kind(Interner) {
 +                TyKind::Adt(_, substs) => {
 +                    cb(type_.derived(ty.clone()));
 +                    walk_substs(db, type_, substs, cb);
 +                }
 +                TyKind::AssociatedType(_, substs) => {
 +                    if ty.associated_type_parent_trait(db).is_some() {
 +                        cb(type_.derived(ty.clone()));
 +                    }
 +                    walk_substs(db, type_, substs, cb);
 +                }
 +                TyKind::OpaqueType(_, subst) => {
 +                    if let Some(bounds) = ty.impl_trait_bounds(db) {
 +                        walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
 +                    }
 +
 +                    walk_substs(db, type_, subst, cb);
 +                }
 +                TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
 +                    if let Some(bounds) = ty.impl_trait_bounds(db) {
 +                        walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
 +                    }
 +
 +                    walk_substs(db, type_, &opaque_ty.substitution, cb);
 +                }
 +                TyKind::Placeholder(_) => {
 +                    if let Some(bounds) = ty.impl_trait_bounds(db) {
 +                        walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
 +                    }
 +                }
 +                TyKind::Dyn(bounds) => {
 +                    walk_bounds(
 +                        db,
 +                        &type_.derived(ty.clone()),
 +                        bounds.bounds.skip_binders().interned(),
 +                        cb,
 +                    );
 +                }
 +
 +                TyKind::Ref(_, _, ty)
 +                | TyKind::Raw(_, ty)
 +                | TyKind::Array(ty, _)
 +                | TyKind::Slice(ty) => {
 +                    walk_type(db, &type_.derived(ty.clone()), cb);
 +                }
 +
 +                TyKind::FnDef(_, substs)
 +                | TyKind::Tuple(_, substs)
 +                | TyKind::Closure(.., substs) => {
 +                    walk_substs(db, type_, substs, cb);
 +                }
 +                TyKind::Function(hir_ty::FnPointer { substitution, .. }) => {
 +                    walk_substs(db, type_, &substitution.0, cb);
 +                }
 +
 +                _ => {}
 +            }
 +        }
 +
 +        walk_type(db, self, &mut cb);
 +    }
 +
 +    pub fn could_unify_with(&self, db: &dyn HirDatabase, other: &Type) -> bool {
 +        let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), other.ty.clone()));
 +        hir_ty::could_unify(db, self.env.clone(), &tys)
 +    }
 +
 +    pub fn could_coerce_to(&self, db: &dyn HirDatabase, to: &Type) -> bool {
 +        let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), to.ty.clone()));
 +        hir_ty::could_coerce(db, self.env.clone(), &tys)
 +    }
 +
 +    pub fn as_type_param(&self, db: &dyn HirDatabase) -> Option<TypeParam> {
 +        match self.ty.kind(Interner) {
 +            TyKind::Placeholder(p) => Some(TypeParam {
 +                id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p)),
 +            }),
 +            _ => None,
 +        }
 +    }
 +}
 +
 +#[derive(Debug)]
 +pub struct Callable {
 +    ty: Type,
 +    sig: CallableSig,
 +    callee: Callee,
 +    pub(crate) is_bound_method: bool,
 +}
 +
 +#[derive(Debug)]
 +enum Callee {
 +    Def(CallableDefId),
 +    Closure(ClosureId),
 +    FnPtr,
 +}
 +
 +pub enum CallableKind {
 +    Function(Function),
 +    TupleStruct(Struct),
 +    TupleEnumVariant(Variant),
 +    Closure,
 +    FnPtr,
 +}
 +
 +impl Callable {
 +    pub fn kind(&self) -> CallableKind {
 +        use Callee::*;
 +        match self.callee {
 +            Def(CallableDefId::FunctionId(it)) => CallableKind::Function(it.into()),
 +            Def(CallableDefId::StructId(it)) => CallableKind::TupleStruct(it.into()),
 +            Def(CallableDefId::EnumVariantId(it)) => CallableKind::TupleEnumVariant(it.into()),
 +            Closure(_) => CallableKind::Closure,
 +            FnPtr => CallableKind::FnPtr,
 +        }
 +    }
 +    pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<ast::SelfParam> {
 +        let func = match self.callee {
 +            Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
 +            _ => return None,
 +        };
 +        let src = func.lookup(db.upcast()).source(db.upcast());
 +        let param_list = src.value.param_list()?;
 +        param_list.self_param()
 +    }
 +    pub fn n_params(&self) -> usize {
 +        self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }
 +    }
 +    pub fn params(
 +        &self,
 +        db: &dyn HirDatabase,
 +    ) -> Vec<(Option<Either<ast::SelfParam, ast::Pat>>, Type)> {
 +        let types = self
 +            .sig
 +            .params()
 +            .iter()
 +            .skip(if self.is_bound_method { 1 } else { 0 })
 +            .map(|ty| self.ty.derived(ty.clone()));
 +        let map_param = |it: ast::Param| it.pat().map(Either::Right);
 +        let patterns = match self.callee {
 +            Callee::Def(CallableDefId::FunctionId(func)) => {
 +                let src = func.lookup(db.upcast()).source(db.upcast());
 +                src.value.param_list().map(|param_list| {
 +                    param_list
 +                        .self_param()
 +                        .map(|it| Some(Either::Left(it)))
 +                        .filter(|_| !self.is_bound_method)
 +                        .into_iter()
 +                        .chain(param_list.params().map(map_param))
 +                })
 +            }
 +            Callee::Closure(closure_id) => match closure_source(db, closure_id) {
 +                Some(src) => src.param_list().map(|param_list| {
 +                    param_list
 +                        .self_param()
 +                        .map(|it| Some(Either::Left(it)))
 +                        .filter(|_| !self.is_bound_method)
 +                        .into_iter()
 +                        .chain(param_list.params().map(map_param))
 +                }),
 +                None => None,
 +            },
 +            _ => None,
 +        };
 +        patterns.into_iter().flatten().chain(iter::repeat(None)).zip(types).collect()
 +    }
 +    pub fn return_type(&self) -> Type {
 +        self.ty.derived(self.sig.ret().clone())
 +    }
 +}
 +
 +fn closure_source(db: &dyn HirDatabase, closure: ClosureId) -> Option<ast::ClosureExpr> {
 +    let (owner, expr_id) = db.lookup_intern_closure(closure.into());
 +    let (_, source_map) = db.body_with_source_map(owner);
 +    let ast = source_map.expr_syntax(expr_id).ok()?;
 +    let root = ast.file_syntax(db.upcast());
 +    let expr = ast.value.to_node(&root);
 +    match expr {
 +        ast::Expr::ClosureExpr(it) => Some(it),
 +        _ => None,
 +    }
 +}
 +
 +#[derive(Copy, Clone, Debug, Eq, PartialEq)]
 +pub enum BindingMode {
 +    Move,
 +    Ref(Mutability),
 +}
 +
 +/// For IDE only
 +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 +pub enum ScopeDef {
 +    ModuleDef(ModuleDef),
 +    GenericParam(GenericParam),
 +    ImplSelfType(Impl),
 +    AdtSelfType(Adt),
 +    Local(Local),
 +    Label(Label),
 +    Unknown,
 +}
 +
 +impl ScopeDef {
 +    pub fn all_items(def: PerNs) -> ArrayVec<Self, 3> {
 +        let mut items = ArrayVec::new();
 +
 +        match (def.take_types(), def.take_values()) {
 +            (Some(m1), None) => items.push(ScopeDef::ModuleDef(m1.into())),
 +            (None, Some(m2)) => items.push(ScopeDef::ModuleDef(m2.into())),
 +            (Some(m1), Some(m2)) => {
 +                // Some items, like unit structs and enum variants, are
 +                // returned as both a type and a value. Here we want
 +                // to de-duplicate them.
 +                if m1 != m2 {
 +                    items.push(ScopeDef::ModuleDef(m1.into()));
 +                    items.push(ScopeDef::ModuleDef(m2.into()));
 +                } else {
 +                    items.push(ScopeDef::ModuleDef(m1.into()));
 +                }
 +            }
 +            (None, None) => {}
 +        };
 +
 +        if let Some(macro_def_id) = def.take_macros() {
 +            items.push(ScopeDef::ModuleDef(ModuleDef::Macro(macro_def_id.into())));
 +        }
 +
 +        if items.is_empty() {
 +            items.push(ScopeDef::Unknown);
 +        }
 +
 +        items
 +    }
 +
 +    pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
 +        match self {
 +            ScopeDef::ModuleDef(it) => it.attrs(db),
 +            ScopeDef::GenericParam(it) => Some(it.attrs(db)),
 +            ScopeDef::ImplSelfType(_)
 +            | ScopeDef::AdtSelfType(_)
 +            | ScopeDef::Local(_)
 +            | ScopeDef::Label(_)
 +            | ScopeDef::Unknown => None,
 +        }
 +    }
 +
 +    pub fn krate(&self, db: &dyn HirDatabase) -> Option<Crate> {
 +        match self {
 +            ScopeDef::ModuleDef(it) => it.module(db).map(|m| m.krate()),
 +            ScopeDef::GenericParam(it) => Some(it.module(db).krate()),
 +            ScopeDef::ImplSelfType(_) => None,
 +            ScopeDef::AdtSelfType(it) => Some(it.module(db).krate()),
 +            ScopeDef::Local(it) => Some(it.module(db).krate()),
 +            ScopeDef::Label(it) => Some(it.module(db).krate()),
 +            ScopeDef::Unknown => None,
 +        }
 +    }
 +}
 +
 +impl From<ItemInNs> for ScopeDef {
 +    fn from(item: ItemInNs) -> Self {
 +        match item {
 +            ItemInNs::Types(id) => ScopeDef::ModuleDef(id),
 +            ItemInNs::Values(id) => ScopeDef::ModuleDef(id),
 +            ItemInNs::Macros(id) => ScopeDef::ModuleDef(ModuleDef::Macro(id)),
 +        }
 +    }
 +}
 +
 +pub trait HasVisibility {
 +    fn visibility(&self, db: &dyn HirDatabase) -> Visibility;
 +    fn is_visible_from(&self, db: &dyn HirDatabase, module: Module) -> bool {
 +        let vis = self.visibility(db);
 +        vis.is_visible_from(db.upcast(), module.id)
 +    }
 +}
 +
 +/// Trait for obtaining the defining crate of an item.
 +pub trait HasCrate {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate;
 +}
 +
 +impl<T: hir_def::HasModule> HasCrate for T {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.module(db.upcast()).krate().into()
 +    }
 +}
 +
 +impl HasCrate for AssocItem {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.module(db).krate()
 +    }
 +}
 +
 +impl HasCrate for Struct {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.module(db).krate()
 +    }
 +}
 +
 +impl HasCrate for Union {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.module(db).krate()
 +    }
 +}
 +
 +impl HasCrate for Field {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.parent_def(db).module(db).krate()
 +    }
 +}
 +
 +impl HasCrate for Variant {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.module(db).krate()
 +    }
 +}
 +
 +impl HasCrate for Function {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.module(db).krate()
 +    }
 +}
 +
 +impl HasCrate for Const {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.module(db).krate()
 +    }
 +}
 +
 +impl HasCrate for TypeAlias {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.module(db).krate()
 +    }
 +}
 +
 +impl HasCrate for Type {
 +    fn krate(&self, _db: &dyn HirDatabase) -> Crate {
 +        self.env.krate.into()
 +    }
 +}
 +
 +impl HasCrate for Macro {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.module(db).krate()
 +    }
 +}
 +
 +impl HasCrate for Trait {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.module(db).krate()
 +    }
 +}
 +
 +impl HasCrate for Static {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.module(db).krate()
 +    }
 +}
 +
 +impl HasCrate for Adt {
 +    fn krate(&self, db: &dyn HirDatabase) -> Crate {
 +        self.module(db).krate()
 +    }
 +}
 +
 +impl HasCrate for Module {
 +    fn krate(&self, _: &dyn HirDatabase) -> Crate {
 +        Module::krate(*self)
 +    }
 +}
index fc8f23f19ab9112839303e2f33c022e056567891,0000000000000000000000000000000000000000..c84318b2fb8774123dbe91b69df2aae53da34547
mode 100644,000000..100644
--- /dev/null
@@@ -1,1517 -1,0 +1,1540 @@@
-         self.wrap_node_infile(node).original_ast_node(self.db.upcast()).map(|it| it.value)
 +//! See `Semantics`.
 +
 +mod source_to_def;
 +
 +use std::{cell::RefCell, fmt, iter, ops};
 +
 +use base_db::{FileId, FileRange};
 +use hir_def::{
 +    body, macro_id_to_def_id,
 +    resolver::{self, HasResolver, Resolver, TypeNs},
 +    type_ref::Mutability,
 +    AsMacroCall, FunctionId, MacroId, TraitId, VariantId,
 +};
 +use hir_expand::{
 +    db::AstDatabase,
 +    name::{known, AsName},
 +    ExpansionInfo, MacroCallId,
 +};
 +use itertools::Itertools;
 +use rustc_hash::{FxHashMap, FxHashSet};
 +use smallvec::{smallvec, SmallVec};
 +use syntax::{
 +    algo::skip_trivia_token,
 +    ast::{self, HasAttrs as _, HasGenericParams, HasLoopBody},
 +    match_ast, AstNode, Direction, SyntaxKind, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextSize,
 +};
 +
 +use crate::{
 +    db::HirDatabase,
 +    semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
 +    source_analyzer::{resolve_hir_path, SourceAnalyzer},
 +    Access, BindingMode, BuiltinAttr, Callable, ConstParam, Crate, DeriveHelper, Field, Function,
 +    HasSource, HirFileId, Impl, InFile, Label, LifetimeParam, Local, Macro, Module, ModuleDef,
 +    Name, Path, ScopeDef, ToolModule, Trait, Type, TypeAlias, TypeParam, VariantDef,
 +};
 +
 +#[derive(Debug, 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)]
 +pub struct TypeInfo {
 +    /// The original type of the expression or pattern.
 +    pub original: Type,
 +    /// The adjusted type, if an adjustment happened.
 +    pub adjusted: Option<Type>,
 +}
 +
 +impl TypeInfo {
 +    pub fn original(self) -> Type {
 +        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 {
 +        self.adjusted.unwrap_or(self.original)
 +    }
 +}
 +
 +/// Primary API to get semantic information, like types, from syntax trees.
 +pub struct Semantics<'db, DB> {
 +    pub db: &'db DB,
 +    imp: SemanticsImpl<'db>,
 +}
 +
 +pub struct SemanticsImpl<'db> {
 +    pub db: &'db dyn HirDatabase,
 +    s2d_cache: RefCell<SourceToDefCache>,
 +    expansion_info_cache: RefCell<FxHashMap<HirFileId, Option<ExpansionInfo>>>,
 +    // Rootnode to HirFileId cache
 +    cache: RefCell<FxHashMap<SyntaxNode, HirFileId>>,
 +    // MacroCall to its expansion's HirFileId cache
 +    macro_call_cache: RefCell<FxHashMap<InFile<ast::MacroCall>, HirFileId>>,
 +}
 +
 +impl<DB> fmt::Debug for Semantics<'_, DB> {
 +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 +        write!(f, "Semantics {{ ... }}")
 +    }
 +}
 +
 +impl<'db, DB: HirDatabase> Semantics<'db, DB> {
 +    pub fn new(db: &DB) -> Semantics<'_, DB> {
 +        let impl_ = SemanticsImpl::new(db);
 +        Semantics { db, imp: impl_ }
 +    }
 +
 +    pub fn parse(&self, file_id: FileId) -> ast::SourceFile {
 +        self.imp.parse(file_id)
 +    }
 +
 +    pub fn parse_or_expand(&self, file_id: HirFileId) -> Option<SyntaxNode> {
 +        self.imp.parse_or_expand(file_id)
 +    }
 +
 +    pub fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
 +        self.imp.expand(macro_call)
 +    }
 +
 +    /// If `item` has an attribute macro attached to it, expands it.
 +    pub fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> {
 +        self.imp.expand_attr_macro(item)
 +    }
 +
 +    pub fn expand_derive_as_pseudo_attr_macro(&self, attr: &ast::Attr) -> Option<SyntaxNode> {
 +        self.imp.expand_derive_as_pseudo_attr_macro(attr)
 +    }
 +
 +    pub fn resolve_derive_macro(&self, derive: &ast::Attr) -> Option<Vec<Option<Macro>>> {
 +        self.imp.resolve_derive_macro(derive)
 +    }
 +
 +    pub fn expand_derive_macro(&self, derive: &ast::Attr) -> Option<Vec<SyntaxNode>> {
 +        self.imp.expand_derive_macro(derive)
 +    }
 +
 +    pub fn is_attr_macro_call(&self, item: &ast::Item) -> bool {
 +        self.imp.is_attr_macro_call(item)
 +    }
 +
 +    pub fn is_derive_annotated(&self, item: &ast::Adt) -> bool {
 +        self.imp.is_derive_annotated(item)
 +    }
 +
 +    pub fn speculative_expand(
 +        &self,
 +        actual_macro_call: &ast::MacroCall,
 +        speculative_args: &ast::TokenTree,
 +        token_to_map: SyntaxToken,
 +    ) -> Option<(SyntaxNode, SyntaxToken)> {
 +        self.imp.speculative_expand(actual_macro_call, speculative_args, token_to_map)
 +    }
 +
 +    pub fn speculative_expand_attr_macro(
 +        &self,
 +        actual_macro_call: &ast::Item,
 +        speculative_args: &ast::Item,
 +        token_to_map: SyntaxToken,
 +    ) -> Option<(SyntaxNode, SyntaxToken)> {
 +        self.imp.speculative_expand_attr(actual_macro_call, speculative_args, 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, SyntaxToken)> {
 +        self.imp.speculative_expand_derive_as_pseudo_attr_macro(
 +            actual_macro_call,
 +            speculative_args,
 +            token_to_map,
 +        )
 +    }
 +
 +    /// Descend the token into macrocalls to its first mapped counterpart.
 +    pub fn descend_into_macros_single(&self, token: SyntaxToken) -> SyntaxToken {
 +        self.imp.descend_into_macros_single(token)
 +    }
 +
 +    /// Descend the token into macrocalls to all its mapped counterparts.
 +    pub fn descend_into_macros(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
 +        self.imp.descend_into_macros(token)
 +    }
 +
 +    /// Descend the token into macrocalls to all its mapped counterparts that have the same text as the input token.
 +    ///
 +    /// Returns the original non descended token if none of the mapped counterparts have the same text.
 +    pub fn descend_into_macros_with_same_text(
 +        &self,
 +        token: SyntaxToken,
 +    ) -> SmallVec<[SyntaxToken; 1]> {
 +        self.imp.descend_into_macros_with_same_text(token)
 +    }
 +
 +    pub fn descend_into_macros_with_kind_preference(&self, token: SyntaxToken) -> SyntaxToken {
 +        self.imp.descend_into_macros_with_kind_preference(token)
 +    }
 +
 +    /// 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]> {
 +        self.imp.descend_node_into_attributes(node)
 +    }
 +
 +    /// 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,
 +    {
 +        self.imp.source(def)
 +    }
 +
 +    pub fn hir_file_for(&self, syntax_node: &SyntaxNode) -> HirFileId {
 +        self.imp.find_file(syntax_node).file_id
 +    }
 +
 +    /// 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 {
 +        self.imp.original_range(node)
 +    }
 +
 +    /// 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> {
 +        self.imp.original_range_opt(node)
 +    }
 +
 +    /// 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.imp.original_ast_node(node)
 +    }
 +
 +    pub fn diagnostics_display_range(&self, diagnostics: InFile<SyntaxNodePtr>) -> FileRange {
 +        self.imp.diagnostics_display_range(diagnostics)
 +    }
 +
 +    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))
 +    }
 +
 +    /// Iterates the ancestors of the given node, climbing up macro expansions while doing so.
 +    pub fn ancestors_with_macros(&self, node: SyntaxNode) -> impl Iterator<Item = SyntaxNode> + '_ {
 +        self.imp.ancestors_with_macros(node)
 +    }
 +
 +    pub fn ancestors_at_offset_with_macros(
 +        &self,
 +        node: &SyntaxNode,
 +        offset: TextSize,
 +    ) -> impl Iterator<Item = SyntaxNode> + '_ {
 +        self.imp.ancestors_at_offset_with_macros(node, offset)
 +    }
 +
 +    /// 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
 +    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 *MacroCall*,
 +    /// descend it and find again
 +    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))
 +    }
 +
 +    pub fn resolve_lifetime_param(&self, lifetime: &ast::Lifetime) -> Option<LifetimeParam> {
 +        self.imp.resolve_lifetime_param(lifetime)
 +    }
 +
 +    pub fn resolve_label(&self, lifetime: &ast::Lifetime) -> Option<Label> {
 +        self.imp.resolve_label(lifetime)
 +    }
 +
 +    pub fn resolve_type(&self, ty: &ast::Type) -> Option<Type> {
 +        self.imp.resolve_type(ty)
 +    }
 +
++    pub fn resolve_trait(&self, trait_: &ast::Path) -> Option<Trait> {
++        self.imp.resolve_trait(trait_)
++    }
++
 +    // FIXME: Figure out a nice interface to inspect adjustments
 +    pub fn is_implicit_reborrow(&self, expr: &ast::Expr) -> Option<Mutability> {
 +        self.imp.is_implicit_reborrow(expr)
 +    }
 +
 +    pub fn type_of_expr(&self, expr: &ast::Expr) -> Option<TypeInfo> {
 +        self.imp.type_of_expr(expr)
 +    }
 +
 +    pub fn type_of_pat(&self, pat: &ast::Pat) -> Option<TypeInfo> {
 +        self.imp.type_of_pat(pat)
 +    }
 +
 +    pub fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
 +        self.imp.type_of_self(param)
 +    }
 +
 +    pub fn pattern_adjustments(&self, pat: &ast::Pat) -> SmallVec<[Type; 1]> {
 +        self.imp.pattern_adjustments(pat)
 +    }
 +
 +    pub fn binding_mode_of_pat(&self, pat: &ast::IdentPat) -> Option<BindingMode> {
 +        self.imp.binding_mode_of_pat(pat)
 +    }
 +
 +    pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
 +        self.imp.resolve_method_call(call).map(Function::from)
 +    }
 +
 +    pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
 +        self.imp.resolve_method_call_as_callable(call)
 +    }
 +
 +    pub fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> {
 +        self.imp.resolve_field(field)
 +    }
 +
 +    pub fn resolve_record_field(
 +        &self,
 +        field: &ast::RecordExprField,
 +    ) -> Option<(Field, Option<Local>, Type)> {
 +        self.imp.resolve_record_field(field)
 +    }
 +
 +    pub fn resolve_record_pat_field(&self, field: &ast::RecordPatField) -> Option<Field> {
 +        self.imp.resolve_record_pat_field(field)
 +    }
 +
 +    pub fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<Macro> {
 +        self.imp.resolve_macro_call(macro_call)
 +    }
 +
 +    pub fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool {
 +        self.imp.is_unsafe_macro_call(macro_call)
 +    }
 +
 +    pub fn resolve_attr_macro_call(&self, item: &ast::Item) -> Option<Macro> {
 +        self.imp.resolve_attr_macro_call(item)
 +    }
 +
 +    pub fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> {
 +        self.imp.resolve_path(path)
 +    }
 +
 +    pub fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> {
 +        self.imp.resolve_extern_crate(extern_crate)
 +    }
 +
 +    pub fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantDef> {
 +        self.imp.resolve_variant(record_lit).map(VariantDef::from)
 +    }
 +
 +    pub fn resolve_bind_pat_to_const(&self, pat: &ast::IdentPat) -> Option<ModuleDef> {
 +        self.imp.resolve_bind_pat_to_const(pat)
 +    }
 +
 +    pub fn record_literal_missing_fields(&self, literal: &ast::RecordExpr) -> Vec<(Field, Type)> {
 +        self.imp.record_literal_missing_fields(literal)
 +    }
 +
 +    pub fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> {
 +        self.imp.record_pattern_missing_fields(pattern)
 +    }
 +
 +    pub fn to_def<T: ToDef>(&self, src: &T) -> Option<T::Def> {
 +        let src = self.imp.find_file(src.syntax()).with_value(src).cloned();
 +        T::to_def(&self.imp, src)
 +    }
 +
 +    pub fn to_module_def(&self, file: FileId) -> Option<Module> {
 +        self.imp.to_module_def(file).next()
 +    }
 +
 +    pub fn to_module_defs(&self, file: FileId) -> impl Iterator<Item = Module> {
 +        self.imp.to_module_def(file)
 +    }
 +
 +    pub fn scope(&self, node: &SyntaxNode) -> Option<SemanticsScope<'db>> {
 +        self.imp.scope(node)
 +    }
 +
 +    pub fn scope_at_offset(
 +        &self,
 +        node: &SyntaxNode,
 +        offset: TextSize,
 +    ) -> Option<SemanticsScope<'db>> {
 +        self.imp.scope_at_offset(node, offset)
 +    }
 +
 +    pub fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
 +        self.imp.scope_for_def(def)
 +    }
 +
 +    pub fn assert_contains_node(&self, node: &SyntaxNode) {
 +        self.imp.assert_contains_node(node)
 +    }
 +
 +    pub fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool {
 +        self.imp.is_unsafe_method_call(method_call_expr)
 +    }
 +
 +    pub fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool {
 +        self.imp.is_unsafe_ref_expr(ref_expr)
 +    }
 +
 +    pub fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool {
 +        self.imp.is_unsafe_ident_pat(ident_pat)
 +    }
 +}
 +
 +impl<'db> SemanticsImpl<'db> {
 +    fn new(db: &'db dyn HirDatabase) -> Self {
 +        SemanticsImpl {
 +            db,
 +            s2d_cache: Default::default(),
 +            cache: Default::default(),
 +            expansion_info_cache: Default::default(),
 +            macro_call_cache: Default::default(),
 +        }
 +    }
 +
 +    fn parse(&self, file_id: FileId) -> ast::SourceFile {
 +        let tree = self.db.parse(file_id).tree();
 +        self.cache(tree.syntax().clone(), file_id.into());
 +        tree
 +    }
 +
 +    fn parse_or_expand(&self, file_id: HirFileId) -> Option<SyntaxNode> {
 +        let node = self.db.parse_or_expand(file_id)?;
 +        self.cache(node.clone(), file_id);
 +        Some(node)
 +    }
 +
 +    fn expand(&self, macro_call: &ast::MacroCall) -> Option<SyntaxNode> {
 +        let sa = self.analyze_no_infer(macro_call.syntax())?;
 +        let file_id = sa.expand(self.db, InFile::new(sa.file_id, macro_call))?;
 +        let node = self.parse_or_expand(file_id)?;
 +        Some(node)
 +    }
 +
 +    fn expand_attr_macro(&self, item: &ast::Item) -> Option<SyntaxNode> {
 +        let src = self.wrap_node_infile(item.clone());
 +        let macro_call_id = self.with_ctx(|ctx| ctx.item_to_macro_call(src))?;
 +        self.parse_or_expand(macro_call_id.as_file())
 +    }
 +
 +    fn expand_derive_as_pseudo_attr_macro(&self, attr: &ast::Attr) -> Option<SyntaxNode> {
 +        let src = self.wrap_node_infile(attr.clone());
 +        let adt = attr.syntax().parent().and_then(ast::Adt::cast)?;
 +        let call_id = self.with_ctx(|ctx| {
 +            ctx.attr_to_derive_macro_call(src.with_value(&adt), src).map(|(_, it, _)| it)
 +        })?;
 +        self.parse_or_expand(call_id.as_file())
 +    }
 +
 +    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, self.db.upcast(), call?).map(|id| Macro { id })
 +                    })
 +                    .collect(),
 +            )
 +        })
 +    }
 +
 +    fn expand_derive_macro(&self, attr: &ast::Attr) -> Option<Vec<SyntaxNode>> {
 +        let res: Vec<_> = self
 +            .derive_macro_calls(attr)?
 +            .into_iter()
 +            .flat_map(|call| {
 +                let file_id = call?.as_file();
 +                let node = self.db.parse_or_expand(file_id)?;
 +                self.cache(node.clone(), file_id);
 +                Some(node)
 +            })
 +            .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())
 +        })
 +    }
 +
 +    fn is_derive_annotated(&self, adt: &ast::Adt) -> bool {
 +        let file_id = self.find_file(adt.syntax()).file_id;
 +        let adt = InFile::new(file_id, adt);
 +        self.with_ctx(|ctx| ctx.has_derives(adt))
 +    }
 +
 +    fn is_attr_macro_call(&self, item: &ast::Item) -> bool {
 +        let file_id = self.find_file(item.syntax()).file_id;
 +        let src = InFile::new(file_id, item.clone());
 +        self.with_ctx(|ctx| ctx.item_to_macro_call(src).is_some())
 +    }
 +
 +    fn speculative_expand(
 +        &self,
 +        actual_macro_call: &ast::MacroCall,
 +        speculative_args: &ast::TokenTree,
 +        token_to_map: SyntaxToken,
 +    ) -> Option<(SyntaxNode, SyntaxToken)> {
 +        let SourceAnalyzer { file_id, resolver, .. } =
 +            self.analyze_no_infer(actual_macro_call.syntax())?;
 +        let macro_call = InFile::new(file_id, actual_macro_call);
 +        let krate = resolver.krate();
 +        let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
 +            resolver
 +                .resolve_path_as_macro(self.db.upcast(), &path)
 +                .map(|it| macro_id_to_def_id(self.db.upcast(), it))
 +        })?;
 +        hir_expand::db::expand_speculative(
 +            self.db.upcast(),
 +            macro_call_id,
 +            speculative_args.syntax(),
 +            token_to_map,
 +        )
 +    }
 +
 +    fn speculative_expand_attr(
 +        &self,
 +        actual_macro_call: &ast::Item,
 +        speculative_args: &ast::Item,
 +        token_to_map: SyntaxToken,
 +    ) -> Option<(SyntaxNode, SyntaxToken)> {
 +        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))?;
 +        hir_expand::db::expand_speculative(
 +            self.db.upcast(),
 +            macro_call_id,
 +            speculative_args.syntax(),
 +            token_to_map,
 +        )
 +    }
 +
 +    fn speculative_expand_derive_as_pseudo_attr_macro(
 +        &self,
 +        actual_macro_call: &ast::Attr,
 +        speculative_args: &ast::Attr,
 +        token_to_map: SyntaxToken,
 +    ) -> Option<(SyntaxNode, SyntaxToken)> {
 +        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.upcast(),
 +            macro_call_id,
 +            speculative_args.syntax(),
 +            token_to_map,
 +        )
 +    }
 +
 +    // This might not be the correct way to do this, but it works for now
 +    fn descend_node_into_attributes<N: AstNode>(&self, node: N) -> SmallVec<[N; 1]> {
 +        let mut res = smallvec![];
 +        let tokens = (|| {
 +            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,
 +        };
 +
 +        if first == last {
 +            self.descend_into_macros_impl(first, &mut |InFile { value, .. }| {
 +                if let Some(node) = value.parent_ancestors().find_map(N::cast) {
 +                    res.push(node)
 +                }
 +                false
 +            });
 +        } 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_impl(first, &mut |token| {
 +                scratch.push(token);
 +                false
 +            });
 +
 +            let mut scratch = scratch.into_iter();
 +            self.descend_into_macros_impl(
 +                last,
 +                &mut |InFile { value: last, file_id: last_fid }| {
 +                    if let Some(InFile { value: first, file_id: first_fid }) = scratch.next() {
 +                        if first_fid == last_fid {
 +                            if 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);
 +                                }
 +                            }
 +                        }
 +                    }
 +                    false
 +                },
 +            );
 +        }
 +        res
 +    }
 +
 +    fn descend_into_macros(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
 +        let mut res = smallvec![];
 +        self.descend_into_macros_impl(token, &mut |InFile { value, .. }| {
 +            res.push(value);
 +            false
 +        });
 +        res
 +    }
 +
 +    fn descend_into_macros_with_same_text(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
 +        let text = token.text();
 +        let mut res = smallvec![];
 +        self.descend_into_macros_impl(token.clone(), &mut |InFile { value, .. }| {
 +            if value.text() == text {
 +                res.push(value);
 +            }
 +            false
 +        });
 +        if res.is_empty() {
 +            res.push(token);
 +        }
 +        res
 +    }
 +
 +    fn descend_into_macros_with_kind_preference(&self, token: SyntaxToken) -> SyntaxToken {
 +        let fetch_kind = |token: &SyntaxToken| match token.parent() {
 +            Some(node) => match node.kind() {
 +                kind @ (SyntaxKind::NAME | SyntaxKind::NAME_REF) => {
 +                    node.parent().map_or(kind, |it| it.kind())
 +                }
 +                _ => token.kind(),
 +            },
 +            None => token.kind(),
 +        };
 +        let preferred_kind = fetch_kind(&token);
 +        let mut res = None;
 +        self.descend_into_macros_impl(token.clone(), &mut |InFile { value, .. }| {
 +            if fetch_kind(&value) == preferred_kind {
 +                res = Some(value);
 +                true
 +            } else {
 +                if let None = res {
 +                    res = Some(value)
 +                }
 +                false
 +            }
 +        });
 +        res.unwrap_or(token)
 +    }
 +
 +    fn descend_into_macros_single(&self, token: SyntaxToken) -> SyntaxToken {
 +        let mut res = token.clone();
 +        self.descend_into_macros_impl(token, &mut |InFile { value, .. }| {
 +            res = value;
 +            true
 +        });
 +        res
 +    }
 +
 +    fn descend_into_macros_impl(
 +        &self,
 +        token: SyntaxToken,
 +        f: &mut dyn FnMut(InFile<SyntaxToken>) -> bool,
 +    ) {
 +        let _p = profile::span("descend_into_macros");
 +        let parent = match token.parent() {
 +            Some(it) => it,
 +            None => return,
 +        };
 +        let sa = match self.analyze_no_infer(&parent) {
 +            Some(it) => it,
 +            None => return,
 +        };
 +        let def_map = sa.resolver.def_map();
 +
 +        let mut stack: SmallVec<[_; 4]> = smallvec![InFile::new(sa.file_id, token)];
 +        let mut cache = self.expansion_info_cache.borrow_mut();
 +        let mut mcache = self.macro_call_cache.borrow_mut();
 +
 +        let mut process_expansion_for_token =
 +            |stack: &mut SmallVec<_>, macro_file, item, token: InFile<&_>| {
 +                let expansion_info = cache
 +                    .entry(macro_file)
 +                    .or_insert_with(|| macro_file.expansion_info(self.db.upcast()))
 +                    .as_ref()?;
 +
 +                {
 +                    let InFile { file_id, value } = expansion_info.expanded();
 +                    self.cache(value, file_id);
 +                }
 +
 +                let mapped_tokens = expansion_info.map_token_down(self.db.upcast(), item, token)?;
 +                let len = stack.len();
 +
 +                // requeue the tokens we got from mapping our current token down
 +                stack.extend(mapped_tokens);
 +                // if the length changed we have found a mapping for the token
 +                (stack.len() != len).then(|| ())
 +            };
 +
 +        // Remap the next token in the queue into a macro call its in, if it is not being remapped
 +        // either due to not being in a macro-call or because its unused push it into the result vec,
 +        // otherwise push the remapped tokens back into the queue as they can potentially be remapped again.
 +        while let Some(token) = stack.pop() {
 +            self.db.unwind_if_cancelled();
 +            let was_not_remapped = (|| {
 +                // First expand into attribute invocations
 +                let containing_attribute_macro_call = self.with_ctx(|ctx| {
 +                    token.value.parent_ancestors().filter_map(ast::Item::cast).find_map(|item| {
 +                        if item.attrs().next().is_none() {
 +                            // Don't force populate the dyn cache for items that don't have an attribute anyways
 +                            return None;
 +                        }
 +                        Some((ctx.item_to_macro_call(token.with_value(item.clone()))?, item))
 +                    })
 +                });
 +                if let Some((call_id, item)) = containing_attribute_macro_call {
 +                    let file_id = call_id.as_file();
 +                    return process_expansion_for_token(
 +                        &mut stack,
 +                        file_id,
 +                        Some(item),
 +                        token.as_ref(),
 +                    );
 +                }
 +
 +                // Then check for token trees, that means we are either in a function-like macro or
 +                // secondary attribute inputs
 +                let tt = token.value.parent_ancestors().map_while(ast::TokenTree::cast).last()?;
 +                let parent = tt.syntax().parent()?;
 +
 +                if tt.left_delimiter_token().map_or(false, |it| it == token.value) {
 +                    return None;
 +                }
 +                if tt.right_delimiter_token().map_or(false, |it| it == token.value) {
 +                    return None;
 +                }
 +
 +                if let Some(macro_call) = ast::MacroCall::cast(parent.clone()) {
 +                    let mcall = token.with_value(macro_call);
 +                    let file_id = match mcache.get(&mcall) {
 +                        Some(&it) => it,
 +                        None => {
 +                            let it = sa.expand(self.db, mcall.as_ref())?;
 +                            mcache.insert(mcall, it);
 +                            it
 +                        }
 +                    };
 +                    process_expansion_for_token(&mut stack, file_id, None, token.as_ref())
 +                } else if let Some(meta) = ast::Meta::cast(parent.clone()) {
 +                    // attribute we failed expansion for earlier, this might be a derive invocation
 +                    // or derive helper attribute
 +                    let attr = meta.parent_attr()?;
 +
 +                    let adt = if let Some(adt) = attr.syntax().parent().and_then(ast::Adt::cast) {
 +                        // this might be a derive, or a derive helper on an ADT
 +                        let derive_call = 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
 +                            ctx.attr_to_derive_macro_call(
 +                                token.with_value(&adt),
 +                                token.with_value(attr.clone()),
 +                            )
 +                            .map(|(_, call_id, _)| call_id)
 +                        });
 +
 +                        match derive_call {
 +                            Some(call_id) => {
 +                                // resolved to a derive
 +                                let file_id = call_id.as_file();
 +                                return process_expansion_for_token(
 +                                    &mut stack,
 +                                    file_id,
 +                                    Some(adt.into()),
 +                                    token.as_ref(),
 +                                );
 +                            }
 +                            None => Some(adt),
 +                        }
 +                    } else {
 +                        // Otherwise this could be a derive helper on a variant or field
 +                        if let Some(field) = attr.syntax().parent().and_then(ast::RecordField::cast)
 +                        {
 +                            field.syntax().ancestors().take(4).find_map(ast::Adt::cast)
 +                        } else if let Some(field) =
 +                            attr.syntax().parent().and_then(ast::TupleField::cast)
 +                        {
 +                            field.syntax().ancestors().take(4).find_map(ast::Adt::cast)
 +                        } else if let Some(variant) =
 +                            attr.syntax().parent().and_then(ast::Variant::cast)
 +                        {
 +                            variant.syntax().ancestors().nth(2).and_then(ast::Adt::cast)
 +                        } else {
 +                            None
 +                        }
 +                    }?;
 +                    if !self.with_ctx(|ctx| ctx.has_derives(InFile::new(token.file_id, &adt))) {
 +                        return None;
 +                    }
 +                    // Not an attribute, nor a derive, so it's either a builtin or a derive helper
 +                    // Try to resolve to a derive helper and downmap
 +                    let attr_name = attr.path().and_then(|it| it.as_single_name_ref())?.as_name();
 +                    let id = self.db.ast_id_map(token.file_id).ast_id(&adt);
 +                    let helpers =
 +                        def_map.derive_helpers_in_scope(InFile::new(token.file_id, id))?;
 +                    let item = Some(adt.into());
 +                    let mut res = None;
 +                    for (.., derive) in helpers.iter().filter(|(helper, ..)| *helper == attr_name) {
 +                        res = res.or(process_expansion_for_token(
 +                            &mut stack,
 +                            derive.as_file(),
 +                            item.clone(),
 +                            token.as_ref(),
 +                        ));
 +                    }
 +                    res
 +                } else {
 +                    None
 +                }
 +            })()
 +            .is_none();
 +
 +            if was_not_remapped && f(token) {
 +                break;
 +            }
 +        }
 +    }
 +
 +    // 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(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()))
 +            })
 +    }
 +
 +    fn original_range(&self, node: &SyntaxNode) -> FileRange {
 +        let node = self.find_file(node);
 +        node.original_file_range(self.db.upcast())
 +    }
 +
 +    fn original_range_opt(&self, node: &SyntaxNode) -> Option<FileRange> {
 +        let node = self.find_file(node);
 +        node.original_file_range_opt(self.db.upcast())
 +    }
 +
 +    fn original_ast_node<N: AstNode>(&self, node: N) -> Option<N> {
++        self.wrap_node_infile(node).original_ast_node(self.db.upcast()).map(
++            |InFile { file_id, value }| {
++                self.cache(find_root(value.syntax()), file_id);
++                value
++            },
++        )
 +    }
 +
 +    fn diagnostics_display_range(&self, src: InFile<SyntaxNodePtr>) -> FileRange {
 +        let root = self.parse_or_expand(src.file_id).unwrap();
 +        let node = src.map(|it| it.to_node(&root));
 +        node.as_ref().original_file_range(self.db.upcast())
 +    }
 +
 +    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))
 +    }
 +
 +    fn ancestors_with_macros(
 +        &self,
 +        node: SyntaxNode,
 +    ) -> impl Iterator<Item = SyntaxNode> + Clone + '_ {
 +        let node = self.find_file(&node);
 +        let db = self.db.upcast();
 +        iter::successors(Some(node.cloned()), move |&InFile { file_id, ref value }| {
 +            match value.parent() {
 +                Some(parent) => Some(InFile::new(file_id, parent)),
 +                None => {
 +                    self.cache(value.clone(), file_id);
 +                    file_id.call_node(db)
 +                }
 +            }
 +        })
 +        .map(|it| it.value)
 +    }
 +
 +    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())
 +    }
 +
 +    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)
 +    }
 +
 +    fn resolve_label(&self, lifetime: &ast::Lifetime) -> Option<Label> {
 +        let text = lifetime.text();
 +        let label = lifetime.syntax().ancestors().find_map(|syn| {
 +            let label = match_ast! {
 +                match syn {
 +                    ast::ForExpr(it) => it.label(),
 +                    ast::WhileExpr(it) => it.label(),
 +                    ast::LoopExpr(it) => it.label(),
 +                    ast::BlockExpr(it) => it.label(),
 +                    _ => None,
 +                }
 +            };
 +            label.filter(|l| {
 +                l.lifetime()
 +                    .and_then(|lt| lt.lifetime_ident_token())
 +                    .map_or(false, |lt| lt.text() == text)
 +            })
 +        })?;
 +        let src = self.wrap_node_infile(label);
 +        ToDef::to_def(self, src)
 +    }
 +
 +    fn resolve_type(&self, ty: &ast::Type) -> Option<Type> {
 +        let analyze = self.analyze(ty.syntax())?;
 +        let ctx = body::LowerCtx::new(self.db.upcast(), analyze.file_id);
 +        let ty = hir_ty::TyLoweringContext::new(self.db, &analyze.resolver)
 +            .lower_ty(&crate::TypeRef::from_ast(&ctx, ty.clone()));
 +        Some(Type::new_with_resolver(self.db, &analyze.resolver, ty))
 +    }
 +
++    fn resolve_trait(&self, path: &ast::Path) -> Option<Trait> {
++        let analyze = self.analyze(path.syntax())?;
++        let hygiene = hir_expand::hygiene::Hygiene::new(self.db.upcast(), analyze.file_id);
++        let ctx = body::LowerCtx::with_hygiene(self.db.upcast(), &hygiene);
++        let hir_path = Path::from_src(path.clone(), &ctx)?;
++        match analyze
++            .resolver
++            .resolve_path_in_type_ns_fully(self.db.upcast(), hir_path.mod_path())?
++        {
++            TypeNs::TraitId(id) => Some(Trait { id }),
++            _ => None,
++        }
++    }
++
 +    fn is_implicit_reborrow(&self, expr: &ast::Expr) -> Option<Mutability> {
 +        self.analyze(expr.syntax())?.is_implicit_reborrow(self.db, expr)
 +    }
 +
 +    fn type_of_expr(&self, expr: &ast::Expr) -> Option<TypeInfo> {
 +        self.analyze(expr.syntax())?
 +            .type_of_expr(self.db, expr)
 +            .map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced })
 +    }
 +
 +    fn type_of_pat(&self, pat: &ast::Pat) -> Option<TypeInfo> {
 +        self.analyze(pat.syntax())?
 +            .type_of_pat(self.db, pat)
 +            .map(|(ty, coerced)| TypeInfo { original: ty, adjusted: coerced })
 +    }
 +
 +    fn type_of_self(&self, param: &ast::SelfParam) -> Option<Type> {
 +        self.analyze(param.syntax())?.type_of_self(self.db, param)
 +    }
 +
 +    fn pattern_adjustments(&self, pat: &ast::Pat) -> SmallVec<[Type; 1]> {
 +        self.analyze(pat.syntax())
 +            .and_then(|it| it.pattern_adjustments(self.db, pat))
 +            .unwrap_or_default()
 +    }
 +
 +    fn binding_mode_of_pat(&self, pat: &ast::IdentPat) -> Option<BindingMode> {
 +        self.analyze(pat.syntax())?.binding_mode_of_pat(self.db, pat)
 +    }
 +
 +    fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
 +        self.analyze(call.syntax())?.resolve_method_call(self.db, call)
 +    }
 +
 +    fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
 +        self.analyze(call.syntax())?.resolve_method_call_as_callable(self.db, call)
 +    }
 +
 +    fn resolve_field(&self, field: &ast::FieldExpr) -> Option<Field> {
 +        self.analyze(field.syntax())?.resolve_field(self.db, field)
 +    }
 +
 +    fn resolve_record_field(
 +        &self,
 +        field: &ast::RecordExprField,
 +    ) -> Option<(Field, Option<Local>, Type)> {
 +        self.analyze(field.syntax())?.resolve_record_field(self.db, field)
 +    }
 +
 +    fn resolve_record_pat_field(&self, field: &ast::RecordPatField) -> Option<Field> {
 +        self.analyze(field.syntax())?.resolve_record_pat_field(self.db, field)
 +    }
 +
 +    fn resolve_macro_call(&self, macro_call: &ast::MacroCall) -> Option<Macro> {
 +        let sa = self.analyze(macro_call.syntax())?;
 +        let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
 +        sa.resolve_macro_call(self.db, macro_call)
 +    }
 +
 +    fn is_unsafe_macro_call(&self, macro_call: &ast::MacroCall) -> bool {
 +        let sa = match self.analyze(macro_call.syntax()) {
 +            Some(it) => it,
 +            None => return false,
 +        };
 +        let macro_call = self.find_file(macro_call.syntax()).with_value(macro_call);
 +        sa.is_unsafe_macro_call(self.db, macro_call)
 +    }
 +
 +    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)?;
 +            macro_call_to_macro_id(ctx, self.db.upcast(), macro_call_id)
 +        })?;
 +        Some(Macro { id })
 +    }
 +
 +    fn resolve_path(&self, path: &ast::Path) -> Option<PathResolution> {
 +        self.analyze(path.syntax())?.resolve_path(self.db, path)
 +    }
 +
 +    fn resolve_extern_crate(&self, extern_crate: &ast::ExternCrate) -> Option<Crate> {
 +        let krate = self.scope(extern_crate.syntax())?.krate();
 +        let name = extern_crate.name_ref()?.as_name();
 +        if name == known::SELF_PARAM {
 +            return Some(krate);
 +        }
 +        krate
 +            .dependencies(self.db)
 +            .into_iter()
 +            .find_map(|dep| (dep.name == name).then(|| dep.krate))
 +    }
 +
 +    fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {
 +        self.analyze(record_lit.syntax())?.resolve_variant(self.db, record_lit)
 +    }
 +
 +    fn resolve_bind_pat_to_const(&self, pat: &ast::IdentPat) -> Option<ModuleDef> {
 +        self.analyze(pat.syntax())?.resolve_bind_pat_to_const(self.db, pat)
 +    }
 +
 +    fn record_literal_missing_fields(&self, literal: &ast::RecordExpr) -> Vec<(Field, Type)> {
 +        self.analyze(literal.syntax())
 +            .and_then(|it| it.record_literal_missing_fields(self.db, literal))
 +            .unwrap_or_default()
 +    }
 +
 +    fn record_pattern_missing_fields(&self, pattern: &ast::RecordPat) -> Vec<(Field, Type)> {
 +        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 cache = self.s2d_cache.borrow_mut();
 +        let mut ctx = SourceToDefCtx { db: self.db, cache: &mut *cache };
 +        f(&mut ctx)
 +    }
 +
 +    fn to_module_def(&self, file: FileId) -> impl Iterator<Item = Module> {
 +        self.with_ctx(|ctx| ctx.file_to_def(file)).into_iter().map(Module::from)
 +    }
 +
 +    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,
 +        })
 +    }
 +
 +    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,
 +            },
 +        )
 +    }
 +
 +    fn scope_for_def(&self, def: Trait) -> SemanticsScope<'db> {
 +        let file_id = self.db.lookup_intern_trait(def.id).id.file_id();
 +        let resolver = def.id.resolver(self.db.upcast());
 +        SemanticsScope { db: self.db, file_id, resolver }
 +    }
 +
 +    fn source<Def: HasSource>(&self, def: Def) -> Option<InFile<Def::Ast>>
 +    where
 +        Def::Ast: AstNode,
 +    {
 +        let res = def.source(self.db)?;
 +        self.cache(find_root(res.value.syntax()), res.file_id);
 +        Some(res)
 +    }
 +
 +    /// Returns none if the file of the node is not part of a crate.
 +    fn analyze(&self, node: &SyntaxNode) -> Option<SourceAnalyzer> {
 +        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> {
 +        self.analyze_impl(node, None, false)
 +    }
 +
 +    fn analyze_with_offset_no_infer(
 +        &self,
 +        node: &SyntaxNode,
 +        offset: TextSize,
 +    ) -> Option<SourceAnalyzer> {
 +        self.analyze_impl(node, Some(offset), false)
 +    }
 +
 +    fn analyze_impl(
 +        &self,
 +        node: &SyntaxNode,
 +        offset: Option<TextSize>,
 +        infer_body: bool,
 +    ) -> Option<SourceAnalyzer> {
 +        let _p = profile::span("Semantics::analyze_impl");
 +        let node = self.find_file(node);
 +
 +        let container = match self.with_ctx(|ctx| ctx.find_container(node)) {
 +            Some(it) => it,
 +            None => return None,
 +        };
 +
 +        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::TraitId(it) => it.resolver(self.db.upcast()),
 +            ChildContainer::ImplId(it) => it.resolver(self.db.upcast()),
 +            ChildContainer::ModuleId(it) => it.resolver(self.db.upcast()),
 +            ChildContainer::EnumId(it) => it.resolver(self.db.upcast()),
 +            ChildContainer::VariantId(it) => it.resolver(self.db.upcast()),
 +            ChildContainer::TypeAliasId(it) => it.resolver(self.db.upcast()),
 +            ChildContainer::GenericDefId(it) => it.resolver(self.db.upcast()),
 +        };
 +        Some(SourceAnalyzer::new_for_resolver(resolver, node))
 +    }
 +
 +    fn cache(&self, root_node: SyntaxNode, file_id: HirFileId) {
 +        assert!(root_node.parent().is_none());
 +        let mut cache = self.cache.borrow_mut();
 +        let prev = cache.insert(root_node, file_id);
 +        assert!(prev == None || prev == Some(file_id))
 +    }
 +
 +    fn assert_contains_node(&self, node: &SyntaxNode) {
 +        self.find_file(node);
 +    }
 +
 +    fn lookup(&self, root_node: &SyntaxNode) -> Option<HirFileId> {
 +        let cache = self.cache.borrow();
 +        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)
 +    }
 +
 +    /// 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 use only query nodes, derived from this instance of Semantics.\n\
 +                 root node:   {:?}\n\
 +                 known nodes: {}\n\n",
 +                node,
 +                root_node,
 +                self.cache
 +                    .borrow()
 +                    .keys()
 +                    .map(|it| format!("{:?}", it))
 +                    .collect::<Vec<_>>()
 +                    .join(", ")
 +            )
 +        });
 +        InFile::new(file_id, node)
 +    }
 +
 +    fn is_unsafe_method_call(&self, method_call_expr: &ast::MethodCallExpr) -> bool {
 +        method_call_expr
 +            .receiver()
 +            .and_then(|expr| {
 +                let field_expr = match expr {
 +                    ast::Expr::FieldExpr(field_expr) => field_expr,
 +                    _ => return None,
 +                };
 +                let ty = self.type_of_expr(&field_expr.expr()?)?.original;
 +                if !ty.is_packed(self.db) {
 +                    return None;
 +                }
 +
 +                let func = self.resolve_method_call(method_call_expr).map(Function::from)?;
 +                let res = match func.self_param(self.db)?.access(self.db) {
 +                    Access::Shared | Access::Exclusive => true,
 +                    Access::Owned => false,
 +                };
 +                Some(res)
 +            })
 +            .unwrap_or(false)
 +    }
 +
 +    fn is_unsafe_ref_expr(&self, ref_expr: &ast::RefExpr) -> bool {
 +        ref_expr
 +            .expr()
 +            .and_then(|expr| {
 +                let field_expr = match expr {
 +                    ast::Expr::FieldExpr(field_expr) => field_expr,
 +                    _ => return None,
 +                };
 +                let expr = field_expr.expr()?;
 +                self.type_of_expr(&expr)
 +            })
 +            // Binding a reference to a packed type is possibly unsafe.
 +            .map(|ty| ty.original.is_packed(self.db))
 +            .unwrap_or(false)
 +
 +        // FIXME This needs layout computation to be correct. It will highlight
 +        // more than it should with the current implementation.
 +    }
 +
 +    fn is_unsafe_ident_pat(&self, ident_pat: &ast::IdentPat) -> bool {
 +        if ident_pat.ref_token().is_none() {
 +            return false;
 +        }
 +
 +        ident_pat
 +            .syntax()
 +            .parent()
 +            .and_then(|parent| {
 +                // `IdentPat` can live under `RecordPat` directly under `RecordPatField` or
 +                // `RecordPatFieldList`. `RecordPatField` also lives under `RecordPatFieldList`,
 +                // so this tries to lookup the `IdentPat` anywhere along that structure to the
 +                // `RecordPat` so we can get the containing type.
 +                let record_pat = ast::RecordPatField::cast(parent.clone())
 +                    .and_then(|record_pat| record_pat.syntax().parent())
 +                    .or_else(|| Some(parent.clone()))
 +                    .and_then(|parent| {
 +                        ast::RecordPatFieldList::cast(parent)?
 +                            .syntax()
 +                            .parent()
 +                            .and_then(ast::RecordPat::cast)
 +                    });
 +
 +                // If this doesn't match a `RecordPat`, fallback to a `LetStmt` to see if
 +                // this is initialized from a `FieldExpr`.
 +                if let Some(record_pat) = record_pat {
 +                    self.type_of_pat(&ast::Pat::RecordPat(record_pat))
 +                } else if let Some(let_stmt) = ast::LetStmt::cast(parent) {
 +                    let field_expr = match let_stmt.initializer()? {
 +                        ast::Expr::FieldExpr(field_expr) => field_expr,
 +                        _ => return None,
 +                    };
 +
 +                    self.type_of_expr(&field_expr.expr()?)
 +                } else {
 +                    None
 +                }
 +            })
 +            // Binding a reference to a packed type is possibly unsafe.
 +            .map(|ty| ty.original.is_packed(self.db))
 +            .unwrap_or(false)
 +    }
 +}
 +
 +fn macro_call_to_macro_id(
 +    ctx: &mut SourceToDefCtx<'_, '_>,
 +    db: &dyn AstDatabase,
 +    macro_call_id: MacroCallId,
 +) -> Option<MacroId> {
 +    let loc = db.lookup_intern_macro_call(macro_call_id);
 +    match loc.def.kind {
 +        hir_expand::MacroDefKind::Declarative(it)
 +        | hir_expand::MacroDefKind::BuiltIn(_, it)
 +        | hir_expand::MacroDefKind::BuiltInAttr(_, it)
 +        | hir_expand::MacroDefKind::BuiltInDerive(_, it)
 +        | hir_expand::MacroDefKind::BuiltInEager(_, it) => {
 +            ctx.macro_to_def(InFile::new(it.file_id, it.to_node(db)))
 +        }
 +        hir_expand::MacroDefKind::ProcMacro(_, _, it) => {
 +            ctx.proc_macro_to_def(InFile::new(it.file_id, it.to_node(db)))
 +        }
 +    }
 +}
 +
 +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),
 +];
 +
 +fn find_root(node: &SyntaxNode) -> SyntaxNode {
 +    node.ancestors().last().unwrap()
 +}
 +
 +/// `SemanticScope` 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<'a> {
 +    pub db: &'a dyn HirDatabase,
 +    file_id: HirFileId,
 +    resolver: Resolver,
 +}
 +
 +impl<'a> SemanticsScope<'a> {
 +    pub fn module(&self) -> Module {
 +        Module { id: self.resolver.module() }
 +    }
 +
 +    pub fn krate(&self) -> Crate {
 +        Crate { id: self.resolver.krate() }
 +    }
 +
 +    pub(crate) fn resolver(&self) -> &Resolver {
 +        &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.upcast()))
 +    }
 +
 +    pub fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
 +        let scope = self.resolver.names_in_scope(self.db.upcast());
 +        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(pat_id) => match self.resolver.body_owner() {
 +                        Some(parent) => ScopeDef::Local(Local { parent, pat_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)
 +            }
 +        }
 +    }
 +
 +    /// 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, path: &ast::Path) -> Option<PathResolution> {
 +        let ctx = body::LowerCtx::new(self.db.upcast(), self.file_id);
 +        let path = Path::from_src(path.clone(), &ctx)?;
 +        resolve_hir_path(self.db, &self.resolver, &path)
 +    }
 +
 +    /// Iterates over associated types that may be specified after the given path (using
 +    /// `Ty::Assoc` syntax).
 +    pub fn assoc_type_shorthand_candidates<R>(
 +        &self,
 +        resolution: &PathResolution,
 +        mut cb: impl FnMut(&Name, TypeAlias) -> Option<R>,
 +    ) -> Option<R> {
 +        let def = self.resolver.generic_def()?;
 +        hir_ty::associated_type_shorthand_candidates(
 +            self.db,
 +            def,
 +            resolution.in_type_ns()?,
 +            |name, _, id| cb(name, id.into()),
 +        )
 +    }
 +}
 +
 +pub struct VisibleTraits(pub FxHashSet<TraitId>);
 +
 +impl ops::Deref for VisibleTraits {
 +    type Target = FxHashSet<TraitId>;
 +
 +    fn deref(&self) -> &Self::Target {
 +        &self.0
 +    }
 +}
index 943c1d90e63659830d017e9ab4b102a594de62f1,0000000000000000000000000000000000000000..87f5018fb69586f44e6307cb8f2561d558d85e03
mode 100644,000000..100644
--- /dev/null
@@@ -1,900 -1,0 +1,900 @@@
- // use foo::{Baz, Bar};
 +use either::Either;
 +use hir::{AssocItem, HasVisibility, Module, ModuleDef, Name, PathResolution, ScopeDef};
 +use ide_db::{
 +    defs::{Definition, NameRefClass},
 +    search::SearchScope,
 +};
 +use stdx::never;
 +use syntax::{
 +    ast::{self, make},
 +    ted, AstNode, Direction, SyntaxNode, SyntaxToken, T,
 +};
 +
 +use crate::{
 +    assist_context::{AssistContext, Assists},
 +    AssistId, AssistKind,
 +};
 +
 +// Assist: expand_glob_import
 +//
 +// Expands glob imports.
 +//
 +// ```
 +// mod foo {
 +//     pub struct Bar;
 +//     pub struct Baz;
 +// }
 +//
 +// use foo::*$0;
 +//
 +// fn qux(bar: Bar, baz: Baz) {}
 +// ```
 +// ->
 +// ```
 +// mod foo {
 +//     pub struct Bar;
 +//     pub struct Baz;
 +// }
 +//
- use foo::{Baz, Bar, f};
++// use foo::{Bar, Baz};
 +//
 +// fn qux(bar: Bar, baz: Baz) {}
 +// ```
 +pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
 +    let star = ctx.find_token_syntax_at_offset(T![*])?;
 +    let use_tree = star.parent().and_then(ast::UseTree::cast)?;
 +    let (parent, mod_path) = find_parent_and_path(&star)?;
 +    let target_module = match ctx.sema.resolve_path(&mod_path)? {
 +        PathResolution::Def(ModuleDef::Module(it)) => it,
 +        _ => return None,
 +    };
 +
 +    let current_scope = ctx.sema.scope(&star.parent()?)?;
 +    let current_module = current_scope.module();
 +
 +    let refs_in_target = find_refs_in_mod(ctx, target_module, current_module)?;
 +    let imported_defs = find_imported_defs(ctx, star)?;
 +
 +    let target = parent.either(|n| n.syntax().clone(), |n| n.syntax().clone());
 +    acc.add(
 +        AssistId("expand_glob_import", AssistKind::RefactorRewrite),
 +        "Expand glob import",
 +        target.text_range(),
 +        |builder| {
 +            let use_tree = builder.make_mut(use_tree);
 +
 +            let names_to_import = find_names_to_import(ctx, refs_in_target, imported_defs);
 +            let expanded = make::use_tree_list(names_to_import.iter().map(|n| {
 +                let path = make::ext::ident_path(&n.to_string());
 +                make::use_tree(path, None, None, false)
 +            }))
 +            .clone_for_update();
 +
 +            match use_tree.star_token() {
 +                Some(star) => {
 +                    let needs_braces = use_tree.path().is_some() && names_to_import.len() != 1;
 +                    if needs_braces {
 +                        ted::replace(star, expanded.syntax())
 +                    } else {
 +                        let without_braces = expanded
 +                            .syntax()
 +                            .children_with_tokens()
 +                            .filter(|child| !matches!(child.kind(), T!['{'] | T!['}']))
 +                            .collect();
 +                        ted::replace_with_many(star, without_braces)
 +                    }
 +                }
 +                None => never!(),
 +            }
 +        },
 +    )
 +}
 +
 +fn find_parent_and_path(
 +    star: &SyntaxToken,
 +) -> Option<(Either<ast::UseTree, ast::UseTreeList>, ast::Path)> {
 +    return star.parent_ancestors().find_map(|n| {
 +        find_use_tree_list(n.clone())
 +            .map(|(u, p)| (Either::Right(u), p))
 +            .or_else(|| find_use_tree(n).map(|(u, p)| (Either::Left(u), p)))
 +    });
 +
 +    fn find_use_tree_list(n: SyntaxNode) -> Option<(ast::UseTreeList, ast::Path)> {
 +        let use_tree_list = ast::UseTreeList::cast(n)?;
 +        let path = use_tree_list.parent_use_tree().path()?;
 +        Some((use_tree_list, path))
 +    }
 +
 +    fn find_use_tree(n: SyntaxNode) -> Option<(ast::UseTree, ast::Path)> {
 +        let use_tree = ast::UseTree::cast(n)?;
 +        let path = use_tree.path()?;
 +        Some((use_tree, path))
 +    }
 +}
 +
 +fn def_is_referenced_in(def: Definition, ctx: &AssistContext<'_>) -> bool {
 +    let search_scope = SearchScope::single_file(ctx.file_id());
 +    def.usages(&ctx.sema).in_scope(search_scope).at_least_one()
 +}
 +
 +#[derive(Debug, Clone)]
 +struct Ref {
 +    // could be alias
 +    visible_name: Name,
 +    def: Definition,
 +}
 +
 +impl Ref {
 +    fn from_scope_def(name: Name, scope_def: ScopeDef) -> Option<Self> {
 +        match scope_def {
 +            ScopeDef::ModuleDef(def) => {
 +                Some(Ref { visible_name: name, def: Definition::from(def) })
 +            }
 +            _ => None,
 +        }
 +    }
 +}
 +
 +#[derive(Debug, Clone)]
 +struct Refs(Vec<Ref>);
 +
 +impl Refs {
 +    fn used_refs(&self, ctx: &AssistContext<'_>) -> Refs {
 +        Refs(
 +            self.0
 +                .clone()
 +                .into_iter()
 +                .filter(|r| {
 +                    if let Definition::Trait(tr) = r.def {
 +                        if tr.items(ctx.db()).into_iter().any(|ai| {
 +                            if let AssocItem::Function(f) = ai {
 +                                def_is_referenced_in(Definition::Function(f), ctx)
 +                            } else {
 +                                false
 +                            }
 +                        }) {
 +                            return true;
 +                        }
 +                    }
 +
 +                    def_is_referenced_in(r.def, ctx)
 +                })
 +                .collect(),
 +        )
 +    }
 +
 +    fn filter_out_by_defs(&self, defs: Vec<Definition>) -> Refs {
 +        Refs(self.0.clone().into_iter().filter(|r| !defs.contains(&r.def)).collect())
 +    }
 +}
 +
 +fn find_refs_in_mod(ctx: &AssistContext<'_>, module: Module, visible_from: Module) -> Option<Refs> {
 +    if !is_mod_visible_from(ctx, module, visible_from) {
 +        return None;
 +    }
 +
 +    let module_scope = module.scope(ctx.db(), Some(visible_from));
 +    let refs = module_scope.into_iter().filter_map(|(n, d)| Ref::from_scope_def(n, d)).collect();
 +    Some(Refs(refs))
 +}
 +
 +fn is_mod_visible_from(ctx: &AssistContext<'_>, module: Module, from: Module) -> bool {
 +    match module.parent(ctx.db()) {
 +        Some(parent) => {
 +            module.visibility(ctx.db()).is_visible_from(ctx.db(), from.into())
 +                && is_mod_visible_from(ctx, parent, from)
 +        }
 +        None => true,
 +    }
 +}
 +
 +// looks for name refs in parent use block's siblings
 +//
 +// mod bar {
 +//     mod qux {
 +//         struct Qux;
 +//     }
 +//
 +//     pub use qux::Qux;
 +// }
 +//
 +// ↓ ---------------
 +// use foo::*$0;
 +// use baz::Baz;
 +// ↑ ---------------
 +fn find_imported_defs(ctx: &AssistContext<'_>, star: SyntaxToken) -> Option<Vec<Definition>> {
 +    let parent_use_item_syntax = star.parent_ancestors().find_map(|n| {
 +        if ast::Use::can_cast(n.kind()) {
 +            Some(n)
 +        } else {
 +            None
 +        }
 +    })?;
 +
 +    Some(
 +        [Direction::Prev, Direction::Next]
 +            .into_iter()
 +            .flat_map(|dir| {
 +                parent_use_item_syntax
 +                    .siblings(dir.to_owned())
 +                    .filter(|n| ast::Use::can_cast(n.kind()))
 +            })
 +            .flat_map(|n| n.descendants().filter_map(ast::NameRef::cast))
 +            .filter_map(|r| match NameRefClass::classify(&ctx.sema, &r)? {
 +                NameRefClass::Definition(
 +                    def @ (Definition::Macro(_)
 +                    | Definition::Module(_)
 +                    | Definition::Function(_)
 +                    | Definition::Adt(_)
 +                    | Definition::Variant(_)
 +                    | Definition::Const(_)
 +                    | Definition::Static(_)
 +                    | Definition::Trait(_)
 +                    | Definition::TypeAlias(_)),
 +                ) => Some(def),
 +                _ => None,
 +            })
 +            .collect(),
 +    )
 +}
 +
 +fn find_names_to_import(
 +    ctx: &AssistContext<'_>,
 +    refs_in_target: Refs,
 +    imported_defs: Vec<Definition>,
 +) -> Vec<Name> {
 +    let used_refs = refs_in_target.used_refs(ctx).filter_out_by_defs(imported_defs);
 +    used_refs.0.iter().map(|r| r.visible_name.clone()).collect()
 +}
 +
 +#[cfg(test)]
 +mod tests {
 +    use crate::tests::{check_assist, check_assist_not_applicable};
 +
 +    use super::*;
 +
 +    #[test]
 +    fn expanding_glob_import() {
 +        check_assist(
 +            expand_glob_import,
 +            r"
 +mod foo {
 +    pub struct Bar;
 +    pub struct Baz;
 +    pub struct Qux;
 +
 +    pub fn f() {}
 +}
 +
 +use foo::*$0;
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +}
 +",
 +            r"
 +mod foo {
 +    pub struct Bar;
 +    pub struct Baz;
 +    pub struct Qux;
 +
 +    pub fn f() {}
 +}
 +
- use foo::{Baz, Bar, f};
++use foo::{Bar, Baz, f};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +}
 +",
 +        )
 +    }
 +
 +    #[test]
 +    fn expanding_glob_import_unused() {
 +        check_assist(
 +            expand_glob_import,
 +            r"
 +mod foo {
 +    pub struct Bar;
 +    pub struct Baz;
 +    pub struct Qux;
 +
 +    pub fn f() {}
 +}
 +
 +use foo::*$0;
 +
 +fn qux() {}
 +",
 +            r"
 +mod foo {
 +    pub struct Bar;
 +    pub struct Baz;
 +    pub struct Qux;
 +
 +    pub fn f() {}
 +}
 +
 +use foo::{};
 +
 +fn qux() {}
 +",
 +        )
 +    }
 +
 +    #[test]
 +    fn expanding_glob_import_with_existing_explicit_names() {
 +        check_assist(
 +            expand_glob_import,
 +            r"
 +mod foo {
 +    pub struct Bar;
 +    pub struct Baz;
 +    pub struct Qux;
 +
 +    pub fn f() {}
 +}
 +
 +use foo::{*$0, f};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +}
 +",
 +            r"
 +mod foo {
 +    pub struct Bar;
 +    pub struct Baz;
 +    pub struct Qux;
 +
 +    pub fn f() {}
 +}
 +
- use foo::{bar::{Baz, Bar, f}, baz::*};
++use foo::{Bar, Baz, f};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +}
 +",
 +        )
 +    }
 +
 +    #[test]
 +    fn expanding_glob_import_with_existing_uses_in_same_module() {
 +        check_assist(
 +            expand_glob_import,
 +            r"
 +mod foo {
 +    pub struct Bar;
 +    pub struct Baz;
 +    pub struct Qux;
 +
 +    pub fn f() {}
 +}
 +
 +use foo::Bar;
 +use foo::{*$0, f};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +}
 +",
 +            r"
 +mod foo {
 +    pub struct Bar;
 +    pub struct Baz;
 +    pub struct Qux;
 +
 +    pub fn f() {}
 +}
 +
 +use foo::Bar;
 +use foo::{Baz, f};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +}
 +",
 +        )
 +    }
 +
 +    #[test]
 +    fn expanding_nested_glob_import() {
 +        check_assist(
 +            expand_glob_import,
 +            r"
 +mod foo {
 +    pub mod bar {
 +        pub struct Bar;
 +        pub struct Baz;
 +        pub struct Qux;
 +
 +        pub fn f() {}
 +    }
 +
 +    pub mod baz {
 +        pub fn g() {}
 +    }
 +}
 +
 +use foo::{bar::{*$0, f}, baz::*};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +    g();
 +}
 +",
 +            r"
 +mod foo {
 +    pub mod bar {
 +        pub struct Bar;
 +        pub struct Baz;
 +        pub struct Qux;
 +
 +        pub fn f() {}
 +    }
 +
 +    pub mod baz {
 +        pub fn g() {}
 +    }
 +}
 +
-     baz::{g, qux::{q, h}}
++use foo::{bar::{Bar, Baz, f}, baz::*};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +    g();
 +}
 +",
 +        );
 +
 +        check_assist(
 +            expand_glob_import,
 +            r"
 +mod foo {
 +    pub mod bar {
 +        pub struct Bar;
 +        pub struct Baz;
 +        pub struct Qux;
 +
 +        pub fn f() {}
 +    }
 +
 +    pub mod baz {
 +        pub fn g() {}
 +    }
 +}
 +
 +use foo::{bar::{Bar, Baz, f}, baz::*$0};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +    g();
 +}
 +",
 +            r"
 +mod foo {
 +    pub mod bar {
 +        pub struct Bar;
 +        pub struct Baz;
 +        pub struct Qux;
 +
 +        pub fn f() {}
 +    }
 +
 +    pub mod baz {
 +        pub fn g() {}
 +    }
 +}
 +
 +use foo::{bar::{Bar, Baz, f}, baz::g};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +    g();
 +}
 +",
 +        );
 +
 +        check_assist(
 +            expand_glob_import,
 +            r"
 +mod foo {
 +    pub mod bar {
 +        pub struct Bar;
 +        pub struct Baz;
 +        pub struct Qux;
 +
 +        pub fn f() {}
 +    }
 +
 +    pub mod baz {
 +        pub fn g() {}
 +
 +        pub mod qux {
 +            pub fn h() {}
 +            pub fn m() {}
 +
 +            pub mod q {
 +                pub fn j() {}
 +            }
 +        }
 +    }
 +}
 +
 +use foo::{
 +    bar::{*, f},
 +    baz::{g, qux::*$0}
 +};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +    g();
 +    h();
 +    q::j();
 +}
 +",
 +            r"
 +mod foo {
 +    pub mod bar {
 +        pub struct Bar;
 +        pub struct Baz;
 +        pub struct Qux;
 +
 +        pub fn f() {}
 +    }
 +
 +    pub mod baz {
 +        pub fn g() {}
 +
 +        pub mod qux {
 +            pub fn h() {}
 +            pub fn m() {}
 +
 +            pub mod q {
 +                pub fn j() {}
 +            }
 +        }
 +    }
 +}
 +
 +use foo::{
 +    bar::{*, f},
++    baz::{g, qux::{h, q}}
 +};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +    g();
 +    h();
 +    q::j();
 +}
 +",
 +        );
 +
 +        check_assist(
 +            expand_glob_import,
 +            r"
 +mod foo {
 +    pub mod bar {
 +        pub struct Bar;
 +        pub struct Baz;
 +        pub struct Qux;
 +
 +        pub fn f() {}
 +    }
 +
 +    pub mod baz {
 +        pub fn g() {}
 +
 +        pub mod qux {
 +            pub fn h() {}
 +            pub fn m() {}
 +
 +            pub mod q {
 +                pub fn j() {}
 +            }
 +        }
 +    }
 +}
 +
 +use foo::{
 +    bar::{*, f},
 +    baz::{g, qux::{h, q::*$0}}
 +};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +    g();
 +    h();
 +    j();
 +}
 +",
 +            r"
 +mod foo {
 +    pub mod bar {
 +        pub struct Bar;
 +        pub struct Baz;
 +        pub struct Qux;
 +
 +        pub fn f() {}
 +    }
 +
 +    pub mod baz {
 +        pub fn g() {}
 +
 +        pub mod qux {
 +            pub fn h() {}
 +            pub fn m() {}
 +
 +            pub mod q {
 +                pub fn j() {}
 +            }
 +        }
 +    }
 +}
 +
 +use foo::{
 +    bar::{*, f},
 +    baz::{g, qux::{h, q::j}}
 +};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +    g();
 +    h();
 +    j();
 +}
 +",
 +        );
 +
 +        check_assist(
 +            expand_glob_import,
 +            r"
 +mod foo {
 +    pub mod bar {
 +        pub struct Bar;
 +        pub struct Baz;
 +        pub struct Qux;
 +
 +        pub fn f() {}
 +    }
 +
 +    pub mod baz {
 +        pub fn g() {}
 +
 +        pub mod qux {
 +            pub fn h() {}
 +            pub fn m() {}
 +
 +            pub mod q {
 +                pub fn j() {}
 +            }
 +        }
 +    }
 +}
 +
 +use foo::{
 +    bar::{*, f},
 +    baz::{g, qux::{q::j, *$0}}
 +};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +    g();
 +    h();
 +    j();
 +}
 +",
 +            r"
 +mod foo {
 +    pub mod bar {
 +        pub struct Bar;
 +        pub struct Baz;
 +        pub struct Qux;
 +
 +        pub fn f() {}
 +    }
 +
 +    pub mod baz {
 +        pub fn g() {}
 +
 +        pub mod qux {
 +            pub fn h() {}
 +            pub fn m() {}
 +
 +            pub mod q {
 +                pub fn j() {}
 +            }
 +        }
 +    }
 +}
 +
 +use foo::{
 +    bar::{*, f},
 +    baz::{g, qux::{q::j, h}}
 +};
 +
 +fn qux(bar: Bar, baz: Baz) {
 +    f();
 +    g();
 +    h();
 +    j();
 +}
 +",
 +        );
 +    }
 +
 +    #[test]
 +    fn expanding_glob_import_with_macro_defs() {
 +        check_assist(
 +            expand_glob_import,
 +            r#"
 +//- /lib.rs crate:foo
 +#[macro_export]
 +macro_rules! bar {
 +    () => ()
 +}
 +
 +pub fn baz() {}
 +
 +//- /main.rs crate:main deps:foo
 +use foo::*$0;
 +
 +fn main() {
 +    bar!();
 +    baz();
 +}
 +"#,
 +            r#"
 +use foo::{bar, baz};
 +
 +fn main() {
 +    bar!();
 +    baz();
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn expanding_glob_import_with_trait_method_uses() {
 +        check_assist(
 +            expand_glob_import,
 +            r"
 +//- /lib.rs crate:foo
 +pub trait Tr {
 +    fn method(&self) {}
 +}
 +impl Tr for () {}
 +
 +//- /main.rs crate:main deps:foo
 +use foo::*$0;
 +
 +fn main() {
 +    ().method();
 +}
 +",
 +            r"
 +use foo::Tr;
 +
 +fn main() {
 +    ().method();
 +}
 +",
 +        );
 +
 +        check_assist(
 +            expand_glob_import,
 +            r"
 +//- /lib.rs crate:foo
 +pub trait Tr {
 +    fn method(&self) {}
 +}
 +impl Tr for () {}
 +
 +pub trait Tr2 {
 +    fn method2(&self) {}
 +}
 +impl Tr2 for () {}
 +
 +//- /main.rs crate:main deps:foo
 +use foo::*$0;
 +
 +fn main() {
 +    ().method();
 +}
 +",
 +            r"
 +use foo::Tr;
 +
 +fn main() {
 +    ().method();
 +}
 +",
 +        );
 +    }
 +
 +    #[test]
 +    fn expanding_is_not_applicable_if_target_module_is_not_accessible_from_current_scope() {
 +        check_assist_not_applicable(
 +            expand_glob_import,
 +            r"
 +mod foo {
 +    mod bar {
 +        pub struct Bar;
 +    }
 +}
 +
 +use foo::bar::*$0;
 +
 +fn baz(bar: Bar) {}
 +",
 +        );
 +
 +        check_assist_not_applicable(
 +            expand_glob_import,
 +            r"
 +mod foo {
 +    mod bar {
 +        pub mod baz {
 +            pub struct Baz;
 +        }
 +    }
 +}
 +
 +use foo::bar::baz::*$0;
 +
 +fn qux(baz: Baz) {}
 +",
 +        );
 +    }
 +
 +    #[test]
 +    fn expanding_is_not_applicable_if_cursor_is_not_in_star_token() {
 +        check_assist_not_applicable(
 +            expand_glob_import,
 +            r"
 +    mod foo {
 +        pub struct Bar;
 +        pub struct Baz;
 +        pub struct Qux;
 +    }
 +
 +    use foo::Bar$0;
 +
 +    fn qux(bar: Bar, baz: Baz) {}
 +    ",
 +        )
 +    }
 +
 +    #[test]
 +    fn expanding_glob_import_single_nested_glob_only() {
 +        check_assist(
 +            expand_glob_import,
 +            r"
 +mod foo {
 +    pub struct Bar;
 +}
 +
 +use foo::{*$0};
 +
 +struct Baz {
 +    bar: Bar
 +}
 +",
 +            r"
 +mod foo {
 +    pub struct Bar;
 +}
 +
 +use foo::{Bar};
 +
 +struct Baz {
 +    bar: Bar
 +}
 +",
 +        );
 +    }
 +}
index 658a1aadf53ecf9e0549f27af1671d3d0b9bd127,0000000000000000000000000000000000000000..80d3b925593674266776a705fadd0c4ea59f9b65
mode 100644,000000..100644
--- /dev/null
@@@ -1,1150 -1,0 +1,1194 @@@
-     syntax_helpers::node_ext::expr_as_name_ref,
 +use ast::make;
 +use either::Either;
 +use hir::{db::HirDatabase, PathResolution, Semantics, TypeInfo};
 +use ide_db::{
 +    base_db::{FileId, FileRange},
 +    defs::Definition,
 +    imports::insert_use::remove_path_if_in_use_stmt,
 +    path_transform::PathTransform,
 +    search::{FileReference, SearchScope},
-     let body = fn_body.clone_for_update();
++    syntax_helpers::{insert_whitespace_into_node::insert_ws_into, node_ext::expr_as_name_ref},
 +    RootDatabase,
 +};
 +use itertools::{izip, Itertools};
 +use syntax::{
 +    ast::{self, edit_in_place::Indent, HasArgList, PathExpr},
 +    ted, AstNode,
 +};
 +
 +use crate::{
 +    assist_context::{AssistContext, Assists},
 +    AssistId, AssistKind,
 +};
 +
 +// Assist: inline_into_callers
 +//
 +// Inline a function or method body into all of its callers where possible, creating a `let` statement per parameter
 +// unless the parameter can be inlined. The parameter will be inlined either if it the supplied argument is a simple local
 +// or if the parameter is only accessed inside the function body once.
 +// If all calls can be inlined the function will be removed.
 +//
 +// ```
 +// fn print(_: &str) {}
 +// fn foo$0(word: &str) {
 +//     if !word.is_empty() {
 +//         print(word);
 +//     }
 +// }
 +// fn bar() {
 +//     foo("안녕하세요");
 +//     foo("여러분");
 +// }
 +// ```
 +// ->
 +// ```
 +// fn print(_: &str) {}
 +//
 +// fn bar() {
 +//     {
 +//         let word = "안녕하세요";
 +//         if !word.is_empty() {
 +//             print(word);
 +//         }
 +//     };
 +//     {
 +//         let word = "여러분";
 +//         if !word.is_empty() {
 +//             print(word);
 +//         }
 +//     };
 +// }
 +// ```
 +pub(crate) fn inline_into_callers(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
 +    let def_file = ctx.file_id();
 +    let name = ctx.find_node_at_offset::<ast::Name>()?;
 +    let ast_func = name.syntax().parent().and_then(ast::Fn::cast)?;
 +    let func_body = ast_func.body()?;
 +    let param_list = ast_func.param_list()?;
 +
 +    let function = ctx.sema.to_def(&ast_func)?;
 +
 +    let params = get_fn_params(ctx.sema.db, function, &param_list)?;
 +
 +    let usages = Definition::Function(function).usages(&ctx.sema);
 +    if !usages.at_least_one() {
 +        return None;
 +    }
 +
 +    let is_recursive_fn = usages
 +        .clone()
 +        .in_scope(SearchScope::file_range(FileRange {
 +            file_id: def_file,
 +            range: func_body.syntax().text_range(),
 +        }))
 +        .at_least_one();
 +    if is_recursive_fn {
 +        cov_mark::hit!(inline_into_callers_recursive);
 +        return None;
 +    }
 +
 +    acc.add(
 +        AssistId("inline_into_callers", AssistKind::RefactorInline),
 +        "Inline into all callers",
 +        name.syntax().text_range(),
 +        |builder| {
 +            let mut usages = usages.all();
 +            let current_file_usage = usages.references.remove(&def_file);
 +
 +            let mut remove_def = true;
 +            let mut inline_refs_for_file = |file_id, refs: Vec<FileReference>| {
 +                builder.edit_file(file_id);
 +                let count = refs.len();
 +                // The collects are required as we are otherwise iterating while mutating 🙅‍♀️🙅‍♂️
 +                let (name_refs, name_refs_use): (Vec<_>, Vec<_>) = refs
 +                    .into_iter()
 +                    .filter_map(|file_ref| match file_ref.name {
 +                        ast::NameLike::NameRef(name_ref) => Some(name_ref),
 +                        _ => None,
 +                    })
 +                    .partition_map(|name_ref| {
 +                        match name_ref.syntax().ancestors().find_map(ast::UseTree::cast) {
 +                            Some(use_tree) => Either::Right(builder.make_mut(use_tree)),
 +                            None => Either::Left(name_ref),
 +                        }
 +                    });
 +                let call_infos: Vec<_> = name_refs
 +                    .into_iter()
 +                    .filter_map(CallInfo::from_name_ref)
 +                    .map(|call_info| {
 +                        let mut_node = builder.make_syntax_mut(call_info.node.syntax().clone());
 +                        (call_info, mut_node)
 +                    })
 +                    .collect();
 +                let replaced = call_infos
 +                    .into_iter()
 +                    .map(|(call_info, mut_node)| {
 +                        let replacement =
 +                            inline(&ctx.sema, def_file, function, &func_body, &params, &call_info);
 +                        ted::replace(mut_node, replacement.syntax());
 +                    })
 +                    .count();
 +                if replaced + name_refs_use.len() == count {
 +                    // we replaced all usages in this file, so we can remove the imports
 +                    name_refs_use.into_iter().for_each(|use_tree| {
 +                        if let Some(path) = use_tree.path() {
 +                            remove_path_if_in_use_stmt(&path);
 +                        }
 +                    })
 +                } else {
 +                    remove_def = false;
 +                }
 +            };
 +            for (file_id, refs) in usages.into_iter() {
 +                inline_refs_for_file(file_id, refs);
 +            }
 +            match current_file_usage {
 +                Some(refs) => inline_refs_for_file(def_file, refs),
 +                None => builder.edit_file(def_file),
 +            }
 +            if remove_def {
 +                builder.delete(ast_func.syntax().text_range());
 +            }
 +        },
 +    )
 +}
 +
 +// Assist: inline_call
 +//
 +// Inlines a function or method body creating a `let` statement per parameter unless the parameter
 +// can be inlined. The parameter will be inlined either if it the supplied argument is a simple local
 +// or if the parameter is only accessed inside the function body once.
 +//
 +// ```
 +// # //- minicore: option
 +// fn foo(name: Option<&str>) {
 +//     let name = name.unwrap$0();
 +// }
 +// ```
 +// ->
 +// ```
 +// fn foo(name: Option<&str>) {
 +//     let name = match name {
 +//             Some(val) => val,
 +//             None => panic!("called `Option::unwrap()` on a `None` value"),
 +//         };
 +// }
 +// ```
 +pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
 +    let name_ref: ast::NameRef = ctx.find_node_at_offset()?;
 +    let call_info = CallInfo::from_name_ref(name_ref.clone())?;
 +    let (function, label) = match &call_info.node {
 +        ast::CallableExpr::Call(call) => {
 +            let path = match call.expr()? {
 +                ast::Expr::PathExpr(path) => path.path(),
 +                _ => None,
 +            }?;
 +            let function = match ctx.sema.resolve_path(&path)? {
 +                PathResolution::Def(hir::ModuleDef::Function(f)) => f,
 +                _ => return None,
 +            };
 +            (function, format!("Inline `{}`", path))
 +        }
 +        ast::CallableExpr::MethodCall(call) => {
 +            (ctx.sema.resolve_method_call(call)?, format!("Inline `{}`", name_ref))
 +        }
 +    };
 +
 +    let fn_source = ctx.sema.source(function)?;
 +    let fn_body = fn_source.value.body()?;
 +    let param_list = fn_source.value.param_list()?;
 +
 +    let FileRange { file_id, range } = fn_source.syntax().original_file_range(ctx.sema.db);
 +    if file_id == ctx.file_id() && range.contains(ctx.offset()) {
 +        cov_mark::hit!(inline_call_recursive);
 +        return None;
 +    }
 +    let params = get_fn_params(ctx.sema.db, function, &param_list)?;
 +
 +    if call_info.arguments.len() != params.len() {
 +        // Can't inline the function because they've passed the wrong number of
 +        // arguments to this function
 +        cov_mark::hit!(inline_call_incorrect_number_of_arguments);
 +        return None;
 +    }
 +
 +    let syntax = call_info.node.syntax().clone();
 +    acc.add(
 +        AssistId("inline_call", AssistKind::RefactorInline),
 +        label,
 +        syntax.text_range(),
 +        |builder| {
 +            let replacement = inline(&ctx.sema, file_id, function, &fn_body, &params, &call_info);
 +
 +            builder.replace_ast(
 +                match call_info.node {
 +                    ast::CallableExpr::Call(it) => ast::Expr::CallExpr(it),
 +                    ast::CallableExpr::MethodCall(it) => ast::Expr::MethodCallExpr(it),
 +                },
 +                replacement,
 +            );
 +        },
 +    )
 +}
 +
 +struct CallInfo {
 +    node: ast::CallableExpr,
 +    arguments: Vec<ast::Expr>,
 +    generic_arg_list: Option<ast::GenericArgList>,
 +}
 +
 +impl CallInfo {
 +    fn from_name_ref(name_ref: ast::NameRef) -> Option<CallInfo> {
 +        let parent = name_ref.syntax().parent()?;
 +        if let Some(call) = ast::MethodCallExpr::cast(parent.clone()) {
 +            let receiver = call.receiver()?;
 +            let mut arguments = vec![receiver];
 +            arguments.extend(call.arg_list()?.args());
 +            Some(CallInfo {
 +                generic_arg_list: call.generic_arg_list(),
 +                node: ast::CallableExpr::MethodCall(call),
 +                arguments,
 +            })
 +        } else if let Some(segment) = ast::PathSegment::cast(parent) {
 +            let path = segment.syntax().parent().and_then(ast::Path::cast)?;
 +            let path = path.syntax().parent().and_then(ast::PathExpr::cast)?;
 +            let call = path.syntax().parent().and_then(ast::CallExpr::cast)?;
 +
 +            Some(CallInfo {
 +                arguments: call.arg_list()?.args().collect(),
 +                node: ast::CallableExpr::Call(call),
 +                generic_arg_list: segment.generic_arg_list(),
 +            })
 +        } else {
 +            None
 +        }
 +    }
 +}
 +
 +fn get_fn_params(
 +    db: &dyn HirDatabase,
 +    function: hir::Function,
 +    param_list: &ast::ParamList,
 +) -> Option<Vec<(ast::Pat, Option<ast::Type>, hir::Param)>> {
 +    let mut assoc_fn_params = function.assoc_fn_params(db).into_iter();
 +
 +    let mut params = Vec::new();
 +    if let Some(self_param) = param_list.self_param() {
 +        // FIXME this should depend on the receiver as well as the self_param
 +        params.push((
 +            make::ident_pat(
 +                self_param.amp_token().is_some(),
 +                self_param.mut_token().is_some(),
 +                make::name("this"),
 +            )
 +            .into(),
 +            None,
 +            assoc_fn_params.next()?,
 +        ));
 +    }
 +    for param in param_list.params() {
 +        params.push((param.pat()?, param.ty(), assoc_fn_params.next()?));
 +    }
 +
 +    Some(params)
 +}
 +
 +fn inline(
 +    sema: &Semantics<'_, RootDatabase>,
 +    function_def_file_id: FileId,
 +    function: hir::Function,
 +    fn_body: &ast::BlockExpr,
 +    params: &[(ast::Pat, Option<ast::Type>, hir::Param)],
 +    CallInfo { node, arguments, generic_arg_list }: &CallInfo,
 +) -> ast::Expr {
++    let body = if sema.hir_file_for(fn_body.syntax()).is_macro() {
++        cov_mark::hit!(inline_call_defined_in_macro);
++        if let Some(body) = ast::BlockExpr::cast(insert_ws_into(fn_body.syntax().clone())) {
++            body
++        } else {
++            fn_body.clone_for_update()
++        }
++    } else {
++        fn_body.clone_for_update()
++    };
 +    let usages_for_locals = |local| {
 +        Definition::Local(local)
 +            .usages(sema)
 +            .all()
 +            .references
 +            .remove(&function_def_file_id)
 +            .unwrap_or_default()
 +            .into_iter()
 +    };
 +    let param_use_nodes: Vec<Vec<_>> = params
 +        .iter()
 +        .map(|(pat, _, param)| {
 +            if !matches!(pat, ast::Pat::IdentPat(pat) if pat.is_simple_ident()) {
 +                return Vec::new();
 +            }
 +            // FIXME: we need to fetch all locals declared in the parameter here
 +            // not only the local if it is a simple binding
 +            match param.as_local(sema.db) {
 +                Some(l) => usages_for_locals(l)
 +                    .map(|FileReference { name, range, .. }| match name {
 +                        ast::NameLike::NameRef(_) => body
 +                            .syntax()
 +                            .covering_element(range)
 +                            .ancestors()
 +                            .nth(3)
 +                            .and_then(ast::PathExpr::cast),
 +                        _ => None,
 +                    })
 +                    .collect::<Option<Vec<_>>>()
 +                    .unwrap_or_default(),
 +                None => Vec::new(),
 +            }
 +        })
 +        .collect();
 +    if function.self_param(sema.db).is_some() {
 +        let this = || make::name_ref("this").syntax().clone_for_update();
 +        if let Some(self_local) = params[0].2.as_local(sema.db) {
 +            usages_for_locals(self_local)
 +                .flat_map(|FileReference { name, range, .. }| match name {
 +                    ast::NameLike::NameRef(_) => Some(body.syntax().covering_element(range)),
 +                    _ => None,
 +                })
 +                .for_each(|it| {
 +                    ted::replace(it, &this());
 +                })
 +        }
 +    }
 +    // Inline parameter expressions or generate `let` statements depending on whether inlining works or not.
 +    for ((pat, param_ty, _), usages, expr) in izip!(params, param_use_nodes, arguments).rev() {
 +        let inline_direct = |usage, replacement: &ast::Expr| {
 +            if let Some(field) = path_expr_as_record_field(usage) {
 +                cov_mark::hit!(inline_call_inline_direct_field);
 +                field.replace_expr(replacement.clone_for_update());
 +            } else {
 +                ted::replace(usage.syntax(), &replacement.syntax().clone_for_update());
 +            }
 +        };
 +        // izip confuses RA due to our lack of hygiene info currently losing us type info causing incorrect errors
 +        let usages: &[ast::PathExpr] = &*usages;
 +        let expr: &ast::Expr = expr;
 +        match usages {
 +            // inline single use closure arguments
 +            [usage]
 +                if matches!(expr, ast::Expr::ClosureExpr(_))
 +                    && usage.syntax().parent().and_then(ast::Expr::cast).is_some() =>
 +            {
 +                cov_mark::hit!(inline_call_inline_closure);
 +                let expr = make::expr_paren(expr.clone());
 +                inline_direct(usage, &expr);
 +            }
 +            // inline single use literals
 +            [usage] if matches!(expr, ast::Expr::Literal(_)) => {
 +                cov_mark::hit!(inline_call_inline_literal);
 +                inline_direct(usage, expr);
 +            }
 +            // inline direct local arguments
 +            [_, ..] if expr_as_name_ref(expr).is_some() => {
 +                cov_mark::hit!(inline_call_inline_locals);
 +                usages.iter().for_each(|usage| inline_direct(usage, expr));
 +            }
 +            // can't inline, emit a let statement
 +            _ => {
 +                let ty =
 +                    sema.type_of_expr(expr).filter(TypeInfo::has_adjustment).and(param_ty.clone());
 +                if let Some(stmt_list) = body.stmt_list() {
 +                    stmt_list.push_front(
 +                        make::let_stmt(pat.clone(), ty, Some(expr.clone()))
 +                            .clone_for_update()
 +                            .into(),
 +                    )
 +                }
 +            }
 +        }
 +    }
 +    if let Some(generic_arg_list) = generic_arg_list.clone() {
 +        if let Some((target, source)) = &sema.scope(node.syntax()).zip(sema.scope(fn_body.syntax()))
 +        {
 +            PathTransform::function_call(target, source, function, generic_arg_list)
 +                .apply(body.syntax());
 +        }
 +    }
 +
 +    let original_indentation = match node {
 +        ast::CallableExpr::Call(it) => it.indent_level(),
 +        ast::CallableExpr::MethodCall(it) => it.indent_level(),
 +    };
 +    body.reindent_to(original_indentation);
 +
 +    match body.tail_expr() {
 +        Some(expr) if body.statements().next().is_none() => expr,
 +        _ => match node
 +            .syntax()
 +            .parent()
 +            .and_then(ast::BinExpr::cast)
 +            .and_then(|bin_expr| bin_expr.lhs())
 +        {
 +            Some(lhs) if lhs.syntax() == node.syntax() => {
 +                make::expr_paren(ast::Expr::BlockExpr(body)).clone_for_update()
 +            }
 +            _ => ast::Expr::BlockExpr(body),
 +        },
 +    }
 +}
 +
 +fn path_expr_as_record_field(usage: &PathExpr) -> Option<ast::RecordExprField> {
 +    let path = usage.path()?;
 +    let name_ref = path.as_single_name_ref()?;
 +    ast::RecordExprField::for_name_ref(&name_ref)
 +}
 +
 +#[cfg(test)]
 +mod tests {
 +    use crate::tests::{check_assist, check_assist_not_applicable};
 +
 +    use super::*;
 +
 +    #[test]
 +    fn no_args_or_return_value_gets_inlined_without_block() {
 +        check_assist(
 +            inline_call,
 +            r#"
 +fn foo() { println!("Hello, World!"); }
 +fn main() {
 +    fo$0o();
 +}
 +"#,
 +            r#"
 +fn foo() { println!("Hello, World!"); }
 +fn main() {
 +    { println!("Hello, World!"); };
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn not_applicable_when_incorrect_number_of_parameters_are_provided() {
 +        cov_mark::check!(inline_call_incorrect_number_of_arguments);
 +        check_assist_not_applicable(
 +            inline_call,
 +            r#"
 +fn add(a: u32, b: u32) -> u32 { a + b }
 +fn main() { let x = add$0(42); }
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn args_with_side_effects() {
 +        check_assist(
 +            inline_call,
 +            r#"
 +fn foo(name: String) {
 +    println!("Hello, {}!", name);
 +}
 +fn main() {
 +    foo$0(String::from("Michael"));
 +}
 +"#,
 +            r#"
 +fn foo(name: String) {
 +    println!("Hello, {}!", name);
 +}
 +fn main() {
 +    {
 +        let name = String::from("Michael");
 +        println!("Hello, {}!", name);
 +    };
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn function_with_multiple_statements() {
 +        check_assist(
 +            inline_call,
 +            r#"
 +fn foo(a: u32, b: u32) -> u32 {
 +    let x = a + b;
 +    let y = x - b;
 +    x * y
 +}
 +
 +fn main() {
 +    let x = foo$0(1, 2);
 +}
 +"#,
 +            r#"
 +fn foo(a: u32, b: u32) -> u32 {
 +    let x = a + b;
 +    let y = x - b;
 +    x * y
 +}
 +
 +fn main() {
 +    let x = {
 +        let b = 2;
 +        let x = 1 + b;
 +        let y = x - b;
 +        x * y
 +    };
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn function_with_self_param() {
 +        check_assist(
 +            inline_call,
 +            r#"
 +struct Foo(u32);
 +
 +impl Foo {
 +    fn add(self, a: u32) -> Self {
 +        Foo(self.0 + a)
 +    }
 +}
 +
 +fn main() {
 +    let x = Foo::add$0(Foo(3), 2);
 +}
 +"#,
 +            r#"
 +struct Foo(u32);
 +
 +impl Foo {
 +    fn add(self, a: u32) -> Self {
 +        Foo(self.0 + a)
 +    }
 +}
 +
 +fn main() {
 +    let x = {
 +        let this = Foo(3);
 +        Foo(this.0 + 2)
 +    };
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn method_by_val() {
 +        check_assist(
 +            inline_call,
 +            r#"
 +struct Foo(u32);
 +
 +impl Foo {
 +    fn add(self, a: u32) -> Self {
 +        Foo(self.0 + a)
 +    }
 +}
 +
 +fn main() {
 +    let x = Foo(3).add$0(2);
 +}
 +"#,
 +            r#"
 +struct Foo(u32);
 +
 +impl Foo {
 +    fn add(self, a: u32) -> Self {
 +        Foo(self.0 + a)
 +    }
 +}
 +
 +fn main() {
 +    let x = {
 +        let this = Foo(3);
 +        Foo(this.0 + 2)
 +    };
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn method_by_ref() {
 +        check_assist(
 +            inline_call,
 +            r#"
 +struct Foo(u32);
 +
 +impl Foo {
 +    fn add(&self, a: u32) -> Self {
 +        Foo(self.0 + a)
 +    }
 +}
 +
 +fn main() {
 +    let x = Foo(3).add$0(2);
 +}
 +"#,
 +            r#"
 +struct Foo(u32);
 +
 +impl Foo {
 +    fn add(&self, a: u32) -> Self {
 +        Foo(self.0 + a)
 +    }
 +}
 +
 +fn main() {
 +    let x = {
 +        let ref this = Foo(3);
 +        Foo(this.0 + 2)
 +    };
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn method_by_ref_mut() {
 +        check_assist(
 +            inline_call,
 +            r#"
 +struct Foo(u32);
 +
 +impl Foo {
 +    fn clear(&mut self) {
 +        self.0 = 0;
 +    }
 +}
 +
 +fn main() {
 +    let mut foo = Foo(3);
 +    foo.clear$0();
 +}
 +"#,
 +            r#"
 +struct Foo(u32);
 +
 +impl Foo {
 +    fn clear(&mut self) {
 +        self.0 = 0;
 +    }
 +}
 +
 +fn main() {
 +    let mut foo = Foo(3);
 +    {
 +        let ref mut this = foo;
 +        this.0 = 0;
 +    };
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn function_multi_use_expr_in_param() {
 +        check_assist(
 +            inline_call,
 +            r#"
 +fn square(x: u32) -> u32 {
 +    x * x
 +}
 +fn main() {
 +    let x = 51;
 +    let y = square$0(10 + x);
 +}
 +"#,
 +            r#"
 +fn square(x: u32) -> u32 {
 +    x * x
 +}
 +fn main() {
 +    let x = 51;
 +    let y = {
 +        let x = 10 + x;
 +        x * x
 +    };
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn function_use_local_in_param() {
 +        cov_mark::check!(inline_call_inline_locals);
 +        check_assist(
 +            inline_call,
 +            r#"
 +fn square(x: u32) -> u32 {
 +    x * x
 +}
 +fn main() {
 +    let local = 51;
 +    let y = square$0(local);
 +}
 +"#,
 +            r#"
 +fn square(x: u32) -> u32 {
 +    x * x
 +}
 +fn main() {
 +    let local = 51;
 +    let y = local * local;
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn method_in_impl() {
 +        check_assist(
 +            inline_call,
 +            r#"
 +struct Foo;
 +impl Foo {
 +    fn foo(&self) {
 +        self;
 +        self;
 +    }
 +    fn bar(&self) {
 +        self.foo$0();
 +    }
 +}
 +"#,
 +            r#"
 +struct Foo;
 +impl Foo {
 +    fn foo(&self) {
 +        self;
 +        self;
 +    }
 +    fn bar(&self) {
 +        {
 +            let ref this = self;
 +            this;
 +            this;
 +        };
 +    }
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn wraps_closure_in_paren() {
 +        cov_mark::check!(inline_call_inline_closure);
 +        check_assist(
 +            inline_call,
 +            r#"
 +fn foo(x: fn()) {
 +    x();
 +}
 +
 +fn main() {
 +    foo$0(|| {})
 +}
 +"#,
 +            r#"
 +fn foo(x: fn()) {
 +    x();
 +}
 +
 +fn main() {
 +    {
 +        (|| {})();
 +    }
 +}
 +"#,
 +        );
 +        check_assist(
 +            inline_call,
 +            r#"
 +fn foo(x: fn()) {
 +    x();
 +}
 +
 +fn main() {
 +    foo$0(main)
 +}
 +"#,
 +            r#"
 +fn foo(x: fn()) {
 +    x();
 +}
 +
 +fn main() {
 +    {
 +        main();
 +    }
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn inline_single_literal_expr() {
 +        cov_mark::check!(inline_call_inline_literal);
 +        check_assist(
 +            inline_call,
 +            r#"
 +fn foo(x: u32) -> u32{
 +    x
 +}
 +
 +fn main() {
 +    foo$0(222);
 +}
 +"#,
 +            r#"
 +fn foo(x: u32) -> u32{
 +    x
 +}
 +
 +fn main() {
 +    222;
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn inline_emits_type_for_coercion() {
 +        check_assist(
 +            inline_call,
 +            r#"
 +fn foo(x: *const u32) -> u32 {
 +    x as u32
 +}
 +
 +fn main() {
 +    foo$0(&222);
 +}
 +"#,
 +            r#"
 +fn foo(x: *const u32) -> u32 {
 +    x as u32
 +}
 +
 +fn main() {
 +    {
 +        let x: *const u32 = &222;
 +        x as u32
 +    };
 +}
 +"#,
 +        );
 +    }
 +
 +    // FIXME: const generics aren't being substituted, this is blocked on better support for them
 +    #[test]
 +    fn inline_substitutes_generics() {
 +        check_assist(
 +            inline_call,
 +            r#"
 +fn foo<T, const N: usize>() {
 +    bar::<T, N>()
 +}
 +
 +fn bar<U, const M: usize>() {}
 +
 +fn main() {
 +    foo$0::<usize, {0}>();
 +}
 +"#,
 +            r#"
 +fn foo<T, const N: usize>() {
 +    bar::<T, N>()
 +}
 +
 +fn bar<U, const M: usize>() {}
 +
 +fn main() {
 +    bar::<usize, N>();
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn inline_callers() {
 +        check_assist(
 +            inline_into_callers,
 +            r#"
 +fn do_the_math$0(b: u32) -> u32 {
 +    let foo = 10;
 +    foo * b + foo
 +}
 +fn foo() {
 +    do_the_math(0);
 +    let bar = 10;
 +    do_the_math(bar);
 +}
 +"#,
 +            r#"
 +
 +fn foo() {
 +    {
 +        let foo = 10;
 +        foo * 0 + foo
 +    };
 +    let bar = 10;
 +    {
 +        let foo = 10;
 +        foo * bar + foo
 +    };
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn inline_callers_across_files() {
 +        check_assist(
 +            inline_into_callers,
 +            r#"
 +//- /lib.rs
 +mod foo;
 +fn do_the_math$0(b: u32) -> u32 {
 +    let foo = 10;
 +    foo * b + foo
 +}
 +//- /foo.rs
 +use super::do_the_math;
 +fn foo() {
 +    do_the_math(0);
 +    let bar = 10;
 +    do_the_math(bar);
 +}
 +"#,
 +            r#"
 +//- /lib.rs
 +mod foo;
 +
 +//- /foo.rs
 +fn foo() {
 +    {
 +        let foo = 10;
 +        foo * 0 + foo
 +    };
 +    let bar = 10;
 +    {
 +        let foo = 10;
 +        foo * bar + foo
 +    };
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn inline_callers_across_files_with_def_file() {
 +        check_assist(
 +            inline_into_callers,
 +            r#"
 +//- /lib.rs
 +mod foo;
 +fn do_the_math$0(b: u32) -> u32 {
 +    let foo = 10;
 +    foo * b + foo
 +}
 +fn bar(a: u32, b: u32) -> u32 {
 +    do_the_math(0);
 +}
 +//- /foo.rs
 +use super::do_the_math;
 +fn foo() {
 +    do_the_math(0);
 +}
 +"#,
 +            r#"
 +//- /lib.rs
 +mod foo;
 +
 +fn bar(a: u32, b: u32) -> u32 {
 +    {
 +        let foo = 10;
 +        foo * 0 + foo
 +    };
 +}
 +//- /foo.rs
 +fn foo() {
 +    {
 +        let foo = 10;
 +        foo * 0 + foo
 +    };
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn inline_callers_recursive() {
 +        cov_mark::check!(inline_into_callers_recursive);
 +        check_assist_not_applicable(
 +            inline_into_callers,
 +            r#"
 +fn foo$0() {
 +    foo();
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn inline_call_recursive() {
 +        cov_mark::check!(inline_call_recursive);
 +        check_assist_not_applicable(
 +            inline_call,
 +            r#"
 +fn foo() {
 +    foo$0();
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn inline_call_field_shorthand() {
 +        cov_mark::check!(inline_call_inline_direct_field);
 +        check_assist(
 +            inline_call,
 +            r#"
 +struct Foo {
 +    field: u32,
 +    field1: u32,
 +    field2: u32,
 +    field3: u32,
 +}
 +fn foo(field: u32, field1: u32, val2: u32, val3: u32) -> Foo {
 +    Foo {
 +        field,
 +        field1,
 +        field2: val2,
 +        field3: val3,
 +    }
 +}
 +fn main() {
 +    let bar = 0;
 +    let baz = 0;
 +    foo$0(bar, 0, baz, 0);
 +}
 +"#,
 +            r#"
 +struct Foo {
 +    field: u32,
 +    field1: u32,
 +    field2: u32,
 +    field3: u32,
 +}
 +fn foo(field: u32, field1: u32, val2: u32, val3: u32) -> Foo {
 +    Foo {
 +        field,
 +        field1,
 +        field2: val2,
 +        field3: val3,
 +    }
 +}
 +fn main() {
 +    let bar = 0;
 +    let baz = 0;
 +    Foo {
 +            field: bar,
 +            field1: 0,
 +            field2: baz,
 +            field3: 0,
 +        };
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn inline_callers_wrapped_in_parentheses() {
 +        check_assist(
 +            inline_into_callers,
 +            r#"
 +fn foo$0() -> u32 {
 +    let x = 0;
 +    x
 +}
 +fn bar() -> u32 {
 +    foo() + foo()
 +}
 +"#,
 +            r#"
 +
 +fn bar() -> u32 {
 +    ({
 +        let x = 0;
 +        x
 +    }) + {
 +        let x = 0;
 +        x
 +    }
 +}
 +"#,
 +        )
 +    }
 +
 +    #[test]
 +    fn inline_call_wrapped_in_parentheses() {
 +        check_assist(
 +            inline_call,
 +            r#"
 +fn foo() -> u32 {
 +    let x = 0;
 +    x
 +}
 +fn bar() -> u32 {
 +    foo$0() + foo()
 +}
 +"#,
 +            r#"
 +fn foo() -> u32 {
 +    let x = 0;
 +    x
 +}
 +fn bar() -> u32 {
 +    ({
 +        let x = 0;
 +        x
 +    }) + foo()
 +}
++"#,
++        )
++    }
++
++    #[test]
++    fn inline_call_defined_in_macro() {
++        cov_mark::check!(inline_call_defined_in_macro);
++        check_assist(
++            inline_call,
++            r#"
++macro_rules! define_foo {
++    () => { fn foo() -> u32 {
++        let x = 0;
++        x
++    } };
++}
++define_foo!();
++fn bar() -> u32 {
++    foo$0()
++}
++"#,
++            r#"
++macro_rules! define_foo {
++    () => { fn foo() -> u32 {
++        let x = 0;
++        x
++    } };
++}
++define_foo!();
++fn bar() -> u32 {
++    {
++      let x = 0;
++      x
++    }
++}
 +"#,
 +        )
 +    }
 +}
index e8d48607be0e9f938814bb94f5995ae6d84bad40,0000000000000000000000000000000000000000..6eaab48a32ba54e567f0e958f9a52d8cebbe9bbe
mode 100644,000000..100644
--- /dev/null
@@@ -1,2259 -1,0 +1,2259 @@@
- use foo::{Baz, Bar};
 +//! Generated by `sourcegen_assists_docs`, do not edit by hand.
 +
 +use super::check_doc_test;
 +
 +#[test]
 +fn doctest_add_explicit_type() {
 +    check_doc_test(
 +        "add_explicit_type",
 +        r#####"
 +fn main() {
 +    let x$0 = 92;
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    let x: i32 = 92;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_add_hash() {
 +    check_doc_test(
 +        "add_hash",
 +        r#####"
 +fn main() {
 +    r#"Hello,$0 World!"#;
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    r##"Hello, World!"##;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_add_impl_default_members() {
 +    check_doc_test(
 +        "add_impl_default_members",
 +        r#####"
 +trait Trait {
 +    type X;
 +    fn foo(&self);
 +    fn bar(&self) {}
 +}
 +
 +impl Trait for () {
 +    type X = ();
 +    fn foo(&self) {}$0
 +}
 +"#####,
 +        r#####"
 +trait Trait {
 +    type X;
 +    fn foo(&self);
 +    fn bar(&self) {}
 +}
 +
 +impl Trait for () {
 +    type X = ();
 +    fn foo(&self) {}
 +
 +    $0fn bar(&self) {}
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_add_impl_missing_members() {
 +    check_doc_test(
 +        "add_impl_missing_members",
 +        r#####"
 +trait Trait<T> {
 +    type X;
 +    fn foo(&self) -> T;
 +    fn bar(&self) {}
 +}
 +
 +impl Trait<u32> for () {$0
 +
 +}
 +"#####,
 +        r#####"
 +trait Trait<T> {
 +    type X;
 +    fn foo(&self) -> T;
 +    fn bar(&self) {}
 +}
 +
 +impl Trait<u32> for () {
 +    $0type X;
 +
 +    fn foo(&self) -> u32 {
 +        todo!()
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_add_label_to_loop() {
 +    check_doc_test(
 +        "add_label_to_loop",
 +        r#####"
 +fn main() {
 +    loop$0 {
 +        break;
 +        continue;
 +    }
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    'l: loop {
 +        break 'l;
 +        continue 'l;
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_add_lifetime_to_type() {
 +    check_doc_test(
 +        "add_lifetime_to_type",
 +        r#####"
 +struct Point {
 +    x: &$0u32,
 +    y: u32,
 +}
 +"#####,
 +        r#####"
 +struct Point<'a> {
 +    x: &'a u32,
 +    y: u32,
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_add_missing_match_arms() {
 +    check_doc_test(
 +        "add_missing_match_arms",
 +        r#####"
 +enum Action { Move { distance: u32 }, Stop }
 +
 +fn handle(action: Action) {
 +    match action {
 +        $0
 +    }
 +}
 +"#####,
 +        r#####"
 +enum Action { Move { distance: u32 }, Stop }
 +
 +fn handle(action: Action) {
 +    match action {
 +        $0Action::Move { distance } => todo!(),
 +        Action::Stop => todo!(),
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_add_return_type() {
 +    check_doc_test(
 +        "add_return_type",
 +        r#####"
 +fn foo() { 4$02i32 }
 +"#####,
 +        r#####"
 +fn foo() -> i32 { 42i32 }
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_add_turbo_fish() {
 +    check_doc_test(
 +        "add_turbo_fish",
 +        r#####"
 +fn make<T>() -> T { todo!() }
 +fn main() {
 +    let x = make$0();
 +}
 +"#####,
 +        r#####"
 +fn make<T>() -> T { todo!() }
 +fn main() {
 +    let x = make::<${0:_}>();
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_apply_demorgan() {
 +    check_doc_test(
 +        "apply_demorgan",
 +        r#####"
 +fn main() {
 +    if x != 4 ||$0 y < 3.14 {}
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    if !(x == 4 && y >= 3.14) {}
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_auto_import() {
 +    check_doc_test(
 +        "auto_import",
 +        r#####"
 +fn main() {
 +    let map = HashMap$0::new();
 +}
 +pub mod std { pub mod collections { pub struct HashMap { } } }
 +"#####,
 +        r#####"
 +use std::collections::HashMap;
 +
 +fn main() {
 +    let map = HashMap::new();
 +}
 +pub mod std { pub mod collections { pub struct HashMap { } } }
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_change_visibility() {
 +    check_doc_test(
 +        "change_visibility",
 +        r#####"
 +$0fn frobnicate() {}
 +"#####,
 +        r#####"
 +pub(crate) fn frobnicate() {}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_convert_bool_then_to_if() {
 +    check_doc_test(
 +        "convert_bool_then_to_if",
 +        r#####"
 +//- minicore: bool_impl
 +fn main() {
 +    (0 == 0).then$0(|| val)
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    if 0 == 0 {
 +        Some(val)
 +    } else {
 +        None
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_convert_for_loop_with_for_each() {
 +    check_doc_test(
 +        "convert_for_loop_with_for_each",
 +        r#####"
 +fn main() {
 +    let x = vec![1, 2, 3];
 +    for$0 v in x {
 +        let y = v * 2;
 +    }
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    let x = vec![1, 2, 3];
 +    x.into_iter().for_each(|v| {
 +        let y = v * 2;
 +    });
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_convert_if_to_bool_then() {
 +    check_doc_test(
 +        "convert_if_to_bool_then",
 +        r#####"
 +//- minicore: option
 +fn main() {
 +    if$0 cond {
 +        Some(val)
 +    } else {
 +        None
 +    }
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    cond.then(|| val)
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_convert_integer_literal() {
 +    check_doc_test(
 +        "convert_integer_literal",
 +        r#####"
 +const _: i32 = 10$0;
 +"#####,
 +        r#####"
 +const _: i32 = 0b1010;
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_convert_into_to_from() {
 +    check_doc_test(
 +        "convert_into_to_from",
 +        r#####"
 +//- minicore: from
 +impl $0Into<Thing> for usize {
 +    fn into(self) -> Thing {
 +        Thing {
 +            b: self.to_string(),
 +            a: self
 +        }
 +    }
 +}
 +"#####,
 +        r#####"
 +impl From<usize> for Thing {
 +    fn from(val: usize) -> Self {
 +        Thing {
 +            b: val.to_string(),
 +            a: val
 +        }
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_convert_iter_for_each_to_for() {
 +    check_doc_test(
 +        "convert_iter_for_each_to_for",
 +        r#####"
 +//- minicore: iterators
 +use core::iter;
 +fn main() {
 +    let iter = iter::repeat((9, 2));
 +    iter.for_each$0(|(x, y)| {
 +        println!("x: {}, y: {}", x, y);
 +    });
 +}
 +"#####,
 +        r#####"
 +use core::iter;
 +fn main() {
 +    let iter = iter::repeat((9, 2));
 +    for (x, y) in iter {
 +        println!("x: {}, y: {}", x, y);
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_convert_let_else_to_match() {
 +    check_doc_test(
 +        "convert_let_else_to_match",
 +        r#####"
 +fn main() {
 +    let Ok(mut x) = f() else$0 { return };
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    let mut x = match f() {
 +        Ok(x) => x,
 +        _ => return,
 +    };
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_convert_to_guarded_return() {
 +    check_doc_test(
 +        "convert_to_guarded_return",
 +        r#####"
 +fn main() {
 +    $0if cond {
 +        foo();
 +        bar();
 +    }
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    if !cond {
 +        return;
 +    }
 +    foo();
 +    bar();
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_convert_tuple_struct_to_named_struct() {
 +    check_doc_test(
 +        "convert_tuple_struct_to_named_struct",
 +        r#####"
 +struct Point$0(f32, f32);
 +
 +impl Point {
 +    pub fn new(x: f32, y: f32) -> Self {
 +        Point(x, y)
 +    }
 +
 +    pub fn x(&self) -> f32 {
 +        self.0
 +    }
 +
 +    pub fn y(&self) -> f32 {
 +        self.1
 +    }
 +}
 +"#####,
 +        r#####"
 +struct Point { field1: f32, field2: f32 }
 +
 +impl Point {
 +    pub fn new(x: f32, y: f32) -> Self {
 +        Point { field1: x, field2: y }
 +    }
 +
 +    pub fn x(&self) -> f32 {
 +        self.field1
 +    }
 +
 +    pub fn y(&self) -> f32 {
 +        self.field2
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_convert_while_to_loop() {
 +    check_doc_test(
 +        "convert_while_to_loop",
 +        r#####"
 +fn main() {
 +    $0while cond {
 +        foo();
 +    }
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    loop {
 +        if !cond {
 +            break;
 +        }
 +        foo();
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_destructure_tuple_binding() {
 +    check_doc_test(
 +        "destructure_tuple_binding",
 +        r#####"
 +fn main() {
 +    let $0t = (1,2);
 +    let v = t.0;
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    let ($0_0, _1) = (1,2);
 +    let v = _0;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_expand_glob_import() {
 +    check_doc_test(
 +        "expand_glob_import",
 +        r#####"
 +mod foo {
 +    pub struct Bar;
 +    pub struct Baz;
 +}
 +
 +use foo::*$0;
 +
 +fn qux(bar: Bar, baz: Baz) {}
 +"#####,
 +        r#####"
 +mod foo {
 +    pub struct Bar;
 +    pub struct Baz;
 +}
 +
++use foo::{Bar, Baz};
 +
 +fn qux(bar: Bar, baz: Baz) {}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_extract_function() {
 +    check_doc_test(
 +        "extract_function",
 +        r#####"
 +fn main() {
 +    let n = 1;
 +    $0let m = n + 2;
 +    // calculate
 +    let k = m + n;$0
 +    let g = 3;
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    let n = 1;
 +    fun_name(n);
 +    let g = 3;
 +}
 +
 +fn $0fun_name(n: i32) {
 +    let m = n + 2;
 +    // calculate
 +    let k = m + n;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_extract_module() {
 +    check_doc_test(
 +        "extract_module",
 +        r#####"
 +$0fn foo(name: i32) -> i32 {
 +    name + 1
 +}$0
 +
 +fn bar(name: i32) -> i32 {
 +    name + 2
 +}
 +"#####,
 +        r#####"
 +mod modname {
 +    pub(crate) fn foo(name: i32) -> i32 {
 +        name + 1
 +    }
 +}
 +
 +fn bar(name: i32) -> i32 {
 +    name + 2
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_extract_struct_from_enum_variant() {
 +    check_doc_test(
 +        "extract_struct_from_enum_variant",
 +        r#####"
 +enum A { $0One(u32, u32) }
 +"#####,
 +        r#####"
 +struct One(u32, u32);
 +
 +enum A { One(One) }
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_extract_type_alias() {
 +    check_doc_test(
 +        "extract_type_alias",
 +        r#####"
 +struct S {
 +    field: $0(u8, u8, u8)$0,
 +}
 +"#####,
 +        r#####"
 +type $0Type = (u8, u8, u8);
 +
 +struct S {
 +    field: Type,
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_extract_variable() {
 +    check_doc_test(
 +        "extract_variable",
 +        r#####"
 +fn main() {
 +    $0(1 + 2)$0 * 4;
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    let $0var_name = (1 + 2);
 +    var_name * 4;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_fix_visibility() {
 +    check_doc_test(
 +        "fix_visibility",
 +        r#####"
 +mod m {
 +    fn frobnicate() {}
 +}
 +fn main() {
 +    m::frobnicate$0() {}
 +}
 +"#####,
 +        r#####"
 +mod m {
 +    $0pub(crate) fn frobnicate() {}
 +}
 +fn main() {
 +    m::frobnicate() {}
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_flip_binexpr() {
 +    check_doc_test(
 +        "flip_binexpr",
 +        r#####"
 +fn main() {
 +    let _ = 90 +$0 2;
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    let _ = 2 + 90;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_flip_comma() {
 +    check_doc_test(
 +        "flip_comma",
 +        r#####"
 +fn main() {
 +    ((1, 2),$0 (3, 4));
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    ((3, 4), (1, 2));
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_flip_trait_bound() {
 +    check_doc_test(
 +        "flip_trait_bound",
 +        r#####"
 +fn foo<T: Clone +$0 Copy>() { }
 +"#####,
 +        r#####"
 +fn foo<T: Copy + Clone>() { }
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_constant() {
 +    check_doc_test(
 +        "generate_constant",
 +        r#####"
 +struct S { i: usize }
 +impl S { pub fn new(n: usize) {} }
 +fn main() {
 +    let v = S::new(CAPA$0CITY);
 +}
 +"#####,
 +        r#####"
 +struct S { i: usize }
 +impl S { pub fn new(n: usize) {} }
 +fn main() {
 +    const CAPACITY: usize = $0;
 +    let v = S::new(CAPACITY);
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_default_from_enum_variant() {
 +    check_doc_test(
 +        "generate_default_from_enum_variant",
 +        r#####"
 +enum Version {
 + Undefined,
 + Minor$0,
 + Major,
 +}
 +"#####,
 +        r#####"
 +enum Version {
 + Undefined,
 + Minor,
 + Major,
 +}
 +
 +impl Default for Version {
 +    fn default() -> Self {
 +        Self::Minor
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_default_from_new() {
 +    check_doc_test(
 +        "generate_default_from_new",
 +        r#####"
 +struct Example { _inner: () }
 +
 +impl Example {
 +    pub fn n$0ew() -> Self {
 +        Self { _inner: () }
 +    }
 +}
 +"#####,
 +        r#####"
 +struct Example { _inner: () }
 +
 +impl Example {
 +    pub fn new() -> Self {
 +        Self { _inner: () }
 +    }
 +}
 +
 +impl Default for Example {
 +    fn default() -> Self {
 +        Self::new()
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_delegate_methods() {
 +    check_doc_test(
 +        "generate_delegate_methods",
 +        r#####"
 +struct Age(u8);
 +impl Age {
 +    fn age(&self) -> u8 {
 +        self.0
 +    }
 +}
 +
 +struct Person {
 +    ag$0e: Age,
 +}
 +"#####,
 +        r#####"
 +struct Age(u8);
 +impl Age {
 +    fn age(&self) -> u8 {
 +        self.0
 +    }
 +}
 +
 +struct Person {
 +    age: Age,
 +}
 +
 +impl Person {
 +    $0fn age(&self) -> u8 {
 +        self.age.age()
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_deref() {
 +    check_doc_test(
 +        "generate_deref",
 +        r#####"
 +//- minicore: deref, deref_mut
 +struct A;
 +struct B {
 +   $0a: A
 +}
 +"#####,
 +        r#####"
 +struct A;
 +struct B {
 +   a: A
 +}
 +
 +impl core::ops::Deref for B {
 +    type Target = A;
 +
 +    fn deref(&self) -> &Self::Target {
 +        &self.a
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_derive() {
 +    check_doc_test(
 +        "generate_derive",
 +        r#####"
 +struct Point {
 +    x: u32,
 +    y: u32,$0
 +}
 +"#####,
 +        r#####"
 +#[derive($0)]
 +struct Point {
 +    x: u32,
 +    y: u32,
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_doc_example() {
 +    check_doc_test(
 +        "generate_doc_example",
 +        r#####"
 +/// Adds two numbers.$0
 +pub fn add(a: i32, b: i32) -> i32 { a + b }
 +"#####,
 +        r#####"
 +/// Adds two numbers.
 +///
 +/// # Examples
 +///
 +/// ```
 +/// use test::add;
 +///
 +/// assert_eq!(add(a, b), );
 +/// ```
 +pub fn add(a: i32, b: i32) -> i32 { a + b }
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_documentation_template() {
 +    check_doc_test(
 +        "generate_documentation_template",
 +        r#####"
 +pub struct S;
 +impl S {
 +    pub unsafe fn set_len$0(&mut self, len: usize) -> Result<(), std::io::Error> {
 +        /* ... */
 +    }
 +}
 +"#####,
 +        r#####"
 +pub struct S;
 +impl S {
 +    /// Sets the length of this [`S`].
 +    ///
 +    /// # Errors
 +    ///
 +    /// This function will return an error if .
 +    ///
 +    /// # Safety
 +    ///
 +    /// .
 +    pub unsafe fn set_len(&mut self, len: usize) -> Result<(), std::io::Error> {
 +        /* ... */
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_enum_as_method() {
 +    check_doc_test(
 +        "generate_enum_as_method",
 +        r#####"
 +enum Value {
 + Number(i32),
 + Text(String)$0,
 +}
 +"#####,
 +        r#####"
 +enum Value {
 + Number(i32),
 + Text(String),
 +}
 +
 +impl Value {
 +    fn as_text(&self) -> Option<&String> {
 +        if let Self::Text(v) = self {
 +            Some(v)
 +        } else {
 +            None
 +        }
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_enum_is_method() {
 +    check_doc_test(
 +        "generate_enum_is_method",
 +        r#####"
 +enum Version {
 + Undefined,
 + Minor$0,
 + Major,
 +}
 +"#####,
 +        r#####"
 +enum Version {
 + Undefined,
 + Minor,
 + Major,
 +}
 +
 +impl Version {
 +    /// Returns `true` if the version is [`Minor`].
 +    ///
 +    /// [`Minor`]: Version::Minor
 +    #[must_use]
 +    fn is_minor(&self) -> bool {
 +        matches!(self, Self::Minor)
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_enum_try_into_method() {
 +    check_doc_test(
 +        "generate_enum_try_into_method",
 +        r#####"
 +enum Value {
 + Number(i32),
 + Text(String)$0,
 +}
 +"#####,
 +        r#####"
 +enum Value {
 + Number(i32),
 + Text(String),
 +}
 +
 +impl Value {
 +    fn try_into_text(self) -> Result<String, Self> {
 +        if let Self::Text(v) = self {
 +            Ok(v)
 +        } else {
 +            Err(self)
 +        }
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_enum_variant() {
 +    check_doc_test(
 +        "generate_enum_variant",
 +        r#####"
 +enum Countries {
 +    Ghana,
 +}
 +
 +fn main() {
 +    let country = Countries::Lesotho$0;
 +}
 +"#####,
 +        r#####"
 +enum Countries {
 +    Ghana,
 +    Lesotho,
 +}
 +
 +fn main() {
 +    let country = Countries::Lesotho;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_from_impl_for_enum() {
 +    check_doc_test(
 +        "generate_from_impl_for_enum",
 +        r#####"
 +enum A { $0One(u32) }
 +"#####,
 +        r#####"
 +enum A { One(u32) }
 +
 +impl From<u32> for A {
 +    fn from(v: u32) -> Self {
 +        Self::One(v)
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_function() {
 +    check_doc_test(
 +        "generate_function",
 +        r#####"
 +struct Baz;
 +fn baz() -> Baz { Baz }
 +fn foo() {
 +    bar$0("", baz());
 +}
 +
 +"#####,
 +        r#####"
 +struct Baz;
 +fn baz() -> Baz { Baz }
 +fn foo() {
 +    bar("", baz());
 +}
 +
 +fn bar(arg: &str, baz: Baz) ${0:-> _} {
 +    todo!()
 +}
 +
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_getter() {
 +    check_doc_test(
 +        "generate_getter",
 +        r#####"
 +//- minicore: as_ref
 +pub struct String;
 +impl AsRef<str> for String {
 +    fn as_ref(&self) -> &str {
 +        ""
 +    }
 +}
 +
 +struct Person {
 +    nam$0e: String,
 +}
 +"#####,
 +        r#####"
 +pub struct String;
 +impl AsRef<str> for String {
 +    fn as_ref(&self) -> &str {
 +        ""
 +    }
 +}
 +
 +struct Person {
 +    name: String,
 +}
 +
 +impl Person {
 +    fn $0name(&self) -> &str {
 +        self.name.as_ref()
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_getter_mut() {
 +    check_doc_test(
 +        "generate_getter_mut",
 +        r#####"
 +struct Person {
 +    nam$0e: String,
 +}
 +"#####,
 +        r#####"
 +struct Person {
 +    name: String,
 +}
 +
 +impl Person {
 +    fn $0name_mut(&mut self) -> &mut String {
 +        &mut self.name
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_impl() {
 +    check_doc_test(
 +        "generate_impl",
 +        r#####"
 +struct Ctx<T: Clone> {
 +    data: T,$0
 +}
 +"#####,
 +        r#####"
 +struct Ctx<T: Clone> {
 +    data: T,
 +}
 +
 +impl<T: Clone> Ctx<T> {
 +    $0
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_is_empty_from_len() {
 +    check_doc_test(
 +        "generate_is_empty_from_len",
 +        r#####"
 +struct MyStruct { data: Vec<String> }
 +
 +impl MyStruct {
 +    #[must_use]
 +    p$0ub fn len(&self) -> usize {
 +        self.data.len()
 +    }
 +}
 +"#####,
 +        r#####"
 +struct MyStruct { data: Vec<String> }
 +
 +impl MyStruct {
 +    #[must_use]
 +    pub fn len(&self) -> usize {
 +        self.data.len()
 +    }
 +
 +    #[must_use]
 +    pub fn is_empty(&self) -> bool {
 +        self.len() == 0
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_new() {
 +    check_doc_test(
 +        "generate_new",
 +        r#####"
 +struct Ctx<T: Clone> {
 +     data: T,$0
 +}
 +"#####,
 +        r#####"
 +struct Ctx<T: Clone> {
 +     data: T,
 +}
 +
 +impl<T: Clone> Ctx<T> {
 +    fn $0new(data: T) -> Self { Self { data } }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_generate_setter() {
 +    check_doc_test(
 +        "generate_setter",
 +        r#####"
 +struct Person {
 +    nam$0e: String,
 +}
 +"#####,
 +        r#####"
 +struct Person {
 +    name: String,
 +}
 +
 +impl Person {
 +    fn set_name(&mut self, name: String) {
 +        self.name = name;
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_inline_call() {
 +    check_doc_test(
 +        "inline_call",
 +        r#####"
 +//- minicore: option
 +fn foo(name: Option<&str>) {
 +    let name = name.unwrap$0();
 +}
 +"#####,
 +        r#####"
 +fn foo(name: Option<&str>) {
 +    let name = match name {
 +            Some(val) => val,
 +            None => panic!("called `Option::unwrap()` on a `None` value"),
 +        };
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_inline_into_callers() {
 +    check_doc_test(
 +        "inline_into_callers",
 +        r#####"
 +fn print(_: &str) {}
 +fn foo$0(word: &str) {
 +    if !word.is_empty() {
 +        print(word);
 +    }
 +}
 +fn bar() {
 +    foo("안녕하세요");
 +    foo("여러분");
 +}
 +"#####,
 +        r#####"
 +fn print(_: &str) {}
 +
 +fn bar() {
 +    {
 +        let word = "안녕하세요";
 +        if !word.is_empty() {
 +            print(word);
 +        }
 +    };
 +    {
 +        let word = "여러분";
 +        if !word.is_empty() {
 +            print(word);
 +        }
 +    };
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_inline_local_variable() {
 +    check_doc_test(
 +        "inline_local_variable",
 +        r#####"
 +fn main() {
 +    let x$0 = 1 + 2;
 +    x * 4;
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    (1 + 2) * 4;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_inline_type_alias() {
 +    check_doc_test(
 +        "inline_type_alias",
 +        r#####"
 +type A<T = u32> = Vec<T>;
 +
 +fn main() {
 +    let a: $0A;
 +}
 +"#####,
 +        r#####"
 +type A<T = u32> = Vec<T>;
 +
 +fn main() {
 +    let a: Vec<u32>;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_introduce_named_generic() {
 +    check_doc_test(
 +        "introduce_named_generic",
 +        r#####"
 +fn foo(bar: $0impl Bar) {}
 +"#####,
 +        r#####"
 +fn foo<B: Bar>(bar: B) {}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_introduce_named_lifetime() {
 +    check_doc_test(
 +        "introduce_named_lifetime",
 +        r#####"
 +impl Cursor<'_$0> {
 +    fn node(self) -> &SyntaxNode {
 +        match self {
 +            Cursor::Replace(node) | Cursor::Before(node) => node,
 +        }
 +    }
 +}
 +"#####,
 +        r#####"
 +impl<'a> Cursor<'a> {
 +    fn node(self) -> &SyntaxNode {
 +        match self {
 +            Cursor::Replace(node) | Cursor::Before(node) => node,
 +        }
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_invert_if() {
 +    check_doc_test(
 +        "invert_if",
 +        r#####"
 +fn main() {
 +    if$0 !y { A } else { B }
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    if y { B } else { A }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_line_to_block() {
 +    check_doc_test(
 +        "line_to_block",
 +        r#####"
 +   // Multi-line$0
 +   // comment
 +"#####,
 +        r#####"
 +  /*
 +  Multi-line
 +  comment
 +  */
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_make_raw_string() {
 +    check_doc_test(
 +        "make_raw_string",
 +        r#####"
 +fn main() {
 +    "Hello,$0 World!";
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    r#"Hello, World!"#;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_make_usual_string() {
 +    check_doc_test(
 +        "make_usual_string",
 +        r#####"
 +fn main() {
 +    r#"Hello,$0 "World!""#;
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    "Hello, \"World!\"";
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_merge_imports() {
 +    check_doc_test(
 +        "merge_imports",
 +        r#####"
 +use std::$0fmt::Formatter;
 +use std::io;
 +"#####,
 +        r#####"
 +use std::{fmt::Formatter, io};
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_merge_match_arms() {
 +    check_doc_test(
 +        "merge_match_arms",
 +        r#####"
 +enum Action { Move { distance: u32 }, Stop }
 +
 +fn handle(action: Action) {
 +    match action {
 +        $0Action::Move(..) => foo(),
 +        Action::Stop => foo(),
 +    }
 +}
 +"#####,
 +        r#####"
 +enum Action { Move { distance: u32 }, Stop }
 +
 +fn handle(action: Action) {
 +    match action {
 +        Action::Move(..) | Action::Stop => foo(),
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_move_arm_cond_to_match_guard() {
 +    check_doc_test(
 +        "move_arm_cond_to_match_guard",
 +        r#####"
 +enum Action { Move { distance: u32 }, Stop }
 +
 +fn handle(action: Action) {
 +    match action {
 +        Action::Move { distance } => $0if distance > 10 { foo() },
 +        _ => (),
 +    }
 +}
 +"#####,
 +        r#####"
 +enum Action { Move { distance: u32 }, Stop }
 +
 +fn handle(action: Action) {
 +    match action {
 +        Action::Move { distance } if distance > 10 => foo(),
 +        _ => (),
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_move_bounds_to_where_clause() {
 +    check_doc_test(
 +        "move_bounds_to_where_clause",
 +        r#####"
 +fn apply<T, U, $0F: FnOnce(T) -> U>(f: F, x: T) -> U {
 +    f(x)
 +}
 +"#####,
 +        r#####"
 +fn apply<T, U, F>(f: F, x: T) -> U where F: FnOnce(T) -> U {
 +    f(x)
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_move_from_mod_rs() {
 +    check_doc_test(
 +        "move_from_mod_rs",
 +        r#####"
 +//- /main.rs
 +mod a;
 +//- /a/mod.rs
 +$0fn t() {}$0
 +"#####,
 +        r#####"
 +fn t() {}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_move_guard_to_arm_body() {
 +    check_doc_test(
 +        "move_guard_to_arm_body",
 +        r#####"
 +enum Action { Move { distance: u32 }, Stop }
 +
 +fn handle(action: Action) {
 +    match action {
 +        Action::Move { distance } $0if distance > 10 => foo(),
 +        _ => (),
 +    }
 +}
 +"#####,
 +        r#####"
 +enum Action { Move { distance: u32 }, Stop }
 +
 +fn handle(action: Action) {
 +    match action {
 +        Action::Move { distance } => if distance > 10 {
 +            foo()
 +        },
 +        _ => (),
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_move_module_to_file() {
 +    check_doc_test(
 +        "move_module_to_file",
 +        r#####"
 +mod $0foo {
 +    fn t() {}
 +}
 +"#####,
 +        r#####"
 +mod foo;
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_move_to_mod_rs() {
 +    check_doc_test(
 +        "move_to_mod_rs",
 +        r#####"
 +//- /main.rs
 +mod a;
 +//- /a.rs
 +$0fn t() {}$0
 +"#####,
 +        r#####"
 +fn t() {}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_promote_local_to_const() {
 +    check_doc_test(
 +        "promote_local_to_const",
 +        r#####"
 +fn main() {
 +    let foo$0 = true;
 +
 +    if foo {
 +        println!("It's true");
 +    } else {
 +        println!("It's false");
 +    }
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    const $0FOO: bool = true;
 +
 +    if FOO {
 +        println!("It's true");
 +    } else {
 +        println!("It's false");
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_pull_assignment_up() {
 +    check_doc_test(
 +        "pull_assignment_up",
 +        r#####"
 +fn main() {
 +    let mut foo = 6;
 +
 +    if true {
 +        $0foo = 5;
 +    } else {
 +        foo = 4;
 +    }
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    let mut foo = 6;
 +
 +    foo = if true {
 +        5
 +    } else {
 +        4
 +    };
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_qualify_method_call() {
 +    check_doc_test(
 +        "qualify_method_call",
 +        r#####"
 +struct Foo;
 +impl Foo {
 +    fn foo(&self) {}
 +}
 +fn main() {
 +    let foo = Foo;
 +    foo.fo$0o();
 +}
 +"#####,
 +        r#####"
 +struct Foo;
 +impl Foo {
 +    fn foo(&self) {}
 +}
 +fn main() {
 +    let foo = Foo;
 +    Foo::foo(&foo);
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_qualify_path() {
 +    check_doc_test(
 +        "qualify_path",
 +        r#####"
 +fn main() {
 +    let map = HashMap$0::new();
 +}
 +pub mod std { pub mod collections { pub struct HashMap { } } }
 +"#####,
 +        r#####"
 +fn main() {
 +    let map = std::collections::HashMap::new();
 +}
 +pub mod std { pub mod collections { pub struct HashMap { } } }
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_reformat_number_literal() {
 +    check_doc_test(
 +        "reformat_number_literal",
 +        r#####"
 +const _: i32 = 1012345$0;
 +"#####,
 +        r#####"
 +const _: i32 = 1_012_345;
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_remove_dbg() {
 +    check_doc_test(
 +        "remove_dbg",
 +        r#####"
 +fn main() {
 +    $0dbg!(92);
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    92;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_remove_hash() {
 +    check_doc_test(
 +        "remove_hash",
 +        r#####"
 +fn main() {
 +    r#"Hello,$0 World!"#;
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    r"Hello, World!";
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_remove_mut() {
 +    check_doc_test(
 +        "remove_mut",
 +        r#####"
 +impl Walrus {
 +    fn feed(&mut$0 self, amount: u32) {}
 +}
 +"#####,
 +        r#####"
 +impl Walrus {
 +    fn feed(&self, amount: u32) {}
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_remove_unused_param() {
 +    check_doc_test(
 +        "remove_unused_param",
 +        r#####"
 +fn frobnicate(x: i32$0) {}
 +
 +fn main() {
 +    frobnicate(92);
 +}
 +"#####,
 +        r#####"
 +fn frobnicate() {}
 +
 +fn main() {
 +    frobnicate();
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_reorder_fields() {
 +    check_doc_test(
 +        "reorder_fields",
 +        r#####"
 +struct Foo {foo: i32, bar: i32};
 +const test: Foo = $0Foo {bar: 0, foo: 1}
 +"#####,
 +        r#####"
 +struct Foo {foo: i32, bar: i32};
 +const test: Foo = Foo {foo: 1, bar: 0}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_reorder_impl_items() {
 +    check_doc_test(
 +        "reorder_impl_items",
 +        r#####"
 +trait Foo {
 +    type A;
 +    const B: u8;
 +    fn c();
 +}
 +
 +struct Bar;
 +$0impl Foo for Bar {
 +    const B: u8 = 17;
 +    fn c() {}
 +    type A = String;
 +}
 +"#####,
 +        r#####"
 +trait Foo {
 +    type A;
 +    const B: u8;
 +    fn c();
 +}
 +
 +struct Bar;
 +impl Foo for Bar {
 +    type A = String;
 +    const B: u8 = 17;
 +    fn c() {}
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_replace_char_with_string() {
 +    check_doc_test(
 +        "replace_char_with_string",
 +        r#####"
 +fn main() {
 +    find('{$0');
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    find("{");
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_replace_derive_with_manual_impl() {
 +    check_doc_test(
 +        "replace_derive_with_manual_impl",
 +        r#####"
 +//- minicore: derive
 +trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
 +#[derive(Deb$0ug, Display)]
 +struct S;
 +"#####,
 +        r#####"
 +trait Debug { fn fmt(&self, f: &mut Formatter) -> Result<()>; }
 +#[derive(Display)]
 +struct S;
 +
 +impl Debug for S {
 +    $0fn fmt(&self, f: &mut Formatter) -> Result<()> {
 +        f.debug_struct("S").finish()
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_replace_if_let_with_match() {
 +    check_doc_test(
 +        "replace_if_let_with_match",
 +        r#####"
 +enum Action { Move { distance: u32 }, Stop }
 +
 +fn handle(action: Action) {
 +    $0if let Action::Move { distance } = action {
 +        foo(distance)
 +    } else {
 +        bar()
 +    }
 +}
 +"#####,
 +        r#####"
 +enum Action { Move { distance: u32 }, Stop }
 +
 +fn handle(action: Action) {
 +    match action {
 +        Action::Move { distance } => foo(distance),
 +        _ => bar(),
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_replace_let_with_if_let() {
 +    check_doc_test(
 +        "replace_let_with_if_let",
 +        r#####"
 +enum Option<T> { Some(T), None }
 +
 +fn main(action: Action) {
 +    $0let x = compute();
 +}
 +
 +fn compute() -> Option<i32> { None }
 +"#####,
 +        r#####"
 +enum Option<T> { Some(T), None }
 +
 +fn main(action: Action) {
 +    if let Some(x) = compute() {
 +    }
 +}
 +
 +fn compute() -> Option<i32> { None }
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_replace_match_with_if_let() {
 +    check_doc_test(
 +        "replace_match_with_if_let",
 +        r#####"
 +enum Action { Move { distance: u32 }, Stop }
 +
 +fn handle(action: Action) {
 +    $0match action {
 +        Action::Move { distance } => foo(distance),
 +        _ => bar(),
 +    }
 +}
 +"#####,
 +        r#####"
 +enum Action { Move { distance: u32 }, Stop }
 +
 +fn handle(action: Action) {
 +    if let Action::Move { distance } = action {
 +        foo(distance)
 +    } else {
 +        bar()
 +    }
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_replace_qualified_name_with_use() {
 +    check_doc_test(
 +        "replace_qualified_name_with_use",
 +        r#####"
 +mod std { pub mod collections { pub struct HashMap<T, U>(T, U); } }
 +fn process(map: std::collections::$0HashMap<String, String>) {}
 +"#####,
 +        r#####"
 +use std::collections::HashMap;
 +
 +mod std { pub mod collections { pub struct HashMap<T, U>(T, U); } }
 +fn process(map: HashMap<String, String>) {}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_replace_string_with_char() {
 +    check_doc_test(
 +        "replace_string_with_char",
 +        r#####"
 +fn main() {
 +    find("{$0");
 +}
 +"#####,
 +        r#####"
 +fn main() {
 +    find('{');
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_replace_try_expr_with_match() {
 +    check_doc_test(
 +        "replace_try_expr_with_match",
 +        r#####"
 +//- minicore:option
 +fn handle() {
 +    let pat = Some(true)$0?;
 +}
 +"#####,
 +        r#####"
 +fn handle() {
 +    let pat = match Some(true) {
 +        Some(it) => it,
 +        None => return None,
 +    };
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_replace_turbofish_with_explicit_type() {
 +    check_doc_test(
 +        "replace_turbofish_with_explicit_type",
 +        r#####"
 +fn make<T>() -> T { ) }
 +fn main() {
 +    let a = make$0::<i32>();
 +}
 +"#####,
 +        r#####"
 +fn make<T>() -> T { ) }
 +fn main() {
 +    let a: i32 = make();
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_sort_items() {
 +    check_doc_test(
 +        "sort_items",
 +        r#####"
 +struct $0Foo$0 { second: u32, first: String }
 +"#####,
 +        r#####"
 +struct Foo { first: String, second: u32 }
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_sort_items_1() {
 +    check_doc_test(
 +        "sort_items",
 +        r#####"
 +trait $0Bar$0 {
 +    fn second(&self) -> u32;
 +    fn first(&self) -> String;
 +}
 +"#####,
 +        r#####"
 +trait Bar {
 +    fn first(&self) -> String;
 +    fn second(&self) -> u32;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_sort_items_2() {
 +    check_doc_test(
 +        "sort_items",
 +        r#####"
 +struct Baz;
 +impl $0Baz$0 {
 +    fn second(&self) -> u32;
 +    fn first(&self) -> String;
 +}
 +"#####,
 +        r#####"
 +struct Baz;
 +impl Baz {
 +    fn first(&self) -> String;
 +    fn second(&self) -> u32;
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_sort_items_3() {
 +    check_doc_test(
 +        "sort_items",
 +        r#####"
 +enum $0Animal$0 {
 +  Dog(String, f64),
 +  Cat { weight: f64, name: String },
 +}
 +"#####,
 +        r#####"
 +enum Animal {
 +  Cat { weight: f64, name: String },
 +  Dog(String, f64),
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_sort_items_4() {
 +    check_doc_test(
 +        "sort_items",
 +        r#####"
 +enum Animal {
 +  Dog(String, f64),
 +  Cat $0{ weight: f64, name: String }$0,
 +}
 +"#####,
 +        r#####"
 +enum Animal {
 +  Dog(String, f64),
 +  Cat { name: String, weight: f64 },
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_split_import() {
 +    check_doc_test(
 +        "split_import",
 +        r#####"
 +use std::$0collections::HashMap;
 +"#####,
 +        r#####"
 +use std::{collections::HashMap};
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_toggle_ignore() {
 +    check_doc_test(
 +        "toggle_ignore",
 +        r#####"
 +$0#[test]
 +fn arithmetics {
 +    assert_eq!(2 + 2, 5);
 +}
 +"#####,
 +        r#####"
 +#[test]
 +#[ignore]
 +fn arithmetics {
 +    assert_eq!(2 + 2, 5);
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_unmerge_use() {
 +    check_doc_test(
 +        "unmerge_use",
 +        r#####"
 +use std::fmt::{Debug, Display$0};
 +"#####,
 +        r#####"
 +use std::fmt::{Debug};
 +use std::fmt::Display;
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_unnecessary_async() {
 +    check_doc_test(
 +        "unnecessary_async",
 +        r#####"
 +pub async f$0n foo() {}
 +pub async fn bar() { foo().await }
 +"#####,
 +        r#####"
 +pub fn foo() {}
 +pub async fn bar() { foo() }
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_unwrap_block() {
 +    check_doc_test(
 +        "unwrap_block",
 +        r#####"
 +fn foo() {
 +    if true {$0
 +        println!("foo");
 +    }
 +}
 +"#####,
 +        r#####"
 +fn foo() {
 +    println!("foo");
 +}
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_unwrap_result_return_type() {
 +    check_doc_test(
 +        "unwrap_result_return_type",
 +        r#####"
 +//- minicore: result
 +fn foo() -> Result<i32>$0 { Ok(42i32) }
 +"#####,
 +        r#####"
 +fn foo() -> i32 { 42i32 }
 +"#####,
 +    )
 +}
 +
 +#[test]
 +fn doctest_wrap_return_type_in_result() {
 +    check_doc_test(
 +        "wrap_return_type_in_result",
 +        r#####"
 +//- minicore: result
 +fn foo() -> i32$0 { 42i32 }
 +"#####,
 +        r#####"
 +fn foo() -> Result<i32, ${0:_}> { Ok(42i32) }
 +"#####,
 +    )
 +}
index 149afcac9d4786e5bc38bf93b4cfdefb72c04021,0000000000000000000000000000000000000000..72579e6026aee736868f1ae64bbdc310b00b46cd
mode 100644,000000..100644
--- /dev/null
@@@ -1,682 -1,0 +1,691 @@@
-             self.add_variant_pat(ctx, pat_ctx, variant, local_name);
 +//! This module defines an accumulator for completions which are going to be presented to user.
 +
 +pub(crate) mod attribute;
 +pub(crate) mod dot;
 +pub(crate) mod expr;
 +pub(crate) mod extern_abi;
 +pub(crate) mod field;
 +pub(crate) mod flyimport;
 +pub(crate) mod fn_param;
 +pub(crate) mod format_string;
 +pub(crate) mod item_list;
 +pub(crate) mod keyword;
 +pub(crate) mod lifetime;
 +pub(crate) mod mod_;
 +pub(crate) mod pattern;
 +pub(crate) mod postfix;
 +pub(crate) mod record;
 +pub(crate) mod snippet;
 +pub(crate) mod r#type;
 +pub(crate) mod use_;
 +pub(crate) mod vis;
 +
 +use std::iter;
 +
 +use hir::{known, ScopeDef};
 +use ide_db::{imports::import_assets::LocatedImport, SymbolKind};
 +use syntax::ast;
 +
 +use crate::{
 +    context::{
 +        DotAccess, ItemListKind, NameContext, NameKind, NameRefContext, NameRefKind,
 +        PathCompletionCtx, PathKind, PatternContext, TypeLocation, Visible,
 +    },
 +    item::Builder,
 +    render::{
 +        const_::render_const,
 +        function::{render_fn, render_method},
 +        literal::{render_struct_literal, render_variant_lit},
 +        macro_::render_macro,
 +        pattern::{render_struct_pat, render_variant_pat},
 +        render_field, render_path_resolution, render_pattern_resolution, render_tuple_field,
 +        type_alias::{render_type_alias, render_type_alias_with_eq},
 +        union_literal::render_union_literal,
 +        RenderContext,
 +    },
 +    CompletionContext, CompletionItem, CompletionItemKind,
 +};
 +
 +/// Represents an in-progress set of completions being built.
 +#[derive(Debug, Default)]
 +pub struct Completions {
 +    buf: Vec<CompletionItem>,
 +}
 +
 +impl From<Completions> for Vec<CompletionItem> {
 +    fn from(val: Completions) -> Self {
 +        val.buf
 +    }
 +}
 +
 +impl Builder {
 +    /// Convenience method, which allows to add a freshly created completion into accumulator
 +    /// without binding it to the variable.
 +    pub(crate) fn add_to(self, acc: &mut Completions) {
 +        acc.add(self.build())
 +    }
 +}
 +
 +impl Completions {
 +    fn add(&mut self, item: CompletionItem) {
 +        self.buf.push(item)
 +    }
 +
 +    fn add_opt(&mut self, item: Option<CompletionItem>) {
 +        if let Some(item) = item {
 +            self.buf.push(item)
 +        }
 +    }
 +
 +    pub(crate) fn add_all<I>(&mut self, items: I)
 +    where
 +        I: IntoIterator,
 +        I::Item: Into<CompletionItem>,
 +    {
 +        items.into_iter().for_each(|item| self.add(item.into()))
 +    }
 +
 +    pub(crate) fn add_keyword(&mut self, ctx: &CompletionContext<'_>, keyword: &'static str) {
 +        let item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), keyword);
 +        item.add_to(self);
 +    }
 +
 +    pub(crate) fn add_nameref_keywords_with_colon(&mut self, ctx: &CompletionContext<'_>) {
 +        ["self::", "crate::"].into_iter().for_each(|kw| self.add_keyword(ctx, kw));
 +
 +        if ctx.depth_from_crate_root > 0 {
 +            self.add_keyword(ctx, "super::");
 +        }
 +    }
 +
 +    pub(crate) fn add_nameref_keywords(&mut self, ctx: &CompletionContext<'_>) {
 +        ["self", "crate"].into_iter().for_each(|kw| self.add_keyword(ctx, kw));
 +
 +        if ctx.depth_from_crate_root > 0 {
 +            self.add_keyword(ctx, "super");
 +        }
 +    }
 +
 +    pub(crate) fn add_super_keyword(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        super_chain_len: Option<usize>,
 +    ) {
 +        if let Some(len) = super_chain_len {
 +            if len > 0 && len < ctx.depth_from_crate_root {
 +                self.add_keyword(ctx, "super::");
 +            }
 +        }
 +    }
 +
 +    pub(crate) fn add_keyword_snippet_expr(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        incomplete_let: bool,
 +        kw: &str,
 +        snippet: &str,
 +    ) {
 +        let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
 +
 +        match ctx.config.snippet_cap {
 +            Some(cap) => {
 +                if incomplete_let && snippet.ends_with('}') {
 +                    // complete block expression snippets with a trailing semicolon, if inside an incomplete let
 +                    cov_mark::hit!(let_semi);
 +                    item.insert_snippet(cap, format!("{};", snippet));
 +                } else {
 +                    item.insert_snippet(cap, snippet);
 +                }
 +            }
 +            None => {
 +                item.insert_text(if snippet.contains('$') { kw } else { snippet });
 +            }
 +        };
 +        item.add_to(self);
 +    }
 +
 +    pub(crate) fn add_keyword_snippet(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        kw: &str,
 +        snippet: &str,
 +    ) {
 +        let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);
 +
 +        match ctx.config.snippet_cap {
 +            Some(cap) => item.insert_snippet(cap, snippet),
 +            None => item.insert_text(if snippet.contains('$') { kw } else { snippet }),
 +        };
 +        item.add_to(self);
 +    }
 +
 +    pub(crate) fn add_crate_roots(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        path_ctx: &PathCompletionCtx,
 +    ) {
 +        ctx.process_all_names(&mut |name, res| match res {
 +            ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) if m.is_crate_root(ctx.db) => {
 +                self.add_module(ctx, path_ctx, m, name);
 +            }
 +            _ => (),
 +        });
 +    }
 +
 +    pub(crate) fn add_path_resolution(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        path_ctx: &PathCompletionCtx,
 +        local_name: hir::Name,
 +        resolution: hir::ScopeDef,
 +    ) {
 +        let is_private_editable = match ctx.def_is_visible(&resolution) {
 +            Visible::Yes => false,
 +            Visible::Editable => true,
 +            Visible::No => return,
 +        };
 +        self.add(
 +            render_path_resolution(
 +                RenderContext::new(ctx).private_editable(is_private_editable),
 +                path_ctx,
 +                local_name,
 +                resolution,
 +            )
 +            .build(),
 +        );
 +    }
 +
 +    pub(crate) fn add_pattern_resolution(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        pattern_ctx: &PatternContext,
 +        local_name: hir::Name,
 +        resolution: hir::ScopeDef,
 +    ) {
 +        let is_private_editable = match ctx.def_is_visible(&resolution) {
 +            Visible::Yes => false,
 +            Visible::Editable => true,
 +            Visible::No => return,
 +        };
 +        self.add(
 +            render_pattern_resolution(
 +                RenderContext::new(ctx).private_editable(is_private_editable),
 +                pattern_ctx,
 +                local_name,
 +                resolution,
 +            )
 +            .build(),
 +        );
 +    }
 +
 +    pub(crate) fn add_enum_variants(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        path_ctx: &PathCompletionCtx,
 +        e: hir::Enum,
 +    ) {
 +        e.variants(ctx.db)
 +            .into_iter()
 +            .for_each(|variant| self.add_enum_variant(ctx, path_ctx, variant, None));
 +    }
 +
 +    pub(crate) fn add_module(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        path_ctx: &PathCompletionCtx,
 +        module: hir::Module,
 +        local_name: hir::Name,
 +    ) {
 +        self.add_path_resolution(
 +            ctx,
 +            path_ctx,
 +            local_name,
 +            hir::ScopeDef::ModuleDef(module.into()),
 +        );
 +    }
 +
 +    pub(crate) fn add_macro(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        path_ctx: &PathCompletionCtx,
 +        mac: hir::Macro,
 +        local_name: hir::Name,
 +    ) {
 +        let is_private_editable = match ctx.is_visible(&mac) {
 +            Visible::Yes => false,
 +            Visible::Editable => true,
 +            Visible::No => return,
 +        };
 +        self.add(
 +            render_macro(
 +                RenderContext::new(ctx).private_editable(is_private_editable),
 +                path_ctx,
 +                local_name,
 +                mac,
 +            )
 +            .build(),
 +        );
 +    }
 +
 +    pub(crate) fn add_function(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        path_ctx: &PathCompletionCtx,
 +        func: hir::Function,
 +        local_name: Option<hir::Name>,
 +    ) {
 +        let is_private_editable = match ctx.is_visible(&func) {
 +            Visible::Yes => false,
 +            Visible::Editable => true,
 +            Visible::No => return,
 +        };
 +        self.add(
 +            render_fn(
 +                RenderContext::new(ctx).private_editable(is_private_editable),
 +                path_ctx,
 +                local_name,
 +                func,
 +            )
 +            .build(),
 +        );
 +    }
 +
 +    pub(crate) fn add_method(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        dot_access: &DotAccess,
 +        func: hir::Function,
 +        receiver: Option<hir::Name>,
 +        local_name: Option<hir::Name>,
 +    ) {
 +        let is_private_editable = match ctx.is_visible(&func) {
 +            Visible::Yes => false,
 +            Visible::Editable => true,
 +            Visible::No => return,
 +        };
 +        self.add(
 +            render_method(
 +                RenderContext::new(ctx).private_editable(is_private_editable),
 +                dot_access,
 +                receiver,
 +                local_name,
 +                func,
 +            )
 +            .build(),
 +        );
 +    }
 +
 +    pub(crate) fn add_method_with_import(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        dot_access: &DotAccess,
 +        func: hir::Function,
 +        import: LocatedImport,
 +    ) {
 +        let is_private_editable = match ctx.is_visible(&func) {
 +            Visible::Yes => false,
 +            Visible::Editable => true,
 +            Visible::No => return,
 +        };
 +        self.add(
 +            render_method(
 +                RenderContext::new(ctx)
 +                    .private_editable(is_private_editable)
 +                    .import_to_add(Some(import)),
 +                dot_access,
 +                None,
 +                None,
 +                func,
 +            )
 +            .build(),
 +        );
 +    }
 +
 +    pub(crate) fn add_const(&mut self, ctx: &CompletionContext<'_>, konst: hir::Const) {
 +        let is_private_editable = match ctx.is_visible(&konst) {
 +            Visible::Yes => false,
 +            Visible::Editable => true,
 +            Visible::No => return,
 +        };
 +        self.add_opt(render_const(
 +            RenderContext::new(ctx).private_editable(is_private_editable),
 +            konst,
 +        ));
 +    }
 +
 +    pub(crate) fn add_type_alias(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        type_alias: hir::TypeAlias,
 +    ) {
 +        let is_private_editable = match ctx.is_visible(&type_alias) {
 +            Visible::Yes => false,
 +            Visible::Editable => true,
 +            Visible::No => return,
 +        };
 +        self.add_opt(render_type_alias(
 +            RenderContext::new(ctx).private_editable(is_private_editable),
 +            type_alias,
 +        ));
 +    }
 +
 +    pub(crate) fn add_type_alias_with_eq(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        type_alias: hir::TypeAlias,
 +    ) {
 +        self.add_opt(render_type_alias_with_eq(RenderContext::new(ctx), type_alias));
 +    }
 +
 +    pub(crate) fn add_qualified_enum_variant(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        path_ctx: &PathCompletionCtx,
 +        variant: hir::Variant,
 +        path: hir::ModPath,
 +    ) {
 +        if let Some(builder) =
 +            render_variant_lit(RenderContext::new(ctx), path_ctx, None, variant, Some(path))
 +        {
 +            self.add(builder.build());
 +        }
 +    }
 +
 +    pub(crate) fn add_enum_variant(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        path_ctx: &PathCompletionCtx,
 +        variant: hir::Variant,
 +        local_name: Option<hir::Name>,
 +    ) {
 +        if let PathCompletionCtx { kind: PathKind::Pat { pat_ctx }, .. } = path_ctx {
 +            cov_mark::hit!(enum_variant_pattern_path);
-         self.add_opt(render_variant_pat(RenderContext::new(ctx), pattern_ctx, variant, None, path));
++            self.add_variant_pat(ctx, pat_ctx, Some(path_ctx), variant, local_name);
 +            return;
 +        }
 +
 +        if let Some(builder) =
 +            render_variant_lit(RenderContext::new(ctx), path_ctx, local_name, variant, None)
 +        {
 +            self.add(builder.build());
 +        }
 +    }
 +
 +    pub(crate) fn add_field(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        dot_access: &DotAccess,
 +        receiver: Option<hir::Name>,
 +        field: hir::Field,
 +        ty: &hir::Type,
 +    ) {
 +        let is_private_editable = match ctx.is_visible(&field) {
 +            Visible::Yes => false,
 +            Visible::Editable => true,
 +            Visible::No => return,
 +        };
 +        let item = render_field(
 +            RenderContext::new(ctx).private_editable(is_private_editable),
 +            dot_access,
 +            receiver,
 +            field,
 +            ty,
 +        );
 +        self.add(item);
 +    }
 +
 +    pub(crate) fn add_struct_literal(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        path_ctx: &PathCompletionCtx,
 +        strukt: hir::Struct,
 +        path: Option<hir::ModPath>,
 +        local_name: Option<hir::Name>,
 +    ) {
 +        if let Some(builder) =
 +            render_struct_literal(RenderContext::new(ctx), path_ctx, strukt, path, local_name)
 +        {
 +            self.add(builder.build());
 +        }
 +    }
 +
 +    pub(crate) fn add_union_literal(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        un: hir::Union,
 +        path: Option<hir::ModPath>,
 +        local_name: Option<hir::Name>,
 +    ) {
 +        let item = render_union_literal(RenderContext::new(ctx), un, path, local_name);
 +        self.add_opt(item);
 +    }
 +
 +    pub(crate) fn add_tuple_field(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        receiver: Option<hir::Name>,
 +        field: usize,
 +        ty: &hir::Type,
 +    ) {
 +        let item = render_tuple_field(RenderContext::new(ctx), receiver, field, ty);
 +        self.add(item);
 +    }
 +
 +    pub(crate) fn add_lifetime(&mut self, ctx: &CompletionContext<'_>, name: hir::Name) {
 +        CompletionItem::new(SymbolKind::LifetimeParam, ctx.source_range(), name.to_smol_str())
 +            .add_to(self)
 +    }
 +
 +    pub(crate) fn add_label(&mut self, ctx: &CompletionContext<'_>, name: hir::Name) {
 +        CompletionItem::new(SymbolKind::Label, ctx.source_range(), name.to_smol_str()).add_to(self)
 +    }
 +
 +    pub(crate) fn add_variant_pat(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        pattern_ctx: &PatternContext,
++        path_ctx: Option<&PathCompletionCtx>,
 +        variant: hir::Variant,
 +        local_name: Option<hir::Name>,
 +    ) {
 +        self.add_opt(render_variant_pat(
 +            RenderContext::new(ctx),
 +            pattern_ctx,
++            path_ctx,
 +            variant,
 +            local_name.clone(),
 +            None,
 +        ));
 +    }
 +
 +    pub(crate) fn add_qualified_variant_pat(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        pattern_ctx: &PatternContext,
 +        variant: hir::Variant,
 +        path: hir::ModPath,
 +    ) {
 +        let path = Some(&path);
++        self.add_opt(render_variant_pat(
++            RenderContext::new(ctx),
++            pattern_ctx,
++            None,
++            variant,
++            None,
++            path,
++        ));
 +    }
 +
 +    pub(crate) fn add_struct_pat(
 +        &mut self,
 +        ctx: &CompletionContext<'_>,
 +        pattern_ctx: &PatternContext,
 +        strukt: hir::Struct,
 +        local_name: Option<hir::Name>,
 +    ) {
 +        self.add_opt(render_struct_pat(RenderContext::new(ctx), pattern_ctx, strukt, local_name));
 +    }
 +}
 +
 +/// Calls the callback for each variant of the provided enum with the path to the variant.
 +/// Skips variants that are visible with single segment paths.
 +fn enum_variants_with_paths(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    enum_: hir::Enum,
 +    impl_: &Option<ast::Impl>,
 +    cb: impl Fn(&mut Completions, &CompletionContext<'_>, hir::Variant, hir::ModPath),
 +) {
 +    let variants = enum_.variants(ctx.db);
 +
 +    if let Some(impl_) = impl_.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) {
 +        if impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_)) {
 +            for &variant in &variants {
 +                let self_path = hir::ModPath::from_segments(
 +                    hir::PathKind::Plain,
 +                    iter::once(known::SELF_TYPE).chain(iter::once(variant.name(ctx.db))),
 +                );
 +                cb(acc, ctx, variant, self_path);
 +            }
 +        }
 +    }
 +
 +    for variant in variants {
 +        if let Some(path) = ctx.module.find_use_path(ctx.db, hir::ModuleDef::from(variant)) {
 +            // Variants with trivial paths are already added by the existing completion logic,
 +            // so we should avoid adding these twice
 +            if path.segments().len() > 1 {
 +                cb(acc, ctx, variant, path);
 +            }
 +        }
 +    }
 +}
 +
 +pub(super) fn complete_name(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    NameContext { name, kind }: &NameContext,
 +) {
 +    match kind {
 +        NameKind::Const => {
 +            item_list::trait_impl::complete_trait_impl_const(acc, ctx, name);
 +        }
 +        NameKind::Function => {
 +            item_list::trait_impl::complete_trait_impl_fn(acc, ctx, name);
 +        }
 +        NameKind::IdentPat(pattern_ctx) => {
 +            if ctx.token.kind() != syntax::T![_] {
 +                complete_patterns(acc, ctx, pattern_ctx)
 +            }
 +        }
 +        NameKind::Module(mod_under_caret) => {
 +            mod_::complete_mod(acc, ctx, mod_under_caret);
 +        }
 +        NameKind::TypeAlias => {
 +            item_list::trait_impl::complete_trait_impl_type_alias(acc, ctx, name);
 +        }
 +        NameKind::RecordField => {
 +            field::complete_field_list_record_variant(acc, ctx);
 +        }
 +        NameKind::ConstParam
 +        | NameKind::Enum
 +        | NameKind::MacroDef
 +        | NameKind::MacroRules
 +        | NameKind::Rename
 +        | NameKind::SelfParam
 +        | NameKind::Static
 +        | NameKind::Struct
 +        | NameKind::Trait
 +        | NameKind::TypeParam
 +        | NameKind::Union
 +        | NameKind::Variant => (),
 +    }
 +}
 +
 +pub(super) fn complete_name_ref(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    NameRefContext { nameref, kind }: &NameRefContext,
 +) {
 +    match kind {
 +        NameRefKind::Path(path_ctx) => {
 +            flyimport::import_on_the_fly_path(acc, ctx, path_ctx);
 +
 +            match &path_ctx.kind {
 +                PathKind::Expr { expr_ctx } => {
 +                    expr::complete_expr_path(acc, ctx, path_ctx, expr_ctx);
 +
 +                    dot::complete_undotted_self(acc, ctx, path_ctx, expr_ctx);
 +                    item_list::complete_item_list_in_expr(acc, ctx, path_ctx, expr_ctx);
 +                    record::complete_record_expr_func_update(acc, ctx, path_ctx, expr_ctx);
 +                    snippet::complete_expr_snippet(acc, ctx, path_ctx, expr_ctx);
 +                }
 +                PathKind::Type { location } => {
 +                    r#type::complete_type_path(acc, ctx, path_ctx, location);
 +
 +                    match location {
 +                        TypeLocation::TupleField => {
 +                            field::complete_field_list_tuple_variant(acc, ctx, path_ctx);
 +                        }
 +                        TypeLocation::TypeAscription(ascription) => {
 +                            r#type::complete_ascribed_type(acc, ctx, path_ctx, ascription);
 +                        }
 +                        TypeLocation::GenericArgList(_)
 +                        | TypeLocation::TypeBound
 +                        | TypeLocation::ImplTarget
 +                        | TypeLocation::ImplTrait
 +                        | TypeLocation::Other => (),
 +                    }
 +                }
 +                PathKind::Attr { attr_ctx } => {
 +                    attribute::complete_attribute_path(acc, ctx, path_ctx, attr_ctx);
 +                }
 +                PathKind::Derive { existing_derives } => {
 +                    attribute::complete_derive_path(acc, ctx, path_ctx, existing_derives);
 +                }
 +                PathKind::Item { kind } => {
 +                    item_list::complete_item_list(acc, ctx, path_ctx, kind);
 +
 +                    snippet::complete_item_snippet(acc, ctx, path_ctx, kind);
 +                    if let ItemListKind::TraitImpl(impl_) = kind {
 +                        item_list::trait_impl::complete_trait_impl_item_by_name(
 +                            acc, ctx, path_ctx, nameref, impl_,
 +                        );
 +                    }
 +                }
 +                PathKind::Pat { .. } => {
 +                    pattern::complete_pattern_path(acc, ctx, path_ctx);
 +                }
 +                PathKind::Vis { has_in_token } => {
 +                    vis::complete_vis_path(acc, ctx, path_ctx, has_in_token);
 +                }
 +                PathKind::Use => {
 +                    use_::complete_use_path(acc, ctx, path_ctx, nameref);
 +                }
 +            }
 +        }
 +        NameRefKind::DotAccess(dot_access) => {
 +            flyimport::import_on_the_fly_dot(acc, ctx, dot_access);
 +            dot::complete_dot(acc, ctx, dot_access);
 +            postfix::complete_postfix(acc, ctx, dot_access);
 +        }
 +        NameRefKind::Keyword(item) => {
 +            keyword::complete_for_and_where(acc, ctx, item);
 +        }
 +        NameRefKind::RecordExpr { dot_prefix, expr } => {
 +            record::complete_record_expr_fields(acc, ctx, expr, dot_prefix);
 +        }
 +        NameRefKind::Pattern(pattern_ctx) => complete_patterns(acc, ctx, pattern_ctx),
 +    }
 +}
 +
 +fn complete_patterns(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    pattern_ctx: &PatternContext,
 +) {
 +    flyimport::import_on_the_fly_pat(acc, ctx, pattern_ctx);
 +    fn_param::complete_fn_param(acc, ctx, pattern_ctx);
 +    pattern::complete_pattern(acc, ctx, pattern_ctx);
 +    record::complete_record_pattern_fields(acc, ctx, pattern_ctx);
 +}
index 1d8a8c5f20db35828438e90abaa8bd1b6dbbed27,0000000000000000000000000000000000000000..d9fe94cb44ee1d3d5e3d4573d5d6e696f411c67b
mode 100644,000000..100644
--- /dev/null
@@@ -1,380 -1,0 +1,380 @@@
-         Qualified::Infer | Qualified::With { .. } => {}
 +//! Completion for (built-in) attributes, derives and lints.
 +//!
 +//! This module uses a bit of static metadata to provide completions for builtin-in attributes and lints.
 +
 +use ide_db::{
 +    generated::lints::{
 +        Lint, CLIPPY_LINTS, CLIPPY_LINT_GROUPS, DEFAULT_LINTS, FEATURES, RUSTDOC_LINTS,
 +    },
 +    syntax_helpers::node_ext::parse_tt_as_comma_sep_paths,
 +    FxHashMap, SymbolKind,
 +};
 +use itertools::Itertools;
 +use once_cell::sync::Lazy;
 +use syntax::{
 +    ast::{self, AttrKind},
 +    AstNode, SyntaxKind, T,
 +};
 +
 +use crate::{
 +    context::{AttrCtx, CompletionContext, PathCompletionCtx, Qualified},
 +    item::CompletionItem,
 +    Completions,
 +};
 +
 +mod cfg;
 +mod derive;
 +mod lint;
 +mod repr;
 +
 +pub(crate) use self::derive::complete_derive_path;
 +
 +/// Complete inputs to known builtin attributes as well as derive attributes
 +pub(crate) fn complete_known_attribute_input(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    &colon_prefix: &bool,
 +    fake_attribute_under_caret: &ast::Attr,
 +) -> Option<()> {
 +    let attribute = fake_attribute_under_caret;
 +    let name_ref = match attribute.path() {
 +        Some(p) => Some(p.as_single_name_ref()?),
 +        None => None,
 +    };
 +    let (path, tt) = name_ref.zip(attribute.token_tree())?;
 +    if tt.l_paren_token().is_none() {
 +        return None;
 +    }
 +
 +    match path.text().as_str() {
 +        "repr" => repr::complete_repr(acc, ctx, tt),
 +        "feature" => {
 +            lint::complete_lint(acc, ctx, colon_prefix, &parse_tt_as_comma_sep_paths(tt)?, FEATURES)
 +        }
 +        "allow" | "warn" | "deny" | "forbid" => {
 +            let existing_lints = parse_tt_as_comma_sep_paths(tt)?;
 +
 +            let lints: Vec<Lint> = CLIPPY_LINT_GROUPS
 +                .iter()
 +                .map(|g| &g.lint)
 +                .chain(DEFAULT_LINTS)
 +                .chain(CLIPPY_LINTS)
 +                .chain(RUSTDOC_LINTS)
 +                .cloned()
 +                .collect();
 +
 +            lint::complete_lint(acc, ctx, colon_prefix, &existing_lints, &lints);
 +        }
 +        "cfg" => cfg::complete_cfg(acc, ctx),
 +        _ => (),
 +    }
 +    Some(())
 +}
 +
 +pub(crate) fn complete_attribute_path(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
 +    &AttrCtx { kind, annotated_item_kind }: &AttrCtx,
 +) {
 +    let is_inner = kind == AttrKind::Inner;
 +
 +    match qualified {
 +        Qualified::With {
 +            resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),
 +            super_chain_len,
 +            ..
 +        } => {
 +            acc.add_super_keyword(ctx, *super_chain_len);
 +
 +            for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
 +                match def {
 +                    hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_attr(ctx.db) => {
 +                        acc.add_macro(ctx, path_ctx, m, name)
 +                    }
 +                    hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => {
 +                        acc.add_module(ctx, path_ctx, m, name)
 +                    }
 +                    _ => (),
 +                }
 +            }
 +            return;
 +        }
 +        // fresh use tree with leading colon2, only show crate roots
 +        Qualified::Absolute => acc.add_crate_roots(ctx, path_ctx),
 +        // only show modules in a fresh UseTree
 +        Qualified::No => {
 +            ctx.process_all_names(&mut |name, def| match def {
 +                hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_attr(ctx.db) => {
 +                    acc.add_macro(ctx, path_ctx, m, name)
 +                }
 +                hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => {
 +                    acc.add_module(ctx, path_ctx, m, name)
 +                }
 +                _ => (),
 +            });
 +            acc.add_nameref_keywords_with_colon(ctx);
 +        }
++        Qualified::TypeAnchor { .. } | Qualified::With { .. } => {}
 +    }
 +
 +    let attributes = annotated_item_kind.and_then(|kind| {
 +        if ast::Expr::can_cast(kind) {
 +            Some(EXPR_ATTRIBUTES)
 +        } else {
 +            KIND_TO_ATTRIBUTES.get(&kind).copied()
 +        }
 +    });
 +
 +    let add_completion = |attr_completion: &AttrCompletion| {
 +        let mut item =
 +            CompletionItem::new(SymbolKind::Attribute, ctx.source_range(), attr_completion.label);
 +
 +        if let Some(lookup) = attr_completion.lookup {
 +            item.lookup_by(lookup);
 +        }
 +
 +        if let Some((snippet, cap)) = attr_completion.snippet.zip(ctx.config.snippet_cap) {
 +            item.insert_snippet(cap, snippet);
 +        }
 +
 +        if is_inner || !attr_completion.prefer_inner {
 +            item.add_to(acc);
 +        }
 +    };
 +
 +    match attributes {
 +        Some(applicable) => applicable
 +            .iter()
 +            .flat_map(|name| ATTRIBUTES.binary_search_by(|attr| attr.key().cmp(name)).ok())
 +            .flat_map(|idx| ATTRIBUTES.get(idx))
 +            .for_each(add_completion),
 +        None if is_inner => ATTRIBUTES.iter().for_each(add_completion),
 +        None => ATTRIBUTES.iter().filter(|compl| !compl.prefer_inner).for_each(add_completion),
 +    }
 +}
 +
 +struct AttrCompletion {
 +    label: &'static str,
 +    lookup: Option<&'static str>,
 +    snippet: Option<&'static str>,
 +    prefer_inner: bool,
 +}
 +
 +impl AttrCompletion {
 +    fn key(&self) -> &'static str {
 +        self.lookup.unwrap_or(self.label)
 +    }
 +
 +    const fn prefer_inner(self) -> AttrCompletion {
 +        AttrCompletion { prefer_inner: true, ..self }
 +    }
 +}
 +
 +const fn attr(
 +    label: &'static str,
 +    lookup: Option<&'static str>,
 +    snippet: Option<&'static str>,
 +) -> AttrCompletion {
 +    AttrCompletion { label, lookup, snippet, prefer_inner: false }
 +}
 +
 +macro_rules! attrs {
 +    // attributes applicable to all items
 +    [@ { item $($tt:tt)* } {$($acc:tt)*}] => {
 +        attrs!(@ { $($tt)* } { $($acc)*, "deprecated", "doc", "dochidden", "docalias", "must_use", "no_mangle" })
 +    };
 +    // attributes applicable to all adts
 +    [@ { adt $($tt:tt)* } {$($acc:tt)*}] => {
 +        attrs!(@ { $($tt)* } { $($acc)*, "derive", "repr" })
 +    };
 +    // attributes applicable to all linkable things aka functions/statics
 +    [@ { linkable $($tt:tt)* } {$($acc:tt)*}] => {
 +        attrs!(@ { $($tt)* } { $($acc)*, "export_name", "link_name", "link_section" })
 +    };
 +    // error fallback for nicer error message
 +    [@ { $ty:ident $($tt:tt)* } {$($acc:tt)*}] => {
 +        compile_error!(concat!("unknown attr subtype ", stringify!($ty)))
 +    };
 +    // general push down accumulation
 +    [@ { $lit:literal $($tt:tt)*} {$($acc:tt)*}] => {
 +        attrs!(@ { $($tt)* } { $($acc)*, $lit })
 +    };
 +    [@ {$($tt:tt)+} {$($tt2:tt)*}] => {
 +        compile_error!(concat!("Unexpected input ", stringify!($($tt)+)))
 +    };
 +    // final output construction
 +    [@ {} {$($tt:tt)*}] => { &[$($tt)*] as _ };
 +    // starting matcher
 +    [$($tt:tt),*] => {
 +        attrs!(@ { $($tt)* } { "allow", "cfg", "cfg_attr", "deny", "forbid", "warn" })
 +    };
 +}
 +
 +#[rustfmt::skip]
 +static KIND_TO_ATTRIBUTES: Lazy<FxHashMap<SyntaxKind, &[&str]>> = Lazy::new(|| {
 +    use SyntaxKind::*;
 +    [
 +        (
 +            SOURCE_FILE,
 +            attrs!(
 +                item,
 +                "crate_name", "feature", "no_implicit_prelude", "no_main", "no_std",
 +                "recursion_limit", "type_length_limit", "windows_subsystem"
 +            ),
 +        ),
 +        (MODULE, attrs!(item, "macro_use", "no_implicit_prelude", "path")),
 +        (ITEM_LIST, attrs!(item, "no_implicit_prelude")),
 +        (MACRO_RULES, attrs!(item, "macro_export", "macro_use")),
 +        (MACRO_DEF, attrs!(item)),
 +        (EXTERN_CRATE, attrs!(item, "macro_use", "no_link")),
 +        (USE, attrs!(item)),
 +        (TYPE_ALIAS, attrs!(item)),
 +        (STRUCT, attrs!(item, adt, "non_exhaustive")),
 +        (ENUM, attrs!(item, adt, "non_exhaustive")),
 +        (UNION, attrs!(item, adt)),
 +        (CONST, attrs!(item)),
 +        (
 +            FN,
 +            attrs!(
 +                item, linkable,
 +                "cold", "ignore", "inline", "must_use", "panic_handler", "proc_macro",
 +                "proc_macro_derive", "proc_macro_attribute", "should_panic", "target_feature",
 +                "test", "track_caller"
 +            ),
 +        ),
 +        (STATIC, attrs!(item, linkable, "global_allocator", "used")),
 +        (TRAIT, attrs!(item, "must_use")),
 +        (IMPL, attrs!(item, "automatically_derived")),
 +        (ASSOC_ITEM_LIST, attrs!(item)),
 +        (EXTERN_BLOCK, attrs!(item, "link")),
 +        (EXTERN_ITEM_LIST, attrs!(item, "link")),
 +        (MACRO_CALL, attrs!()),
 +        (SELF_PARAM, attrs!()),
 +        (PARAM, attrs!()),
 +        (RECORD_FIELD, attrs!()),
 +        (VARIANT, attrs!("non_exhaustive")),
 +        (TYPE_PARAM, attrs!()),
 +        (CONST_PARAM, attrs!()),
 +        (LIFETIME_PARAM, attrs!()),
 +        (LET_STMT, attrs!()),
 +        (EXPR_STMT, attrs!()),
 +        (LITERAL, attrs!()),
 +        (RECORD_EXPR_FIELD_LIST, attrs!()),
 +        (RECORD_EXPR_FIELD, attrs!()),
 +        (MATCH_ARM_LIST, attrs!()),
 +        (MATCH_ARM, attrs!()),
 +        (IDENT_PAT, attrs!()),
 +        (RECORD_PAT_FIELD, attrs!()),
 +    ]
 +    .into_iter()
 +    .collect()
 +});
 +const EXPR_ATTRIBUTES: &[&str] = attrs!();
 +
 +/// <https://doc.rust-lang.org/reference/attributes.html#built-in-attributes-index>
 +// Keep these sorted for the binary search!
 +const ATTRIBUTES: &[AttrCompletion] = &[
 +    attr("allow(…)", Some("allow"), Some("allow(${0:lint})")),
 +    attr("automatically_derived", None, None),
 +    attr("cfg(…)", Some("cfg"), Some("cfg(${0:predicate})")),
 +    attr("cfg_attr(…)", Some("cfg_attr"), Some("cfg_attr(${1:predicate}, ${0:attr})")),
 +    attr("cold", None, None),
 +    attr(r#"crate_name = """#, Some("crate_name"), Some(r#"crate_name = "${0:crate_name}""#))
 +        .prefer_inner(),
 +    attr("deny(…)", Some("deny"), Some("deny(${0:lint})")),
 +    attr(r#"deprecated"#, Some("deprecated"), Some(r#"deprecated"#)),
 +    attr("derive(…)", Some("derive"), Some(r#"derive(${0:Debug})"#)),
 +    attr(r#"doc = "…""#, Some("doc"), Some(r#"doc = "${0:docs}""#)),
 +    attr(r#"doc(alias = "…")"#, Some("docalias"), Some(r#"doc(alias = "${0:docs}")"#)),
 +    attr(r#"doc(hidden)"#, Some("dochidden"), Some(r#"doc(hidden)"#)),
 +    attr(
 +        r#"export_name = "…""#,
 +        Some("export_name"),
 +        Some(r#"export_name = "${0:exported_symbol_name}""#),
 +    ),
 +    attr("feature(…)", Some("feature"), Some("feature(${0:flag})")).prefer_inner(),
 +    attr("forbid(…)", Some("forbid"), Some("forbid(${0:lint})")),
 +    attr("global_allocator", None, None),
 +    attr(r#"ignore = "…""#, Some("ignore"), Some(r#"ignore = "${0:reason}""#)),
 +    attr("inline", Some("inline"), Some("inline")),
 +    attr("link", None, None),
 +    attr(r#"link_name = "…""#, Some("link_name"), Some(r#"link_name = "${0:symbol_name}""#)),
 +    attr(
 +        r#"link_section = "…""#,
 +        Some("link_section"),
 +        Some(r#"link_section = "${0:section_name}""#),
 +    ),
 +    attr("macro_export", None, None),
 +    attr("macro_use", None, None),
 +    attr(r#"must_use"#, Some("must_use"), Some(r#"must_use"#)),
 +    attr("no_implicit_prelude", None, None).prefer_inner(),
 +    attr("no_link", None, None).prefer_inner(),
 +    attr("no_main", None, None).prefer_inner(),
 +    attr("no_mangle", None, None),
 +    attr("no_std", None, None).prefer_inner(),
 +    attr("non_exhaustive", None, None),
 +    attr("panic_handler", None, None),
 +    attr(r#"path = "…""#, Some("path"), Some(r#"path ="${0:path}""#)),
 +    attr("proc_macro", None, None),
 +    attr("proc_macro_attribute", None, None),
 +    attr("proc_macro_derive(…)", Some("proc_macro_derive"), Some("proc_macro_derive(${0:Trait})")),
 +    attr(
 +        r#"recursion_limit = "…""#,
 +        Some("recursion_limit"),
 +        Some(r#"recursion_limit = "${0:128}""#),
 +    )
 +    .prefer_inner(),
 +    attr("repr(…)", Some("repr"), Some("repr(${0:C})")),
 +    attr("should_panic", Some("should_panic"), Some(r#"should_panic"#)),
 +    attr(
 +        r#"target_feature(enable = "…")"#,
 +        Some("target_feature"),
 +        Some(r#"target_feature(enable = "${0:feature}")"#),
 +    ),
 +    attr("test", None, None),
 +    attr("track_caller", None, None),
 +    attr("type_length_limit = …", Some("type_length_limit"), Some("type_length_limit = ${0:128}"))
 +        .prefer_inner(),
 +    attr("used", None, None),
 +    attr("warn(…)", Some("warn"), Some("warn(${0:lint})")),
 +    attr(
 +        r#"windows_subsystem = "…""#,
 +        Some("windows_subsystem"),
 +        Some(r#"windows_subsystem = "${0:subsystem}""#),
 +    )
 +    .prefer_inner(),
 +];
 +
 +fn parse_comma_sep_expr(input: ast::TokenTree) -> Option<Vec<ast::Expr>> {
 +    let r_paren = input.r_paren_token()?;
 +    let tokens = input
 +        .syntax()
 +        .children_with_tokens()
 +        .skip(1)
 +        .take_while(|it| it.as_token() != Some(&r_paren));
 +    let input_expressions = tokens.group_by(|tok| tok.kind() == T![,]);
 +    Some(
 +        input_expressions
 +            .into_iter()
 +            .filter_map(|(is_sep, group)| (!is_sep).then(|| group))
 +            .filter_map(|mut tokens| syntax::hacks::parse_expr_from_str(&tokens.join("")))
 +            .collect::<Vec<ast::Expr>>(),
 +    )
 +}
 +
 +#[test]
 +fn attributes_are_sorted() {
 +    let mut attrs = ATTRIBUTES.iter().map(|attr| attr.key());
 +    let mut prev = attrs.next().unwrap();
 +
 +    attrs.for_each(|next| {
 +        assert!(
 +            prev < next,
 +            r#"ATTRIBUTES array is not sorted, "{}" should come after "{}""#,
 +            prev,
 +            next
 +        );
 +        prev = next;
 +    });
 +}
index 14538fef6072c8b8a481b182321ab6cb5a6d1b5c,0000000000000000000000000000000000000000..793c22630bf8959039856f2ecd9ddd126565cc1a
mode 100644,000000..100644
--- /dev/null
@@@ -1,116 -1,0 +1,116 @@@
-         Qualified::Infer | Qualified::With { .. } => {}
 +//! Completion for derives
 +use hir::{HasAttrs, ScopeDef};
 +use ide_db::SymbolKind;
 +use itertools::Itertools;
 +use syntax::SmolStr;
 +
 +use crate::{
 +    context::{CompletionContext, ExistingDerives, PathCompletionCtx, Qualified},
 +    item::CompletionItem,
 +    Completions,
 +};
 +
 +pub(crate) fn complete_derive_path(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
 +    existing_derives: &ExistingDerives,
 +) {
 +    let core = ctx.famous_defs().core();
 +
 +    match qualified {
 +        Qualified::With {
 +            resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),
 +            super_chain_len,
 +            ..
 +        } => {
 +            acc.add_super_keyword(ctx, *super_chain_len);
 +
 +            for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
 +                match def {
 +                    ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac))
 +                        if !existing_derives.contains(&mac) && mac.is_derive(ctx.db) =>
 +                    {
 +                        acc.add_macro(ctx, path_ctx, mac, name)
 +                    }
 +                    ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => {
 +                        acc.add_module(ctx, path_ctx, m, name)
 +                    }
 +                    _ => (),
 +                }
 +            }
 +        }
 +        Qualified::Absolute => acc.add_crate_roots(ctx, path_ctx),
 +        // only show modules in a fresh UseTree
 +        Qualified::No => {
 +            ctx.process_all_names(&mut |name, def| {
 +                let mac = match def {
 +                    ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac))
 +                        if !existing_derives.contains(&mac) && mac.is_derive(ctx.db) =>
 +                    {
 +                        mac
 +                    }
 +                    ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => {
 +                        return acc.add_module(ctx, path_ctx, m, name);
 +                    }
 +                    _ => return,
 +                };
 +
 +                match (core, mac.module(ctx.db).krate()) {
 +                    // show derive dependencies for `core`/`std` derives
 +                    (Some(core), mac_krate) if core == mac_krate => {}
 +                    _ => return acc.add_macro(ctx, path_ctx, mac, name),
 +                };
 +
 +                let name_ = name.to_smol_str();
 +                let find = DEFAULT_DERIVE_DEPENDENCIES
 +                    .iter()
 +                    .find(|derive_completion| derive_completion.label == name_);
 +
 +                match find {
 +                    Some(derive_completion) => {
 +                        let mut components = vec![derive_completion.label];
 +                        components.extend(derive_completion.dependencies.iter().filter(
 +                            |&&dependency| {
 +                                !existing_derives
 +                                    .iter()
 +                                    .map(|it| it.name(ctx.db))
 +                                    .any(|it| it.to_smol_str() == dependency)
 +                            },
 +                        ));
 +                        let lookup = components.join(", ");
 +                        let label = Itertools::intersperse(components.into_iter().rev(), ", ");
 +
 +                        let mut item = CompletionItem::new(
 +                            SymbolKind::Derive,
 +                            ctx.source_range(),
 +                            SmolStr::from_iter(label),
 +                        );
 +                        if let Some(docs) = mac.docs(ctx.db) {
 +                            item.documentation(docs);
 +                        }
 +                        item.lookup_by(lookup);
 +                        item.add_to(acc);
 +                    }
 +                    None => acc.add_macro(ctx, path_ctx, mac, name),
 +                }
 +            });
 +            acc.add_nameref_keywords_with_colon(ctx);
 +        }
++        Qualified::TypeAnchor { .. } | Qualified::With { .. } => {}
 +    }
 +}
 +
 +struct DeriveDependencies {
 +    label: &'static str,
 +    dependencies: &'static [&'static str],
 +}
 +
 +/// Standard Rust derives that have dependencies
 +/// (the dependencies are needed so that the main derive don't break the compilation when added)
 +const DEFAULT_DERIVE_DEPENDENCIES: &[DeriveDependencies] = &[
 +    DeriveDependencies { label: "Copy", dependencies: &["Clone"] },
 +    DeriveDependencies { label: "Eq", dependencies: &["PartialEq"] },
 +    DeriveDependencies { label: "Ord", dependencies: &["PartialOrd", "Eq", "PartialEq"] },
 +    DeriveDependencies { label: "PartialOrd", dependencies: &["PartialEq"] },
 +];
index bdf6e64f09696d27660409743a8d42842e8f7751,0000000000000000000000000000000000000000..5d0ddaaf2a22854e96f1029db1a14722afbe08a2
mode 100644,000000..100644
--- /dev/null
@@@ -1,246 -1,0 +1,280 @@@
-     &ExprCtx {
 +//! Completion of names from the current scope in expression position.
 +
 +use hir::ScopeDef;
 +
 +use crate::{
 +    context::{ExprCtx, PathCompletionCtx, Qualified},
 +    CompletionContext, Completions,
 +};
 +
 +pub(crate) fn complete_expr_path(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
-     }: &ExprCtx,
- ) {
-     let _p = profile::span("complete_expr_path");
-     if !ctx.qualifier_ctx.none() {
-         return;
-     }
++    expr_ctx: &ExprCtx,
++) {
++    let _p = profile::span("complete_expr_path");
++    if !ctx.qualifier_ctx.none() {
++        return;
++    }
++
++    let &ExprCtx {
 +        in_block_expr,
 +        in_loop_body,
 +        after_if_expr,
 +        in_condition,
 +        incomplete_let,
 +        ref ref_expr_parent,
 +        ref is_func_update,
 +        ref innermost_ret_ty,
 +        ref impl_,
 +        in_match_guard,
 +        ..
-         Qualified::Infer => ctx
++    } = expr_ctx;
 +
 +    let wants_mut_token =
 +        ref_expr_parent.as_ref().map(|it| it.mut_token().is_none()).unwrap_or(false);
 +
 +    let scope_def_applicable = |def| match def {
 +        ScopeDef::GenericParam(hir::GenericParam::LifetimeParam(_)) | ScopeDef::Label(_) => false,
 +        ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
 +        _ => true,
 +    };
 +
 +    let add_assoc_item = |acc: &mut Completions, item| match item {
 +        hir::AssocItem::Function(func) => acc.add_function(ctx, path_ctx, func, None),
 +        hir::AssocItem::Const(ct) => acc.add_const(ctx, ct),
 +        hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
 +    };
 +
 +    match qualified {
-             ctx.process_all_names(&mut |name, def| {
-                 if scope_def_applicable(def) {
-                     acc.add_path_resolution(ctx, path_ctx, name, def);
++        Qualified::TypeAnchor { ty: None, trait_: None } => ctx
 +            .traits_in_scope()
 +            .iter()
 +            .flat_map(|&it| hir::Trait::from(it).items(ctx.sema.db))
 +            .for_each(|item| add_assoc_item(acc, item)),
++        Qualified::TypeAnchor { trait_: Some(trait_), .. } => {
++            trait_.items(ctx.sema.db).into_iter().for_each(|item| add_assoc_item(acc, item))
++        }
++        Qualified::TypeAnchor { ty: Some(ty), trait_: None } => {
++            if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
++                cov_mark::hit!(completes_variant_through_alias);
++                acc.add_enum_variants(ctx, path_ctx, e);
++            }
++
++            ctx.iterate_path_candidates(&ty, |item| {
++                add_assoc_item(acc, item);
++            });
++
++            // Iterate assoc types separately
++            ty.iterate_assoc_items(ctx.db, ctx.krate, |item| {
++                if let hir::AssocItem::TypeAlias(ty) = item {
++                    acc.add_type_alias(ctx, ty)
++                }
++                None::<()>
++            });
++        }
 +        Qualified::With { resolution: None, .. } => {}
 +        Qualified::With { resolution: Some(resolution), .. } => {
 +            // Add associated types on type parameters and `Self`.
 +            ctx.scope.assoc_type_shorthand_candidates(resolution, |_, alias| {
 +                acc.add_type_alias(ctx, alias);
 +                None::<()>
 +            });
 +            match resolution {
 +                hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
 +                    let module_scope = module.scope(ctx.db, Some(ctx.module));
 +                    for (name, def) in module_scope {
 +                        if scope_def_applicable(def) {
 +                            acc.add_path_resolution(ctx, path_ctx, name, def);
 +                        }
 +                    }
 +                }
 +                hir::PathResolution::Def(
 +                    def @ (hir::ModuleDef::Adt(_)
 +                    | hir::ModuleDef::TypeAlias(_)
 +                    | hir::ModuleDef::BuiltinType(_)),
 +                ) => {
 +                    let ty = match def {
 +                        hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
 +                        hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
 +                        hir::ModuleDef::BuiltinType(builtin) => {
 +                            cov_mark::hit!(completes_primitive_assoc_const);
 +                            builtin.ty(ctx.db)
 +                        }
 +                        _ => return,
 +                    };
 +
 +                    if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
 +                        cov_mark::hit!(completes_variant_through_alias);
 +                        acc.add_enum_variants(ctx, path_ctx, e);
 +                    }
 +
 +                    // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
 +                    // (where AssocType is defined on a trait, not an inherent impl)
 +
 +                    ctx.iterate_path_candidates(&ty, |item| {
 +                        add_assoc_item(acc, item);
 +                    });
 +
 +                    // Iterate assoc types separately
 +                    ty.iterate_assoc_items(ctx.db, ctx.krate, |item| {
 +                        if let hir::AssocItem::TypeAlias(ty) = item {
 +                            acc.add_type_alias(ctx, ty)
 +                        }
 +                        None::<()>
 +                    });
 +                }
 +                hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => {
 +                    // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
 +                    for item in t.items(ctx.db) {
 +                        add_assoc_item(acc, item);
 +                    }
 +                }
 +                hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => {
 +                    let ty = match resolution {
 +                        hir::PathResolution::TypeParam(param) => param.ty(ctx.db),
 +                        hir::PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db),
 +                        _ => return,
 +                    };
 +
 +                    if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
 +                        cov_mark::hit!(completes_variant_through_self);
 +                        acc.add_enum_variants(ctx, path_ctx, e);
 +                    }
 +
 +                    ctx.iterate_path_candidates(&ty, |item| {
 +                        add_assoc_item(acc, item);
 +                    });
 +                }
 +                _ => (),
 +            }
 +        }
 +        Qualified::Absolute => acc.add_crate_roots(ctx, path_ctx),
 +        Qualified::No => {
 +            acc.add_nameref_keywords_with_colon(ctx);
 +            if let Some(adt) =
 +                ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
 +            {
 +                let self_ty = (|| ctx.sema.to_def(impl_.as_ref()?)?.self_ty(ctx.db).as_adt())();
 +                let complete_self = self_ty == Some(adt);
 +
 +                match adt {
 +                    hir::Adt::Struct(strukt) => {
 +                        let path = ctx
 +                            .module
 +                            .find_use_path(ctx.db, hir::ModuleDef::from(strukt))
 +                            .filter(|it| it.len() > 1);
 +
 +                        acc.add_struct_literal(ctx, path_ctx, strukt, path, None);
 +
 +                        if complete_self {
 +                            acc.add_struct_literal(
 +                                ctx,
 +                                path_ctx,
 +                                strukt,
 +                                None,
 +                                Some(hir::known::SELF_TYPE),
 +                            );
 +                        }
 +                    }
 +                    hir::Adt::Union(un) => {
 +                        let path = ctx
 +                            .module
 +                            .find_use_path(ctx.db, hir::ModuleDef::from(un))
 +                            .filter(|it| it.len() > 1);
 +
 +                        acc.add_union_literal(ctx, un, path, None);
 +                        if complete_self {
 +                            acc.add_union_literal(ctx, un, None, Some(hir::known::SELF_TYPE));
 +                        }
 +                    }
 +                    hir::Adt::Enum(e) => {
 +                        super::enum_variants_with_paths(
 +                            acc,
 +                            ctx,
 +                            e,
 +                            impl_,
 +                            |acc, ctx, variant, path| {
 +                                acc.add_qualified_enum_variant(ctx, path_ctx, variant, path)
 +                            },
 +                        );
 +                    }
 +                }
 +            }
++            ctx.process_all_names(&mut |name, def| match def {
++                ScopeDef::ModuleDef(hir::ModuleDef::Trait(t)) => {
++                    let assocs = t.items_with_supertraits(ctx.db);
++                    match &*assocs {
++                        // traits with no assoc items are unusable as expressions since
++                        // there is no associated item path that can be constructed with them
++                        [] => (),
++                        // FIXME: Render the assoc item with the trait qualified
++                        &[_item] => acc.add_path_resolution(ctx, path_ctx, name, def),
++                        // FIXME: Append `::` to the thing here, since a trait on its own won't work
++                        [..] => acc.add_path_resolution(ctx, path_ctx, name, def),
++                    }
 +                }
++                _ if scope_def_applicable(def) => acc.add_path_resolution(ctx, path_ctx, name, def),
++                _ => (),
 +            });
 +
 +            if is_func_update.is_none() {
 +                let mut add_keyword =
 +                    |kw, snippet| acc.add_keyword_snippet_expr(ctx, incomplete_let, kw, snippet);
 +
 +                if !in_block_expr {
 +                    add_keyword("unsafe", "unsafe {\n    $0\n}");
 +                }
 +                add_keyword("match", "match $1 {\n    $0\n}");
 +                add_keyword("while", "while $1 {\n    $0\n}");
 +                add_keyword("while let", "while let $1 = $2 {\n    $0\n}");
 +                add_keyword("loop", "loop {\n    $0\n}");
 +                if in_match_guard {
 +                    add_keyword("if", "if $0");
 +                } else {
 +                    add_keyword("if", "if $1 {\n    $0\n}");
 +                }
 +                add_keyword("if let", "if let $1 = $2 {\n    $0\n}");
 +                add_keyword("for", "for $1 in $2 {\n    $0\n}");
 +                add_keyword("true", "true");
 +                add_keyword("false", "false");
 +
 +                if in_condition || in_block_expr {
 +                    add_keyword("let", "let");
 +                }
 +
 +                if after_if_expr {
 +                    add_keyword("else", "else {\n    $0\n}");
 +                    add_keyword("else if", "else if $1 {\n    $0\n}");
 +                }
 +
 +                if wants_mut_token {
 +                    add_keyword("mut", "mut ");
 +                }
 +
 +                if in_loop_body {
 +                    if in_block_expr {
 +                        add_keyword("continue", "continue;");
 +                        add_keyword("break", "break;");
 +                    } else {
 +                        add_keyword("continue", "continue");
 +                        add_keyword("break", "break");
 +                    }
 +                }
 +
 +                if let Some(ty) = innermost_ret_ty {
 +                    add_keyword(
 +                        "return",
 +                        match (in_block_expr, ty.is_unit()) {
 +                            (true, true) => "return ;",
 +                            (true, false) => "return;",
 +                            (false, true) => "return $0",
 +                            (false, false) => "return",
 +                        },
 +                    );
 +                }
 +            }
 +        }
 +    }
 +}
index 4e4c9fba6cc57250498a877f159967ca9051e538,0000000000000000000000000000000000000000..60d05ae46b9168181d7823f660867a1b3ad36462
mode 100644,000000..100644
--- /dev/null
@@@ -1,133 -1,0 +1,133 @@@
-         Qualified::Infer | Qualified::No | Qualified::With { .. } => {}
 +//! Completion of paths and keywords at item list position.
 +
 +use crate::{
 +    context::{ExprCtx, ItemListKind, PathCompletionCtx, Qualified},
 +    CompletionContext, Completions,
 +};
 +
 +pub(crate) mod trait_impl;
 +
 +pub(crate) fn complete_item_list_in_expr(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    path_ctx: &PathCompletionCtx,
 +    expr_ctx: &ExprCtx,
 +) {
 +    if !expr_ctx.in_block_expr {
 +        return;
 +    }
 +    if !path_ctx.is_trivial_path() {
 +        return;
 +    }
 +    add_keywords(acc, ctx, None);
 +}
 +
 +pub(crate) fn complete_item_list(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
 +    kind: &ItemListKind,
 +) {
 +    let _p = profile::span("complete_item_list");
 +    if path_ctx.is_trivial_path() {
 +        add_keywords(acc, ctx, Some(kind));
 +    }
 +
 +    match qualified {
 +        Qualified::With {
 +            resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),
 +            super_chain_len,
 +            ..
 +        } => {
 +            for (name, def) in module.scope(ctx.db, Some(ctx.module)) {
 +                match def {
 +                    hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_fn_like(ctx.db) => {
 +                        acc.add_macro(ctx, path_ctx, m, name)
 +                    }
 +                    hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => {
 +                        acc.add_module(ctx, path_ctx, m, name)
 +                    }
 +                    _ => (),
 +                }
 +            }
 +
 +            acc.add_super_keyword(ctx, *super_chain_len);
 +        }
 +        Qualified::Absolute => acc.add_crate_roots(ctx, path_ctx),
 +        Qualified::No if ctx.qualifier_ctx.none() => {
 +            ctx.process_all_names(&mut |name, def| match def {
 +                hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(m)) if m.is_fn_like(ctx.db) => {
 +                    acc.add_macro(ctx, path_ctx, m, name)
 +                }
 +                hir::ScopeDef::ModuleDef(hir::ModuleDef::Module(m)) => {
 +                    acc.add_module(ctx, path_ctx, m, name)
 +                }
 +                _ => (),
 +            });
 +            acc.add_nameref_keywords_with_colon(ctx);
 +        }
++        Qualified::TypeAnchor { .. } | Qualified::No | Qualified::With { .. } => {}
 +    }
 +}
 +
 +fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option<&ItemListKind>) {
 +    let mut add_keyword = |kw, snippet| acc.add_keyword_snippet(ctx, kw, snippet);
 +
 +    let in_item_list = matches!(kind, Some(ItemListKind::SourceFile | ItemListKind::Module) | None);
 +    let in_assoc_non_trait_impl = matches!(kind, Some(ItemListKind::Impl | ItemListKind::Trait));
 +    let in_extern_block = matches!(kind, Some(ItemListKind::ExternBlock));
 +    let in_trait = matches!(kind, Some(ItemListKind::Trait));
 +    let in_trait_impl = matches!(kind, Some(ItemListKind::TraitImpl(_)));
 +    let in_inherent_impl = matches!(kind, Some(ItemListKind::Impl));
 +    let no_qualifiers = ctx.qualifier_ctx.vis_node.is_none();
 +    let in_block = matches!(kind, None);
 +
 +    if !in_trait_impl {
 +        if ctx.qualifier_ctx.unsafe_tok.is_some() {
 +            if in_item_list || in_assoc_non_trait_impl {
 +                add_keyword("fn", "fn $1($2) {\n    $0\n}");
 +            }
 +            if in_item_list {
 +                add_keyword("trait", "trait $1 {\n    $0\n}");
 +                if no_qualifiers {
 +                    add_keyword("impl", "impl $1 {\n    $0\n}");
 +                }
 +            }
 +            return;
 +        }
 +
 +        if in_item_list {
 +            add_keyword("enum", "enum $1 {\n    $0\n}");
 +            add_keyword("mod", "mod $0");
 +            add_keyword("static", "static $0");
 +            add_keyword("struct", "struct $0");
 +            add_keyword("trait", "trait $1 {\n    $0\n}");
 +            add_keyword("union", "union $1 {\n    $0\n}");
 +            add_keyword("use", "use $0");
 +            if no_qualifiers {
 +                add_keyword("impl", "impl $1 {\n    $0\n}");
 +            }
 +        }
 +
 +        if !in_trait && !in_block && no_qualifiers {
 +            add_keyword("pub(crate)", "pub(crate)");
 +            add_keyword("pub(super)", "pub(super)");
 +            add_keyword("pub", "pub");
 +        }
 +
 +        if in_extern_block {
 +            add_keyword("fn", "fn $1($2);");
 +        } else {
 +            if !in_inherent_impl {
 +                if !in_trait {
 +                    add_keyword("extern", "extern $0");
 +                }
 +                add_keyword("type", "type $0");
 +            }
 +
 +            add_keyword("fn", "fn $1($2) {\n    $0\n}");
 +            add_keyword("unsafe", "unsafe");
 +            add_keyword("const", "const $0");
 +        }
 +    }
 +}
index 17dfe432b3529e453e81a8fbaebf174c99d63046,0000000000000000000000000000000000000000..71d2d9d434b449f915dbad29a58c756ae591b651
mode 100644,000000..100644
--- /dev/null
@@@ -1,185 -1,0 +1,185 @@@
-                     acc.add_variant_pat(ctx, pattern_ctx, variant, Some(name.clone()));
 +//! Completes constants and paths in unqualified patterns.
 +
 +use hir::{db::DefDatabase, AssocItem, ScopeDef};
 +use syntax::ast::Pat;
 +
 +use crate::{
 +    context::{PathCompletionCtx, PatternContext, PatternRefutability, Qualified},
 +    CompletionContext, Completions,
 +};
 +
 +/// Completes constants and paths in unqualified patterns.
 +pub(crate) fn complete_pattern(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    pattern_ctx: &PatternContext,
 +) {
 +    match pattern_ctx.parent_pat.as_ref() {
 +        Some(Pat::RangePat(_) | Pat::BoxPat(_)) => (),
 +        Some(Pat::RefPat(r)) => {
 +            if r.mut_token().is_none() {
 +                acc.add_keyword(ctx, "mut");
 +            }
 +        }
 +        _ => {
 +            let tok = ctx.token.text_range().start();
 +            match (pattern_ctx.ref_token.as_ref(), pattern_ctx.mut_token.as_ref()) {
 +                (None, None) => {
 +                    acc.add_keyword(ctx, "ref");
 +                    acc.add_keyword(ctx, "mut");
 +                }
 +                (None, Some(m)) if tok < m.text_range().start() => {
 +                    acc.add_keyword(ctx, "ref");
 +                }
 +                (Some(r), None) if tok > r.text_range().end() => {
 +                    acc.add_keyword(ctx, "mut");
 +                }
 +                _ => (),
 +            }
 +        }
 +    }
 +
 +    if pattern_ctx.record_pat.is_some() {
 +        return;
 +    }
 +
 +    let refutable = pattern_ctx.refutability == PatternRefutability::Refutable;
 +    let single_variant_enum = |enum_: hir::Enum| ctx.db.enum_data(enum_.into()).variants.len() == 1;
 +
 +    if let Some(hir::Adt::Enum(e)) =
 +        ctx.expected_type.as_ref().and_then(|ty| ty.strip_references().as_adt())
 +    {
 +        if refutable || single_variant_enum(e) {
 +            super::enum_variants_with_paths(
 +                acc,
 +                ctx,
 +                e,
 +                &pattern_ctx.impl_,
 +                |acc, ctx, variant, path| {
 +                    acc.add_qualified_variant_pat(ctx, pattern_ctx, variant, path);
 +                },
 +            );
 +        }
 +    }
 +
 +    // FIXME: ideally, we should look at the type we are matching against and
 +    // suggest variants + auto-imports
 +    ctx.process_all_names(&mut |name, res| {
 +        let add_simple_path = match res {
 +            hir::ScopeDef::ModuleDef(def) => match def {
 +                hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => {
 +                    acc.add_struct_pat(ctx, pattern_ctx, strukt, Some(name.clone()));
 +                    true
 +                }
 +                hir::ModuleDef::Variant(variant)
 +                    if refutable || single_variant_enum(variant.parent_enum(ctx.db)) =>
 +                {
-         Qualified::Infer | Qualified::With { .. } => {}
++                    acc.add_variant_pat(ctx, pattern_ctx, None, variant, Some(name.clone()));
 +                    true
 +                }
 +                hir::ModuleDef::Adt(hir::Adt::Enum(e)) => refutable || single_variant_enum(e),
 +                hir::ModuleDef::Const(..) => refutable,
 +                hir::ModuleDef::Module(..) => true,
 +                hir::ModuleDef::Macro(mac) => mac.is_fn_like(ctx.db),
 +                _ => false,
 +            },
 +            hir::ScopeDef::ImplSelfType(impl_) => match impl_.self_ty(ctx.db).as_adt() {
 +                Some(hir::Adt::Struct(strukt)) => {
 +                    acc.add_struct_pat(ctx, pattern_ctx, strukt, Some(name.clone()));
 +                    true
 +                }
 +                Some(hir::Adt::Enum(e)) => refutable || single_variant_enum(e),
 +                Some(hir::Adt::Union(_)) => true,
 +                _ => false,
 +            },
 +            ScopeDef::GenericParam(hir::GenericParam::ConstParam(_)) => true,
 +            ScopeDef::GenericParam(_)
 +            | ScopeDef::AdtSelfType(_)
 +            | ScopeDef::Local(_)
 +            | ScopeDef::Label(_)
 +            | ScopeDef::Unknown => false,
 +        };
 +        if add_simple_path {
 +            acc.add_pattern_resolution(ctx, pattern_ctx, name, res);
 +        }
 +    });
 +}
 +
 +pub(crate) fn complete_pattern_path(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
 +) {
 +    match qualified {
 +        Qualified::With { resolution: Some(resolution), super_chain_len, .. } => {
 +            acc.add_super_keyword(ctx, *super_chain_len);
 +
 +            match resolution {
 +                hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
 +                    let module_scope = module.scope(ctx.db, Some(ctx.module));
 +                    for (name, def) in module_scope {
 +                        let add_resolution = match def {
 +                            ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => {
 +                                mac.is_fn_like(ctx.db)
 +                            }
 +                            ScopeDef::ModuleDef(_) => true,
 +                            _ => false,
 +                        };
 +
 +                        if add_resolution {
 +                            acc.add_path_resolution(ctx, path_ctx, name, def);
 +                        }
 +                    }
 +                }
 +                res => {
 +                    let ty = match res {
 +                        hir::PathResolution::TypeParam(param) => param.ty(ctx.db),
 +                        hir::PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db),
 +                        hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Struct(s))) => {
 +                            s.ty(ctx.db)
 +                        }
 +                        hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e))) => {
 +                            e.ty(ctx.db)
 +                        }
 +                        hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Union(u))) => {
 +                            u.ty(ctx.db)
 +                        }
 +                        hir::PathResolution::Def(hir::ModuleDef::BuiltinType(ty)) => ty.ty(ctx.db),
 +                        _ => return,
 +                    };
 +
 +                    if let Some(hir::Adt::Enum(e)) = ty.as_adt() {
 +                        acc.add_enum_variants(ctx, path_ctx, e);
 +                    }
 +
 +                    ctx.iterate_path_candidates(&ty, |item| match item {
 +                        AssocItem::TypeAlias(ta) => acc.add_type_alias(ctx, ta),
 +                        AssocItem::Const(c) => acc.add_const(ctx, c),
 +                        _ => {}
 +                    });
 +                }
 +            }
 +        }
 +        Qualified::Absolute => acc.add_crate_roots(ctx, path_ctx),
 +        Qualified::No => {
 +            // this will only be hit if there are brackets or braces, otherwise this will be parsed as an ident pattern
 +            ctx.process_all_names(&mut |name, res| {
 +                // FIXME: we should check what kind of pattern we are in and filter accordingly
 +                let add_completion = match res {
 +                    ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => mac.is_fn_like(ctx.db),
 +                    ScopeDef::ModuleDef(hir::ModuleDef::Adt(_)) => true,
 +                    ScopeDef::ModuleDef(hir::ModuleDef::Variant(_)) => true,
 +                    ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
 +                    ScopeDef::ImplSelfType(_) => true,
 +                    _ => false,
 +                };
 +                if add_completion {
 +                    acc.add_path_resolution(ctx, path_ctx, name, res);
 +                }
 +            });
 +
 +            acc.add_nameref_keywords_with_colon(ctx);
 +        }
++        Qualified::TypeAnchor { .. } | Qualified::With { .. } => {}
 +    }
 +}
index 87a998dfcce6bfab229e85d6302330a2e7b891bc,0000000000000000000000000000000000000000..8f9db2f94c204c5e78bd962c0de7e07b3a08e3f0
mode 100644,000000..100644
--- /dev/null
@@@ -1,230 -1,0 +1,246 @@@
-         Qualified::Infer => ctx
 +//! Completion of names from the current scope in type position.
 +
 +use hir::{HirDisplay, ScopeDef};
 +use syntax::{ast, AstNode, SyntaxKind};
 +
 +use crate::{
 +    context::{PathCompletionCtx, Qualified, TypeAscriptionTarget, TypeLocation},
 +    render::render_type_inference,
 +    CompletionContext, Completions,
 +};
 +
 +pub(crate) fn complete_type_path(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
 +    location: &TypeLocation,
 +) {
 +    let _p = profile::span("complete_type_path");
 +
 +    let scope_def_applicable = |def| {
 +        use hir::{GenericParam::*, ModuleDef::*};
 +        match def {
 +            ScopeDef::GenericParam(LifetimeParam(_)) | ScopeDef::Label(_) => false,
 +            // no values in type places
 +            ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_)) | ScopeDef::Local(_) => false,
 +            // unless its a constant in a generic arg list position
 +            ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => {
 +                matches!(location, TypeLocation::GenericArgList(_))
 +            }
 +            ScopeDef::ImplSelfType(_) => {
 +                !matches!(location, TypeLocation::ImplTarget | TypeLocation::ImplTrait)
 +            }
 +            // Don't suggest attribute macros and derives.
 +            ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
 +            // Type things are fine
 +            ScopeDef::ModuleDef(BuiltinType(_) | Adt(_) | Module(_) | Trait(_) | TypeAlias(_))
 +            | ScopeDef::AdtSelfType(_)
 +            | ScopeDef::Unknown
 +            | ScopeDef::GenericParam(TypeParam(_)) => true,
 +        }
 +    };
 +
 +    let add_assoc_item = |acc: &mut Completions, item| match item {
 +        hir::AssocItem::Const(ct) if matches!(location, TypeLocation::GenericArgList(_)) => {
 +            acc.add_const(ctx, ct)
 +        }
 +        hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => (),
 +        hir::AssocItem::TypeAlias(ty) => acc.add_type_alias(ctx, ty),
 +    };
 +
 +    match qualified {
++        Qualified::TypeAnchor { ty: None, trait_: None } => ctx
 +            .traits_in_scope()
 +            .iter()
 +            .flat_map(|&it| hir::Trait::from(it).items(ctx.sema.db))
 +            .for_each(|item| add_assoc_item(acc, item)),
++        Qualified::TypeAnchor { trait_: Some(trait_), .. } => {
++            trait_.items(ctx.sema.db).into_iter().for_each(|item| add_assoc_item(acc, item))
++        }
++        Qualified::TypeAnchor { ty: Some(ty), trait_: None } => {
++            ctx.iterate_path_candidates(&ty, |item| {
++                add_assoc_item(acc, item);
++            });
++
++            // Iterate assoc types separately
++            ty.iterate_assoc_items(ctx.db, ctx.krate, |item| {
++                if let hir::AssocItem::TypeAlias(ty) = item {
++                    acc.add_type_alias(ctx, ty)
++                }
++                None::<()>
++            });
++        }
 +        Qualified::With { resolution: None, .. } => {}
 +        Qualified::With { resolution: Some(resolution), .. } => {
 +            // Add associated types on type parameters and `Self`.
 +            ctx.scope.assoc_type_shorthand_candidates(resolution, |_, alias| {
 +                acc.add_type_alias(ctx, alias);
 +                None::<()>
 +            });
 +
 +            match resolution {
 +                hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
 +                    let module_scope = module.scope(ctx.db, Some(ctx.module));
 +                    for (name, def) in module_scope {
 +                        if scope_def_applicable(def) {
 +                            acc.add_path_resolution(ctx, path_ctx, name, def);
 +                        }
 +                    }
 +                }
 +                hir::PathResolution::Def(
 +                    def @ (hir::ModuleDef::Adt(_)
 +                    | hir::ModuleDef::TypeAlias(_)
 +                    | hir::ModuleDef::BuiltinType(_)),
 +                ) => {
 +                    let ty = match def {
 +                        hir::ModuleDef::Adt(adt) => adt.ty(ctx.db),
 +                        hir::ModuleDef::TypeAlias(a) => a.ty(ctx.db),
 +                        hir::ModuleDef::BuiltinType(builtin) => builtin.ty(ctx.db),
 +                        _ => return,
 +                    };
 +
 +                    // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
 +                    // (where AssocType is defined on a trait, not an inherent impl)
 +
 +                    ctx.iterate_path_candidates(&ty, |item| {
 +                        add_assoc_item(acc, item);
 +                    });
 +
 +                    // Iterate assoc types separately
 +                    ty.iterate_assoc_items(ctx.db, ctx.krate, |item| {
 +                        if let hir::AssocItem::TypeAlias(ty) = item {
 +                            acc.add_type_alias(ctx, ty)
 +                        }
 +                        None::<()>
 +                    });
 +                }
 +                hir::PathResolution::Def(hir::ModuleDef::Trait(t)) => {
 +                    // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
 +                    for item in t.items(ctx.db) {
 +                        add_assoc_item(acc, item);
 +                    }
 +                }
 +                hir::PathResolution::TypeParam(_) | hir::PathResolution::SelfType(_) => {
 +                    let ty = match resolution {
 +                        hir::PathResolution::TypeParam(param) => param.ty(ctx.db),
 +                        hir::PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db),
 +                        _ => return,
 +                    };
 +
 +                    ctx.iterate_path_candidates(&ty, |item| {
 +                        add_assoc_item(acc, item);
 +                    });
 +                }
 +                _ => (),
 +            }
 +        }
 +        Qualified::Absolute => acc.add_crate_roots(ctx, path_ctx),
 +        Qualified::No => {
 +            match location {
 +                TypeLocation::TypeBound => {
 +                    acc.add_nameref_keywords_with_colon(ctx);
 +                    ctx.process_all_names(&mut |name, res| {
 +                        let add_resolution = match res {
 +                            ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => {
 +                                mac.is_fn_like(ctx.db)
 +                            }
 +                            ScopeDef::ModuleDef(
 +                                hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_),
 +                            ) => true,
 +                            _ => false,
 +                        };
 +                        if add_resolution {
 +                            acc.add_path_resolution(ctx, path_ctx, name, res);
 +                        }
 +                    });
 +                    return;
 +                }
 +                TypeLocation::GenericArgList(Some(arg_list)) => {
 +                    let in_assoc_type_arg = ctx
 +                        .original_token
 +                        .parent_ancestors()
 +                        .any(|node| node.kind() == SyntaxKind::ASSOC_TYPE_ARG);
 +
 +                    if !in_assoc_type_arg {
 +                        if let Some(path_seg) =
 +                            arg_list.syntax().parent().and_then(ast::PathSegment::cast)
 +                        {
 +                            if path_seg
 +                                .syntax()
 +                                .ancestors()
 +                                .find_map(ast::TypeBound::cast)
 +                                .is_some()
 +                            {
 +                                if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(
 +                                    trait_,
 +                                ))) = ctx.sema.resolve_path(&path_seg.parent_path())
 +                                {
 +                                    let arg_idx = arg_list
 +                                        .generic_args()
 +                                        .filter(|arg| {
 +                                            arg.syntax().text_range().end()
 +                                                < ctx.original_token.text_range().start()
 +                                        })
 +                                        .count();
 +
 +                                    let n_required_params =
 +                                        trait_.type_or_const_param_count(ctx.sema.db, true);
 +                                    if arg_idx >= n_required_params {
 +                                        trait_
 +                                            .items_with_supertraits(ctx.sema.db)
 +                                            .into_iter()
 +                                            .for_each(|it| {
 +                                                if let hir::AssocItem::TypeAlias(alias) = it {
 +                                                    cov_mark::hit!(
 +                                                        complete_assoc_type_in_generics_list
 +                                                    );
 +                                                    acc.add_type_alias_with_eq(ctx, alias);
 +                                                }
 +                                            });
 +
 +                                        let n_params =
 +                                            trait_.type_or_const_param_count(ctx.sema.db, false);
 +                                        if arg_idx >= n_params {
 +                                            return; // only show assoc types
 +                                        }
 +                                    }
 +                                }
 +                            }
 +                        }
 +                    }
 +                }
 +                _ => {}
 +            };
 +
 +            acc.add_nameref_keywords_with_colon(ctx);
 +            ctx.process_all_names(&mut |name, def| {
 +                if scope_def_applicable(def) {
 +                    acc.add_path_resolution(ctx, path_ctx, name, def);
 +                }
 +            });
 +        }
 +    }
 +}
 +
 +pub(crate) fn complete_ascribed_type(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    path_ctx: &PathCompletionCtx,
 +    ascription: &TypeAscriptionTarget,
 +) -> Option<()> {
 +    if !path_ctx.is_trivial_path() {
 +        return None;
 +    }
 +    let x = match ascription {
 +        TypeAscriptionTarget::Let(pat) | TypeAscriptionTarget::FnParam(pat) => {
 +            ctx.sema.type_of_pat(pat.as_ref()?)
 +        }
 +        TypeAscriptionTarget::Const(exp) | TypeAscriptionTarget::RetType(exp) => {
 +            ctx.sema.type_of_expr(exp.as_ref()?)
 +        }
 +    }?
 +    .adjusted();
 +    let ty_string = x.display_source_code(ctx.db, ctx.module.into()).ok()?;
 +    acc.add(render_type_inference(ty_string, ctx));
 +    None
 +}
index bb2ecc9fdde76b384464d22b9c5df5b1056b0a10,0000000000000000000000000000000000000000..2555c34aa7477090bc7f588ae66a908990f9db34
mode 100644,000000..100644
--- /dev/null
@@@ -1,120 -1,0 +1,120 @@@
-         Qualified::Infer | Qualified::With { resolution: None, .. } => {}
 +//! Completion for use trees
 +
 +use hir::ScopeDef;
 +use ide_db::{FxHashSet, SymbolKind};
 +use syntax::{ast, AstNode};
 +
 +use crate::{
 +    context::{CompletionContext, PathCompletionCtx, Qualified},
 +    item::Builder,
 +    CompletionItem, CompletionItemKind, CompletionRelevance, Completions,
 +};
 +
 +pub(crate) fn complete_use_path(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    path_ctx @ PathCompletionCtx { qualified, use_tree_parent, .. }: &PathCompletionCtx,
 +    name_ref: &Option<ast::NameRef>,
 +) {
 +    match qualified {
 +        Qualified::With { path, resolution: Some(resolution), super_chain_len } => {
 +            acc.add_super_keyword(ctx, *super_chain_len);
 +
 +            // only show `self` in a new use-tree when the qualifier doesn't end in self
 +            let not_preceded_by_self = *use_tree_parent
 +                && !matches!(
 +                    path.segment().and_then(|it| it.kind()),
 +                    Some(ast::PathSegmentKind::SelfKw)
 +                );
 +            if not_preceded_by_self {
 +                acc.add_keyword(ctx, "self");
 +            }
 +
 +            let mut already_imported_names = FxHashSet::default();
 +            if let Some(list) = ctx.token.parent_ancestors().find_map(ast::UseTreeList::cast) {
 +                let use_tree = list.parent_use_tree();
 +                if use_tree.path().as_ref() == Some(path) {
 +                    for tree in list.use_trees().filter(|tree| tree.is_simple_path()) {
 +                        if let Some(name) = tree.path().and_then(|path| path.as_single_name_ref()) {
 +                            already_imported_names.insert(name.to_string());
 +                        }
 +                    }
 +                }
 +            }
 +
 +            match resolution {
 +                hir::PathResolution::Def(hir::ModuleDef::Module(module)) => {
 +                    let module_scope = module.scope(ctx.db, Some(ctx.module));
 +                    let unknown_is_current = |name: &hir::Name| {
 +                        matches!(
 +                            name_ref,
 +                            Some(name_ref) if name_ref.syntax().text() == name.to_smol_str().as_str()
 +                        )
 +                    };
 +                    for (name, def) in module_scope {
 +                        let is_name_already_imported = name
 +                            .as_text()
 +                            .map_or(false, |text| already_imported_names.contains(text.as_str()));
 +
 +                        let add_resolution = match def {
 +                            ScopeDef::Unknown if unknown_is_current(&name) => {
 +                                // for `use self::foo$0`, don't suggest `foo` as a completion
 +                                cov_mark::hit!(dont_complete_current_use);
 +                                continue;
 +                            }
 +                            ScopeDef::ModuleDef(_) | ScopeDef::Unknown => true,
 +                            _ => false,
 +                        };
 +
 +                        if add_resolution {
 +                            let mut builder = Builder::from_resolution(ctx, path_ctx, name, def);
 +                            builder.set_relevance(CompletionRelevance {
 +                                is_name_already_imported,
 +                                ..Default::default()
 +                            });
 +                            acc.add(builder.build());
 +                        }
 +                    }
 +                }
 +                hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Enum(e))) => {
 +                    cov_mark::hit!(enum_plain_qualified_use_tree);
 +                    acc.add_enum_variants(ctx, path_ctx, *e);
 +                }
 +                _ => {}
 +            }
 +        }
 +        // fresh use tree with leading colon2, only show crate roots
 +        Qualified::Absolute => {
 +            cov_mark::hit!(use_tree_crate_roots_only);
 +            acc.add_crate_roots(ctx, path_ctx);
 +        }
 +        // only show modules and non-std enum in a fresh UseTree
 +        Qualified::No => {
 +            cov_mark::hit!(unqualified_path_selected_only);
 +            ctx.process_all_names(&mut |name, res| {
 +                match res {
 +                    ScopeDef::ModuleDef(hir::ModuleDef::Module(module)) => {
 +                        acc.add_module(ctx, path_ctx, module, name);
 +                    }
 +                    ScopeDef::ModuleDef(hir::ModuleDef::Adt(hir::Adt::Enum(e))) => {
 +                        // exclude prelude enum
 +                        let is_builtin =
 +                            res.krate(ctx.db).map_or(false, |krate| krate.is_builtin(ctx.db));
 +
 +                        if !is_builtin {
 +                            let item = CompletionItem::new(
 +                                CompletionItemKind::SymbolKind(SymbolKind::Enum),
 +                                ctx.source_range(),
 +                                format!("{}::", e.name(ctx.db)),
 +                            );
 +                            acc.add(item.build());
 +                        }
 +                    }
 +                    _ => {}
 +                };
 +            });
 +            acc.add_nameref_keywords_with_colon(ctx);
 +        }
++        Qualified::TypeAnchor { .. } | Qualified::With { resolution: None, .. } => {}
 +    }
 +}
index ca8303906a800a82f425cdd716a9f442c8f8ef16,0000000000000000000000000000000000000000..5e6cf4bf9a52142d572924a5f280d5625f88f2a1
mode 100644,000000..100644
--- /dev/null
@@@ -1,41 -1,0 +1,41 @@@
-         Qualified::Absolute | Qualified::Infer | Qualified::With { .. } => {}
 +//! Completion for visibility specifiers.
 +
 +use crate::{
 +    context::{CompletionContext, PathCompletionCtx, Qualified},
 +    Completions,
 +};
 +
 +pub(crate) fn complete_vis_path(
 +    acc: &mut Completions,
 +    ctx: &CompletionContext<'_>,
 +    path_ctx @ PathCompletionCtx { qualified, .. }: &PathCompletionCtx,
 +    &has_in_token: &bool,
 +) {
 +    match qualified {
 +        Qualified::With {
 +            resolution: Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))),
 +            super_chain_len,
 +            ..
 +        } => {
 +            // Try completing next child module of the path that is still a parent of the current module
 +            let next_towards_current =
 +                ctx.module.path_to_root(ctx.db).into_iter().take_while(|it| it != module).last();
 +            if let Some(next) = next_towards_current {
 +                if let Some(name) = next.name(ctx.db) {
 +                    cov_mark::hit!(visibility_qualified);
 +                    acc.add_module(ctx, path_ctx, next, name);
 +                }
 +            }
 +
 +            acc.add_super_keyword(ctx, *super_chain_len);
 +        }
++        Qualified::Absolute | Qualified::TypeAnchor { .. } | Qualified::With { .. } => {}
 +        Qualified::No => {
 +            if !has_in_token {
 +                cov_mark::hit!(kw_completion_in);
 +                acc.add_keyword(ctx, "in");
 +            }
 +            acc.add_nameref_keywords(ctx);
 +        }
 +    }
 +}
index 93b6ad5d145dff545f979c2aad0d9f06ad96179d,0000000000000000000000000000000000000000..e35f79d2b6951e05a57c943af8eba44bb60e7f57
mode 100644,000000..100644
--- /dev/null
@@@ -1,636 -1,0 +1,639 @@@
-     Infer,
 +//! See `CompletionContext` structure.
 +
 +mod analysis;
 +#[cfg(test)]
 +mod tests;
 +
 +use std::iter;
 +
 +use base_db::SourceDatabaseExt;
 +use hir::{
 +    HasAttrs, Local, Name, PathResolution, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo,
 +};
 +use ide_db::{
 +    base_db::{FilePosition, SourceDatabase},
 +    famous_defs::FamousDefs,
 +    FxHashMap, FxHashSet, RootDatabase,
 +};
 +use syntax::{
 +    ast::{self, AttrKind, NameOrNameRef},
 +    AstNode,
 +    SyntaxKind::{self, *},
 +    SyntaxToken, TextRange, TextSize,
 +};
 +use text_edit::Indel;
 +
 +use crate::CompletionConfig;
 +
 +const COMPLETION_MARKER: &str = "intellijRulezz";
 +
 +#[derive(Copy, Clone, Debug, PartialEq, Eq)]
 +pub(crate) enum PatternRefutability {
 +    Refutable,
 +    Irrefutable,
 +}
 +
 +#[derive(Debug)]
 +pub(crate) enum Visible {
 +    Yes,
 +    Editable,
 +    No,
 +}
 +
 +/// Existing qualifiers for the thing we are currently completing.
 +#[derive(Debug, Default)]
 +pub(super) struct QualifierCtx {
 +    pub(super) unsafe_tok: Option<SyntaxToken>,
 +    pub(super) vis_node: Option<ast::Visibility>,
 +}
 +
 +impl QualifierCtx {
 +    pub(super) fn none(&self) -> bool {
 +        self.unsafe_tok.is_none() && self.vis_node.is_none()
 +    }
 +}
 +
 +/// The state of the path we are currently completing.
 +#[derive(Debug)]
 +pub(crate) struct PathCompletionCtx {
 +    /// If this is a call with () already there (or {} in case of record patterns)
 +    pub(super) has_call_parens: bool,
 +    /// If this has a macro call bang !
 +    pub(super) has_macro_bang: bool,
 +    /// The qualifier of the current path.
 +    pub(super) qualified: Qualified,
 +    /// The parent of the path we are completing.
 +    pub(super) parent: Option<ast::Path>,
 +    /// The path of which we are completing the segment
 +    pub(super) path: ast::Path,
 +    pub(super) kind: PathKind,
 +    /// Whether the path segment has type args or not.
 +    pub(super) has_type_args: bool,
 +    /// Whether the qualifier comes from a use tree parent or not
 +    pub(crate) use_tree_parent: bool,
 +}
 +
 +impl PathCompletionCtx {
 +    pub(super) fn is_trivial_path(&self) -> bool {
 +        matches!(
 +            self,
 +            PathCompletionCtx {
 +                has_call_parens: false,
 +                has_macro_bang: false,
 +                qualified: Qualified::No,
 +                parent: None,
 +                has_type_args: false,
 +                ..
 +            }
 +        )
 +    }
 +}
 +
 +/// The kind of path we are completing right now.
 +#[derive(Debug, PartialEq, Eq)]
 +pub(super) enum PathKind {
 +    Expr {
 +        expr_ctx: ExprCtx,
 +    },
 +    Type {
 +        location: TypeLocation,
 +    },
 +    Attr {
 +        attr_ctx: AttrCtx,
 +    },
 +    Derive {
 +        existing_derives: ExistingDerives,
 +    },
 +    /// Path in item position, that is inside an (Assoc)ItemList
 +    Item {
 +        kind: ItemListKind,
 +    },
 +    Pat {
 +        pat_ctx: PatternContext,
 +    },
 +    Vis {
 +        has_in_token: bool,
 +    },
 +    Use,
 +}
 +
 +pub(crate) type ExistingDerives = FxHashSet<hir::Macro>;
 +
 +#[derive(Debug, PartialEq, Eq)]
 +pub(crate) struct AttrCtx {
 +    pub(crate) kind: AttrKind,
 +    pub(crate) annotated_item_kind: Option<SyntaxKind>,
 +}
 +
 +#[derive(Debug, PartialEq, Eq)]
 +pub(crate) struct ExprCtx {
 +    pub(crate) in_block_expr: bool,
 +    pub(crate) in_loop_body: bool,
 +    pub(crate) after_if_expr: bool,
 +    /// Whether this expression is the direct condition of an if or while expression
 +    pub(crate) in_condition: bool,
 +    pub(crate) incomplete_let: bool,
 +    pub(crate) ref_expr_parent: Option<ast::RefExpr>,
 +    pub(crate) is_func_update: Option<ast::RecordExpr>,
 +    pub(crate) self_param: Option<hir::SelfParam>,
 +    pub(crate) innermost_ret_ty: Option<hir::Type>,
 +    pub(crate) impl_: Option<ast::Impl>,
 +    /// Whether this expression occurs in match arm guard position: before the
 +    /// fat arrow token
 +    pub(crate) in_match_guard: bool,
 +}
 +
 +/// Original file ast nodes
 +#[derive(Clone, Debug, PartialEq, Eq)]
 +pub(crate) enum TypeLocation {
 +    TupleField,
 +    TypeAscription(TypeAscriptionTarget),
 +    GenericArgList(Option<ast::GenericArgList>),
 +    TypeBound,
 +    ImplTarget,
 +    ImplTrait,
 +    Other,
 +}
 +
 +#[derive(Clone, Debug, PartialEq, Eq)]
 +pub(crate) enum TypeAscriptionTarget {
 +    Let(Option<ast::Pat>),
 +    FnParam(Option<ast::Pat>),
 +    RetType(Option<ast::Expr>),
 +    Const(Option<ast::Expr>),
 +}
 +
 +/// The kind of item list a [`PathKind::Item`] belongs to.
 +#[derive(Debug, PartialEq, Eq)]
 +pub(super) enum ItemListKind {
 +    SourceFile,
 +    Module,
 +    Impl,
 +    TraitImpl(Option<ast::Impl>),
 +    Trait,
 +    ExternBlock,
 +}
 +
 +#[derive(Debug)]
 +pub(super) enum Qualified {
 +    No,
 +    With {
 +        path: ast::Path,
 +        resolution: Option<PathResolution>,
 +        /// How many `super` segments are present in the path
 +        ///
 +        /// This would be None, if path is not solely made of
 +        /// `super` segments, e.g.
 +        ///
 +        /// ```rust
 +        ///   use super::foo;
 +        /// ```
 +        ///
 +        /// Otherwise it should be Some(count of `super`)
 +        super_chain_len: Option<usize>,
 +    },
 +    /// <_>::
++    TypeAnchor {
++        ty: Option<hir::Type>,
++        trait_: Option<hir::Trait>,
++    },
 +    /// Whether the path is an absolute path
 +    Absolute,
 +}
 +
 +/// The state of the pattern we are completing.
 +#[derive(Debug, Clone, PartialEq, Eq)]
 +pub(super) struct PatternContext {
 +    pub(super) refutability: PatternRefutability,
 +    pub(super) param_ctx: Option<ParamContext>,
 +    pub(super) has_type_ascription: bool,
 +    pub(super) parent_pat: Option<ast::Pat>,
 +    pub(super) ref_token: Option<SyntaxToken>,
 +    pub(super) mut_token: Option<SyntaxToken>,
 +    /// The record pattern this name or ref is a field of
 +    pub(super) record_pat: Option<ast::RecordPat>,
 +    pub(super) impl_: Option<ast::Impl>,
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq)]
 +pub(super) struct ParamContext {
 +    pub(super) param_list: ast::ParamList,
 +    pub(super) param: ast::Param,
 +    pub(super) kind: ParamKind,
 +}
 +
 +/// The state of the lifetime we are completing.
 +#[derive(Debug)]
 +pub(super) struct LifetimeContext {
 +    pub(super) lifetime: Option<ast::Lifetime>,
 +    pub(super) kind: LifetimeKind,
 +}
 +
 +/// The kind of lifetime we are completing.
 +#[derive(Debug)]
 +pub(super) enum LifetimeKind {
 +    LifetimeParam { is_decl: bool, param: ast::LifetimeParam },
 +    Lifetime,
 +    LabelRef,
 +    LabelDef,
 +}
 +
 +/// The state of the name we are completing.
 +#[derive(Debug)]
 +pub(super) struct NameContext {
 +    #[allow(dead_code)]
 +    pub(super) name: Option<ast::Name>,
 +    pub(super) kind: NameKind,
 +}
 +
 +/// The kind of the name we are completing.
 +#[derive(Debug)]
 +#[allow(dead_code)]
 +pub(super) enum NameKind {
 +    Const,
 +    ConstParam,
 +    Enum,
 +    Function,
 +    IdentPat(PatternContext),
 +    MacroDef,
 +    MacroRules,
 +    /// Fake node
 +    Module(ast::Module),
 +    RecordField,
 +    Rename,
 +    SelfParam,
 +    Static,
 +    Struct,
 +    Trait,
 +    TypeAlias,
 +    TypeParam,
 +    Union,
 +    Variant,
 +}
 +
 +/// The state of the NameRef we are completing.
 +#[derive(Debug)]
 +pub(super) struct NameRefContext {
 +    /// NameRef syntax in the original file
 +    pub(super) nameref: Option<ast::NameRef>,
 +    pub(super) kind: NameRefKind,
 +}
 +
 +/// The kind of the NameRef we are completing.
 +#[derive(Debug)]
 +pub(super) enum NameRefKind {
 +    Path(PathCompletionCtx),
 +    DotAccess(DotAccess),
 +    /// Position where we are only interested in keyword completions
 +    Keyword(ast::Item),
 +    /// The record expression this nameref is a field of and whether a dot precedes the completion identifier.
 +    RecordExpr {
 +        dot_prefix: bool,
 +        expr: ast::RecordExpr,
 +    },
 +    Pattern(PatternContext),
 +}
 +
 +/// The identifier we are currently completing.
 +#[derive(Debug)]
 +pub(super) enum CompletionAnalysis {
 +    Name(NameContext),
 +    NameRef(NameRefContext),
 +    Lifetime(LifetimeContext),
 +    /// The string the cursor is currently inside
 +    String {
 +        /// original token
 +        original: ast::String,
 +        /// fake token
 +        expanded: Option<ast::String>,
 +    },
 +    /// Set if we are currently completing in an unexpanded attribute, this usually implies a builtin attribute like `allow($0)`
 +    UnexpandedAttrTT {
 +        colon_prefix: bool,
 +        fake_attribute_under_caret: Option<ast::Attr>,
 +    },
 +}
 +
 +/// Information about the field or method access we are completing.
 +#[derive(Debug)]
 +pub(super) struct DotAccess {
 +    pub(super) receiver: Option<ast::Expr>,
 +    pub(super) receiver_ty: Option<TypeInfo>,
 +    pub(super) kind: DotAccessKind,
 +}
 +
 +#[derive(Debug)]
 +pub(super) enum DotAccessKind {
 +    Field {
 +        /// True if the receiver is an integer and there is no ident in the original file after it yet
 +        /// like `0.$0`
 +        receiver_is_ambiguous_float_literal: bool,
 +    },
 +    Method {
 +        has_parens: bool,
 +    },
 +}
 +
 +#[derive(Clone, Debug, PartialEq, Eq)]
 +pub(crate) enum ParamKind {
 +    Function(ast::Fn),
 +    Closure(ast::ClosureExpr),
 +}
 +
 +/// `CompletionContext` is created early during completion to figure out, where
 +/// exactly is the cursor, syntax-wise.
 +#[derive(Debug)]
 +pub(crate) struct CompletionContext<'a> {
 +    pub(super) sema: Semantics<'a, RootDatabase>,
 +    pub(super) scope: SemanticsScope<'a>,
 +    pub(super) db: &'a RootDatabase,
 +    pub(super) config: &'a CompletionConfig,
 +    pub(super) position: FilePosition,
 +
 +    /// The token before the cursor, in the original file.
 +    pub(super) original_token: SyntaxToken,
 +    /// The token before the cursor, in the macro-expanded file.
 +    pub(super) token: SyntaxToken,
 +    /// The crate of the current file.
 +    pub(super) krate: hir::Crate,
 +    /// The module of the `scope`.
 +    pub(super) module: hir::Module,
 +
 +    /// The expected name of what we are completing.
 +    /// This is usually the parameter name of the function argument we are completing.
 +    pub(super) expected_name: Option<NameOrNameRef>,
 +    /// The expected type of what we are completing.
 +    pub(super) expected_type: Option<Type>,
 +
 +    pub(super) qualifier_ctx: QualifierCtx,
 +
 +    pub(super) locals: FxHashMap<Name, Local>,
 +
 +    /// The module depth of the current module of the cursor position.
 +    /// - crate-root
 +    ///  - mod foo
 +    ///   - mod bar
 +    /// Here depth will be 2
 +    pub(super) depth_from_crate_root: usize,
 +}
 +
 +impl<'a> CompletionContext<'a> {
 +    /// The range of the identifier that is being completed.
 +    pub(crate) fn source_range(&self) -> TextRange {
 +        // check kind of macro-expanded token, but use range of original token
 +        let kind = self.token.kind();
 +        match kind {
 +            CHAR => {
 +                // assume we are completing a lifetime but the user has only typed the '
 +                cov_mark::hit!(completes_if_lifetime_without_idents);
 +                TextRange::at(self.original_token.text_range().start(), TextSize::from(1))
 +            }
 +            IDENT | LIFETIME_IDENT | UNDERSCORE => self.original_token.text_range(),
 +            _ if kind.is_keyword() => self.original_token.text_range(),
 +            _ => TextRange::empty(self.position.offset),
 +        }
 +    }
 +
 +    pub(crate) fn famous_defs(&self) -> FamousDefs<'_, '_> {
 +        FamousDefs(&self.sema, self.krate)
 +    }
 +
 +    /// Checks if an item is visible and not `doc(hidden)` at the completion site.
 +    pub(crate) fn def_is_visible(&self, item: &ScopeDef) -> Visible {
 +        match item {
 +            ScopeDef::ModuleDef(def) => match def {
 +                hir::ModuleDef::Module(it) => self.is_visible(it),
 +                hir::ModuleDef::Function(it) => self.is_visible(it),
 +                hir::ModuleDef::Adt(it) => self.is_visible(it),
 +                hir::ModuleDef::Variant(it) => self.is_visible(it),
 +                hir::ModuleDef::Const(it) => self.is_visible(it),
 +                hir::ModuleDef::Static(it) => self.is_visible(it),
 +                hir::ModuleDef::Trait(it) => self.is_visible(it),
 +                hir::ModuleDef::TypeAlias(it) => self.is_visible(it),
 +                hir::ModuleDef::Macro(it) => self.is_visible(it),
 +                hir::ModuleDef::BuiltinType(_) => Visible::Yes,
 +            },
 +            ScopeDef::GenericParam(_)
 +            | ScopeDef::ImplSelfType(_)
 +            | ScopeDef::AdtSelfType(_)
 +            | ScopeDef::Local(_)
 +            | ScopeDef::Label(_)
 +            | ScopeDef::Unknown => Visible::Yes,
 +        }
 +    }
 +
 +    /// Checks if an item is visible and not `doc(hidden)` at the completion site.
 +    pub(crate) fn is_visible<I>(&self, item: &I) -> Visible
 +    where
 +        I: hir::HasVisibility + hir::HasAttrs + hir::HasCrate + Copy,
 +    {
 +        let vis = item.visibility(self.db);
 +        let attrs = item.attrs(self.db);
 +        self.is_visible_impl(&vis, &attrs, item.krate(self.db))
 +    }
 +
 +    /// Check if an item is `#[doc(hidden)]`.
 +    pub(crate) fn is_item_hidden(&self, item: &hir::ItemInNs) -> bool {
 +        let attrs = item.attrs(self.db);
 +        let krate = item.krate(self.db);
 +        match (attrs, krate) {
 +            (Some(attrs), Some(krate)) => self.is_doc_hidden(&attrs, krate),
 +            _ => false,
 +        }
 +    }
 +
 +    /// Whether the given trait is an operator trait or not.
 +    pub(crate) fn is_ops_trait(&self, trait_: hir::Trait) -> bool {
 +        match trait_.attrs(self.db).lang() {
 +            Some(lang) => OP_TRAIT_LANG_NAMES.contains(&lang.as_str()),
 +            None => false,
 +        }
 +    }
 +
 +    /// Returns the traits in scope, with the [`Drop`] trait removed.
 +    pub(crate) fn traits_in_scope(&self) -> hir::VisibleTraits {
 +        let mut traits_in_scope = self.scope.visible_traits();
 +        if let Some(drop) = self.famous_defs().core_ops_Drop() {
 +            traits_in_scope.0.remove(&drop.into());
 +        }
 +        traits_in_scope
 +    }
 +
 +    pub(crate) fn iterate_path_candidates(
 +        &self,
 +        ty: &hir::Type,
 +        mut cb: impl FnMut(hir::AssocItem),
 +    ) {
 +        let mut seen = FxHashSet::default();
 +        ty.iterate_path_candidates(
 +            self.db,
 +            &self.scope,
 +            &self.traits_in_scope(),
 +            Some(self.module),
 +            None,
 +            |item| {
 +                // We might iterate candidates of a trait multiple times here, so deduplicate
 +                // them.
 +                if seen.insert(item) {
 +                    cb(item)
 +                }
 +                None::<()>
 +            },
 +        );
 +    }
 +
 +    /// A version of [`SemanticsScope::process_all_names`] that filters out `#[doc(hidden)]` items.
 +    pub(crate) fn process_all_names(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
 +        let _p = profile::span("CompletionContext::process_all_names");
 +        self.scope.process_all_names(&mut |name, def| {
 +            if self.is_scope_def_hidden(def) {
 +                return;
 +            }
 +
 +            f(name, def);
 +        });
 +    }
 +
 +    pub(crate) fn process_all_names_raw(&self, f: &mut dyn FnMut(Name, ScopeDef)) {
 +        let _p = profile::span("CompletionContext::process_all_names_raw");
 +        self.scope.process_all_names(&mut |name, def| f(name, def));
 +    }
 +
 +    fn is_scope_def_hidden(&self, scope_def: ScopeDef) -> bool {
 +        if let (Some(attrs), Some(krate)) = (scope_def.attrs(self.db), scope_def.krate(self.db)) {
 +            return self.is_doc_hidden(&attrs, krate);
 +        }
 +
 +        false
 +    }
 +
 +    fn is_visible_impl(
 +        &self,
 +        vis: &hir::Visibility,
 +        attrs: &hir::Attrs,
 +        defining_crate: hir::Crate,
 +    ) -> Visible {
 +        if !vis.is_visible_from(self.db, self.module.into()) {
 +            if !self.config.enable_private_editable {
 +                return Visible::No;
 +            }
 +            // If the definition location is editable, also show private items
 +            let root_file = defining_crate.root_file(self.db);
 +            let source_root_id = self.db.file_source_root(root_file);
 +            let is_editable = !self.db.source_root(source_root_id).is_library;
 +            return if is_editable { Visible::Editable } else { Visible::No };
 +        }
 +
 +        if self.is_doc_hidden(attrs, defining_crate) {
 +            Visible::No
 +        } else {
 +            Visible::Yes
 +        }
 +    }
 +
 +    fn is_doc_hidden(&self, attrs: &hir::Attrs, defining_crate: hir::Crate) -> bool {
 +        // `doc(hidden)` items are only completed within the defining crate.
 +        self.krate != defining_crate && attrs.has_doc_hidden()
 +    }
 +}
 +
 +// CompletionContext construction
 +impl<'a> CompletionContext<'a> {
 +    pub(super) fn new(
 +        db: &'a RootDatabase,
 +        position @ FilePosition { file_id, offset }: FilePosition,
 +        config: &'a CompletionConfig,
 +    ) -> Option<(CompletionContext<'a>, CompletionAnalysis)> {
 +        let _p = profile::span("CompletionContext::new");
 +        let sema = Semantics::new(db);
 +
 +        let original_file = sema.parse(file_id);
 +
 +        // Insert a fake ident to get a valid parse tree. We will use this file
 +        // to determine context, though the original_file will be used for
 +        // actual completion.
 +        let file_with_fake_ident = {
 +            let parse = db.parse(file_id);
 +            let edit = Indel::insert(offset, COMPLETION_MARKER.to_string());
 +            parse.reparse(&edit).tree()
 +        };
 +        let fake_ident_token =
 +            file_with_fake_ident.syntax().token_at_offset(offset).right_biased()?;
 +
 +        let original_token = original_file.syntax().token_at_offset(offset).left_biased()?;
 +        let token = sema.descend_into_macros_single(original_token.clone());
 +
 +        // adjust for macro input, this still fails if there is no token written yet
 +        let scope_offset = if original_token == token { offset } else { token.text_range().end() };
 +        let scope = sema.scope_at_offset(&token.parent()?, scope_offset)?;
 +
 +        let krate = scope.krate();
 +        let module = scope.module();
 +
 +        let mut locals = FxHashMap::default();
 +        scope.process_all_names(&mut |name, scope| {
 +            if let ScopeDef::Local(local) = scope {
 +                locals.insert(name, local);
 +            }
 +        });
 +
 +        let depth_from_crate_root = iter::successors(module.parent(db), |m| m.parent(db)).count();
 +
 +        let mut ctx = CompletionContext {
 +            sema,
 +            scope,
 +            db,
 +            config,
 +            position,
 +            original_token,
 +            token,
 +            krate,
 +            module,
 +            expected_name: None,
 +            expected_type: None,
 +            qualifier_ctx: Default::default(),
 +            locals,
 +            depth_from_crate_root,
 +        };
 +        let ident_ctx = ctx.expand_and_analyze(
 +            original_file.syntax().clone(),
 +            file_with_fake_ident.syntax().clone(),
 +            offset,
 +            fake_ident_token,
 +        )?;
 +        Some((ctx, ident_ctx))
 +    }
 +}
 +
 +const OP_TRAIT_LANG_NAMES: &[&str] = &[
 +    "add_assign",
 +    "add",
 +    "bitand_assign",
 +    "bitand",
 +    "bitor_assign",
 +    "bitor",
 +    "bitxor_assign",
 +    "bitxor",
 +    "deref_mut",
 +    "deref",
 +    "div_assign",
 +    "div",
 +    "eq",
 +    "fn_mut",
 +    "fn_once",
 +    "fn",
 +    "index_mut",
 +    "index",
 +    "mul_assign",
 +    "mul",
 +    "neg",
 +    "not",
 +    "partial_ord",
 +    "rem_assign",
 +    "rem",
 +    "shl_assign",
 +    "shl",
 +    "shr_assign",
 +    "shr",
 +    "sub",
 +];
index c71ffa0ed86fd754c4d7a0ab6cd29041998d444b,0000000000000000000000000000000000000000..22ec7cead4988cc54d33b9f8c49e6c4b34cd1d88
mode 100644,000000..100644
--- /dev/null
@@@ -1,1233 -1,0 +1,1293 @@@
-     fn expected_type_and_name(&self) -> (Option<Type>, Option<NameOrNameRef>) {
 +//! Module responsible for analyzing the code surrounding the cursor for completion.
 +use std::iter;
 +
 +use hir::{Semantics, Type, TypeInfo};
 +use ide_db::{active_parameter::ActiveParameter, RootDatabase};
 +use syntax::{
 +    algo::{find_node_at_offset, non_trivia_sibling},
 +    ast::{self, AttrKind, HasArgList, HasLoopBody, HasName, NameOrNameRef},
 +    match_ast, AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode,
 +    SyntaxToken, TextRange, TextSize, T,
 +};
 +
 +use crate::context::{
 +    AttrCtx, CompletionAnalysis, CompletionContext, DotAccess, DotAccessKind, ExprCtx,
 +    ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind, NameRefContext,
 +    NameRefKind, ParamContext, ParamKind, PathCompletionCtx, PathKind, PatternContext,
 +    PatternRefutability, Qualified, QualifierCtx, TypeAscriptionTarget, TypeLocation,
 +    COMPLETION_MARKER,
 +};
 +
 +impl<'a> CompletionContext<'a> {
 +    /// Expand attributes and macro calls at the current cursor position for both the original file
 +    /// and fake file repeatedly. As soon as one of the two expansions fail we stop so the original
 +    /// and speculative states stay in sync.
 +    pub(super) fn expand_and_analyze(
 +        &mut self,
 +        mut original_file: SyntaxNode,
 +        mut speculative_file: SyntaxNode,
 +        mut offset: TextSize,
 +        mut fake_ident_token: SyntaxToken,
 +    ) -> Option<CompletionAnalysis> {
 +        let _p = profile::span("CompletionContext::expand_and_fill");
 +        let mut derive_ctx = None;
 +
 +        'expansion: loop {
 +            let parent_item =
 +                |item: &ast::Item| item.syntax().ancestors().skip(1).find_map(ast::Item::cast);
 +            let ancestor_items = iter::successors(
 +                Option::zip(
 +                    find_node_at_offset::<ast::Item>(&original_file, offset),
 +                    find_node_at_offset::<ast::Item>(&speculative_file, offset),
 +                ),
 +                |(a, b)| parent_item(a).zip(parent_item(b)),
 +            );
 +
 +            // first try to expand attributes as these are always the outermost macro calls
 +            'ancestors: for (actual_item, item_with_fake_ident) in ancestor_items {
 +                match (
 +                    self.sema.expand_attr_macro(&actual_item),
 +                    self.sema.speculative_expand_attr_macro(
 +                        &actual_item,
 +                        &item_with_fake_ident,
 +                        fake_ident_token.clone(),
 +                    ),
 +                ) {
 +                    // maybe parent items have attributes, so continue walking the ancestors
 +                    (None, None) => continue 'ancestors,
 +                    // successful expansions
 +                    (Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) => {
 +                        let new_offset = fake_mapped_token.text_range().start();
 +                        if new_offset > actual_expansion.text_range().end() {
 +                            // offset outside of bounds from the original expansion,
 +                            // stop here to prevent problems from happening
 +                            break 'expansion;
 +                        }
 +                        original_file = actual_expansion;
 +                        speculative_file = fake_expansion;
 +                        fake_ident_token = fake_mapped_token;
 +                        offset = new_offset;
 +                        continue 'expansion;
 +                    }
 +                    // exactly one expansion failed, inconsistent state so stop expanding completely
 +                    _ => break 'expansion,
 +                }
 +            }
 +
 +            // No attributes have been expanded, so look for macro_call! token trees or derive token trees
 +            let orig_tt = match find_node_at_offset::<ast::TokenTree>(&original_file, offset) {
 +                Some(it) => it,
 +                None => break 'expansion,
 +            };
 +            let spec_tt = match find_node_at_offset::<ast::TokenTree>(&speculative_file, offset) {
 +                Some(it) => it,
 +                None => break 'expansion,
 +            };
 +
 +            // Expand pseudo-derive expansion
 +            if let (Some(orig_attr), Some(spec_attr)) = (
 +                orig_tt.syntax().parent().and_then(ast::Meta::cast).and_then(|it| it.parent_attr()),
 +                spec_tt.syntax().parent().and_then(ast::Meta::cast).and_then(|it| it.parent_attr()),
 +            ) {
 +                if let (Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) = (
 +                    self.sema.expand_derive_as_pseudo_attr_macro(&orig_attr),
 +                    self.sema.speculative_expand_derive_as_pseudo_attr_macro(
 +                        &orig_attr,
 +                        &spec_attr,
 +                        fake_ident_token.clone(),
 +                    ),
 +                ) {
 +                    derive_ctx = Some((
 +                        actual_expansion,
 +                        fake_expansion,
 +                        fake_mapped_token.text_range().start(),
 +                        orig_attr,
 +                    ));
 +                }
 +                // at this point we won't have any more successful expansions, so stop
 +                break 'expansion;
 +            }
 +
 +            // Expand fn-like macro calls
 +            if let (Some(actual_macro_call), Some(macro_call_with_fake_ident)) = (
 +                orig_tt.syntax().ancestors().find_map(ast::MacroCall::cast),
 +                spec_tt.syntax().ancestors().find_map(ast::MacroCall::cast),
 +            ) {
 +                let mac_call_path0 = actual_macro_call.path().as_ref().map(|s| s.syntax().text());
 +                let mac_call_path1 =
 +                    macro_call_with_fake_ident.path().as_ref().map(|s| s.syntax().text());
 +
 +                // inconsistent state, stop expanding
 +                if mac_call_path0 != mac_call_path1 {
 +                    break 'expansion;
 +                }
 +                let speculative_args = match macro_call_with_fake_ident.token_tree() {
 +                    Some(tt) => tt,
 +                    None => break 'expansion,
 +                };
 +
 +                match (
 +                    self.sema.expand(&actual_macro_call),
 +                    self.sema.speculative_expand(
 +                        &actual_macro_call,
 +                        &speculative_args,
 +                        fake_ident_token.clone(),
 +                    ),
 +                ) {
 +                    // successful expansions
 +                    (Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) => {
 +                        let new_offset = fake_mapped_token.text_range().start();
 +                        if new_offset > actual_expansion.text_range().end() {
 +                            // offset outside of bounds from the original expansion,
 +                            // stop here to prevent problems from happening
 +                            break 'expansion;
 +                        }
 +                        original_file = actual_expansion;
 +                        speculative_file = fake_expansion;
 +                        fake_ident_token = fake_mapped_token;
 +                        offset = new_offset;
 +                        continue 'expansion;
 +                    }
 +                    // at least on expansion failed, we won't have anything to expand from this point
 +                    // onwards so break out
 +                    _ => break 'expansion,
 +                }
 +            }
 +
 +            // none of our states have changed so stop the loop
 +            break 'expansion;
 +        }
 +
 +        self.analyze(&original_file, speculative_file, offset, derive_ctx)
 +    }
 +
 +    /// Calculate the expected type and name of the cursor position.
-                             let ty = if has_ref(&self.token) {
-                                 cov_mark::hit!(expected_type_fn_param_ref);
-                                 ap.ty.remove_ref()
-                             } else {
-                                 Some(ap.ty)
-                             };
-                             (ty, name)
++    fn expected_type_and_name(
++        &self,
++        name_like: &ast::NameLike,
++    ) -> (Option<Type>, Option<NameOrNameRef>) {
 +        let mut node = match self.token.parent() {
 +            Some(it) => it,
 +            None => return (None, None),
 +        };
++
++        let strip_refs = |mut ty: Type| match name_like {
++            ast::NameLike::NameRef(n) => {
++                let p = match n.syntax().parent() {
++                    Some(it) => it,
++                    None => return ty,
++                };
++                let top_syn = match_ast! {
++                    match p {
++                        ast::FieldExpr(e) => e
++                            .syntax()
++                            .ancestors()
++                            .map_while(ast::FieldExpr::cast)
++                            .last()
++                            .map(|it| it.syntax().clone()),
++                        ast::PathSegment(e) => e
++                            .syntax()
++                            .ancestors()
++                            .skip(1)
++                            .take_while(|it| ast::Path::can_cast(it.kind()) || ast::PathExpr::can_cast(it.kind()))
++                            .find_map(ast::PathExpr::cast)
++                            .map(|it| it.syntax().clone()),
++                        _ => None
++                    }
++                };
++                let top_syn = match top_syn {
++                    Some(it) => it,
++                    None => return ty,
++                };
++                for _ in top_syn.ancestors().skip(1).map_while(ast::RefExpr::cast) {
++                    cov_mark::hit!(expected_type_fn_param_ref);
++                    ty = ty.strip_reference();
++                }
++                ty
++            }
++            _ => ty,
++        };
++
 +        loop {
 +            break match_ast! {
 +                match node {
 +                    ast::LetStmt(it) => {
 +                        cov_mark::hit!(expected_type_let_with_leading_char);
 +                        cov_mark::hit!(expected_type_let_without_leading_char);
 +                        let ty = it.pat()
 +                            .and_then(|pat| self.sema.type_of_pat(&pat))
 +                            .or_else(|| it.initializer().and_then(|it| self.sema.type_of_expr(&it)))
 +                            .map(TypeInfo::original);
 +                        let name = match it.pat() {
 +                            Some(ast::Pat::IdentPat(ident)) => ident.name().map(NameOrNameRef::Name),
 +                            Some(_) | None => None,
 +                        };
 +
 +                        (ty, name)
 +                    },
 +                    ast::LetExpr(it) => {
 +                        cov_mark::hit!(expected_type_if_let_without_leading_char);
 +                        let ty = it.pat()
 +                            .and_then(|pat| self.sema.type_of_pat(&pat))
 +                            .or_else(|| it.expr().and_then(|it| self.sema.type_of_expr(&it)))
 +                            .map(TypeInfo::original);
 +                        (ty, None)
 +                    },
 +                    ast::ArgList(_) => {
 +                        cov_mark::hit!(expected_type_fn_param);
 +                        ActiveParameter::at_token(
 +                            &self.sema,
 +                            self.token.clone(),
 +                        ).map(|ap| {
 +                            let name = ap.ident().map(NameOrNameRef::Name);
-         (self.expected_type, self.expected_name) = self.expected_type_and_name();
++
++                            let ty = strip_refs(ap.ty);
++                            (Some(ty), name)
 +                        })
 +                        .unwrap_or((None, None))
 +                    },
 +                    ast::RecordExprFieldList(it) => {
 +                        // wouldn't try {} be nice...
 +                        (|| {
 +                            if self.token.kind() == T![..]
 +                                || self.token.prev_token().map(|t| t.kind()) == Some(T![..])
 +                            {
 +                                cov_mark::hit!(expected_type_struct_func_update);
 +                                let record_expr = it.syntax().parent().and_then(ast::RecordExpr::cast)?;
 +                                let ty = self.sema.type_of_expr(&record_expr.into())?;
 +                                Some((
 +                                    Some(ty.original),
 +                                    None
 +                                ))
 +                            } else {
 +                                cov_mark::hit!(expected_type_struct_field_without_leading_char);
 +                                let expr_field = self.token.prev_sibling_or_token()?
 +                                    .into_node()
 +                                    .and_then(ast::RecordExprField::cast)?;
 +                                let (_, _, ty) = self.sema.resolve_record_field(&expr_field)?;
 +                                Some((
 +                                    Some(ty),
 +                                    expr_field.field_name().map(NameOrNameRef::NameRef),
 +                                ))
 +                            }
 +                        })().unwrap_or((None, None))
 +                    },
 +                    ast::RecordExprField(it) => {
 +                        if let Some(expr) = it.expr() {
 +                            cov_mark::hit!(expected_type_struct_field_with_leading_char);
 +                            (
 +                                self.sema.type_of_expr(&expr).map(TypeInfo::original),
 +                                it.field_name().map(NameOrNameRef::NameRef),
 +                            )
 +                        } else {
 +                            cov_mark::hit!(expected_type_struct_field_followed_by_comma);
 +                            let ty = self.sema.resolve_record_field(&it)
 +                                .map(|(_, _, ty)| ty);
 +                            (
 +                                ty,
 +                                it.field_name().map(NameOrNameRef::NameRef),
 +                            )
 +                        }
 +                    },
 +                    // match foo { $0 }
 +                    // match foo { ..., pat => $0 }
 +                    ast::MatchExpr(it) => {
 +                        let on_arrow = previous_non_trivia_token(self.token.clone()).map_or(false, |it| T![=>] == it.kind());
 +
 +                        let ty = if on_arrow {
 +                            // match foo { ..., pat => $0 }
 +                            cov_mark::hit!(expected_type_match_arm_body_without_leading_char);
 +                            cov_mark::hit!(expected_type_match_arm_body_with_leading_char);
 +                            self.sema.type_of_expr(&it.into())
 +                        } else {
 +                            // match foo { $0 }
 +                            cov_mark::hit!(expected_type_match_arm_without_leading_char);
 +                            it.expr().and_then(|e| self.sema.type_of_expr(&e))
 +                        }.map(TypeInfo::original);
 +                        (ty, None)
 +                    },
 +                    ast::IfExpr(it) => {
 +                        let ty = it.condition()
 +                            .and_then(|e| self.sema.type_of_expr(&e))
 +                            .map(TypeInfo::original);
 +                        (ty, None)
 +                    },
 +                    ast::IdentPat(it) => {
 +                        cov_mark::hit!(expected_type_if_let_with_leading_char);
 +                        cov_mark::hit!(expected_type_match_arm_with_leading_char);
 +                        let ty = self.sema.type_of_pat(&ast::Pat::from(it)).map(TypeInfo::original);
 +                        (ty, None)
 +                    },
 +                    ast::Fn(it) => {
 +                        cov_mark::hit!(expected_type_fn_ret_with_leading_char);
 +                        cov_mark::hit!(expected_type_fn_ret_without_leading_char);
 +                        let def = self.sema.to_def(&it);
 +                        (def.map(|def| def.ret_type(self.db)), None)
 +                    },
 +                    ast::ClosureExpr(it) => {
 +                        let ty = self.sema.type_of_expr(&it.into());
 +                        ty.and_then(|ty| ty.original.as_callable(self.db))
 +                            .map(|c| (Some(c.return_type()), None))
 +                            .unwrap_or((None, None))
 +                    },
 +                    ast::ParamList(_) => (None, None),
 +                    ast::Stmt(_) => (None, None),
 +                    ast::Item(_) => (None, None),
 +                    _ => {
 +                        match node.parent() {
 +                            Some(n) => {
 +                                node = n;
 +                                continue;
 +                            },
 +                            None => (None, None),
 +                        }
 +                    },
 +                }
 +            };
 +        }
 +    }
 +
 +    /// Fill the completion context, this is what does semantic reasoning about the surrounding context
 +    /// of the completion location.
 +    fn analyze(
 +        &mut self,
 +        original_file: &SyntaxNode,
 +        file_with_fake_ident: SyntaxNode,
 +        offset: TextSize,
 +        derive_ctx: Option<(SyntaxNode, SyntaxNode, TextSize, ast::Attr)>,
 +    ) -> Option<CompletionAnalysis> {
 +        let fake_ident_token = file_with_fake_ident.token_at_offset(offset).right_biased()?;
 +        let syntax_element = NodeOrToken::Token(fake_ident_token);
 +        if is_in_token_of_for_loop(syntax_element.clone()) {
 +            // for pat $0
 +            // there is nothing to complete here except `in` keyword
 +            // don't bother populating the context
 +            // FIXME: the completion calculations should end up good enough
 +            // such that this special case becomes unnecessary
 +            return None;
 +        }
 +
-             parent: path.parent_path(),
 +        // Overwrite the path kind for derives
 +        if let Some((original_file, file_with_fake_ident, offset, origin_attr)) = derive_ctx {
 +            if let Some(ast::NameLike::NameRef(name_ref)) =
 +                find_node_at_offset(&file_with_fake_ident, offset)
 +            {
 +                let parent = name_ref.syntax().parent()?;
 +                let (mut nameref_ctx, _) =
 +                    Self::classify_name_ref(&self.sema, &original_file, name_ref, parent)?;
 +                if let NameRefKind::Path(path_ctx) = &mut nameref_ctx.kind {
 +                    path_ctx.kind = PathKind::Derive {
 +                        existing_derives: self
 +                            .sema
 +                            .resolve_derive_macro(&origin_attr)
 +                            .into_iter()
 +                            .flatten()
 +                            .flatten()
 +                            .collect(),
 +                    };
 +                }
 +                return Some(CompletionAnalysis::NameRef(nameref_ctx));
 +            }
 +            return None;
 +        }
 +
 +        let name_like = match find_node_at_offset(&file_with_fake_ident, offset) {
 +            Some(it) => it,
 +            None => {
 +                let analysis =
 +                    if let Some(original) = ast::String::cast(self.original_token.clone()) {
 +                        CompletionAnalysis::String {
 +                            original,
 +                            expanded: ast::String::cast(self.token.clone()),
 +                        }
 +                    } else {
 +                        // Fix up trailing whitespace problem
 +                        // #[attr(foo = $0
 +                        let token =
 +                            syntax::algo::skip_trivia_token(self.token.clone(), Direction::Prev)?;
 +                        let p = token.parent()?;
 +                        if p.kind() == SyntaxKind::TOKEN_TREE
 +                            && p.ancestors().any(|it| it.kind() == SyntaxKind::META)
 +                        {
 +                            let colon_prefix = previous_non_trivia_token(self.token.clone())
 +                                .map_or(false, |it| T![:] == it.kind());
 +                            CompletionAnalysis::UnexpandedAttrTT {
 +                                fake_attribute_under_caret: syntax_element
 +                                    .ancestors()
 +                                    .find_map(ast::Attr::cast),
 +                                colon_prefix,
 +                            }
 +                        } else {
 +                            return None;
 +                        }
 +                    };
 +                return Some(analysis);
 +            }
 +        };
++        (self.expected_type, self.expected_name) = self.expected_type_and_name(&name_like);
 +        let analysis = match name_like {
 +            ast::NameLike::Lifetime(lifetime) => CompletionAnalysis::Lifetime(
 +                Self::classify_lifetime(&self.sema, original_file, lifetime)?,
 +            ),
 +            ast::NameLike::NameRef(name_ref) => {
 +                let parent = name_ref.syntax().parent()?;
 +                let (nameref_ctx, qualifier_ctx) =
 +                    Self::classify_name_ref(&self.sema, &original_file, name_ref, parent.clone())?;
 +
 +                self.qualifier_ctx = qualifier_ctx;
 +                CompletionAnalysis::NameRef(nameref_ctx)
 +            }
 +            ast::NameLike::Name(name) => {
 +                let name_ctx = Self::classify_name(&self.sema, original_file, name)?;
 +                CompletionAnalysis::Name(name_ctx)
 +            }
 +        };
 +        Some(analysis)
 +    }
 +
 +    fn classify_lifetime(
 +        _sema: &Semantics<'_, RootDatabase>,
 +        original_file: &SyntaxNode,
 +        lifetime: ast::Lifetime,
 +    ) -> Option<LifetimeContext> {
 +        let parent = lifetime.syntax().parent()?;
 +        if parent.kind() == SyntaxKind::ERROR {
 +            return None;
 +        }
 +
 +        let kind = match_ast! {
 +            match parent {
 +                ast::LifetimeParam(param) => LifetimeKind::LifetimeParam {
 +                    is_decl: param.lifetime().as_ref() == Some(&lifetime),
 +                    param
 +                },
 +                ast::BreakExpr(_) => LifetimeKind::LabelRef,
 +                ast::ContinueExpr(_) => LifetimeKind::LabelRef,
 +                ast::Label(_) => LifetimeKind::LabelDef,
 +                _ => LifetimeKind::Lifetime,
 +            }
 +        };
 +        let lifetime = find_node_at_offset(&original_file, lifetime.syntax().text_range().start());
 +
 +        Some(LifetimeContext { lifetime, kind })
 +    }
 +
 +    fn classify_name(
 +        sema: &Semantics<'_, RootDatabase>,
 +        original_file: &SyntaxNode,
 +        name: ast::Name,
 +    ) -> Option<NameContext> {
 +        let parent = name.syntax().parent()?;
 +        let kind = match_ast! {
 +            match parent {
 +                ast::Const(_) => NameKind::Const,
 +                ast::ConstParam(_) => NameKind::ConstParam,
 +                ast::Enum(_) => NameKind::Enum,
 +                ast::Fn(_) => NameKind::Function,
 +                ast::IdentPat(bind_pat) => {
 +                    let mut pat_ctx = pattern_context_for(sema, original_file, bind_pat.into());
 +                    if let Some(record_field) = ast::RecordPatField::for_field_name(&name) {
 +                        pat_ctx.record_pat = find_node_in_file_compensated(sema, original_file, &record_field.parent_record_pat());
 +                    }
 +
 +                    NameKind::IdentPat(pat_ctx)
 +                },
 +                ast::MacroDef(_) => NameKind::MacroDef,
 +                ast::MacroRules(_) => NameKind::MacroRules,
 +                ast::Module(module) => NameKind::Module(module),
 +                ast::RecordField(_) => NameKind::RecordField,
 +                ast::Rename(_) => NameKind::Rename,
 +                ast::SelfParam(_) => NameKind::SelfParam,
 +                ast::Static(_) => NameKind::Static,
 +                ast::Struct(_) => NameKind::Struct,
 +                ast::Trait(_) => NameKind::Trait,
 +                ast::TypeAlias(_) => NameKind::TypeAlias,
 +                ast::TypeParam(_) => NameKind::TypeParam,
 +                ast::Union(_) => NameKind::Union,
 +                ast::Variant(_) => NameKind::Variant,
 +                _ => return None,
 +            }
 +        };
 +        let name = find_node_at_offset(&original_file, name.syntax().text_range().start());
 +        Some(NameContext { name, kind })
 +    }
 +
 +    fn classify_name_ref(
 +        sema: &Semantics<'_, RootDatabase>,
 +        original_file: &SyntaxNode,
 +        name_ref: ast::NameRef,
 +        parent: SyntaxNode,
 +    ) -> Option<(NameRefContext, QualifierCtx)> {
 +        let nameref = find_node_at_offset(&original_file, name_ref.syntax().text_range().start());
 +
 +        let make_res =
 +            |kind| (NameRefContext { nameref: nameref.clone(), kind }, Default::default());
 +
 +        if let Some(record_field) = ast::RecordExprField::for_field_name(&name_ref) {
 +            let dot_prefix = previous_non_trivia_token(name_ref.syntax().clone())
 +                .map_or(false, |it| T![.] == it.kind());
 +
 +            return find_node_in_file_compensated(
 +                sema,
 +                original_file,
 +                &record_field.parent_record_lit(),
 +            )
 +            .map(|expr| NameRefKind::RecordExpr { expr, dot_prefix })
 +            .map(make_res);
 +        }
 +        if let Some(record_field) = ast::RecordPatField::for_field_name_ref(&name_ref) {
 +            let kind = NameRefKind::Pattern(PatternContext {
 +                param_ctx: None,
 +                has_type_ascription: false,
 +                ref_token: None,
 +                mut_token: None,
 +                record_pat: find_node_in_file_compensated(
 +                    sema,
 +                    original_file,
 +                    &record_field.parent_record_pat(),
 +                ),
 +                ..pattern_context_for(
 +                    sema,
 +                    original_file,
 +                    record_field.parent_record_pat().clone().into(),
 +                )
 +            });
 +            return Some(make_res(kind));
 +        }
 +
 +        let segment = match_ast! {
 +            match parent {
 +                ast::PathSegment(segment) => segment,
 +                ast::FieldExpr(field) => {
 +                    let receiver = find_opt_node_in_file(original_file, field.expr());
 +                    let receiver_is_ambiguous_float_literal = match &receiver {
 +                        Some(ast::Expr::Literal(l)) => matches! {
 +                            l.kind(),
 +                            ast::LiteralKind::FloatNumber { .. } if l.syntax().last_token().map_or(false, |it| it.text().ends_with('.'))
 +                        },
 +                        _ => false,
 +                    };
 +                    let kind = NameRefKind::DotAccess(DotAccess {
 +                        receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
 +                        kind: DotAccessKind::Field { receiver_is_ambiguous_float_literal },
 +                        receiver
 +                    });
 +                    return Some(make_res(kind));
 +                },
 +                ast::MethodCallExpr(method) => {
 +                    let receiver = find_opt_node_in_file(original_file, method.receiver());
 +                    let kind = NameRefKind::DotAccess(DotAccess {
 +                        receiver_ty: receiver.as_ref().and_then(|it| sema.type_of_expr(it)),
 +                        kind: DotAccessKind::Method { has_parens: method.arg_list().map_or(false, |it| it.l_paren_token().is_some()) },
 +                        receiver
 +                    });
 +                    return Some(make_res(kind));
 +                },
 +                _ => return None,
 +            }
 +        };
 +
 +        let path = segment.parent_path();
 +        let mut path_ctx = PathCompletionCtx {
 +            has_call_parens: false,
 +            has_macro_bang: false,
 +            qualified: Qualified::No,
-                 match parent {
-                     ast::PathType(it) => make_path_kind_type(it.into()),
-                     ast::PathExpr(it) => {
-                         if let Some(p) = it.syntax().parent() {
-                             if ast::ExprStmt::can_cast(p.kind()) {
-                                 if let Some(kind) = inbetween_body_and_decl_check(p) {
-                                     return Some(make_res(NameRefKind::Keyword(kind)));
-                                 }
++            parent: None,
 +            path: path.clone(),
 +            kind: PathKind::Item { kind: ItemListKind::SourceFile },
 +            has_type_args: false,
 +            use_tree_parent: false,
 +        };
 +
 +        let is_in_block = |it: &SyntaxNode| {
 +            it.parent()
 +                .map(|node| {
 +                    ast::ExprStmt::can_cast(node.kind()) || ast::StmtList::can_cast(node.kind())
 +                })
 +                .unwrap_or(false)
 +        };
 +        let func_update_record = |syn: &SyntaxNode| {
 +            if let Some(record_expr) = syn.ancestors().nth(2).and_then(ast::RecordExpr::cast) {
 +                find_node_in_file_compensated(sema, original_file, &record_expr)
 +            } else {
 +                None
 +            }
 +        };
 +        let after_if_expr = |node: SyntaxNode| {
 +            let prev_expr = (|| {
 +                let prev_sibling = non_trivia_sibling(node.into(), Direction::Prev)?.into_node()?;
 +                ast::ExprStmt::cast(prev_sibling)?.expr()
 +            })();
 +            matches!(prev_expr, Some(ast::Expr::IfExpr(_)))
 +        };
 +
 +        // We do not want to generate path completions when we are sandwiched between an item decl signature and its body.
 +        // ex. trait Foo $0 {}
 +        // in these cases parser recovery usually kicks in for our inserted identifier, causing it
 +        // to either be parsed as an ExprStmt or a MacroCall, depending on whether it is in a block
 +        // expression or an item list.
 +        // The following code checks if the body is missing, if it is we either cut off the body
 +        // from the item or it was missing in the first place
 +        let inbetween_body_and_decl_check = |node: SyntaxNode| {
 +            if let Some(NodeOrToken::Node(n)) =
 +                syntax::algo::non_trivia_sibling(node.into(), syntax::Direction::Prev)
 +            {
 +                if let Some(item) = ast::Item::cast(n) {
 +                    let is_inbetween = match &item {
 +                        ast::Item::Const(it) => it.body().is_none(),
 +                        ast::Item::Enum(it) => it.variant_list().is_none(),
 +                        ast::Item::ExternBlock(it) => it.extern_item_list().is_none(),
 +                        ast::Item::Fn(it) => it.body().is_none(),
 +                        ast::Item::Impl(it) => it.assoc_item_list().is_none(),
 +                        ast::Item::Module(it) => it.item_list().is_none(),
 +                        ast::Item::Static(it) => it.body().is_none(),
 +                        ast::Item::Struct(it) => it.field_list().is_none(),
 +                        ast::Item::Trait(it) => it.assoc_item_list().is_none(),
 +                        ast::Item::TypeAlias(it) => it.ty().is_none(),
 +                        ast::Item::Union(it) => it.record_field_list().is_none(),
 +                        _ => false,
 +                    };
 +                    if is_inbetween {
 +                        return Some(item);
 +                    }
 +                }
 +            }
 +            None
 +        };
 +
 +        let type_location = |node: &SyntaxNode| {
 +            let parent = node.parent()?;
 +            let res = match_ast! {
 +                match parent {
 +                    ast::Const(it) => {
 +                        let name = find_opt_node_in_file(original_file, it.name())?;
 +                        let original = ast::Const::cast(name.syntax().parent()?)?;
 +                        TypeLocation::TypeAscription(TypeAscriptionTarget::Const(original.body()))
 +                    },
 +                    ast::RetType(it) => {
 +                        if it.thin_arrow_token().is_none() {
 +                            return None;
 +                        }
 +                        let parent = match ast::Fn::cast(parent.parent()?) {
 +                            Some(x) => x.param_list(),
 +                            None => ast::ClosureExpr::cast(parent.parent()?)?.param_list(),
 +                        };
 +
 +                        let parent = find_opt_node_in_file(original_file, parent)?.syntax().parent()?;
 +                        TypeLocation::TypeAscription(TypeAscriptionTarget::RetType(match_ast! {
 +                            match parent {
 +                                ast::ClosureExpr(it) => {
 +                                    it.body()
 +                                },
 +                                ast::Fn(it) => {
 +                                    it.body().map(ast::Expr::BlockExpr)
 +                                },
 +                                _ => return None,
 +                            }
 +                        }))
 +                    },
 +                    ast::Param(it) => {
 +                        if it.colon_token().is_none() {
 +                            return None;
 +                        }
 +                        TypeLocation::TypeAscription(TypeAscriptionTarget::FnParam(find_opt_node_in_file(original_file, it.pat())))
 +                    },
 +                    ast::LetStmt(it) => {
 +                        if it.colon_token().is_none() {
 +                            return None;
 +                        }
 +                        TypeLocation::TypeAscription(TypeAscriptionTarget::Let(find_opt_node_in_file(original_file, it.pat())))
 +                    },
 +                    ast::Impl(it) => {
 +                        match it.trait_() {
 +                            Some(t) if t.syntax() == node => TypeLocation::ImplTrait,
 +                            _ => match it.self_ty() {
 +                                Some(t) if t.syntax() == node => TypeLocation::ImplTarget,
 +                                _ => return None,
 +                            },
 +                        }
 +                    },
 +                    ast::TypeBound(_) => TypeLocation::TypeBound,
 +                    // is this case needed?
 +                    ast::TypeBoundList(_) => TypeLocation::TypeBound,
 +                    ast::GenericArg(it) => TypeLocation::GenericArgList(find_opt_node_in_file_compensated(sema, original_file, it.syntax().parent().and_then(ast::GenericArgList::cast))),
 +                    // is this case needed?
 +                    ast::GenericArgList(it) => TypeLocation::GenericArgList(find_opt_node_in_file_compensated(sema, original_file, Some(it))),
 +                    ast::TupleField(_) => TypeLocation::TupleField,
 +                    _ => return None,
 +                }
 +            };
 +            Some(res)
 +        };
 +
 +        let is_in_condition = |it: &ast::Expr| {
 +            (|| {
 +                let parent = it.syntax().parent()?;
 +                if let Some(expr) = ast::WhileExpr::cast(parent.clone()) {
 +                    Some(expr.condition()? == *it)
 +                } else if let Some(expr) = ast::IfExpr::cast(parent) {
 +                    Some(expr.condition()? == *it)
 +                } else {
 +                    None
 +                }
 +            })()
 +            .unwrap_or(false)
 +        };
 +
 +        let make_path_kind_expr = |expr: ast::Expr| {
 +            let it = expr.syntax();
 +            let in_block_expr = is_in_block(it);
 +            let in_loop_body = is_in_loop_body(it);
 +            let after_if_expr = after_if_expr(it.clone());
 +            let ref_expr_parent =
 +                path.as_single_name_ref().and_then(|_| it.parent()).and_then(ast::RefExpr::cast);
 +            let (innermost_ret_ty, self_param) = {
 +                let find_ret_ty = |it: SyntaxNode| {
 +                    if let Some(item) = ast::Item::cast(it.clone()) {
 +                        match item {
 +                            ast::Item::Fn(f) => {
 +                                Some(sema.to_def(&f).map(|it| it.ret_type(sema.db)))
 +                            }
 +                            ast::Item::MacroCall(_) => None,
 +                            _ => Some(None),
 +                        }
 +                    } else {
 +                        let expr = ast::Expr::cast(it)?;
 +                        let callable = match expr {
 +                            // FIXME
 +                            // ast::Expr::BlockExpr(b) if b.async_token().is_some() || b.try_token().is_some() => sema.type_of_expr(b),
 +                            ast::Expr::ClosureExpr(_) => sema.type_of_expr(&expr),
 +                            _ => return None,
 +                        };
 +                        Some(
 +                            callable
 +                                .and_then(|c| c.adjusted().as_callable(sema.db))
 +                                .map(|it| it.return_type()),
 +                        )
 +                    }
 +                };
 +                let find_fn_self_param = |it| match it {
 +                    ast::Item::Fn(fn_) => {
 +                        Some(sema.to_def(&fn_).and_then(|it| it.self_param(sema.db)))
 +                    }
 +                    ast::Item::MacroCall(_) => None,
 +                    _ => Some(None),
 +                };
 +
 +                match find_node_in_file_compensated(sema, original_file, &expr) {
 +                    Some(it) => {
 +                        let innermost_ret_ty = sema
 +                            .ancestors_with_macros(it.syntax().clone())
 +                            .find_map(find_ret_ty)
 +                            .flatten();
 +
 +                        let self_param = sema
 +                            .ancestors_with_macros(it.syntax().clone())
 +                            .filter_map(ast::Item::cast)
 +                            .find_map(find_fn_self_param)
 +                            .flatten();
 +                        (innermost_ret_ty, self_param)
 +                    }
 +                    None => (None, None),
 +                }
 +            };
 +            let is_func_update = func_update_record(it);
 +            let in_condition = is_in_condition(&expr);
 +            let incomplete_let = it
 +                .parent()
 +                .and_then(ast::LetStmt::cast)
 +                .map_or(false, |it| it.semicolon_token().is_none());
 +            let impl_ = fetch_immediate_impl(sema, original_file, expr.syntax());
 +
 +            let in_match_guard = match it.parent().and_then(ast::MatchArm::cast) {
 +                Some(arm) => arm
 +                    .fat_arrow_token()
 +                    .map_or(true, |arrow| it.text_range().start() < arrow.text_range().start()),
 +                None => false,
 +            };
 +
 +            PathKind::Expr {
 +                expr_ctx: ExprCtx {
 +                    in_block_expr,
 +                    in_loop_body,
 +                    after_if_expr,
 +                    in_condition,
 +                    ref_expr_parent,
 +                    is_func_update,
 +                    innermost_ret_ty,
 +                    self_param,
 +                    incomplete_let,
 +                    impl_,
 +                    in_match_guard,
 +                },
 +            }
 +        };
 +        let make_path_kind_type = |ty: ast::Type| {
 +            let location = type_location(ty.syntax());
 +            PathKind::Type { location: location.unwrap_or(TypeLocation::Other) }
 +        };
 +
++        let mut kind_macro_call = |it: ast::MacroCall| {
++            path_ctx.has_macro_bang = it.excl_token().is_some();
++            let parent = it.syntax().parent()?;
++            // Any path in an item list will be treated as a macro call by the parser
++            let kind = match_ast! {
++                match parent {
++                    ast::MacroExpr(expr) => make_path_kind_expr(expr.into()),
++                    ast::MacroPat(it) => PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())},
++                    ast::MacroType(ty) => make_path_kind_type(ty.into()),
++                    ast::ItemList(_) => PathKind::Item { kind: ItemListKind::Module },
++                    ast::AssocItemList(_) => PathKind::Item { kind: match parent.parent() {
++                        Some(it) => match_ast! {
++                            match it {
++                                ast::Trait(_) => ItemListKind::Trait,
++                                ast::Impl(it) => if it.trait_().is_some() {
++                                    ItemListKind::TraitImpl(find_node_in_file_compensated(sema, original_file, &it))
++                                } else {
++                                    ItemListKind::Impl
++                                },
++                                _ => return None
++                            }
++                        },
++                        None => return None,
++                    } },
++                    ast::ExternItemList(_) => PathKind::Item { kind: ItemListKind::ExternBlock },
++                    ast::SourceFile(_) => PathKind::Item { kind: ItemListKind::SourceFile },
++                    _ => return None,
++                }
++            };
++            Some(kind)
++        };
++        let make_path_kind_attr = |meta: ast::Meta| {
++            let attr = meta.parent_attr()?;
++            let kind = attr.kind();
++            let attached = attr.syntax().parent()?;
++            let is_trailing_outer_attr = kind != AttrKind::Inner
++                && non_trivia_sibling(attr.syntax().clone().into(), syntax::Direction::Next)
++                    .is_none();
++            let annotated_item_kind =
++                if is_trailing_outer_attr { None } else { Some(attached.kind()) };
++            Some(PathKind::Attr { attr_ctx: AttrCtx { kind, annotated_item_kind } })
++        };
++
 +        // Infer the path kind
 +        let parent = path.syntax().parent()?;
 +        let kind = match_ast! {
-                         path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
++            match parent {
++                ast::PathType(it) => make_path_kind_type(it.into()),
++                ast::PathExpr(it) => {
++                    if let Some(p) = it.syntax().parent() {
++                        if ast::ExprStmt::can_cast(p.kind()) {
++                            if let Some(kind) = inbetween_body_and_decl_check(p) {
++                                return Some(make_res(NameRefKind::Keyword(kind)));
 +                            }
 +                        }
++                    }
 +
-                         make_path_kind_expr(it.into())
-                     },
-                     ast::TupleStructPat(it) => {
-                         path_ctx.has_call_parens = true;
-                         PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())}
-                     },
-                     ast::RecordPat(it) => {
-                         path_ctx.has_call_parens = true;
-                         PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())}
-                     },
-                     ast::PathPat(it) => {
-                         PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())}
-                     },
-                     ast::MacroCall(it) => {
-                         // A macro call in this position is usually a result of parsing recovery, so check that
-                         if let Some(kind) = inbetween_body_and_decl_check(it.syntax().clone()) {
-                             return Some(make_res(NameRefKind::Keyword(kind)));
-                         }
++                    path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
 +
-                         path_ctx.has_macro_bang = it.excl_token().is_some();
-                         let parent = it.syntax().parent()?;
-                         // Any path in an item list will be treated as a macro call by the parser
-                         match_ast! {
-                             match parent {
-                                 ast::MacroExpr(expr) => make_path_kind_expr(expr.into()),
-                                 ast::MacroPat(it) => PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())},
-                                 ast::MacroType(ty) => make_path_kind_type(ty.into()),
-                                 ast::ItemList(_) => PathKind::Item { kind: ItemListKind::Module },
-                                 ast::AssocItemList(_) => PathKind::Item { kind: match parent.parent() {
-                                     Some(it) => match_ast! {
-                                         match it {
-                                             ast::Trait(_) => ItemListKind::Trait,
-                                             ast::Impl(it) => if it.trait_().is_some() {
-                                                 ItemListKind::TraitImpl(find_node_in_file_compensated(sema, original_file, &it))
-                                             } else {
-                                                 ItemListKind::Impl
-                                             },
-                                             _ => return None
-                                         }
-                                     },
-                                     None => return None,
-                                 } },
-                                 ast::ExternItemList(_) => PathKind::Item { kind: ItemListKind::ExternBlock },
-                                 ast::SourceFile(_) => PathKind::Item { kind: ItemListKind::SourceFile },
-                                 _ => return None,
-                             }
-                         }
-                     },
-                     ast::Meta(meta) => {
-                         let attr = meta.parent_attr()?;
-                         let kind = attr.kind();
-                         let attached = attr.syntax().parent()?;
-                         let is_trailing_outer_attr = kind != AttrKind::Inner
-                             && non_trivia_sibling(attr.syntax().clone().into(), syntax::Direction::Next).is_none();
-                         let annotated_item_kind = if is_trailing_outer_attr {
-                             None
-                         } else {
-                             Some(attached.kind())
-                         };
-                         PathKind::Attr {
-                             attr_ctx: AttrCtx {
-                                 kind,
-                                 annotated_item_kind,
-                             }
++                    make_path_kind_expr(it.into())
++                },
++                ast::TupleStructPat(it) => {
++                    path_ctx.has_call_parens = true;
++                    PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into()) }
++                },
++                ast::RecordPat(it) => {
++                    path_ctx.has_call_parens = true;
++                    PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into()) }
++                },
++                ast::PathPat(it) => {
++                    PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())}
++                },
++                ast::MacroCall(it) => {
++                    // A macro call in this position is usually a result of parsing recovery, so check that
++                    if let Some(kind) = inbetween_body_and_decl_check(it.syntax().clone()) {
++                        return Some(make_res(NameRefKind::Keyword(kind)));
++                    }
 +
-                     },
-                     ast::Visibility(it) => PathKind::Vis { has_in_token: it.in_token().is_some() },
-                     ast::UseTree(_) => PathKind::Use,
-                     _ => return None,
++                    kind_macro_call(it)?
++                },
++                ast::Meta(meta) => make_path_kind_attr(meta)?,
++                ast::Visibility(it) => PathKind::Vis { has_in_token: it.in_token().is_some() },
++                ast::UseTree(_) => PathKind::Use,
++                // completing inside a qualifier
++                ast::Path(parent) => {
++                    path_ctx.parent = Some(parent.clone());
++                    let parent = iter::successors(Some(parent), |it| it.parent_path()).last()?.syntax().parent()?;
++                    match_ast! {
++                        match parent {
++                            ast::PathType(it) => make_path_kind_type(it.into()),
++                            ast::PathExpr(it) => {
++                                path_ctx.has_call_parens = it.syntax().parent().map_or(false, |it| ast::CallExpr::can_cast(it.kind()));
++
++                                make_path_kind_expr(it.into())
++                            },
++                            ast::TupleStructPat(it) => {
++                                path_ctx.has_call_parens = true;
++                                PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into()) }
++                            },
++                            ast::RecordPat(it) => {
++                                path_ctx.has_call_parens = true;
++                                PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into()) }
++                            },
++                            ast::PathPat(it) => {
++                                PathKind::Pat { pat_ctx: pattern_context_for(sema, original_file, it.into())}
++                            },
++                            ast::MacroCall(it) => {
++                                kind_macro_call(it)?
++                            },
++                            ast::Meta(meta) => make_path_kind_attr(meta)?,
++                            ast::Visibility(it) => PathKind::Vis { has_in_token: it.in_token().is_some() },
++                            ast::UseTree(_) => PathKind::Use,
++                            ast::RecordExpr(it) => make_path_kind_expr(it.into()),
++                            _ => return None,
 +                        }
-         if let Some((path, use_tree_parent)) = path_or_use_tree_qualifier(&path) {
++                    }
++                },
++                ast::RecordExpr(it) => make_path_kind_expr(it.into()),
++                _ => return None,
 +            }
 +        };
 +
 +        path_ctx.kind = kind;
 +        path_ctx.has_type_args = segment.generic_arg_list().is_some();
 +
 +        // calculate the qualifier context
-                 let path = path
++        if let Some((qualifier, use_tree_parent)) = path_or_use_tree_qualifier(&path) {
 +            path_ctx.use_tree_parent = use_tree_parent;
 +            if !use_tree_parent && segment.coloncolon_token().is_some() {
 +                path_ctx.qualified = Qualified::Absolute;
 +            } else {
-                 if let Some(path) = path {
-                     // `<_>::$0`
-                     let is_infer_qualifier = path.qualifier().is_none()
-                         && matches!(
-                             path.segment().and_then(|it| it.kind()),
-                             Some(ast::PathSegmentKind::Type {
-                                 type_ref: Some(ast::Type::InferType(_)),
-                                 trait_ref: None,
-                             })
-                         );
++                let qualifier = qualifier
 +                    .segment()
 +                    .and_then(|it| find_node_in_file(original_file, &it))
 +                    .map(|it| it.parent_path());
-                     path_ctx.qualified = if is_infer_qualifier {
-                         Qualified::Infer
++                if let Some(qualifier) = qualifier {
++                    let type_anchor = match qualifier.segment().and_then(|it| it.kind()) {
++                        Some(ast::PathSegmentKind::Type {
++                            type_ref: Some(type_ref),
++                            trait_ref,
++                        }) if qualifier.qualifier().is_none() => Some((type_ref, trait_ref)),
++                        _ => None,
++                    };
 +
-                         let res = sema.resolve_path(&path);
++                    path_ctx.qualified = if let Some((ty, trait_ref)) = type_anchor {
++                        let ty = match ty {
++                            ast::Type::InferType(_) => None,
++                            ty => sema.resolve_type(&ty),
++                        };
++                        let trait_ = trait_ref.and_then(|it| sema.resolve_trait(&it.path()?));
++                        Qualified::TypeAnchor { ty, trait_ }
 +                    } else {
-                         let super_count = iter::successors(Some(path.clone()), |p| p.qualifier())
-                             .take_while(|p| {
-                                 p.segment()
-                                     .and_then(|s| {
-                                         segment_count += 1;
-                                         s.super_token()
-                                     })
-                                     .is_some()
-                             })
-                             .count();
++                        let res = sema.resolve_path(&qualifier);
 +
 +                        // For understanding how and why super_chain_len is calculated the way it
 +                        // is check the documentation at it's definition
 +                        let mut segment_count = 0;
-                         Qualified::With { path, resolution: res, super_chain_len }
++                        let super_count =
++                            iter::successors(Some(qualifier.clone()), |p| p.qualifier())
++                                .take_while(|p| {
++                                    p.segment()
++                                        .and_then(|s| {
++                                            segment_count += 1;
++                                            s.super_token()
++                                        })
++                                        .is_some()
++                                })
++                                .count();
 +
 +                        let super_chain_len =
 +                            if segment_count > super_count { None } else { Some(super_count) };
 +
- fn has_ref(token: &SyntaxToken) -> bool {
-     let mut token = token.clone();
-     for skip in [SyntaxKind::IDENT, SyntaxKind::WHITESPACE, T![mut]] {
-         if token.kind() == skip {
-             token = match token.prev_token() {
-                 Some(it) => it,
-                 None => return false,
-             }
-         }
-     }
-     token.kind() == T![&]
- }
++                        Qualified::With { path: qualifier, resolution: res, super_chain_len }
 +                    }
 +                };
 +            }
 +        } else if let Some(segment) = path.segment() {
 +            if segment.coloncolon_token().is_some() {
 +                path_ctx.qualified = Qualified::Absolute;
 +            }
 +        }
 +
 +        let mut qualifier_ctx = QualifierCtx::default();
 +        if path_ctx.is_trivial_path() {
 +            // fetch the full expression that may have qualifiers attached to it
 +            let top_node = match path_ctx.kind {
 +                PathKind::Expr { expr_ctx: ExprCtx { in_block_expr: true, .. } } => {
 +                    parent.ancestors().find(|it| ast::PathExpr::can_cast(it.kind())).and_then(|p| {
 +                        let parent = p.parent()?;
 +                        if ast::StmtList::can_cast(parent.kind()) {
 +                            Some(p)
 +                        } else if ast::ExprStmt::can_cast(parent.kind()) {
 +                            Some(parent)
 +                        } else {
 +                            None
 +                        }
 +                    })
 +                }
 +                PathKind::Item { .. } => {
 +                    parent.ancestors().find(|it| ast::MacroCall::can_cast(it.kind()))
 +                }
 +                _ => None,
 +            };
 +            if let Some(top) = top_node {
 +                if let Some(NodeOrToken::Node(error_node)) =
 +                    syntax::algo::non_trivia_sibling(top.clone().into(), syntax::Direction::Prev)
 +                {
 +                    if error_node.kind() == SyntaxKind::ERROR {
 +                        qualifier_ctx.unsafe_tok = error_node
 +                            .children_with_tokens()
 +                            .filter_map(NodeOrToken::into_token)
 +                            .find(|it| it.kind() == T![unsafe]);
 +                        qualifier_ctx.vis_node =
 +                            error_node.children().find_map(ast::Visibility::cast);
 +                    }
 +                }
 +
 +                if let PathKind::Item { .. } = path_ctx.kind {
 +                    if qualifier_ctx.none() {
 +                        if let Some(t) = top.first_token() {
 +                            if let Some(prev) = t
 +                                .prev_token()
 +                                .and_then(|t| syntax::algo::skip_trivia_token(t, Direction::Prev))
 +                            {
 +                                if ![T![;], T!['}'], T!['{']].contains(&prev.kind()) {
 +                                    // This was inferred to be an item position path, but it seems
 +                                    // to be part of some other broken node which leaked into an item
 +                                    // list
 +                                    return None;
 +                                }
 +                            }
 +                        }
 +                    }
 +                }
 +            }
 +        }
 +        Some((NameRefContext { nameref, kind: NameRefKind::Path(path_ctx) }, qualifier_ctx))
 +    }
 +}
 +
 +fn pattern_context_for(
 +    sema: &Semantics<'_, RootDatabase>,
 +    original_file: &SyntaxNode,
 +    pat: ast::Pat,
 +) -> PatternContext {
 +    let mut param_ctx = None;
 +    let (refutability, has_type_ascription) =
 +    pat
 +        .syntax()
 +        .ancestors()
 +        .skip_while(|it| ast::Pat::can_cast(it.kind()))
 +        .next()
 +        .map_or((PatternRefutability::Irrefutable, false), |node| {
 +            let refutability = match_ast! {
 +                match node {
 +                    ast::LetStmt(let_) => return (PatternRefutability::Irrefutable, let_.ty().is_some()),
 +                    ast::Param(param) => {
 +                        let has_type_ascription = param.ty().is_some();
 +                        param_ctx = (|| {
 +                            let fake_param_list = param.syntax().parent().and_then(ast::ParamList::cast)?;
 +                            let param_list = find_node_in_file_compensated(sema, original_file, &fake_param_list)?;
 +                            let param_list_owner = param_list.syntax().parent()?;
 +                            let kind = match_ast! {
 +                                match param_list_owner {
 +                                    ast::ClosureExpr(closure) => ParamKind::Closure(closure),
 +                                    ast::Fn(fn_) => ParamKind::Function(fn_),
 +                                    _ => return None,
 +                                }
 +                            };
 +                            Some(ParamContext {
 +                                param_list, param, kind
 +                            })
 +                        })();
 +                        return (PatternRefutability::Irrefutable, has_type_ascription)
 +                    },
 +                    ast::MatchArm(_) => PatternRefutability::Refutable,
 +                    ast::LetExpr(_) => PatternRefutability::Refutable,
 +                    ast::ForExpr(_) => PatternRefutability::Irrefutable,
 +                    _ => PatternRefutability::Irrefutable,
 +                }
 +            };
 +            (refutability, false)
 +        });
 +    let (ref_token, mut_token) = match &pat {
 +        ast::Pat::IdentPat(it) => (it.ref_token(), it.mut_token()),
 +        _ => (None, None),
 +    };
 +
 +    PatternContext {
 +        refutability,
 +        param_ctx,
 +        has_type_ascription,
 +        parent_pat: pat.syntax().parent().and_then(ast::Pat::cast),
 +        mut_token,
 +        ref_token,
 +        record_pat: None,
 +        impl_: fetch_immediate_impl(sema, original_file, pat.syntax()),
 +    }
 +}
 +
 +fn fetch_immediate_impl(
 +    sema: &Semantics<'_, RootDatabase>,
 +    original_file: &SyntaxNode,
 +    node: &SyntaxNode,
 +) -> Option<ast::Impl> {
 +    let mut ancestors = ancestors_in_file_compensated(sema, original_file, node)?
 +        .filter_map(ast::Item::cast)
 +        .filter(|it| !matches!(it, ast::Item::MacroCall(_)));
 +
 +    match ancestors.next()? {
 +        ast::Item::Const(_) | ast::Item::Fn(_) | ast::Item::TypeAlias(_) => (),
 +        ast::Item::Impl(it) => return Some(it),
 +        _ => return None,
 +    }
 +    match ancestors.next()? {
 +        ast::Item::Impl(it) => Some(it),
 +        _ => None,
 +    }
 +}
 +
 +/// Attempts to find `node` inside `syntax` via `node`'s text range.
 +/// If the fake identifier has been inserted after this node or inside of this node use the `_compensated` version instead.
 +fn find_opt_node_in_file<N: AstNode>(syntax: &SyntaxNode, node: Option<N>) -> Option<N> {
 +    find_node_in_file(syntax, &node?)
 +}
 +
 +/// Attempts to find `node` inside `syntax` via `node`'s text range.
 +/// If the fake identifier has been inserted after this node or inside of this node use the `_compensated` version instead.
 +fn find_node_in_file<N: AstNode>(syntax: &SyntaxNode, node: &N) -> Option<N> {
 +    let syntax_range = syntax.text_range();
 +    let range = node.syntax().text_range();
 +    let intersection = range.intersect(syntax_range)?;
 +    syntax.covering_element(intersection).ancestors().find_map(N::cast)
 +}
 +
 +/// Attempts to find `node` inside `syntax` via `node`'s text range while compensating
 +/// for the offset introduced by the fake ident.
 +/// This is wrong if `node` comes before the insertion point! Use `find_node_in_file` instead.
 +fn find_node_in_file_compensated<N: AstNode>(
 +    sema: &Semantics<'_, RootDatabase>,
 +    in_file: &SyntaxNode,
 +    node: &N,
 +) -> Option<N> {
 +    ancestors_in_file_compensated(sema, in_file, node.syntax())?.find_map(N::cast)
 +}
 +
 +fn ancestors_in_file_compensated<'sema>(
 +    sema: &'sema Semantics<'_, RootDatabase>,
 +    in_file: &SyntaxNode,
 +    node: &SyntaxNode,
 +) -> Option<impl Iterator<Item = SyntaxNode> + 'sema> {
 +    let syntax_range = in_file.text_range();
 +    let range = node.text_range();
 +    let end = range.end().checked_sub(TextSize::try_from(COMPLETION_MARKER.len()).ok()?)?;
 +    if end < range.start() {
 +        return None;
 +    }
 +    let range = TextRange::new(range.start(), end);
 +    // our inserted ident could cause `range` to go outside of the original syntax, so cap it
 +    let intersection = range.intersect(syntax_range)?;
 +    let node = match in_file.covering_element(intersection) {
 +        NodeOrToken::Node(node) => node,
 +        NodeOrToken::Token(tok) => tok.parent()?,
 +    };
 +    Some(sema.ancestors_with_macros(node))
 +}
 +
 +/// Attempts to find `node` inside `syntax` via `node`'s text range while compensating
 +/// for the offset introduced by the fake ident..
 +/// This is wrong if `node` comes before the insertion point! Use `find_node_in_file` instead.
 +fn find_opt_node_in_file_compensated<N: AstNode>(
 +    sema: &Semantics<'_, RootDatabase>,
 +    syntax: &SyntaxNode,
 +    node: Option<N>,
 +) -> Option<N> {
 +    find_node_in_file_compensated(sema, syntax, &node?)
 +}
 +
 +fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> {
 +    if let Some(qual) = path.qualifier() {
 +        return Some((qual, false));
 +    }
 +    let use_tree_list = path.syntax().ancestors().find_map(ast::UseTreeList::cast)?;
 +    let use_tree = use_tree_list.syntax().parent().and_then(ast::UseTree::cast)?;
 +    Some((use_tree.path()?, true))
 +}
 +
 +pub(crate) fn is_in_token_of_for_loop(element: SyntaxElement) -> bool {
 +    // oh my ...
 +    (|| {
 +        let syntax_token = element.into_token()?;
 +        let range = syntax_token.text_range();
 +        let for_expr = syntax_token.parent_ancestors().find_map(ast::ForExpr::cast)?;
 +
 +        // check if the current token is the `in` token of a for loop
 +        if let Some(token) = for_expr.in_token() {
 +            return Some(syntax_token == token);
 +        }
 +        let pat = for_expr.pat()?;
 +        if range.end() < pat.syntax().text_range().end() {
 +            // if we are inside or before the pattern we can't be at the `in` token position
 +            return None;
 +        }
 +        let next_sibl = next_non_trivia_sibling(pat.syntax().clone().into())?;
 +        Some(match next_sibl {
 +            // the loop body is some node, if our token is at the start we are at the `in` position,
 +            // otherwise we could be in a recovered expression, we don't wanna ruin completions there
 +            syntax::NodeOrToken::Node(n) => n.text_range().start() == range.start(),
 +            // the loop body consists of a single token, if we are this we are certainly at the `in` token position
 +            syntax::NodeOrToken::Token(t) => t == syntax_token,
 +        })
 +    })()
 +    .unwrap_or(false)
 +}
 +
 +#[test]
 +fn test_for_is_prev2() {
 +    crate::tests::check_pattern_is_applicable(r"fn __() { for i i$0 }", is_in_token_of_for_loop);
 +}
 +
 +pub(crate) fn is_in_loop_body(node: &SyntaxNode) -> bool {
 +    node.ancestors()
 +        .take_while(|it| it.kind() != SyntaxKind::FN && it.kind() != SyntaxKind::CLOSURE_EXPR)
 +        .find_map(|it| {
 +            let loop_body = match_ast! {
 +                match it {
 +                    ast::ForExpr(it) => it.loop_body(),
 +                    ast::WhileExpr(it) => it.loop_body(),
 +                    ast::LoopExpr(it) => it.loop_body(),
 +                    _ => None,
 +                }
 +            };
 +            loop_body.filter(|it| it.syntax().text_range().contains_range(node.text_range()))
 +        })
 +        .is_some()
 +}
 +
 +fn previous_non_trivia_token(e: impl Into<SyntaxElement>) -> Option<SyntaxToken> {
 +    let mut token = match e.into() {
 +        SyntaxElement::Node(n) => n.first_token()?,
 +        SyntaxElement::Token(t) => t,
 +    }
 +    .prev_token();
 +    while let Some(inner) = token {
 +        if !inner.kind().is_trivia() {
 +            return Some(inner);
 +        } else {
 +            token = inner.prev_token();
 +        }
 +    }
 +    None
 +}
 +
 +fn next_non_trivia_sibling(ele: SyntaxElement) -> Option<SyntaxElement> {
 +    let mut e = ele.next_sibling_or_token();
 +    while let Some(inner) = e {
 +        if !inner.kind().is_trivia() {
 +            return Some(inner);
 +        } else {
 +            e = inner.next_sibling_or_token();
 +        }
 +    }
 +    None
 +}
index c5557bdafb339e1abc1e08a2705d2d6ec2f4b17b,0000000000000000000000000000000000000000..50845b3881f433953014dfa47d3ec00261806bf7
mode 100644,000000..100644
--- /dev/null
@@@ -1,393 -1,0 +1,413 @@@
 +use expect_test::{expect, Expect};
 +use hir::HirDisplay;
 +
 +use crate::{
 +    context::CompletionContext,
 +    tests::{position, TEST_CONFIG},
 +};
 +
 +fn check_expected_type_and_name(ra_fixture: &str, expect: Expect) {
 +    let (db, pos) = position(ra_fixture);
 +    let config = TEST_CONFIG;
 +    let (completion_context, _analysis) = CompletionContext::new(&db, pos, &config).unwrap();
 +
 +    let ty = completion_context
 +        .expected_type
 +        .map(|t| t.display_test(&db).to_string())
 +        .unwrap_or("?".to_owned());
 +
 +    let name =
 +        completion_context.expected_name.map_or_else(|| "?".to_owned(), |name| name.to_string());
 +
 +    expect.assert_eq(&format!("ty: {}, name: {}", ty, name));
 +}
 +
 +#[test]
 +fn expected_type_let_without_leading_char() {
 +    cov_mark::check!(expected_type_let_without_leading_char);
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() {
 +    let x: u32 = $0;
 +}
 +"#,
 +        expect![[r#"ty: u32, name: x"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_let_with_leading_char() {
 +    cov_mark::check!(expected_type_let_with_leading_char);
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() {
 +    let x: u32 = c$0;
 +}
 +"#,
 +        expect![[r#"ty: u32, name: x"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_let_pat() {
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() {
 +    let x$0 = 0u32;
 +}
 +"#,
 +        expect![[r#"ty: u32, name: ?"#]],
 +    );
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() {
 +    let $0 = 0u32;
 +}
 +"#,
 +        expect![[r#"ty: u32, name: ?"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_fn_param() {
 +    cov_mark::check!(expected_type_fn_param);
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() { bar($0); }
 +fn bar(x: u32) {}
 +"#,
 +        expect![[r#"ty: u32, name: x"#]],
 +    );
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() { bar(c$0); }
 +fn bar(x: u32) {}
 +"#,
 +        expect![[r#"ty: u32, name: x"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_fn_param_ref() {
 +    cov_mark::check!(expected_type_fn_param_ref);
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() { bar(&$0); }
 +fn bar(x: &u32) {}
 +"#,
 +        expect![[r#"ty: u32, name: x"#]],
 +    );
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() { bar(&mut $0); }
 +fn bar(x: &mut u32) {}
 +"#,
 +        expect![[r#"ty: u32, name: x"#]],
 +    );
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() { bar(& c$0); }
 +fn bar(x: &u32) {}
 +        "#,
 +        expect![[r#"ty: u32, name: x"#]],
 +    );
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() { bar(&mut c$0); }
 +fn bar(x: &mut u32) {}
 +"#,
 +        expect![[r#"ty: u32, name: x"#]],
 +    );
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() { bar(&c$0); }
 +fn bar(x: &u32) {}
 +        "#,
 +        expect![[r#"ty: u32, name: x"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_struct_field_without_leading_char() {
 +    cov_mark::check!(expected_type_struct_field_without_leading_char);
 +    check_expected_type_and_name(
 +        r#"
 +struct Foo { a: u32 }
 +fn foo() {
 +    Foo { a: $0 };
 +}
 +"#,
 +        expect![[r#"ty: u32, name: a"#]],
 +    )
 +}
 +
 +#[test]
 +fn expected_type_struct_field_followed_by_comma() {
 +    cov_mark::check!(expected_type_struct_field_followed_by_comma);
 +    check_expected_type_and_name(
 +        r#"
 +struct Foo { a: u32 }
 +fn foo() {
 +    Foo { a: $0, };
 +}
 +"#,
 +        expect![[r#"ty: u32, name: a"#]],
 +    )
 +}
 +
 +#[test]
 +fn expected_type_generic_struct_field() {
 +    check_expected_type_and_name(
 +        r#"
 +struct Foo<T> { a: T }
 +fn foo() -> Foo<u32> {
 +    Foo { a: $0 }
 +}
 +"#,
 +        expect![[r#"ty: u32, name: a"#]],
 +    )
 +}
 +
 +#[test]
 +fn expected_type_struct_field_with_leading_char() {
 +    cov_mark::check!(expected_type_struct_field_with_leading_char);
 +    check_expected_type_and_name(
 +        r#"
 +struct Foo { a: u32 }
 +fn foo() {
 +    Foo { a: c$0 };
 +}
 +"#,
 +        expect![[r#"ty: u32, name: a"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_match_arm_without_leading_char() {
 +    cov_mark::check!(expected_type_match_arm_without_leading_char);
 +    check_expected_type_and_name(
 +        r#"
 +enum E { X }
 +fn foo() {
 +   match E::X { $0 }
 +}
 +"#,
 +        expect![[r#"ty: E, name: ?"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_match_arm_with_leading_char() {
 +    cov_mark::check!(expected_type_match_arm_with_leading_char);
 +    check_expected_type_and_name(
 +        r#"
 +enum E { X }
 +fn foo() {
 +   match E::X { c$0 }
 +}
 +"#,
 +        expect![[r#"ty: E, name: ?"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_match_arm_body_without_leading_char() {
 +    cov_mark::check!(expected_type_match_arm_body_without_leading_char);
 +    check_expected_type_and_name(
 +        r#"
 +struct Foo;
 +enum E { X }
 +fn foo() -> Foo {
 +   match E::X { E::X => $0 }
 +}
 +"#,
 +        expect![[r#"ty: Foo, name: ?"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_match_body_arm_with_leading_char() {
 +    cov_mark::check!(expected_type_match_arm_body_with_leading_char);
 +    check_expected_type_and_name(
 +        r#"
 +struct Foo;
 +enum E { X }
 +fn foo() -> Foo {
 +   match E::X { E::X => c$0 }
 +}
 +"#,
 +        expect![[r#"ty: Foo, name: ?"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_if_let_without_leading_char() {
 +    cov_mark::check!(expected_type_if_let_without_leading_char);
 +    check_expected_type_and_name(
 +        r#"
 +enum Foo { Bar, Baz, Quux }
 +
 +fn foo() {
 +    let f = Foo::Quux;
 +    if let $0 = f { }
 +}
 +"#,
 +        expect![[r#"ty: Foo, name: ?"#]],
 +    )
 +}
 +
 +#[test]
 +fn expected_type_if_let_with_leading_char() {
 +    cov_mark::check!(expected_type_if_let_with_leading_char);
 +    check_expected_type_and_name(
 +        r#"
 +enum Foo { Bar, Baz, Quux }
 +
 +fn foo() {
 +    let f = Foo::Quux;
 +    if let c$0 = f { }
 +}
 +"#,
 +        expect![[r#"ty: Foo, name: ?"#]],
 +    )
 +}
 +
 +#[test]
 +fn expected_type_fn_ret_without_leading_char() {
 +    cov_mark::check!(expected_type_fn_ret_without_leading_char);
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() -> u32 {
 +    $0
 +}
 +"#,
 +        expect![[r#"ty: u32, name: ?"#]],
 +    )
 +}
 +
 +#[test]
 +fn expected_type_fn_ret_with_leading_char() {
 +    cov_mark::check!(expected_type_fn_ret_with_leading_char);
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() -> u32 {
 +    c$0
 +}
 +"#,
 +        expect![[r#"ty: u32, name: ?"#]],
 +    )
 +}
 +
 +#[test]
 +fn expected_type_fn_ret_fn_ref_fully_typed() {
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() -> u32 {
 +    foo$0
 +}
 +"#,
 +        expect![[r#"ty: u32, name: ?"#]],
 +    )
 +}
 +
 +#[test]
 +fn expected_type_closure_param_return() {
 +    // FIXME: make this work with `|| $0`
 +    check_expected_type_and_name(
 +        r#"
 +//- minicore: fn
 +fn foo() {
 +    bar(|| a$0);
 +}
 +
 +fn bar(f: impl FnOnce() -> u32) {}
 +"#,
 +        expect![[r#"ty: u32, name: ?"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_generic_function() {
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() {
 +    bar::<u32>($0);
 +}
 +
 +fn bar<T>(t: T) {}
 +"#,
 +        expect![[r#"ty: u32, name: t"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_generic_method() {
 +    check_expected_type_and_name(
 +        r#"
 +fn foo() {
 +    S(1u32).bar($0);
 +}
 +
 +struct S<T>(T);
 +impl<T> S<T> {
 +    fn bar(self, t: T) {}
 +}
 +"#,
 +        expect![[r#"ty: u32, name: t"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_functional_update() {
 +    cov_mark::check!(expected_type_struct_func_update);
 +    check_expected_type_and_name(
 +        r#"
 +struct Foo { field: u32 }
 +fn foo() {
 +    Foo {
 +        ..$0
 +    }
 +}
 +"#,
 +        expect![[r#"ty: Foo, name: ?"#]],
 +    );
 +}
 +
 +#[test]
 +fn expected_type_param_pat() {
 +    check_expected_type_and_name(
 +        r#"
 +struct Foo { field: u32 }
 +fn foo(a$0: Foo) {}
 +"#,
 +        expect![[r#"ty: Foo, name: ?"#]],
 +    );
 +    check_expected_type_and_name(
 +        r#"
 +struct Foo { field: u32 }
 +fn foo($0: Foo) {}
 +"#,
 +        // FIXME make this work, currently fails due to pattern recovery eating the `:`
 +        expect![[r#"ty: ?, name: ?"#]],
 +    );
 +}
++
++#[test]
++fn expected_type_ref_prefix_on_field() {
++    check_expected_type_and_name(
++        r#"
++fn foo(_: &mut i32) {}
++struct S {
++    field: i32,
++}
++
++fn main() {
++    let s = S {
++        field: 100,
++    };
++    foo(&mut s.f$0);
++}
++"#,
++        expect!["ty: i32, name: ?"],
++    );
++}
index 9b25964a6086e704e0c4ca5ef5676cf1f985127c,0000000000000000000000000000000000000000..946134b0ff95db78cb4682f847c6e4131dbf3fd4
mode 100644,000000..100644
--- /dev/null
@@@ -1,1913 -1,0 +1,1910 @@@
-                 fn main() []
 +//! `render` module provides utilities for rendering completion suggestions
 +//! into code pieces that will be presented to user.
 +
 +pub(crate) mod macro_;
 +pub(crate) mod function;
 +pub(crate) mod const_;
 +pub(crate) mod pattern;
 +pub(crate) mod type_alias;
 +pub(crate) mod variant;
 +pub(crate) mod union_literal;
 +pub(crate) mod literal;
 +
 +use hir::{AsAssocItem, HasAttrs, HirDisplay, ScopeDef};
 +use ide_db::{
 +    helpers::item_name, imports::import_assets::LocatedImport, RootDatabase, SnippetCap, SymbolKind,
 +};
 +use syntax::{AstNode, SmolStr, SyntaxKind, TextRange};
 +
 +use crate::{
 +    context::{DotAccess, PathCompletionCtx, PathKind, PatternContext},
 +    item::{Builder, CompletionRelevanceTypeMatch},
 +    render::{
 +        function::render_fn,
 +        literal::render_variant_lit,
 +        macro_::{render_macro, render_macro_pat},
 +    },
 +    CompletionContext, CompletionItem, CompletionItemKind, CompletionRelevance,
 +};
 +/// Interface for data and methods required for items rendering.
 +#[derive(Debug, Clone)]
 +pub(crate) struct RenderContext<'a> {
 +    completion: &'a CompletionContext<'a>,
 +    is_private_editable: bool,
 +    import_to_add: Option<LocatedImport>,
 +}
 +
 +impl<'a> RenderContext<'a> {
 +    pub(crate) fn new(completion: &'a CompletionContext<'a>) -> RenderContext<'a> {
 +        RenderContext { completion, is_private_editable: false, import_to_add: None }
 +    }
 +
 +    pub(crate) fn private_editable(mut self, private_editable: bool) -> Self {
 +        self.is_private_editable = private_editable;
 +        self
 +    }
 +
 +    pub(crate) fn import_to_add(mut self, import_to_add: Option<LocatedImport>) -> Self {
 +        self.import_to_add = import_to_add;
 +        self
 +    }
 +
 +    fn snippet_cap(&self) -> Option<SnippetCap> {
 +        self.completion.config.snippet_cap
 +    }
 +
 +    fn db(&self) -> &'a RootDatabase {
 +        self.completion.db
 +    }
 +
 +    fn source_range(&self) -> TextRange {
 +        self.completion.source_range()
 +    }
 +
 +    fn completion_relevance(&self) -> CompletionRelevance {
 +        CompletionRelevance {
 +            is_private_editable: self.is_private_editable,
 +            requires_import: self.import_to_add.is_some(),
 +            ..Default::default()
 +        }
 +    }
 +
 +    fn is_immediately_after_macro_bang(&self) -> bool {
 +        self.completion.token.kind() == SyntaxKind::BANG
 +            && self
 +                .completion
 +                .token
 +                .parent()
 +                .map_or(false, |it| it.kind() == SyntaxKind::MACRO_CALL)
 +    }
 +
 +    fn is_deprecated(&self, def: impl HasAttrs) -> bool {
 +        let attrs = def.attrs(self.db());
 +        attrs.by_key("deprecated").exists()
 +    }
 +
 +    fn is_deprecated_assoc_item(&self, as_assoc_item: impl AsAssocItem) -> bool {
 +        let db = self.db();
 +        let assoc = match as_assoc_item.as_assoc_item(db) {
 +            Some(assoc) => assoc,
 +            None => return false,
 +        };
 +
 +        let is_assoc_deprecated = match assoc {
 +            hir::AssocItem::Function(it) => self.is_deprecated(it),
 +            hir::AssocItem::Const(it) => self.is_deprecated(it),
 +            hir::AssocItem::TypeAlias(it) => self.is_deprecated(it),
 +        };
 +        is_assoc_deprecated
 +            || assoc
 +                .containing_trait_or_trait_impl(db)
 +                .map(|trait_| self.is_deprecated(trait_))
 +                .unwrap_or(false)
 +    }
 +
 +    // FIXME: remove this
 +    fn docs(&self, def: impl HasAttrs) -> Option<hir::Documentation> {
 +        def.docs(self.db())
 +    }
 +}
 +
 +pub(crate) fn render_field(
 +    ctx: RenderContext<'_>,
 +    dot_access: &DotAccess,
 +    receiver: Option<hir::Name>,
 +    field: hir::Field,
 +    ty: &hir::Type,
 +) -> CompletionItem {
 +    let is_deprecated = ctx.is_deprecated(field);
 +    let name = field.name(ctx.db());
 +    let (name, escaped_name) = (name.to_smol_str(), name.escaped().to_smol_str());
 +    let mut item = CompletionItem::new(
 +        SymbolKind::Field,
 +        ctx.source_range(),
 +        field_with_receiver(receiver.as_ref(), &name),
 +    );
 +    item.set_relevance(CompletionRelevance {
 +        type_match: compute_type_match(ctx.completion, ty),
 +        exact_name_match: compute_exact_name_match(ctx.completion, name.as_str()),
 +        ..CompletionRelevance::default()
 +    });
 +    item.detail(ty.display(ctx.db()).to_string())
 +        .set_documentation(field.docs(ctx.db()))
 +        .set_deprecated(is_deprecated)
 +        .lookup_by(name.clone());
 +    item.insert_text(field_with_receiver(receiver.as_ref(), &escaped_name));
 +    if let Some(receiver) = &dot_access.receiver {
 +        if let Some(original) = ctx.completion.sema.original_ast_node(receiver.clone()) {
 +            if let Some(ref_match) = compute_ref_match(ctx.completion, ty) {
 +                item.ref_match(ref_match, original.syntax().text_range().start());
 +            }
 +        }
 +    }
 +    item.build()
 +}
 +
 +fn field_with_receiver(receiver: Option<&hir::Name>, field_name: &str) -> SmolStr {
 +    receiver
 +        .map_or_else(|| field_name.into(), |receiver| format!("{}.{}", receiver, field_name).into())
 +}
 +
 +pub(crate) fn render_tuple_field(
 +    ctx: RenderContext<'_>,
 +    receiver: Option<hir::Name>,
 +    field: usize,
 +    ty: &hir::Type,
 +) -> CompletionItem {
 +    let mut item = CompletionItem::new(
 +        SymbolKind::Field,
 +        ctx.source_range(),
 +        field_with_receiver(receiver.as_ref(), &field.to_string()),
 +    );
 +    item.detail(ty.display(ctx.db()).to_string()).lookup_by(field.to_string());
 +    item.build()
 +}
 +
 +pub(crate) fn render_type_inference(
 +    ty_string: String,
 +    ctx: &CompletionContext<'_>,
 +) -> CompletionItem {
 +    let mut builder =
 +        CompletionItem::new(CompletionItemKind::InferredType, ctx.source_range(), ty_string);
 +    builder.set_relevance(CompletionRelevance { is_definite: true, ..Default::default() });
 +    builder.build()
 +}
 +
 +pub(crate) fn render_path_resolution(
 +    ctx: RenderContext<'_>,
 +    path_ctx: &PathCompletionCtx,
 +    local_name: hir::Name,
 +    resolution: ScopeDef,
 +) -> Builder {
 +    render_resolution_path(ctx, path_ctx, local_name, None, resolution)
 +}
 +
 +pub(crate) fn render_pattern_resolution(
 +    ctx: RenderContext<'_>,
 +    pattern_ctx: &PatternContext,
 +    local_name: hir::Name,
 +    resolution: ScopeDef,
 +) -> Builder {
 +    render_resolution_pat(ctx, pattern_ctx, local_name, None, resolution)
 +}
 +
 +pub(crate) fn render_resolution_with_import(
 +    ctx: RenderContext<'_>,
 +    path_ctx: &PathCompletionCtx,
 +    import_edit: LocatedImport,
 +) -> Option<Builder> {
 +    let resolution = ScopeDef::from(import_edit.original_item);
 +    let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?;
 +
 +    Some(render_resolution_path(ctx, path_ctx, local_name, Some(import_edit), resolution))
 +}
 +
 +pub(crate) fn render_resolution_with_import_pat(
 +    ctx: RenderContext<'_>,
 +    pattern_ctx: &PatternContext,
 +    import_edit: LocatedImport,
 +) -> Option<Builder> {
 +    let resolution = ScopeDef::from(import_edit.original_item);
 +    let local_name = scope_def_to_name(resolution, &ctx, &import_edit)?;
 +    Some(render_resolution_pat(ctx, pattern_ctx, local_name, Some(import_edit), resolution))
 +}
 +
 +fn scope_def_to_name(
 +    resolution: ScopeDef,
 +    ctx: &RenderContext<'_>,
 +    import_edit: &LocatedImport,
 +) -> Option<hir::Name> {
 +    Some(match resolution {
 +        ScopeDef::ModuleDef(hir::ModuleDef::Function(f)) => f.name(ctx.completion.db),
 +        ScopeDef::ModuleDef(hir::ModuleDef::Const(c)) => c.name(ctx.completion.db)?,
 +        ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db),
 +        _ => item_name(ctx.db(), import_edit.original_item)?,
 +    })
 +}
 +
 +fn render_resolution_pat(
 +    ctx: RenderContext<'_>,
 +    pattern_ctx: &PatternContext,
 +    local_name: hir::Name,
 +    import_to_add: Option<LocatedImport>,
 +    resolution: ScopeDef,
 +) -> Builder {
 +    let _p = profile::span("render_resolution");
 +    use hir::ModuleDef::*;
 +
 +    match resolution {
 +        ScopeDef::ModuleDef(Macro(mac)) => {
 +            let ctx = ctx.import_to_add(import_to_add);
 +            return render_macro_pat(ctx, pattern_ctx, local_name, mac);
 +        }
 +        _ => (),
 +    }
 +
 +    render_resolution_simple_(ctx, &local_name, import_to_add, resolution)
 +}
 +
 +fn render_resolution_path(
 +    ctx: RenderContext<'_>,
 +    path_ctx: &PathCompletionCtx,
 +    local_name: hir::Name,
 +    import_to_add: Option<LocatedImport>,
 +    resolution: ScopeDef,
 +) -> Builder {
 +    let _p = profile::span("render_resolution");
 +    use hir::ModuleDef::*;
 +
 +    match resolution {
 +        ScopeDef::ModuleDef(Macro(mac)) => {
 +            let ctx = ctx.import_to_add(import_to_add);
 +            return render_macro(ctx, path_ctx, local_name, mac);
 +        }
 +        ScopeDef::ModuleDef(Function(func)) => {
 +            let ctx = ctx.import_to_add(import_to_add);
 +            return render_fn(ctx, path_ctx, Some(local_name), func);
 +        }
 +        ScopeDef::ModuleDef(Variant(var)) => {
 +            let ctx = ctx.clone().import_to_add(import_to_add.clone());
 +            if let Some(item) =
 +                render_variant_lit(ctx, path_ctx, Some(local_name.clone()), var, None)
 +            {
 +                return item;
 +            }
 +        }
 +        _ => (),
 +    }
 +
 +    let completion = ctx.completion;
 +    let cap = ctx.snippet_cap();
 +    let db = completion.db;
 +    let config = completion.config;
 +
 +    let name = local_name.to_smol_str();
 +    let mut item = render_resolution_simple_(ctx, &local_name, import_to_add, resolution);
 +    if local_name.escaped().is_escaped() {
 +        item.insert_text(local_name.escaped().to_smol_str());
 +    }
 +    // Add `<>` for generic types
 +    let type_path_no_ty_args = matches!(
 +        path_ctx,
 +        PathCompletionCtx { kind: PathKind::Type { .. }, has_type_args: false, .. }
 +    ) && config.callable.is_some();
 +    if type_path_no_ty_args {
 +        if let Some(cap) = cap {
 +            let has_non_default_type_params = match resolution {
 +                ScopeDef::ModuleDef(hir::ModuleDef::Adt(it)) => it.has_non_default_type_params(db),
 +                ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(it)) => {
 +                    it.has_non_default_type_params(db)
 +                }
 +                _ => false,
 +            };
 +
 +            if has_non_default_type_params {
 +                cov_mark::hit!(inserts_angle_brackets_for_generics);
 +                item.lookup_by(name.clone())
 +                    .label(SmolStr::from_iter([&name, "<…>"]))
 +                    .trigger_call_info()
 +                    .insert_snippet(cap, format!("{}<$0>", local_name.escaped()));
 +            }
 +        }
 +    }
 +    if let ScopeDef::Local(local) = resolution {
 +        let ty = local.ty(db);
 +        if !ty.is_unknown() {
 +            item.detail(ty.display(db).to_string());
 +        }
 +
 +        item.set_relevance(CompletionRelevance {
 +            type_match: compute_type_match(completion, &ty),
 +            exact_name_match: compute_exact_name_match(completion, &name),
 +            is_local: true,
 +            ..CompletionRelevance::default()
 +        });
 +
 +        if let Some(ref_match) = compute_ref_match(completion, &ty) {
 +            item.ref_match(ref_match, path_ctx.path.syntax().text_range().start());
 +        }
 +    };
 +    item
 +}
 +
 +fn render_resolution_simple_(
 +    ctx: RenderContext<'_>,
 +    local_name: &hir::Name,
 +    import_to_add: Option<LocatedImport>,
 +    resolution: ScopeDef,
 +) -> Builder {
 +    let _p = profile::span("render_resolution");
 +
 +    let db = ctx.db();
 +    let ctx = ctx.import_to_add(import_to_add);
 +    let kind = res_to_kind(resolution);
 +
 +    let mut item = CompletionItem::new(kind, ctx.source_range(), local_name.to_smol_str());
 +    item.set_relevance(ctx.completion_relevance())
 +        .set_documentation(scope_def_docs(db, resolution))
 +        .set_deprecated(scope_def_is_deprecated(&ctx, resolution));
 +
 +    if let Some(import_to_add) = ctx.import_to_add {
 +        item.add_import(import_to_add);
 +    }
 +    item
 +}
 +
 +fn res_to_kind(resolution: ScopeDef) -> CompletionItemKind {
 +    use hir::ModuleDef::*;
 +    match resolution {
 +        ScopeDef::Unknown => CompletionItemKind::UnresolvedReference,
 +        ScopeDef::ModuleDef(Function(_)) => CompletionItemKind::SymbolKind(SymbolKind::Function),
 +        ScopeDef::ModuleDef(Variant(_)) => CompletionItemKind::SymbolKind(SymbolKind::Variant),
 +        ScopeDef::ModuleDef(Macro(_)) => CompletionItemKind::SymbolKind(SymbolKind::Macro),
 +        ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
 +        ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
 +            hir::Adt::Struct(_) => SymbolKind::Struct,
 +            hir::Adt::Union(_) => SymbolKind::Union,
 +            hir::Adt::Enum(_) => SymbolKind::Enum,
 +        }),
 +        ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
 +        ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
 +        ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
 +        ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::SymbolKind(SymbolKind::TypeAlias),
 +        ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
 +        ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
 +            hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
 +            hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
 +            hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
 +        }),
 +        ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
 +        ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
 +        ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => {
 +            CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
 +        }
 +    }
 +}
 +
 +fn scope_def_docs(db: &RootDatabase, resolution: ScopeDef) -> Option<hir::Documentation> {
 +    use hir::ModuleDef::*;
 +    match resolution {
 +        ScopeDef::ModuleDef(Module(it)) => it.docs(db),
 +        ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
 +        ScopeDef::ModuleDef(Variant(it)) => it.docs(db),
 +        ScopeDef::ModuleDef(Const(it)) => it.docs(db),
 +        ScopeDef::ModuleDef(Static(it)) => it.docs(db),
 +        ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
 +        ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(db),
 +        _ => None,
 +    }
 +}
 +
 +fn scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: ScopeDef) -> bool {
 +    match resolution {
 +        ScopeDef::ModuleDef(it) => ctx.is_deprecated_assoc_item(it),
 +        ScopeDef::GenericParam(it) => ctx.is_deprecated(it),
 +        ScopeDef::AdtSelfType(it) => ctx.is_deprecated(it),
 +        _ => false,
 +    }
 +}
 +
 +fn compute_type_match(
 +    ctx: &CompletionContext<'_>,
 +    completion_ty: &hir::Type,
 +) -> Option<CompletionRelevanceTypeMatch> {
 +    let expected_type = ctx.expected_type.as_ref()?;
 +
 +    // We don't ever consider unit type to be an exact type match, since
 +    // nearly always this is not meaningful to the user.
 +    if expected_type.is_unit() {
 +        return None;
 +    }
 +
 +    if completion_ty == expected_type {
 +        Some(CompletionRelevanceTypeMatch::Exact)
 +    } else if expected_type.could_unify_with(ctx.db, completion_ty) {
 +        Some(CompletionRelevanceTypeMatch::CouldUnify)
 +    } else {
 +        None
 +    }
 +}
 +
 +fn compute_exact_name_match(ctx: &CompletionContext<'_>, completion_name: &str) -> bool {
 +    ctx.expected_name.as_ref().map_or(false, |name| name.text() == completion_name)
 +}
 +
 +fn compute_ref_match(
 +    ctx: &CompletionContext<'_>,
 +    completion_ty: &hir::Type,
 +) -> Option<hir::Mutability> {
 +    let expected_type = ctx.expected_type.as_ref()?;
 +    if completion_ty != expected_type {
 +        let expected_type_without_ref = expected_type.remove_ref()?;
 +        if completion_ty.autoderef(ctx.db).any(|deref_ty| deref_ty == expected_type_without_ref) {
 +            cov_mark::hit!(suggest_ref);
 +            let mutability = if expected_type.is_mutable_reference() {
 +                hir::Mutability::Mut
 +            } else {
 +                hir::Mutability::Shared
 +            };
 +            return Some(mutability);
 +        };
 +    }
 +    None
 +}
 +
 +#[cfg(test)]
 +mod tests {
 +    use std::cmp;
 +
 +    use expect_test::{expect, Expect};
 +    use ide_db::SymbolKind;
 +    use itertools::Itertools;
 +
 +    use crate::{
 +        item::CompletionRelevanceTypeMatch,
 +        tests::{check_edit, do_completion, get_all_items, TEST_CONFIG},
 +        CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
 +    };
 +
 +    #[track_caller]
 +    fn check(ra_fixture: &str, kind: impl Into<CompletionItemKind>, expect: Expect) {
 +        let actual = do_completion(ra_fixture, kind.into());
 +        expect.assert_debug_eq(&actual);
 +    }
 +
 +    #[track_caller]
 +    fn check_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
 +        let actual: Vec<_> =
 +            kinds.iter().flat_map(|&kind| do_completion(ra_fixture, kind)).collect();
 +        expect.assert_debug_eq(&actual);
 +    }
 +
 +    #[track_caller]
 +    fn check_relevance_for_kinds(ra_fixture: &str, kinds: &[CompletionItemKind], expect: Expect) {
 +        let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
 +        actual.retain(|it| kinds.contains(&it.kind()));
 +        actual.sort_by_key(|it| cmp::Reverse(it.relevance().score()));
 +        check_relevance_(actual, expect);
 +    }
 +
 +    #[track_caller]
 +    fn check_relevance(ra_fixture: &str, expect: Expect) {
 +        let mut actual = get_all_items(TEST_CONFIG, ra_fixture, None);
 +        actual.retain(|it| it.kind() != CompletionItemKind::Snippet);
 +        actual.retain(|it| it.kind() != CompletionItemKind::Keyword);
 +        actual.retain(|it| it.kind() != CompletionItemKind::BuiltinType);
 +        actual.sort_by_key(|it| cmp::Reverse(it.relevance().score()));
 +        check_relevance_(actual, expect);
 +    }
 +
 +    #[track_caller]
 +    fn check_relevance_(actual: Vec<CompletionItem>, expect: Expect) {
 +        let actual = actual
 +            .into_iter()
 +            .flat_map(|it| {
 +                let mut items = vec![];
 +
 +                let tag = it.kind().tag();
 +                let relevance = display_relevance(it.relevance());
 +                items.push(format!("{} {} {}\n", tag, it.label(), relevance));
 +
 +                if let Some((mutability, _offset, relevance)) = it.ref_match() {
 +                    let label = format!("&{}{}", mutability.as_keyword_for_ref(), it.label());
 +                    let relevance = display_relevance(relevance);
 +
 +                    items.push(format!("{} {} {}\n", tag, label, relevance));
 +                }
 +
 +                items
 +            })
 +            .collect::<String>();
 +
 +        expect.assert_eq(&actual);
 +
 +        fn display_relevance(relevance: CompletionRelevance) -> String {
 +            let relevance_factors = vec![
 +                (relevance.type_match == Some(CompletionRelevanceTypeMatch::Exact), "type"),
 +                (
 +                    relevance.type_match == Some(CompletionRelevanceTypeMatch::CouldUnify),
 +                    "type_could_unify",
 +                ),
 +                (relevance.exact_name_match, "name"),
 +                (relevance.is_local, "local"),
 +                (
 +                    relevance.postfix_match == Some(CompletionRelevancePostfixMatch::Exact),
 +                    "snippet",
 +                ),
 +                (relevance.is_op_method, "op_method"),
 +                (relevance.requires_import, "requires_import"),
 +            ]
 +            .into_iter()
 +            .filter_map(|(cond, desc)| if cond { Some(desc) } else { None })
 +            .join("+");
 +
 +            format!("[{}]", relevance_factors)
 +        }
 +    }
 +
 +    #[test]
 +    fn enum_detail_includes_record_fields() {
 +        check(
 +            r#"
 +enum Foo { Foo { x: i32, y: i32 } }
 +
 +fn main() { Foo::Fo$0 }
 +"#,
 +            SymbolKind::Variant,
 +            expect![[r#"
 +                [
 +                    CompletionItem {
 +                        label: "Foo {…}",
 +                        source_range: 54..56,
 +                        delete: 54..56,
 +                        insert: "Foo { x: ${1:()}, y: ${2:()} }$0",
 +                        kind: SymbolKind(
 +                            Variant,
 +                        ),
 +                        detail: "Foo { x: i32, y: i32 }",
 +                    },
 +                ]
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn enum_detail_includes_tuple_fields() {
 +        check(
 +            r#"
 +enum Foo { Foo (i32, i32) }
 +
 +fn main() { Foo::Fo$0 }
 +"#,
 +            SymbolKind::Variant,
 +            expect![[r#"
 +                [
 +                    CompletionItem {
 +                        label: "Foo(…)",
 +                        source_range: 46..48,
 +                        delete: 46..48,
 +                        insert: "Foo(${1:()}, ${2:()})$0",
 +                        kind: SymbolKind(
 +                            Variant,
 +                        ),
 +                        detail: "Foo(i32, i32)",
 +                    },
 +                ]
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn fn_detail_includes_args_and_return_type() {
 +        check(
 +            r#"
 +fn foo<T>(a: u32, b: u32, t: T) -> (u32, T) { (a, t) }
 +
 +fn main() { fo$0 }
 +"#,
 +            SymbolKind::Function,
 +            expect![[r#"
 +                [
 +                    CompletionItem {
 +                        label: "foo(…)",
 +                        source_range: 68..70,
 +                        delete: 68..70,
 +                        insert: "foo(${1:a}, ${2:b}, ${3:t})$0",
 +                        kind: SymbolKind(
 +                            Function,
 +                        ),
 +                        lookup: "foo",
 +                        detail: "fn(u32, u32, T) -> (u32, T)",
 +                        trigger_call_info: true,
 +                    },
 +                    CompletionItem {
 +                        label: "main()",
 +                        source_range: 68..70,
 +                        delete: 68..70,
 +                        insert: "main()$0",
 +                        kind: SymbolKind(
 +                            Function,
 +                        ),
 +                        lookup: "main",
 +                        detail: "fn()",
 +                    },
 +                ]
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn enum_detail_just_name_for_unit() {
 +        check(
 +            r#"
 +enum Foo { Foo }
 +
 +fn main() { Foo::Fo$0 }
 +"#,
 +            SymbolKind::Variant,
 +            expect![[r#"
 +                [
 +                    CompletionItem {
 +                        label: "Foo",
 +                        source_range: 35..37,
 +                        delete: 35..37,
 +                        insert: "Foo$0",
 +                        kind: SymbolKind(
 +                            Variant,
 +                        ),
 +                        detail: "Foo",
 +                    },
 +                ]
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn lookup_enums_by_two_qualifiers() {
 +        check_kinds(
 +            r#"
 +mod m {
 +    pub enum Spam { Foo, Bar(i32) }
 +}
 +fn main() { let _: m::Spam = S$0 }
 +"#,
 +            &[
 +                CompletionItemKind::SymbolKind(SymbolKind::Function),
 +                CompletionItemKind::SymbolKind(SymbolKind::Module),
 +                CompletionItemKind::SymbolKind(SymbolKind::Variant),
 +            ],
 +            expect![[r#"
 +                [
 +                    CompletionItem {
 +                        label: "main()",
 +                        source_range: 75..76,
 +                        delete: 75..76,
 +                        insert: "main()$0",
 +                        kind: SymbolKind(
 +                            Function,
 +                        ),
 +                        lookup: "main",
 +                        detail: "fn()",
 +                    },
 +                    CompletionItem {
 +                        label: "m",
 +                        source_range: 75..76,
 +                        delete: 75..76,
 +                        insert: "m",
 +                        kind: SymbolKind(
 +                            Module,
 +                        ),
 +                    },
 +                    CompletionItem {
 +                        label: "m::Spam::Bar(…)",
 +                        source_range: 75..76,
 +                        delete: 75..76,
 +                        insert: "m::Spam::Bar(${1:()})$0",
 +                        kind: SymbolKind(
 +                            Variant,
 +                        ),
 +                        lookup: "Spam::Bar(…)",
 +                        detail: "m::Spam::Bar(i32)",
 +                        relevance: CompletionRelevance {
 +                            exact_name_match: false,
 +                            type_match: Some(
 +                                Exact,
 +                            ),
 +                            is_local: false,
 +                            is_item_from_trait: false,
 +                            is_name_already_imported: false,
 +                            requires_import: false,
 +                            is_op_method: false,
 +                            is_private_editable: false,
 +                            postfix_match: None,
 +                            is_definite: false,
 +                        },
 +                    },
 +                    CompletionItem {
 +                        label: "m::Spam::Foo",
 +                        source_range: 75..76,
 +                        delete: 75..76,
 +                        insert: "m::Spam::Foo$0",
 +                        kind: SymbolKind(
 +                            Variant,
 +                        ),
 +                        lookup: "Spam::Foo",
 +                        detail: "m::Spam::Foo",
 +                        relevance: CompletionRelevance {
 +                            exact_name_match: false,
 +                            type_match: Some(
 +                                Exact,
 +                            ),
 +                            is_local: false,
 +                            is_item_from_trait: false,
 +                            is_name_already_imported: false,
 +                            requires_import: false,
 +                            is_op_method: false,
 +                            is_private_editable: false,
 +                            postfix_match: None,
 +                            is_definite: false,
 +                        },
 +                    },
 +                ]
 +            "#]],
 +        )
 +    }
 +
 +    #[test]
 +    fn sets_deprecated_flag_in_items() {
 +        check(
 +            r#"
 +#[deprecated]
 +fn something_deprecated() {}
 +
 +fn main() { som$0 }
 +"#,
 +            SymbolKind::Function,
 +            expect![[r#"
 +                [
 +                    CompletionItem {
 +                        label: "main()",
 +                        source_range: 56..59,
 +                        delete: 56..59,
 +                        insert: "main()$0",
 +                        kind: SymbolKind(
 +                            Function,
 +                        ),
 +                        lookup: "main",
 +                        detail: "fn()",
 +                    },
 +                    CompletionItem {
 +                        label: "something_deprecated()",
 +                        source_range: 56..59,
 +                        delete: 56..59,
 +                        insert: "something_deprecated()$0",
 +                        kind: SymbolKind(
 +                            Function,
 +                        ),
 +                        lookup: "something_deprecated",
 +                        detail: "fn()",
 +                        deprecated: true,
 +                    },
 +                ]
 +            "#]],
 +        );
 +
 +        check(
 +            r#"
 +struct A { #[deprecated] the_field: u32 }
 +fn foo() { A { the$0 } }
 +"#,
 +            SymbolKind::Field,
 +            expect![[r#"
 +                [
 +                    CompletionItem {
 +                        label: "the_field",
 +                        source_range: 57..60,
 +                        delete: 57..60,
 +                        insert: "the_field",
 +                        kind: SymbolKind(
 +                            Field,
 +                        ),
 +                        detail: "u32",
 +                        deprecated: true,
 +                        relevance: CompletionRelevance {
 +                            exact_name_match: false,
 +                            type_match: Some(
 +                                CouldUnify,
 +                            ),
 +                            is_local: false,
 +                            is_item_from_trait: false,
 +                            is_name_already_imported: false,
 +                            requires_import: false,
 +                            is_op_method: false,
 +                            is_private_editable: false,
 +                            postfix_match: None,
 +                            is_definite: false,
 +                        },
 +                    },
 +                ]
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn renders_docs() {
 +        check_kinds(
 +            r#"
 +struct S {
 +    /// Field docs
 +    foo:
 +}
 +impl S {
 +    /// Method docs
 +    fn bar(self) { self.$0 }
 +}"#,
 +            &[CompletionItemKind::Method, CompletionItemKind::SymbolKind(SymbolKind::Field)],
 +            expect![[r#"
 +                [
 +                    CompletionItem {
 +                        label: "bar()",
 +                        source_range: 94..94,
 +                        delete: 94..94,
 +                        insert: "bar()$0",
 +                        kind: Method,
 +                        lookup: "bar",
 +                        detail: "fn(self)",
 +                        documentation: Documentation(
 +                            "Method docs",
 +                        ),
 +                    },
 +                    CompletionItem {
 +                        label: "foo",
 +                        source_range: 94..94,
 +                        delete: 94..94,
 +                        insert: "foo",
 +                        kind: SymbolKind(
 +                            Field,
 +                        ),
 +                        detail: "{unknown}",
 +                        documentation: Documentation(
 +                            "Field docs",
 +                        ),
 +                    },
 +                ]
 +            "#]],
 +        );
 +
 +        check_kinds(
 +            r#"
 +use self::my$0;
 +
 +/// mod docs
 +mod my { }
 +
 +/// enum docs
 +enum E {
 +    /// variant docs
 +    V
 +}
 +use self::E::*;
 +"#,
 +            &[
 +                CompletionItemKind::SymbolKind(SymbolKind::Module),
 +                CompletionItemKind::SymbolKind(SymbolKind::Variant),
 +                CompletionItemKind::SymbolKind(SymbolKind::Enum),
 +            ],
 +            expect![[r#"
 +                [
 +                    CompletionItem {
 +                        label: "my",
 +                        source_range: 10..12,
 +                        delete: 10..12,
 +                        insert: "my",
 +                        kind: SymbolKind(
 +                            Module,
 +                        ),
 +                        documentation: Documentation(
 +                            "mod docs",
 +                        ),
 +                    },
 +                    CompletionItem {
 +                        label: "V",
 +                        source_range: 10..12,
 +                        delete: 10..12,
 +                        insert: "V$0",
 +                        kind: SymbolKind(
 +                            Variant,
 +                        ),
 +                        detail: "V",
 +                        documentation: Documentation(
 +                            "variant docs",
 +                        ),
 +                    },
 +                    CompletionItem {
 +                        label: "E",
 +                        source_range: 10..12,
 +                        delete: 10..12,
 +                        insert: "E",
 +                        kind: SymbolKind(
 +                            Enum,
 +                        ),
 +                        documentation: Documentation(
 +                            "enum docs",
 +                        ),
 +                    },
 +                ]
 +            "#]],
 +        )
 +    }
 +
 +    #[test]
 +    fn dont_render_attrs() {
 +        check(
 +            r#"
 +struct S;
 +impl S {
 +    #[inline]
 +    fn the_method(&self) { }
 +}
 +fn foo(s: S) { s.$0 }
 +"#,
 +            CompletionItemKind::Method,
 +            expect![[r#"
 +                [
 +                    CompletionItem {
 +                        label: "the_method()",
 +                        source_range: 81..81,
 +                        delete: 81..81,
 +                        insert: "the_method()$0",
 +                        kind: Method,
 +                        lookup: "the_method",
 +                        detail: "fn(&self)",
 +                    },
 +                ]
 +            "#]],
 +        )
 +    }
 +
 +    #[test]
 +    fn no_call_parens_if_fn_ptr_needed() {
 +        cov_mark::check!(no_call_parens_if_fn_ptr_needed);
 +        check_edit(
 +            "foo",
 +            r#"
 +fn foo(foo: u8, bar: u8) {}
 +struct ManualVtable { f: fn(u8, u8) }
 +
 +fn main() -> ManualVtable {
 +    ManualVtable { f: f$0 }
 +}
 +"#,
 +            r#"
 +fn foo(foo: u8, bar: u8) {}
 +struct ManualVtable { f: fn(u8, u8) }
 +
 +fn main() -> ManualVtable {
 +    ManualVtable { f: foo }
 +}
 +"#,
 +        );
 +        check_edit(
 +            "type",
 +            r#"
 +struct RawIdentTable { r#type: u32 }
 +
 +fn main() -> RawIdentTable {
 +    RawIdentTable { t$0: 42 }
 +}
 +"#,
 +            r#"
 +struct RawIdentTable { r#type: u32 }
 +
 +fn main() -> RawIdentTable {
 +    RawIdentTable { r#type: 42 }
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn no_parens_in_use_item() {
 +        check_edit(
 +            "foo",
 +            r#"
 +mod m { pub fn foo() {} }
 +use crate::m::f$0;
 +"#,
 +            r#"
 +mod m { pub fn foo() {} }
 +use crate::m::foo;
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn no_parens_in_call() {
 +        check_edit(
 +            "foo",
 +            r#"
 +fn foo(x: i32) {}
 +fn main() { f$0(); }
 +"#,
 +            r#"
 +fn foo(x: i32) {}
 +fn main() { foo(); }
 +"#,
 +        );
 +        check_edit(
 +            "foo",
 +            r#"
 +struct Foo;
 +impl Foo { fn foo(&self){} }
 +fn f(foo: &Foo) { foo.f$0(); }
 +"#,
 +            r#"
 +struct Foo;
 +impl Foo { fn foo(&self){} }
 +fn f(foo: &Foo) { foo.foo(); }
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn inserts_angle_brackets_for_generics() {
 +        cov_mark::check!(inserts_angle_brackets_for_generics);
 +        check_edit(
 +            "Vec",
 +            r#"
 +struct Vec<T> {}
 +fn foo(xs: Ve$0)
 +"#,
 +            r#"
 +struct Vec<T> {}
 +fn foo(xs: Vec<$0>)
 +"#,
 +        );
 +        check_edit(
 +            "Vec",
 +            r#"
 +type Vec<T> = (T,);
 +fn foo(xs: Ve$0)
 +"#,
 +            r#"
 +type Vec<T> = (T,);
 +fn foo(xs: Vec<$0>)
 +"#,
 +        );
 +        check_edit(
 +            "Vec",
 +            r#"
 +struct Vec<T = i128> {}
 +fn foo(xs: Ve$0)
 +"#,
 +            r#"
 +struct Vec<T = i128> {}
 +fn foo(xs: Vec)
 +"#,
 +        );
 +        check_edit(
 +            "Vec",
 +            r#"
 +struct Vec<T> {}
 +fn foo(xs: Ve$0<i128>)
 +"#,
 +            r#"
 +struct Vec<T> {}
 +fn foo(xs: Vec<i128>)
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn active_param_relevance() {
 +        check_relevance(
 +            r#"
 +struct S { foo: i64, bar: u32, baz: u32 }
 +fn test(bar: u32) { }
 +fn foo(s: S) { test(s.$0) }
 +"#,
 +            expect![[r#"
 +                fd bar [type+name]
 +                fd baz [type]
 +                fd foo []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn record_field_relevances() {
 +        check_relevance(
 +            r#"
 +struct A { foo: i64, bar: u32, baz: u32 }
 +struct B { x: (), y: f32, bar: u32 }
 +fn foo(a: A) { B { bar: a.$0 }; }
 +"#,
 +            expect![[r#"
 +                fd bar [type+name]
 +                fd baz [type]
 +                fd foo []
 +            "#]],
 +        )
 +    }
 +
 +    #[test]
 +    fn record_field_and_call_relevances() {
 +        check_relevance(
 +            r#"
 +struct A { foo: i64, bar: u32, baz: u32 }
 +struct B { x: (), y: f32, bar: u32 }
 +fn f(foo: i64) {  }
 +fn foo(a: A) { B { bar: f(a.$0) }; }
 +"#,
 +            expect![[r#"
 +                fd foo [type+name]
 +                fd bar []
 +                fd baz []
 +            "#]],
 +        );
 +        check_relevance(
 +            r#"
 +struct A { foo: i64, bar: u32, baz: u32 }
 +struct B { x: (), y: f32, bar: u32 }
 +fn f(foo: i64) {  }
 +fn foo(a: A) { f(B { bar: a.$0 }); }
 +"#,
 +            expect![[r#"
 +                fd bar [type+name]
 +                fd baz [type]
 +                fd foo []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn prioritize_exact_ref_match() {
 +        check_relevance(
 +            r#"
 +struct WorldSnapshot { _f: () };
 +fn go(world: &WorldSnapshot) { go(w$0) }
 +"#,
 +            expect![[r#"
 +                lc world [type+name+local]
 +                st WorldSnapshot {…} []
 +                st &WorldSnapshot {…} [type]
 +                st WorldSnapshot []
 +                fn go(…) []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn too_many_arguments() {
 +        cov_mark::check!(too_many_arguments);
 +        check_relevance(
 +            r#"
 +struct Foo;
 +fn f(foo: &Foo) { f(foo, w$0) }
 +"#,
 +            expect![[r#"
 +                lc foo [local]
 +                st Foo []
 +                fn f(…) []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn score_fn_type_and_name_match() {
 +        check_relevance(
 +            r#"
 +struct A { bar: u8 }
 +fn baz() -> u8 { 0 }
 +fn bar() -> u8 { 0 }
 +fn f() { A { bar: b$0 }; }
 +"#,
 +            expect![[r#"
 +                fn bar() [type+name]
 +                fn baz() [type]
 +                st A []
 +                fn f() []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn score_method_type_and_name_match() {
 +        check_relevance(
 +            r#"
 +fn baz(aaa: u32){}
 +struct Foo;
 +impl Foo {
 +fn aaa(&self) -> u32 { 0 }
 +fn bbb(&self) -> u32 { 0 }
 +fn ccc(&self) -> u64 { 0 }
 +}
 +fn f() {
 +    baz(Foo.$0
 +}
 +"#,
 +            expect![[r#"
 +                me aaa() [type+name]
 +                me bbb() [type]
 +                me ccc() []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn score_method_name_match_only() {
 +        check_relevance(
 +            r#"
 +fn baz(aaa: u32){}
 +struct Foo;
 +impl Foo {
 +fn aaa(&self) -> u64 { 0 }
 +}
 +fn f() {
 +    baz(Foo.$0
 +}
 +"#,
 +            expect![[r#"
 +                me aaa() [name]
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn suggest_ref_mut() {
 +        cov_mark::check!(suggest_ref);
 +        check_relevance(
 +            r#"
 +struct S;
 +fn foo(s: &mut S) {}
 +fn main() {
 +    let mut s = S;
 +    foo($0);
 +}
 +            "#,
 +            expect![[r#"
 +                lc s [name+local]
 +                lc &mut s [type+name+local]
 +                st S []
 +                st &mut S [type]
 +                st S []
-                 fn main() []
 +                fn foo(…) []
++                fn main() []
 +            "#]],
 +        );
 +        check_relevance(
 +            r#"
 +struct S;
 +fn foo(s: &mut S) {}
 +fn main() {
 +    let mut s = S;
 +    foo(&mut $0);
 +}
 +            "#,
 +            expect![[r#"
 +                lc s [type+name+local]
 +                st S [type]
 +                st S []
-                 fn main() []
 +                fn foo(…) []
++                fn main() []
 +            "#]],
 +        );
 +        check_relevance(
 +            r#"
 +struct S;
 +fn foo(s: &mut S) {}
 +fn main() {
 +    let mut ssss = S;
 +    foo(&mut s$0);
 +}
 +            "#,
 +            expect![[r#"
 +                lc ssss [type+local]
 +                st S [type]
 +                st S []
-                 st T []
 +                fn foo(…) []
++                fn main() []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn suggest_deref() {
 +        check_relevance(
 +            r#"
 +//- minicore: deref
 +struct S;
 +struct T(S);
 +
 +impl core::ops::Deref for T {
 +    type Target = S;
 +
 +    fn deref(&self) -> &Self::Target {
 +        &self.0
 +    }
 +}
 +
 +fn foo(s: &S) {}
 +
 +fn main() {
 +    let t = T(S);
 +    let m = 123;
 +
 +    foo($0);
 +}
 +            "#,
 +            expect![[r#"
 +                lc m [local]
 +                lc t [local]
 +                lc &t [type+local]
 +                st S []
 +                st &S [type]
-                 fn main() []
 +                st S []
-                 tt Sized []
++                st T []
 +                fn foo(…) []
++                fn main() []
 +                md core []
-                 st T []
 +            "#]],
 +        )
 +    }
 +
 +    #[test]
 +    fn suggest_deref_mut() {
 +        check_relevance(
 +            r#"
 +//- minicore: deref_mut
 +struct S;
 +struct T(S);
 +
 +impl core::ops::Deref for T {
 +    type Target = S;
 +
 +    fn deref(&self) -> &Self::Target {
 +        &self.0
 +    }
 +}
 +
 +impl core::ops::DerefMut for T {
 +    fn deref_mut(&mut self) -> &mut Self::Target {
 +        &mut self.0
 +    }
 +}
 +
 +fn foo(s: &mut S) {}
 +
 +fn main() {
 +    let t = T(S);
 +    let m = 123;
 +
 +    foo($0);
 +}
 +            "#,
 +            expect![[r#"
 +                lc m [local]
 +                lc t [local]
 +                lc &mut t [type+local]
 +                st S []
 +                st &mut S [type]
-                 fn main() []
 +                st S []
-                 tt Sized []
++                st T []
 +                fn foo(…) []
++                fn main() []
 +                md core []
-                 st T []
 +            "#]],
 +        )
 +    }
 +
 +    #[test]
 +    fn locals() {
 +        check_relevance(
 +            r#"
 +fn foo(bar: u32) {
 +    let baz = 0;
 +
 +    f$0
 +}
 +"#,
 +            expect![[r#"
 +                lc baz [local]
 +                lc bar [local]
 +                fn foo(…) []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn enum_owned() {
 +        check_relevance(
 +            r#"
 +enum Foo { A, B }
 +fn foo() {
 +    bar($0);
 +}
 +fn bar(t: Foo) {}
 +"#,
 +            expect![[r#"
 +                ev Foo::A [type]
 +                ev Foo::B [type]
 +                en Foo []
 +                fn bar(…) []
 +                fn foo() []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn enum_ref() {
 +        check_relevance(
 +            r#"
 +enum Foo { A, B }
 +fn foo() {
 +    bar($0);
 +}
 +fn bar(t: &Foo) {}
 +"#,
 +            expect![[r#"
 +                ev Foo::A []
 +                ev &Foo::A [type]
 +                ev Foo::B []
 +                ev &Foo::B [type]
 +                en Foo []
 +                fn bar(…) []
 +                fn foo() []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn suggest_deref_fn_ret() {
 +        check_relevance(
 +            r#"
 +//- minicore: deref
 +struct S;
 +struct T(S);
 +
 +impl core::ops::Deref for T {
 +    type Target = S;
 +
 +    fn deref(&self) -> &Self::Target {
 +        &self.0
 +    }
 +}
 +
 +fn foo(s: &S) {}
 +fn bar() -> T {}
 +
 +fn main() {
 +    foo($0);
 +}
 +"#,
 +            expect![[r#"
 +                st S []
 +                st &S [type]
-                 fn main() []
 +                st S []
-                 tt Sized []
++                st T []
 +                fn bar() []
 +                fn &bar() [type]
 +                fn foo(…) []
++                fn main() []
 +                md core []
-                 fn baz() []
 +            "#]],
 +        )
 +    }
 +
 +    #[test]
 +    fn op_function_relevances() {
 +        check_relevance(
 +            r#"
 +#[lang = "sub"]
 +trait Sub {
 +    fn sub(self, other: Self) -> Self { self }
 +}
 +impl Sub for u32 {}
 +fn foo(a: u32) { a.$0 }
 +"#,
 +            expect![[r#"
 +                me sub(…) (as Sub) [op_method]
 +            "#]],
 +        );
 +        check_relevance(
 +            r#"
 +struct Foo;
 +impl Foo {
 +    fn new() -> Self {}
 +}
 +#[lang = "eq"]
 +pub trait PartialEq<Rhs: ?Sized = Self> {
 +    fn eq(&self, other: &Rhs) -> bool;
 +    fn ne(&self, other: &Rhs) -> bool;
 +}
 +
 +impl PartialEq for Foo {}
 +fn main() {
 +    Foo::$0
 +}
 +"#,
 +            expect![[r#"
 +                fn new() []
 +                me eq(…) (as PartialEq) [op_method]
 +                me ne(…) (as PartialEq) [op_method]
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn struct_field_method_ref() {
 +        check_kinds(
 +            r#"
 +struct Foo { bar: u32 }
 +impl Foo { fn baz(&self) -> u32 { 0 } }
 +
 +fn foo(f: Foo) { let _: &u32 = f.b$0 }
 +"#,
 +            &[CompletionItemKind::Method, CompletionItemKind::SymbolKind(SymbolKind::Field)],
 +            expect![[r#"
 +                [
 +                    CompletionItem {
 +                        label: "baz()",
 +                        source_range: 98..99,
 +                        delete: 98..99,
 +                        insert: "baz()$0",
 +                        kind: Method,
 +                        lookup: "baz",
 +                        detail: "fn(&self) -> u32",
 +                        ref_match: "&@96",
 +                    },
 +                    CompletionItem {
 +                        label: "bar",
 +                        source_range: 98..99,
 +                        delete: 98..99,
 +                        insert: "bar",
 +                        kind: SymbolKind(
 +                            Field,
 +                        ),
 +                        detail: "u32",
 +                        ref_match: "&@96",
 +                    },
 +                ]
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn qualified_path_ref() {
 +        check_kinds(
 +            r#"
 +struct S;
 +
 +struct T;
 +impl T {
 +    fn foo() -> S {}
 +}
 +
 +fn bar(s: &S) {}
 +
 +fn main() {
 +    bar(T::$0);
 +}
 +"#,
 +            &[CompletionItemKind::SymbolKind(SymbolKind::Function)],
 +            expect![[r#"
 +                [
 +                    CompletionItem {
 +                        label: "foo()",
 +                        source_range: 95..95,
 +                        delete: 95..95,
 +                        insert: "foo()$0",
 +                        kind: SymbolKind(
 +                            Function,
 +                        ),
 +                        lookup: "foo",
 +                        detail: "fn() -> S",
 +                        ref_match: "&@92",
 +                    },
 +                ]
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn generic_enum() {
 +        check_relevance(
 +            r#"
 +enum Foo<T> { A(T), B }
 +// bar() should not be an exact type match
 +// because the generic parameters are different
 +fn bar() -> Foo<u8> { Foo::B }
 +// FIXME baz() should be an exact type match
 +// because the types could unify, but it currently
 +// is not. This is due to the T here being
 +// TyKind::Placeholder rather than TyKind::Missing.
 +fn baz<T>() -> Foo<T> { Foo::B }
 +fn foo() {
 +    let foo: Foo<u32> = Foo::B;
 +    let _: Foo<u32> = f$0;
 +}
 +"#,
 +            expect![[r#"
 +                lc foo [type+local]
 +                ev Foo::A(…) [type_could_unify]
 +                ev Foo::B [type_could_unify]
 +                fn foo() []
 +                en Foo []
-                 md std []
 +                fn bar() []
++                fn baz() []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn postfix_exact_match_is_high_priority() {
 +        cov_mark::check!(postfix_exact_match_is_high_priority);
 +        check_relevance_for_kinds(
 +            r#"
 +mod ops {
 +    pub trait Not {
 +        type Output;
 +        fn not(self) -> Self::Output;
 +    }
 +
 +    impl Not for bool {
 +        type Output = bool;
 +        fn not(self) -> bool { if self { false } else { true }}
 +    }
 +}
 +
 +fn main() {
 +    let _: bool = (9 > 2).not$0;
 +}
 +    "#,
 +            &[CompletionItemKind::Snippet, CompletionItemKind::Method],
 +            expect![[r#"
 +                sn not [snippet]
 +                me not() (use ops::Not) [type_could_unify+requires_import]
 +                sn if []
 +                sn while []
 +                sn ref []
 +                sn refm []
 +                sn match []
 +                sn box []
 +                sn dbg []
 +                sn dbgr []
 +                sn call []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn postfix_inexact_match_is_low_priority() {
 +        cov_mark::check!(postfix_inexact_match_is_low_priority);
 +        check_relevance_for_kinds(
 +            r#"
 +struct S;
 +impl S {
 +    fn f(&self) {}
 +}
 +fn main() {
 +    S.$0
 +}
 +    "#,
 +            &[CompletionItemKind::Snippet, CompletionItemKind::Method],
 +            expect![[r#"
 +                me f() []
 +                sn ref []
 +                sn refm []
 +                sn match []
 +                sn box []
 +                sn dbg []
 +                sn dbgr []
 +                sn call []
 +                sn let []
 +                sn letm []
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn flyimport_reduced_relevance() {
 +        check_relevance(
 +            r#"
 +mod std {
 +    pub mod io {
 +        pub trait BufRead {}
 +        pub struct BufReader;
 +        pub struct BufWriter;
 +    }
 +}
 +struct Buffer;
 +
 +fn f() {
 +    Buf$0
 +}
 +"#,
 +            expect![[r#"
 +                st Buffer []
 +                fn f() []
++                md std []
 +                tt BufRead (use std::io::BufRead) [requires_import]
 +                st BufReader (use std::io::BufReader) [requires_import]
 +                st BufWriter (use std::io::BufWriter) [requires_import]
 +            "#]],
 +        );
 +    }
 +
 +    #[test]
 +    fn completes_struct_with_raw_identifier() {
 +        check_edit(
 +            "type",
 +            r#"
 +mod m { pub struct r#type {} }
 +fn main() {
 +    let r#type = m::t$0;
 +}
 +"#,
 +            r#"
 +mod m { pub struct r#type {} }
 +fn main() {
 +    let r#type = m::r#type;
 +}
 +"#,
 +        )
 +    }
 +
 +    #[test]
 +    fn completes_fn_with_raw_identifier() {
 +        check_edit(
 +            "type",
 +            r#"
 +mod m { pub fn r#type {} }
 +fn main() {
 +    m::t$0
 +}
 +"#,
 +            r#"
 +mod m { pub fn r#type {} }
 +fn main() {
 +    m::r#type()$0
 +}
 +"#,
 +        )
 +    }
 +
 +    #[test]
 +    fn completes_macro_with_raw_identifier() {
 +        check_edit(
 +            "let!",
 +            r#"
 +macro_rules! r#let { () => {} }
 +fn main() {
 +    $0
 +}
 +"#,
 +            r#"
 +macro_rules! r#let { () => {} }
 +fn main() {
 +    r#let!($0)
 +}
 +"#,
 +        )
 +    }
 +
 +    #[test]
 +    fn completes_variant_with_raw_identifier() {
 +        check_edit(
 +            "type",
 +            r#"
 +enum A { r#type }
 +fn main() {
 +    let a = A::t$0
 +}
 +"#,
 +            r#"
 +enum A { r#type }
 +fn main() {
 +    let a = A::r#type$0
 +}
 +"#,
 +        )
 +    }
 +
 +    #[test]
 +    fn completes_field_with_raw_identifier() {
 +        check_edit(
 +            "fn",
 +            r#"
 +mod r#type {
 +    pub struct r#struct {
 +        pub r#fn: u32
 +    }
 +}
 +
 +fn main() {
 +    let a = r#type::r#struct {};
 +    a.$0
 +}
 +"#,
 +            r#"
 +mod r#type {
 +    pub struct r#struct {
 +        pub r#fn: u32
 +    }
 +}
 +
 +fn main() {
 +    let a = r#type::r#struct {};
 +    a.r#fn
 +}
 +"#,
 +        )
 +    }
 +
 +    #[test]
 +    fn completes_const_with_raw_identifier() {
 +        check_edit(
 +            "type",
 +            r#"
 +struct r#struct {}
 +impl r#struct { pub const r#type: u8 = 1; }
 +fn main() {
 +    r#struct::t$0
 +}
 +"#,
 +            r#"
 +struct r#struct {}
 +impl r#struct { pub const r#type: u8 = 1; }
 +fn main() {
 +    r#struct::r#type
 +}
 +"#,
 +        )
 +    }
 +
 +    #[test]
 +    fn completes_type_alias_with_raw_identifier() {
 +        check_edit(
 +            "type type",
 +            r#"
 +struct r#struct {}
 +trait r#trait { type r#type; }
 +impl r#trait for r#struct { type t$0 }
 +"#,
 +            r#"
 +struct r#struct {}
 +trait r#trait { type r#type; }
 +impl r#trait for r#struct { type r#type = $0; }
 +"#,
 +        )
 +    }
 +
 +    #[test]
 +    fn field_access_includes_self() {
 +        check_edit(
 +            "length",
 +            r#"
 +struct S {
 +    length: i32
 +}
 +
 +impl S {
 +    fn some_fn(&self) {
 +        let l = len$0
 +    }
 +}
 +"#,
 +            r#"
 +struct S {
 +    length: i32
 +}
 +
 +impl S {
 +    fn some_fn(&self) {
 +        let l = self.length
 +    }
 +}
 +"#,
 +        )
 +    }
 +}
index 241de0a1834a0c1759fd4cd280df61ce94475fe3,0000000000000000000000000000000000000000..4b5535718c5dfd4027df9e1d8132db83dad9ec54
mode 100644,000000..100644
--- /dev/null
@@@ -1,669 -1,0 +1,671 @@@
-                 item.ref_match(ref_match, receiver.syntax().text_range().start());
 +//! Renderer for function calls.
 +
 +use hir::{db::HirDatabase, AsAssocItem, HirDisplay};
 +use ide_db::{SnippetCap, SymbolKind};
 +use itertools::Itertools;
 +use stdx::{format_to, to_lower_snake_case};
 +use syntax::{AstNode, SmolStr};
 +
 +use crate::{
 +    context::{CompletionContext, DotAccess, DotAccessKind, PathCompletionCtx, PathKind},
 +    item::{Builder, CompletionItem, CompletionItemKind, CompletionRelevance},
 +    render::{compute_exact_name_match, compute_ref_match, compute_type_match, RenderContext},
 +    CallableSnippets,
 +};
 +
 +#[derive(Debug)]
 +enum FuncKind<'ctx> {
 +    Function(&'ctx PathCompletionCtx),
 +    Method(&'ctx DotAccess, Option<hir::Name>),
 +}
 +
 +pub(crate) fn render_fn(
 +    ctx: RenderContext<'_>,
 +    path_ctx: &PathCompletionCtx,
 +    local_name: Option<hir::Name>,
 +    func: hir::Function,
 +) -> Builder {
 +    let _p = profile::span("render_fn");
 +    render(ctx, local_name, func, FuncKind::Function(path_ctx))
 +}
 +
 +pub(crate) fn render_method(
 +    ctx: RenderContext<'_>,
 +    dot_access: &DotAccess,
 +    receiver: Option<hir::Name>,
 +    local_name: Option<hir::Name>,
 +    func: hir::Function,
 +) -> Builder {
 +    let _p = profile::span("render_method");
 +    render(ctx, local_name, func, FuncKind::Method(dot_access, receiver))
 +}
 +
 +fn render(
 +    ctx @ RenderContext { completion, .. }: RenderContext<'_>,
 +    local_name: Option<hir::Name>,
 +    func: hir::Function,
 +    func_kind: FuncKind<'_>,
 +) -> Builder {
 +    let db = completion.db;
 +
 +    let name = local_name.unwrap_or_else(|| func.name(db));
 +
 +    let (call, escaped_call) = match &func_kind {
 +        FuncKind::Method(_, Some(receiver)) => (
 +            format!("{}.{}", receiver, &name).into(),
 +            format!("{}.{}", receiver.escaped(), name.escaped()).into(),
 +        ),
 +        _ => (name.to_smol_str(), name.escaped().to_smol_str()),
 +    };
 +    let mut item = CompletionItem::new(
 +        if func.self_param(db).is_some() {
 +            CompletionItemKind::Method
 +        } else {
 +            CompletionItemKind::SymbolKind(SymbolKind::Function)
 +        },
 +        ctx.source_range(),
 +        call.clone(),
 +    );
 +
 +    let ret_type = func.ret_type(db);
 +    let is_op_method = func
 +        .as_assoc_item(ctx.db())
 +        .and_then(|trait_| trait_.containing_trait_or_trait_impl(ctx.db()))
 +        .map_or(false, |trait_| completion.is_ops_trait(trait_));
 +    item.set_relevance(CompletionRelevance {
 +        type_match: compute_type_match(completion, &ret_type),
 +        exact_name_match: compute_exact_name_match(completion, &call),
 +        is_op_method,
 +        ..ctx.completion_relevance()
 +    });
 +
 +    if let Some(ref_match) = compute_ref_match(completion, &ret_type) {
 +        match func_kind {
 +            FuncKind::Function(path_ctx) => {
 +                item.ref_match(ref_match, path_ctx.path.syntax().text_range().start());
 +            }
 +            FuncKind::Method(DotAccess { receiver: Some(receiver), .. }, _) => {
++                if let Some(original_expr) = completion.sema.original_ast_node(receiver.clone()) {
++                    item.ref_match(ref_match, original_expr.syntax().text_range().start());
++                }
 +            }
 +            _ => (),
 +        }
 +    }
 +
 +    item.set_documentation(ctx.docs(func))
 +        .set_deprecated(ctx.is_deprecated(func) || ctx.is_deprecated_assoc_item(func))
 +        .detail(detail(db, func))
 +        .lookup_by(name.to_smol_str());
 +
 +    match ctx.completion.config.snippet_cap {
 +        Some(cap) => {
 +            let complete_params = match func_kind {
 +                FuncKind::Function(PathCompletionCtx {
 +                    kind: PathKind::Expr { .. },
 +                    has_call_parens: false,
 +                    ..
 +                }) => Some(false),
 +                FuncKind::Method(
 +                    DotAccess {
 +                        kind:
 +                            DotAccessKind::Method { has_parens: false } | DotAccessKind::Field { .. },
 +                        ..
 +                    },
 +                    _,
 +                ) => Some(true),
 +                _ => None,
 +            };
 +            if let Some(has_dot_receiver) = complete_params {
 +                if let Some((self_param, params)) =
 +                    params(ctx.completion, func, &func_kind, has_dot_receiver)
 +                {
 +                    add_call_parens(
 +                        &mut item,
 +                        completion,
 +                        cap,
 +                        call,
 +                        escaped_call,
 +                        self_param,
 +                        params,
 +                    );
 +                }
 +            }
 +        }
 +        _ => (),
 +    };
 +
 +    match ctx.import_to_add {
 +        Some(import_to_add) => {
 +            item.add_import(import_to_add);
 +        }
 +        None => {
 +            if let Some(actm) = func.as_assoc_item(db) {
 +                if let Some(trt) = actm.containing_trait_or_trait_impl(db) {
 +                    item.trait_name(trt.name(db).to_smol_str());
 +                }
 +            }
 +        }
 +    }
 +    item
 +}
 +
 +pub(super) fn add_call_parens<'b>(
 +    builder: &'b mut Builder,
 +    ctx: &CompletionContext<'_>,
 +    cap: SnippetCap,
 +    name: SmolStr,
 +    escaped_name: SmolStr,
 +    self_param: Option<hir::SelfParam>,
 +    params: Vec<hir::Param>,
 +) -> &'b mut Builder {
 +    cov_mark::hit!(inserts_parens_for_function_calls);
 +
 +    let (snippet, label_suffix) = if self_param.is_none() && params.is_empty() {
 +        (format!("{}()$0", escaped_name), "()")
 +    } else {
 +        builder.trigger_call_info();
 +        let snippet = if let Some(CallableSnippets::FillArguments) = ctx.config.callable {
 +            let offset = if self_param.is_some() { 2 } else { 1 };
 +            let function_params_snippet =
 +                params.iter().enumerate().format_with(", ", |(index, param), f| {
 +                    match param.name(ctx.db) {
 +                        Some(n) => {
 +                            let smol_str = n.to_smol_str();
 +                            let text = smol_str.as_str().trim_start_matches('_');
 +                            let ref_ = ref_of_param(ctx, text, param.ty());
 +                            f(&format_args!("${{{}:{}{}}}", index + offset, ref_, text))
 +                        }
 +                        None => {
 +                            let name = match param.ty().as_adt() {
 +                                None => "_".to_string(),
 +                                Some(adt) => adt
 +                                    .name(ctx.db)
 +                                    .as_text()
 +                                    .map(|s| to_lower_snake_case(s.as_str()))
 +                                    .unwrap_or_else(|| "_".to_string()),
 +                            };
 +                            f(&format_args!("${{{}:{}}}", index + offset, name))
 +                        }
 +                    }
 +                });
 +            match self_param {
 +                Some(self_param) => {
 +                    format!(
 +                        "{}(${{1:{}}}{}{})$0",
 +                        escaped_name,
 +                        self_param.display(ctx.db),
 +                        if params.is_empty() { "" } else { ", " },
 +                        function_params_snippet
 +                    )
 +                }
 +                None => {
 +                    format!("{}({})$0", escaped_name, function_params_snippet)
 +                }
 +            }
 +        } else {
 +            cov_mark::hit!(suppress_arg_snippets);
 +            format!("{}($0)", escaped_name)
 +        };
 +
 +        (snippet, "(…)")
 +    };
 +    builder.label(SmolStr::from_iter([&name, label_suffix])).insert_snippet(cap, snippet)
 +}
 +
 +fn ref_of_param(ctx: &CompletionContext<'_>, arg: &str, ty: &hir::Type) -> &'static str {
 +    if let Some(derefed_ty) = ty.remove_ref() {
 +        for (name, local) in ctx.locals.iter() {
 +            if name.as_text().as_deref() == Some(arg) {
 +                return if local.ty(ctx.db) == derefed_ty {
 +                    if ty.is_mutable_reference() {
 +                        "&mut "
 +                    } else {
 +                        "&"
 +                    }
 +                } else {
 +                    ""
 +                };
 +            }
 +        }
 +    }
 +    ""
 +}
 +
 +fn detail(db: &dyn HirDatabase, func: hir::Function) -> String {
 +    let mut ret_ty = func.ret_type(db);
 +    let mut detail = String::new();
 +
 +    if func.is_const(db) {
 +        format_to!(detail, "const ");
 +    }
 +    if func.is_async(db) {
 +        format_to!(detail, "async ");
 +        if let Some(async_ret) = func.async_ret_type(db) {
 +            ret_ty = async_ret;
 +        }
 +    }
 +    if func.is_unsafe_to_call(db) {
 +        format_to!(detail, "unsafe ");
 +    }
 +
 +    format_to!(detail, "fn({})", params_display(db, func));
 +    if !ret_ty.is_unit() {
 +        format_to!(detail, " -> {}", ret_ty.display(db));
 +    }
 +    detail
 +}
 +
 +fn params_display(db: &dyn HirDatabase, func: hir::Function) -> String {
 +    if let Some(self_param) = func.self_param(db) {
 +        let assoc_fn_params = func.assoc_fn_params(db);
 +        let params = assoc_fn_params
 +            .iter()
 +            .skip(1) // skip the self param because we are manually handling that
 +            .map(|p| p.ty().display(db));
 +        format!(
 +            "{}{}",
 +            self_param.display(db),
 +            params.format_with("", |display, f| {
 +                f(&", ")?;
 +                f(&display)
 +            })
 +        )
 +    } else {
 +        let assoc_fn_params = func.assoc_fn_params(db);
 +        assoc_fn_params.iter().map(|p| p.ty().display(db)).join(", ")
 +    }
 +}
 +
 +fn params(
 +    ctx: &CompletionContext<'_>,
 +    func: hir::Function,
 +    func_kind: &FuncKind<'_>,
 +    has_dot_receiver: bool,
 +) -> Option<(Option<hir::SelfParam>, Vec<hir::Param>)> {
 +    if ctx.config.callable.is_none() {
 +        return None;
 +    }
 +
 +    // Don't add parentheses if the expected type is some function reference.
 +    if let Some(ty) = &ctx.expected_type {
 +        // FIXME: check signature matches?
 +        if ty.is_fn() {
 +            cov_mark::hit!(no_call_parens_if_fn_ptr_needed);
 +            return None;
 +        }
 +    }
 +
 +    let self_param = if has_dot_receiver || matches!(func_kind, FuncKind::Method(_, Some(_))) {
 +        None
 +    } else {
 +        func.self_param(ctx.db)
 +    };
 +    Some((self_param, func.params_without_self(ctx.db)))
 +}
 +
 +#[cfg(test)]
 +mod tests {
 +    use crate::{
 +        tests::{check_edit, check_edit_with_config, TEST_CONFIG},
 +        CallableSnippets, CompletionConfig,
 +    };
 +
 +    #[test]
 +    fn inserts_parens_for_function_calls() {
 +        cov_mark::check!(inserts_parens_for_function_calls);
 +        check_edit(
 +            "no_args",
 +            r#"
 +fn no_args() {}
 +fn main() { no_$0 }
 +"#,
 +            r#"
 +fn no_args() {}
 +fn main() { no_args()$0 }
 +"#,
 +        );
 +
 +        check_edit(
 +            "with_args",
 +            r#"
 +fn with_args(x: i32, y: String) {}
 +fn main() { with_$0 }
 +"#,
 +            r#"
 +fn with_args(x: i32, y: String) {}
 +fn main() { with_args(${1:x}, ${2:y})$0 }
 +"#,
 +        );
 +
 +        check_edit(
 +            "foo",
 +            r#"
 +struct S;
 +impl S {
 +    fn foo(&self) {}
 +}
 +fn bar(s: &S) { s.f$0 }
 +"#,
 +            r#"
 +struct S;
 +impl S {
 +    fn foo(&self) {}
 +}
 +fn bar(s: &S) { s.foo()$0 }
 +"#,
 +        );
 +
 +        check_edit(
 +            "foo",
 +            r#"
 +struct S {}
 +impl S {
 +    fn foo(&self, x: i32) {}
 +}
 +fn bar(s: &S) {
 +    s.f$0
 +}
 +"#,
 +            r#"
 +struct S {}
 +impl S {
 +    fn foo(&self, x: i32) {}
 +}
 +fn bar(s: &S) {
 +    s.foo(${1:x})$0
 +}
 +"#,
 +        );
 +
 +        check_edit(
 +            "foo",
 +            r#"
 +struct S {}
 +impl S {
 +    fn foo(&self, x: i32) {
 +        $0
 +    }
 +}
 +"#,
 +            r#"
 +struct S {}
 +impl S {
 +    fn foo(&self, x: i32) {
 +        self.foo(${1:x})$0
 +    }
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn parens_for_method_call_as_assoc_fn() {
 +        check_edit(
 +            "foo",
 +            r#"
 +struct S;
 +impl S {
 +    fn foo(&self) {}
 +}
 +fn main() { S::f$0 }
 +"#,
 +            r#"
 +struct S;
 +impl S {
 +    fn foo(&self) {}
 +}
 +fn main() { S::foo(${1:&self})$0 }
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn suppress_arg_snippets() {
 +        cov_mark::check!(suppress_arg_snippets);
 +        check_edit_with_config(
 +            CompletionConfig { callable: Some(CallableSnippets::AddParentheses), ..TEST_CONFIG },
 +            "with_args",
 +            r#"
 +fn with_args(x: i32, y: String) {}
 +fn main() { with_$0 }
 +"#,
 +            r#"
 +fn with_args(x: i32, y: String) {}
 +fn main() { with_args($0) }
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn strips_underscores_from_args() {
 +        check_edit(
 +            "foo",
 +            r#"
 +fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {}
 +fn main() { f$0 }
 +"#,
 +            r#"
 +fn foo(_foo: i32, ___bar: bool, ho_ge_: String) {}
 +fn main() { foo(${1:foo}, ${2:bar}, ${3:ho_ge_})$0 }
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn insert_ref_when_matching_local_in_scope() {
 +        check_edit(
 +            "ref_arg",
 +            r#"
 +struct Foo {}
 +fn ref_arg(x: &Foo) {}
 +fn main() {
 +    let x = Foo {};
 +    ref_ar$0
 +}
 +"#,
 +            r#"
 +struct Foo {}
 +fn ref_arg(x: &Foo) {}
 +fn main() {
 +    let x = Foo {};
 +    ref_arg(${1:&x})$0
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn insert_mut_ref_when_matching_local_in_scope() {
 +        check_edit(
 +            "ref_arg",
 +            r#"
 +struct Foo {}
 +fn ref_arg(x: &mut Foo) {}
 +fn main() {
 +    let x = Foo {};
 +    ref_ar$0
 +}
 +"#,
 +            r#"
 +struct Foo {}
 +fn ref_arg(x: &mut Foo) {}
 +fn main() {
 +    let x = Foo {};
 +    ref_arg(${1:&mut x})$0
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn insert_ref_when_matching_local_in_scope_for_method() {
 +        check_edit(
 +            "apply_foo",
 +            r#"
 +struct Foo {}
 +struct Bar {}
 +impl Bar {
 +    fn apply_foo(&self, x: &Foo) {}
 +}
 +
 +fn main() {
 +    let x = Foo {};
 +    let y = Bar {};
 +    y.$0
 +}
 +"#,
 +            r#"
 +struct Foo {}
 +struct Bar {}
 +impl Bar {
 +    fn apply_foo(&self, x: &Foo) {}
 +}
 +
 +fn main() {
 +    let x = Foo {};
 +    let y = Bar {};
 +    y.apply_foo(${1:&x})$0
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn trim_mut_keyword_in_func_completion() {
 +        check_edit(
 +            "take_mutably",
 +            r#"
 +fn take_mutably(mut x: &i32) {}
 +
 +fn main() {
 +    take_m$0
 +}
 +"#,
 +            r#"
 +fn take_mutably(mut x: &i32) {}
 +
 +fn main() {
 +    take_mutably(${1:x})$0
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn complete_pattern_args_with_type_name_if_adt() {
 +        check_edit(
 +            "qux",
 +            r#"
 +struct Foo {
 +    bar: i32
 +}
 +
 +fn qux(Foo { bar }: Foo) {
 +    println!("{}", bar);
 +}
 +
 +fn main() {
 +  qu$0
 +}
 +"#,
 +            r#"
 +struct Foo {
 +    bar: i32
 +}
 +
 +fn qux(Foo { bar }: Foo) {
 +    println!("{}", bar);
 +}
 +
 +fn main() {
 +  qux(${1:foo})$0
 +}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn complete_fn_param() {
 +        // has mut kw
 +        check_edit(
 +            "mut bar: u32",
 +            r#"
 +fn f(foo: (), mut bar: u32) {}
 +fn g(foo: (), mut ba$0)
 +"#,
 +            r#"
 +fn f(foo: (), mut bar: u32) {}
 +fn g(foo: (), mut bar: u32)
 +"#,
 +        );
 +
 +        // has type param
 +        check_edit(
 +            "mut bar: u32",
 +            r#"
 +fn g(foo: (), mut ba$0: u32)
 +fn f(foo: (), mut bar: u32) {}
 +"#,
 +            r#"
 +fn g(foo: (), mut bar: u32)
 +fn f(foo: (), mut bar: u32) {}
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn complete_fn_mut_param_add_comma() {
 +        // add leading and trailing comma
 +        check_edit(
 +            ", mut bar: u32,",
 +            r#"
 +fn f(foo: (), mut bar: u32) {}
 +fn g(foo: ()mut ba$0 baz: ())
 +"#,
 +            r#"
 +fn f(foo: (), mut bar: u32) {}
 +fn g(foo: (), mut bar: u32, baz: ())
 +"#,
 +        );
 +    }
 +
 +    #[test]
 +    fn complete_fn_mut_param_has_attribute() {
 +        check_edit(
 +            r#"#[baz = "qux"] mut bar: u32"#,
 +            r#"
 +fn f(foo: (), #[baz = "qux"] mut bar: u32) {}
 +fn g(foo: (), mut ba$0)
 +"#,
 +            r#"
 +fn f(foo: (), #[baz = "qux"] mut bar: u32) {}
 +fn g(foo: (), #[baz = "qux"] mut bar: u32)
 +"#,
 +        );
 +
 +        check_edit(
 +            r#"#[baz = "qux"] mut bar: u32"#,
 +            r#"
 +fn f(foo: (), #[baz = "qux"] mut bar: u32) {}
 +fn g(foo: (), #[baz = "qux"] mut ba$0)
 +"#,
 +            r#"
 +fn f(foo: (), #[baz = "qux"] mut bar: u32) {}
 +fn g(foo: (), #[baz = "qux"] mut bar: u32)
 +"#,
 +        );
 +
 +        check_edit(
 +            r#", #[baz = "qux"] mut bar: u32"#,
 +            r#"
 +fn f(foo: (), #[baz = "qux"] mut bar: u32) {}
 +fn g(foo: ()#[baz = "qux"] mut ba$0)
 +"#,
 +            r#"
 +fn f(foo: (), #[baz = "qux"] mut bar: u32) {}
 +fn g(foo: (), #[baz = "qux"] mut bar: u32)
 +"#,
 +        );
 +    }
 +}
index 03db08a911e92afc8c7abd89603fb3bde9257ff9,0000000000000000000000000000000000000000..34a384f2f7ae8cabdffbdc986101c5f71bed1936
mode 100644,000000..100644
--- /dev/null
@@@ -1,178 -1,0 +1,193 @@@
-     context::{ParamContext, ParamKind, PatternContext},
 +//! Renderer for patterns.
 +
 +use hir::{db::HirDatabase, HasAttrs, Name, StructKind};
 +use ide_db::SnippetCap;
 +use itertools::Itertools;
 +use syntax::SmolStr;
 +
 +use crate::{
-     let kind = variant.kind(ctx.db());
-     let label = format_literal_label(name.as_str(), kind);
-     let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?;
++    context::{ParamContext, ParamKind, PathCompletionCtx, PatternContext},
 +    render::{
 +        variant::{format_literal_label, visible_fields},
 +        RenderContext,
 +    },
 +    CompletionItem, CompletionItemKind,
 +};
 +
 +pub(crate) fn render_struct_pat(
 +    ctx: RenderContext<'_>,
 +    pattern_ctx: &PatternContext,
 +    strukt: hir::Struct,
 +    local_name: Option<Name>,
 +) -> Option<CompletionItem> {
 +    let _p = profile::span("render_struct_pat");
 +
 +    let fields = strukt.fields(ctx.db());
 +    let (visible_fields, fields_omitted) = visible_fields(ctx.completion, &fields, strukt)?;
 +
 +    if visible_fields.is_empty() {
 +        // Matching a struct without matching its fields is pointless, unlike matching a Variant without its fields
 +        return None;
 +    }
 +
 +    let name = local_name.unwrap_or_else(|| strukt.name(ctx.db()));
 +    let (name, escaped_name) = (name.to_smol_str(), name.escaped().to_smol_str());
 +    let kind = strukt.kind(ctx.db());
 +    let label = format_literal_label(name.as_str(), kind);
 +    let pat = render_pat(&ctx, pattern_ctx, &escaped_name, kind, &visible_fields, fields_omitted)?;
 +
 +    Some(build_completion(ctx, label, pat, strukt))
 +}
 +
 +pub(crate) fn render_variant_pat(
 +    ctx: RenderContext<'_>,
 +    pattern_ctx: &PatternContext,
++    path_ctx: Option<&PathCompletionCtx>,
 +    variant: hir::Variant,
 +    local_name: Option<Name>,
 +    path: Option<&hir::ModPath>,
 +) -> Option<CompletionItem> {
 +    let _p = profile::span("render_variant_pat");
 +
 +    let fields = variant.fields(ctx.db());
 +    let (visible_fields, fields_omitted) = visible_fields(ctx.completion, &fields, variant)?;
 +
 +    let (name, escaped_name) = match path {
 +        Some(path) => (path.to_string().into(), path.escaped().to_string().into()),
 +        None => {
 +            let name = local_name.unwrap_or_else(|| variant.name(ctx.db()));
 +            (name.to_smol_str(), name.escaped().to_smol_str())
 +        }
 +    };
++
++    let (label, pat) = match path_ctx {
++        Some(PathCompletionCtx { has_call_parens: true, .. }) => (name, escaped_name.to_string()),
++        _ => {
++            let kind = variant.kind(ctx.db());
++            let label = format_literal_label(name.as_str(), kind);
++            let pat = render_pat(
++                &ctx,
++                pattern_ctx,
++                &escaped_name,
++                kind,
++                &visible_fields,
++                fields_omitted,
++            )?;
++            (label, pat)
++        }
++    };
 +
 +    Some(build_completion(ctx, label, pat, variant))
 +}
 +
 +fn build_completion(
 +    ctx: RenderContext<'_>,
 +    label: SmolStr,
 +    pat: String,
 +    def: impl HasAttrs + Copy,
 +) -> CompletionItem {
 +    let mut item = CompletionItem::new(CompletionItemKind::Binding, ctx.source_range(), label);
 +    item.set_documentation(ctx.docs(def))
 +        .set_deprecated(ctx.is_deprecated(def))
 +        .detail(&pat)
 +        .set_relevance(ctx.completion_relevance());
 +    match ctx.snippet_cap() {
 +        Some(snippet_cap) => item.insert_snippet(snippet_cap, pat),
 +        None => item.insert_text(pat),
 +    };
 +    item.build()
 +}
 +
 +fn render_pat(
 +    ctx: &RenderContext<'_>,
 +    pattern_ctx: &PatternContext,
 +    name: &str,
 +    kind: StructKind,
 +    fields: &[hir::Field],
 +    fields_omitted: bool,
 +) -> Option<String> {
 +    let mut pat = match kind {
 +        StructKind::Tuple => render_tuple_as_pat(ctx.snippet_cap(), fields, name, fields_omitted),
 +        StructKind::Record => {
 +            render_record_as_pat(ctx.db(), ctx.snippet_cap(), fields, name, fields_omitted)
 +        }
 +        StructKind::Unit => name.to_string(),
 +    };
 +
 +    let needs_ascription = matches!(
 +        pattern_ctx,
 +        PatternContext {
 +            param_ctx: Some(ParamContext { kind: ParamKind::Function(_), .. }),
 +            has_type_ascription: false,
 +            ..
 +        }
 +    );
 +    if needs_ascription {
 +        pat.push(':');
 +        pat.push(' ');
 +        pat.push_str(name);
 +    }
 +    if ctx.snippet_cap().is_some() {
 +        pat.push_str("$0");
 +    }
 +    Some(pat)
 +}
 +
 +fn render_record_as_pat(
 +    db: &dyn HirDatabase,
 +    snippet_cap: Option<SnippetCap>,
 +    fields: &[hir::Field],
 +    name: &str,
 +    fields_omitted: bool,
 +) -> String {
 +    let fields = fields.iter();
 +    match snippet_cap {
 +        Some(_) => {
 +            format!(
 +                "{name} {{ {}{} }}",
 +                fields.enumerate().format_with(", ", |(idx, field), f| {
 +                    f(&format_args!("{}${}", field.name(db).escaped(), idx + 1))
 +                }),
 +                if fields_omitted { ", .." } else { "" },
 +                name = name
 +            )
 +        }
 +        None => {
 +            format!(
 +                "{name} {{ {}{} }}",
 +                fields.map(|field| field.name(db).escaped().to_smol_str()).format(", "),
 +                if fields_omitted { ", .." } else { "" },
 +                name = name
 +            )
 +        }
 +    }
 +}
 +
 +fn render_tuple_as_pat(
 +    snippet_cap: Option<SnippetCap>,
 +    fields: &[hir::Field],
 +    name: &str,
 +    fields_omitted: bool,
 +) -> String {
 +    let fields = fields.iter();
 +    match snippet_cap {
 +        Some(_) => {
 +            format!(
 +                "{name}({}{})",
 +                fields
 +                    .enumerate()
 +                    .format_with(", ", |(idx, _), f| { f(&format_args!("${}", idx + 1)) }),
 +                if fields_omitted { ", .." } else { "" },
 +                name = name
 +            )
 +        }
 +        None => {
 +            format!(
 +                "{name}({}{})",
 +                fields.enumerate().map(|(idx, _)| idx).format(", "),
 +                if fields_omitted { ", .." } else { "" },
 +                name = name
 +            )
 +        }
 +    }
 +}
index 4be6acbe8461eef57bb1ca6686ac4459ec4346fe,0000000000000000000000000000000000000000..cf826648dcf7b92426d162055248a2f7248a91c3
mode 100644,000000..100644
--- /dev/null
@@@ -1,310 -1,0 +1,305 @@@
- use std::mem;
 +//! Tests and test utilities for completions.
 +//!
 +//! Most tests live in this module or its submodules. The tests in these submodules are "location"
 +//! oriented, that is they try to check completions for something like type position, param position
 +//! etc.
 +//! Tests that are more orientated towards specific completion types like visibility checks of path
 +//! completions or `check_edit` tests usually live in their respective completion modules instead.
 +//! This gives this test module and its submodules here the main purpose of giving the developer an
 +//! overview of whats being completed where, not how.
 +
 +mod attribute;
 +mod expression;
 +mod flyimport;
 +mod fn_param;
 +mod item_list;
 +mod item;
 +mod pattern;
 +mod predicate;
 +mod proc_macros;
 +mod record;
 +mod special;
 +mod type_pos;
 +mod use_tree;
 +mod visibility;
 +
-     let mut bt_seen = false;
 +use hir::{db::DefDatabase, PrefixKind, Semantics};
 +use ide_db::{
 +    base_db::{fixture::ChangeFixture, FileLoader, FilePosition},
 +    imports::insert_use::{ImportGranularity, InsertUseConfig},
 +    RootDatabase, SnippetCap,
 +};
 +use itertools::Itertools;
 +use stdx::{format_to, trim_indent};
 +use syntax::{AstNode, NodeOrToken, SyntaxElement};
 +use test_utils::assert_eq_text;
 +
 +use crate::{
 +    resolve_completion_edits, CallableSnippets, CompletionConfig, CompletionItem,
 +    CompletionItemKind,
 +};
 +
 +/// Lots of basic item definitions
 +const BASE_ITEMS_FIXTURE: &str = r#"
 +enum Enum { TupleV(u32), RecordV { field: u32 }, UnitV }
 +use self::Enum::TupleV;
 +mod module {}
 +
 +trait Trait {}
 +static STATIC: Unit = Unit;
 +const CONST: Unit = Unit;
 +struct Record { field: u32 }
 +struct Tuple(u32);
 +struct Unit;
 +#[macro_export]
 +macro_rules! makro {}
 +#[rustc_builtin_macro]
 +pub macro Clone {}
 +fn function() {}
 +union Union { field: i32 }
 +"#;
 +
 +pub(crate) const TEST_CONFIG: CompletionConfig = CompletionConfig {
 +    enable_postfix_completions: true,
 +    enable_imports_on_the_fly: true,
 +    enable_self_on_the_fly: true,
 +    enable_private_editable: false,
 +    callable: Some(CallableSnippets::FillArguments),
 +    snippet_cap: SnippetCap::new(true),
 +    insert_use: InsertUseConfig {
 +        granularity: ImportGranularity::Crate,
 +        prefix_kind: PrefixKind::Plain,
 +        enforce_granularity: true,
 +        group: true,
 +        skip_glob_imports: true,
 +    },
 +    snippets: Vec::new(),
 +};
 +
 +pub(crate) fn completion_list(ra_fixture: &str) -> String {
 +    completion_list_with_config(TEST_CONFIG, ra_fixture, true, None)
 +}
 +
 +pub(crate) fn completion_list_no_kw(ra_fixture: &str) -> String {
 +    completion_list_with_config(TEST_CONFIG, ra_fixture, false, None)
 +}
 +
 +pub(crate) fn completion_list_no_kw_with_private_editable(ra_fixture: &str) -> String {
 +    let mut config = TEST_CONFIG.clone();
 +    config.enable_private_editable = true;
 +    completion_list_with_config(config, ra_fixture, false, None)
 +}
 +
 +pub(crate) fn completion_list_with_trigger_character(
 +    ra_fixture: &str,
 +    trigger_character: Option<char>,
 +) -> String {
 +    completion_list_with_config(TEST_CONFIG, ra_fixture, true, trigger_character)
 +}
 +
 +fn completion_list_with_config(
 +    config: CompletionConfig,
 +    ra_fixture: &str,
 +    include_keywords: bool,
 +    trigger_character: Option<char>,
 +) -> String {
 +    // filter out all but one builtintype completion for smaller test outputs
 +    let items = get_all_items(config, ra_fixture, trigger_character);
-         .filter(|it| {
-             it.kind() != CompletionItemKind::BuiltinType || !mem::replace(&mut bt_seen, true)
-         })
 +    let items = items
 +        .into_iter()
++        .filter(|it| it.kind() != CompletionItemKind::BuiltinType || it.label() == "u32")
 +        .filter(|it| include_keywords || it.kind() != CompletionItemKind::Keyword)
 +        .filter(|it| include_keywords || it.kind() != CompletionItemKind::Snippet)
 +        .sorted_by_key(|it| (it.kind(), it.label().to_owned(), it.detail().map(ToOwned::to_owned)))
 +        .collect();
 +    render_completion_list(items)
 +}
 +
 +/// Creates analysis from a multi-file fixture, returns positions marked with $0.
 +pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) {
 +    let change_fixture = ChangeFixture::parse(ra_fixture);
 +    let mut database = RootDatabase::default();
 +    database.set_enable_proc_attr_macros(true);
 +    database.apply_change(change_fixture.change);
 +    let (file_id, range_or_offset) = change_fixture.file_position.expect("expected a marker ($0)");
 +    let offset = range_or_offset.expect_offset();
 +    (database, FilePosition { file_id, offset })
 +}
 +
 +pub(crate) fn do_completion(code: &str, kind: CompletionItemKind) -> Vec<CompletionItem> {
 +    do_completion_with_config(TEST_CONFIG, code, kind)
 +}
 +
 +pub(crate) fn do_completion_with_config(
 +    config: CompletionConfig,
 +    code: &str,
 +    kind: CompletionItemKind,
 +) -> Vec<CompletionItem> {
 +    get_all_items(config, code, None)
 +        .into_iter()
 +        .filter(|c| c.kind() == kind)
 +        .sorted_by(|l, r| l.label().cmp(r.label()))
 +        .collect()
 +}
 +
 +fn render_completion_list(completions: Vec<CompletionItem>) -> String {
 +    fn monospace_width(s: &str) -> usize {
 +        s.chars().count()
 +    }
 +    let label_width =
 +        completions.iter().map(|it| monospace_width(it.label())).max().unwrap_or_default().min(22);
 +    completions
 +        .into_iter()
 +        .map(|it| {
 +            let tag = it.kind().tag();
 +            let var_name = format!("{} {}", tag, it.label());
 +            let mut buf = var_name;
 +            if let Some(detail) = it.detail() {
 +                let width = label_width.saturating_sub(monospace_width(it.label()));
 +                format_to!(buf, "{:width$} {}", "", detail, width = width);
 +            }
 +            if it.deprecated() {
 +                format_to!(buf, " DEPRECATED");
 +            }
 +            format_to!(buf, "\n");
 +            buf
 +        })
 +        .collect()
 +}
 +
 +#[track_caller]
 +pub(crate) fn check_edit(what: &str, ra_fixture_before: &str, ra_fixture_after: &str) {
 +    check_edit_with_config(TEST_CONFIG, what, ra_fixture_before, ra_fixture_after)
 +}
 +
 +#[track_caller]
 +pub(crate) fn check_edit_with_config(
 +    config: CompletionConfig,
 +    what: &str,
 +    ra_fixture_before: &str,
 +    ra_fixture_after: &str,
 +) {
 +    let ra_fixture_after = trim_indent(ra_fixture_after);
 +    let (db, position) = position(ra_fixture_before);
 +    let completions: Vec<CompletionItem> =
 +        crate::completions(&db, &config, position, None).unwrap().into();
 +    let (completion,) = completions
 +        .iter()
 +        .filter(|it| it.lookup() == what)
 +        .collect_tuple()
 +        .unwrap_or_else(|| panic!("can't find {:?} completion in {:#?}", what, completions));
 +    let mut actual = db.file_text(position.file_id).to_string();
 +
 +    let mut combined_edit = completion.text_edit().to_owned();
 +
 +    resolve_completion_edits(
 +        &db,
 +        &config,
 +        position,
 +        completion.imports_to_add().iter().filter_map(|import_edit| {
 +            let import_path = &import_edit.import_path;
 +            let import_name = import_path.segments().last()?;
 +            Some((import_path.to_string(), import_name.to_string()))
 +        }),
 +    )
 +    .into_iter()
 +    .flatten()
 +    .for_each(|text_edit| {
 +        combined_edit.union(text_edit).expect(
 +            "Failed to apply completion resolve changes: change ranges overlap, but should not",
 +        )
 +    });
 +
 +    combined_edit.apply(&mut actual);
 +    assert_eq_text!(&ra_fixture_after, &actual)
 +}
 +
 +pub(crate) fn check_pattern_is_applicable(code: &str, check: impl FnOnce(SyntaxElement) -> bool) {
 +    let (db, pos) = position(code);
 +
 +    let sema = Semantics::new(&db);
 +    let original_file = sema.parse(pos.file_id);
 +    let token = original_file.syntax().token_at_offset(pos.offset).left_biased().unwrap();
 +    assert!(check(NodeOrToken::Token(token)));
 +}
 +
 +pub(crate) fn get_all_items(
 +    config: CompletionConfig,
 +    code: &str,
 +    trigger_character: Option<char>,
 +) -> Vec<CompletionItem> {
 +    let (db, position) = position(code);
 +    let res = crate::completions(&db, &config, position, trigger_character)
 +        .map_or_else(Vec::default, Into::into);
 +    // validate
 +    res.iter().for_each(|it| {
 +        let sr = it.source_range();
 +        assert!(
 +            sr.contains_inclusive(position.offset),
 +            "source range {sr:?} does not contain the offset {:?} of the completion request: {it:?}",
 +            position.offset
 +        );
 +    });
 +    res
 +}
 +
 +#[test]
 +fn test_no_completions_required() {
 +    assert_eq!(completion_list(r#"fn foo() { for i i$0 }"#), String::new());
 +}
 +
 +#[test]
 +fn regression_10042() {
 +    completion_list(
 +        r#"
 +macro_rules! preset {
 +    ($($x:ident)&&*) => {
 +        {
 +            let mut v = Vec::new();
 +            $(
 +                v.push($x.into());
 +            )*
 +            v
 +        }
 +    };
 +}
 +
 +fn foo() {
 +    preset!(foo$0);
 +}
 +"#,
 +    );
 +}
 +
 +#[test]
 +fn no_completions_in_comments() {
 +    assert_eq!(
 +        completion_list(
 +            r#"
 +fn test() {
 +let x = 2; // A comment$0
 +}
 +"#,
 +        ),
 +        String::new(),
 +    );
 +    assert_eq!(
 +        completion_list(
 +            r#"
 +/*
 +Some multi-line comment$0
 +*/
 +"#,
 +        ),
 +        String::new(),
 +    );
 +    assert_eq!(
 +        completion_list(
 +            r#"
 +/// Some doc comment
 +/// let test$0 = 1
 +"#,
 +        ),
 +        String::new(),
 +    );
 +}
index ce9d01d337bae55378f75eb02bd2b2ddaf7a7ee1,0000000000000000000000000000000000000000..925081ebf66025552c5a5a1e03bbbf0c2e058176
mode 100644,000000..100644
--- /dev/null
@@@ -1,655 -1,0 +1,672 @@@
-             tt Trait
 +//! Completion tests for expressions.
 +use expect_test::{expect, Expect};
 +
 +use crate::tests::{completion_list, BASE_ITEMS_FIXTURE};
 +
 +fn check(ra_fixture: &str, expect: Expect) {
 +    let actual = completion_list(&format!("{}{}", BASE_ITEMS_FIXTURE, ra_fixture));
 +    expect.assert_eq(&actual)
 +}
 +
 +fn check_empty(ra_fixture: &str, expect: Expect) {
 +    let actual = completion_list(ra_fixture);
 +    expect.assert_eq(&actual);
 +}
 +
 +#[test]
 +fn complete_literal_struct_with_a_private_field() {
 +    // `FooDesc.bar` is private, the completion should not be triggered.
 +    check(
 +        r#"
 +mod _69latrick {
 +    pub struct FooDesc { pub six: bool, pub neuf: Vec<String>, bar: bool }
 +    pub fn create_foo(foo_desc: &FooDesc) -> () { () }
 +}
 +
 +fn baz() {
 +    use _69latrick::*;
 +
 +    let foo = create_foo(&$0);
 +}
 +            "#,
 +        // This should not contain `FooDesc {…}`.
 +        expect![[r#"
 +            ct CONST
 +            en Enum
 +            fn baz()         fn()
 +            fn create_foo(…) fn(&FooDesc)
 +            fn function()    fn()
 +            ma makro!(…)     macro_rules! makro
 +            md _69latrick
 +            md module
 +            sc STATIC
 +            st FooDesc
 +            st Record
 +            st Tuple
 +            st Unit
-             tt Trait
 +            un Union
 +            ev TupleV(…)     TupleV(u32)
 +            bt u32
 +            kw crate::
 +            kw false
 +            kw for
 +            kw if
 +            kw if let
 +            kw loop
 +            kw match
 +            kw mut
 +            kw return
 +            kw self::
 +            kw true
 +            kw unsafe
 +            kw while
 +            kw while let
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn completes_various_bindings() {
 +    check_empty(
 +        r#"
 +fn func(param0 @ (param1, param2): (i32, i32)) {
 +    let letlocal = 92;
 +    if let ifletlocal = 100 {
 +        match 0 {
 +            matcharm => 1 + $0,
 +            otherwise => (),
 +        }
 +    }
 +    let letlocal2 = 44;
 +}
 +"#,
 +        expect![[r#"
 +            fn func(…)    fn((i32, i32))
 +            lc ifletlocal i32
 +            lc letlocal   i32
 +            lc matcharm   i32
 +            lc param0     (i32, i32)
 +            lc param1     i32
 +            lc param2     i32
 +            bt u32
 +            kw crate::
 +            kw false
 +            kw for
 +            kw if
 +            kw if let
 +            kw loop
 +            kw match
 +            kw return
 +            kw self::
 +            kw true
 +            kw unsafe
 +            kw while
 +            kw while let
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_all_the_things_in_fn_body() {
 +    check(
 +        r#"
 +use non_existant::Unresolved;
 +mod qualified { pub enum Enum { Variant } }
 +
 +impl Unit {
 +    fn foo<'lifetime, TypeParam, const CONST_PARAM: usize>(self) {
 +        fn local_func() {}
 +        $0
 +    }
 +}
 +"#,
 +        // `self` is in here twice, once as the module, once as the local
 +        expect![[r#"
 +            ct CONST
 +            cp CONST_PARAM
 +            en Enum
 +            fn function()   fn()
 +            fn local_func() fn()
 +            lc self         Unit
 +            ma makro!(…)    macro_rules! makro
 +            md module
 +            md qualified
 +            sp Self
 +            sc STATIC
 +            st Record
 +            st Tuple
 +            st Unit
 +            tp TypeParam
 +            un Union
 +            ev TupleV(…)    TupleV(u32)
 +            bt u32
 +            kw const
 +            kw crate::
 +            kw enum
 +            kw extern
 +            kw false
 +            kw fn
 +            kw for
 +            kw if
 +            kw if let
 +            kw impl
 +            kw let
 +            kw loop
 +            kw match
 +            kw mod
 +            kw return
 +            kw self::
 +            kw static
 +            kw struct
 +            kw trait
 +            kw true
 +            kw type
 +            kw union
 +            kw unsafe
 +            kw use
 +            kw while
 +            kw while let
 +            me self.foo()   fn(self)
 +            sn macro_rules
 +            sn pd
 +            sn ppd
 +            ?? Unresolved
 +        "#]],
 +    );
 +    check(
 +        r#"
 +use non_existant::Unresolved;
 +mod qualified { pub enum Enum { Variant } }
 +
 +impl Unit {
 +    fn foo<'lifetime, TypeParam, const CONST_PARAM: usize>(self) {
 +        fn local_func() {}
 +        self::$0
 +    }
 +}
 +"#,
 +        expect![[r#"
 +            ct CONST
 +            en Enum
 +            fn function() fn()
 +            ma makro!(…)  macro_rules! makro
 +            md module
 +            md qualified
 +            sc STATIC
 +            st Record
 +            st Tuple
 +            st Unit
 +            tt Trait
 +            un Union
 +            ev TupleV(…)  TupleV(u32)
 +            ?? Unresolved
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn complete_in_block() {
 +    check_empty(
 +        r#"
 +    fn foo() {
 +        if true {
 +            $0
 +        }
 +    }
 +"#,
 +        expect![[r#"
 +            fn foo()       fn()
 +            bt u32
 +            kw const
 +            kw crate::
 +            kw enum
 +            kw extern
 +            kw false
 +            kw fn
 +            kw for
 +            kw if
 +            kw if let
 +            kw impl
 +            kw let
 +            kw loop
 +            kw match
 +            kw mod
 +            kw return
 +            kw self::
 +            kw static
 +            kw struct
 +            kw trait
 +            kw true
 +            kw type
 +            kw union
 +            kw unsafe
 +            kw use
 +            kw while
 +            kw while let
 +            sn macro_rules
 +            sn pd
 +            sn ppd
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn complete_after_if_expr() {
 +    check_empty(
 +        r#"
 +    fn foo() {
 +        if true {}
 +        $0
 +    }
 +"#,
 +        expect![[r#"
 +            fn foo()       fn()
 +            bt u32
 +            kw const
 +            kw crate::
 +            kw else
 +            kw else if
 +            kw enum
 +            kw extern
 +            kw false
 +            kw fn
 +            kw for
 +            kw if
 +            kw if let
 +            kw impl
 +            kw let
 +            kw loop
 +            kw match
 +            kw mod
 +            kw return
 +            kw self::
 +            kw static
 +            kw struct
 +            kw trait
 +            kw true
 +            kw type
 +            kw union
 +            kw unsafe
 +            kw use
 +            kw while
 +            kw while let
 +            sn macro_rules
 +            sn pd
 +            sn ppd
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn complete_in_match_arm() {
 +    check_empty(
 +        r#"
 +    fn foo() {
 +        match () {
 +            () => $0
 +        }
 +    }
 +"#,
 +        expect![[r#"
 +            fn foo()     fn()
 +            bt u32
 +            kw crate::
 +            kw false
 +            kw for
 +            kw if
 +            kw if let
 +            kw loop
 +            kw match
 +            kw return
 +            kw self::
 +            kw true
 +            kw unsafe
 +            kw while
 +            kw while let
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn completes_in_loop_ctx() {
 +    check_empty(
 +        r"fn my() { loop { $0 } }",
 +        expect![[r#"
 +            fn my()        fn()
 +            bt u32
 +            kw break
 +            kw const
 +            kw continue
 +            kw crate::
 +            kw enum
 +            kw extern
 +            kw false
 +            kw fn
 +            kw for
 +            kw if
 +            kw if let
 +            kw impl
 +            kw let
 +            kw loop
 +            kw match
 +            kw mod
 +            kw return
 +            kw self::
 +            kw static
 +            kw struct
 +            kw trait
 +            kw true
 +            kw type
 +            kw union
 +            kw unsafe
 +            kw use
 +            kw while
 +            kw while let
 +            sn macro_rules
 +            sn pd
 +            sn ppd
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_in_let_initializer() {
 +    check_empty(
 +        r#"fn main() { let _ = $0 }"#,
 +        expect![[r#"
 +            fn main()    fn()
 +            bt u32
 +            kw crate::
 +            kw false
 +            kw for
 +            kw if
 +            kw if let
 +            kw loop
 +            kw match
 +            kw return
 +            kw self::
 +            kw true
 +            kw unsafe
 +            kw while
 +            kw while let
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn struct_initializer_field_expr() {
 +    check_empty(
 +        r#"
 +struct Foo {
 +    pub f: i32,
 +}
 +fn foo() {
 +    Foo {
 +        f: $0
 +    }
 +}
 +"#,
 +        expect![[r#"
 +            fn foo()     fn()
 +            st Foo
 +            bt u32
 +            kw crate::
 +            kw false
 +            kw for
 +            kw if
 +            kw if let
 +            kw loop
 +            kw match
 +            kw return
 +            kw self::
 +            kw true
 +            kw unsafe
 +            kw while
 +            kw while let
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn shadowing_shows_single_completion() {
 +    cov_mark::check!(shadowing_shows_single_completion);
 +
 +    check_empty(
 +        r#"
 +fn foo() {
 +    let bar = 92;
 +    {
 +        let bar = 62;
 +        drop($0)
 +    }
 +}
 +"#,
 +        expect![[r#"
 +            fn foo()     fn()
 +            lc bar       i32
 +            bt u32
 +            kw crate::
 +            kw false
 +            kw for
 +            kw if
 +            kw if let
 +            kw loop
 +            kw match
 +            kw return
 +            kw self::
 +            kw true
 +            kw unsafe
 +            kw while
 +            kw while let
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn in_macro_expr_frag() {
 +    check_empty(
 +        r#"
 +macro_rules! m { ($e:expr) => { $e } }
 +fn quux(x: i32) {
 +    m!($0);
 +}
 +"#,
 +        expect![[r#"
 +            fn quux(…)   fn(i32)
 +            lc x         i32
 +            ma m!(…)     macro_rules! m
 +            bt u32
 +            kw crate::
 +            kw false
 +            kw for
 +            kw if
 +            kw if let
 +            kw loop
 +            kw match
 +            kw return
 +            kw self::
 +            kw true
 +            kw unsafe
 +            kw while
 +            kw while let
 +        "#]],
 +    );
 +    check_empty(
 +        r"
 +macro_rules! m { ($e:expr) => { $e } }
 +fn quux(x: i32) {
 +    m!(x$0);
 +}
 +",
 +        expect![[r#"
 +            fn quux(…)   fn(i32)
 +            lc x         i32
 +            ma m!(…)     macro_rules! m
 +            bt u32
 +            kw crate::
 +            kw false
 +            kw for
 +            kw if
 +            kw if let
 +            kw loop
 +            kw match
 +            kw return
 +            kw self::
 +            kw true
 +            kw unsafe
 +            kw while
 +            kw while let
 +        "#]],
 +    );
 +    check_empty(
 +        r#"
 +macro_rules! m { ($e:expr) => { $e } }
 +fn quux(x: i32) {
 +    let y = 92;
 +    m!(x$0
 +}
 +"#,
 +        expect![[r#""#]],
 +    );
 +}
 +
 +#[test]
 +fn enum_qualified() {
 +    check(
 +        r#"
 +impl Enum {
 +    type AssocType = ();
 +    const ASSOC_CONST: () = ();
 +    fn assoc_fn() {}
 +}
 +fn func() {
 +    Enum::$0
 +}
 +"#,
 +        expect![[r#"
 +            ct ASSOC_CONST const ASSOC_CONST: ()
 +            fn assoc_fn()  fn()
 +            ta AssocType   type AssocType = ()
 +            ev RecordV {…} RecordV { field: u32 }
 +            ev TupleV(…)   TupleV(u32)
 +            ev UnitV       UnitV
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn ty_qualified_no_drop() {
 +    check_empty(
 +        r#"
 +//- minicore: drop
 +struct Foo;
 +impl Drop for Foo {
 +    fn drop(&mut self) {}
 +}
 +fn func() {
 +    Foo::$0
 +}
 +"#,
 +        expect![[r#""#]],
 +    );
 +}
 +
 +#[test]
 +fn with_parens() {
 +    check_empty(
 +        r#"
 +enum Enum {
 +    Variant()
 +}
 +impl Enum {
 +    fn variant() -> Self { Enum::Variant() }
 +}
 +fn func() {
 +    Enum::$0()
 +}
 +"#,
 +        expect![[r#"
 +            fn variant fn() -> Enum
 +            ev Variant Variant
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn detail_impl_trait_in_return_position() {
 +    check_empty(
 +        r"
 +//- minicore: sized
 +trait Trait<T> {}
 +fn foo<U>() -> impl Trait<U> {}
 +fn main() {
 +    self::$0
 +}
 +",
 +        expect![[r#"
 +            fn foo()  fn() -> impl Trait<U>
 +            fn main() fn()
 +            tt Trait
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn detail_async_fn() {
 +    check_empty(
 +        r#"
 +//- minicore: future, sized
 +trait Trait<T> {}
 +async fn foo() -> u8 {}
 +async fn bar<U>() -> impl Trait<U> {}
 +fn main() {
 +    self::$0
 +}
 +"#,
 +        expect![[r#"
 +            fn bar()  async fn() -> impl Trait<U>
 +            fn foo()  async fn() -> u8
 +            fn main() fn()
 +            tt Trait
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn detail_impl_trait_in_argument_position() {
 +    check_empty(
 +        r"
 +//- minicore: sized
 +trait Trait<T> {}
 +struct Foo;
 +impl Foo {
 +    fn bar<U>(_: impl Trait<U>) {}
 +}
 +fn main() {
 +    Foo::$0
 +}
 +",
 +        expect![[r"
 +            fn bar(…) fn(impl Trait<U>)
 +        "]],
 +    );
 +}
++
++#[test]
++fn complete_record_expr_path() {
++    check(
++        r#"
++struct Zulu;
++impl Zulu {
++    fn test() -> Self { }
++}
++fn boi(val: Zulu) { }
++fn main() {
++    boi(Zulu:: $0 {});
++}
++"#,
++        expect![[r#"
++            fn test() fn() -> Zulu
++        "#]],
++    );
++}
index 877b5f216433171995b578ba6ae316a4075e831a,0000000000000000000000000000000000000000..30ddbe2dc6f6010caca0c48d70e718a3178c1c90
mode 100644,000000..100644
--- /dev/null
@@@ -1,716 -1,0 +1,716 @@@
-             bn TupleVariant(…) TupleVariant($1)$0
 +//! Completion tests for pattern position.
 +use expect_test::{expect, Expect};
 +
 +use crate::tests::{check_edit, completion_list, BASE_ITEMS_FIXTURE};
 +
 +fn check_empty(ra_fixture: &str, expect: Expect) {
 +    let actual = completion_list(ra_fixture);
 +    expect.assert_eq(&actual)
 +}
 +
 +fn check(ra_fixture: &str, expect: Expect) {
 +    let actual = completion_list(&format!("{}\n{}", BASE_ITEMS_FIXTURE, ra_fixture));
 +    expect.assert_eq(&actual)
 +}
 +
 +#[test]
 +fn wildcard() {
 +    check(
 +        r#"
 +fn quux() {
 +    let _$0
 +}
 +"#,
 +        expect![""],
 +    );
 +}
 +
 +#[test]
 +fn ident_rebind_pat() {
 +    check_empty(
 +        r#"
 +fn quux() {
 +    let en$0 @ x
 +}
 +"#,
 +        expect![[r#"
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn ident_ref_pat() {
 +    check_empty(
 +        r#"
 +fn quux() {
 +    let ref en$0
 +}
 +"#,
 +        expect![[r#"
 +            kw mut
 +        "#]],
 +    );
 +    check_empty(
 +        r#"
 +fn quux() {
 +    let ref en$0 @ x
 +}
 +"#,
 +        expect![[r#"
 +            kw mut
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn ident_ref_mut_pat() {
 +    check_empty(
 +        r#"
 +fn quux() {
 +    let ref mut en$0
 +}
 +"#,
 +        expect![[r#""#]],
 +    );
 +    check_empty(
 +        r#"
 +fn quux() {
 +    let ref mut en$0 @ x
 +}
 +"#,
 +        expect![[r#""#]],
 +    );
 +}
 +
 +#[test]
 +fn ref_pat() {
 +    check_empty(
 +        r#"
 +fn quux() {
 +    let &en$0
 +}
 +"#,
 +        expect![[r#"
 +            kw mut
 +        "#]],
 +    );
 +    check_empty(
 +        r#"
 +fn quux() {
 +    let &mut en$0
 +}
 +"#,
 +        expect![[r#""#]],
 +    );
 +    check_empty(
 +        r#"
 +fn foo() {
 +    for &$0 in () {}
 +}
 +"#,
 +        expect![[r#"
 +            kw mut
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn refutable() {
 +    check(
 +        r#"
 +fn foo() {
 +    if let a$0
 +}
 +"#,
 +        expect![[r#"
 +            ct CONST
 +            en Enum
 +            ma makro!(…)  macro_rules! makro
 +            md module
 +            st Record
 +            st Tuple
 +            st Unit
 +            ev TupleV
 +            bn Record {…} Record { field$1 }$0
 +            bn Tuple(…)   Tuple($1)$0
 +            bn TupleV(…)  TupleV($1)$0
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn irrefutable() {
 +    check(
 +        r#"
 +enum SingleVariantEnum {
 +    Variant
 +}
 +use SingleVariantEnum::Variant;
 +fn foo() {
 +   let a$0
 +}
 +"#,
 +        expect![[r#"
 +            en SingleVariantEnum
 +            ma makro!(…)         macro_rules! makro
 +            md module
 +            st Record
 +            st Tuple
 +            st Unit
 +            ev Variant
 +            bn Record {…}        Record { field$1 }$0
 +            bn Tuple(…)          Tuple($1)$0
 +            bn Variant           Variant$0
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn in_param() {
 +    check(
 +        r#"
 +fn foo(a$0) {
 +}
 +"#,
 +        expect![[r#"
 +            ma makro!(…)  macro_rules! makro
 +            md module
 +            st Record
 +            st Tuple
 +            st Unit
 +            bn Record {…} Record { field$1 }: Record$0
 +            bn Tuple(…)   Tuple($1): Tuple$0
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +    check(
 +        r#"
 +fn foo(a$0: Tuple) {
 +}
 +"#,
 +        expect![[r#"
 +            ma makro!(…)  macro_rules! makro
 +            md module
 +            st Record
 +            st Tuple
 +            st Unit
 +            bn Record {…} Record { field$1 }$0
 +            bn Tuple(…)   Tuple($1)$0
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn only_fn_like_macros() {
 +    check_empty(
 +        r#"
 +macro_rules! m { ($e:expr) => { $e } }
 +
 +#[rustc_builtin_macro]
 +macro Clone {}
 +
 +fn foo() {
 +    let x$0
 +}
 +"#,
 +        expect![[r#"
 +            ma m!(…) macro_rules! m
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn in_simple_macro_call() {
 +    check_empty(
 +        r#"
 +macro_rules! m { ($e:expr) => { $e } }
 +enum E { X }
 +
 +fn foo() {
 +   m!(match E::X { a$0 })
 +}
 +"#,
 +        expect![[r#"
 +            en E
 +            ma m!(…) macro_rules! m
 +            bn E::X  E::X$0
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn omits_private_fields_pat() {
 +    check_empty(
 +        r#"
 +mod foo {
 +    pub struct Record { pub field: i32, _field: i32 }
 +    pub struct Tuple(pub u32, u32);
 +    pub struct Invisible(u32, u32);
 +}
 +use foo::*;
 +
 +fn outer() {
 +    if let a$0
 +}
 +"#,
 +        expect![[r#"
 +            md foo
 +            st Invisible
 +            st Record
 +            st Tuple
 +            bn Record {…} Record { field$1, .. }$0
 +            bn Tuple(…)   Tuple($1, ..)$0
 +            kw mut
 +            kw ref
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn completes_self_pats() {
 +    check_empty(
 +        r#"
 +struct Foo(i32);
 +impl Foo {
 +    fn foo() {
 +        match Foo(0) {
 +            a$0
 +        }
 +    }
 +}
 +    "#,
 +        expect![[r#"
 +            sp Self
 +            st Foo
 +            bn Foo(…)  Foo($1)$0
 +            bn Self(…) Self($1)$0
 +            kw mut
 +            kw ref
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn enum_qualified() {
 +    check(
 +        r#"
 +impl Enum {
 +    type AssocType = ();
 +    const ASSOC_CONST: () = ();
 +    fn assoc_fn() {}
 +}
 +fn func() {
 +    if let Enum::$0 = unknown {}
 +}
 +"#,
 +        expect![[r#"
 +            ct ASSOC_CONST const ASSOC_CONST: ()
 +            bn RecordV {…} RecordV { field$1 }$0
 +            bn TupleV(…)   TupleV($1)$0
 +            bn UnitV       UnitV$0
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_in_record_field_pat() {
 +    check_empty(
 +        r#"
 +struct Foo { bar: Bar }
 +struct Bar(u32);
 +fn outer(Foo { bar: $0 }: Foo) {}
 +"#,
 +        expect![[r#"
 +            st Bar
 +            st Foo
 +            bn Bar(…)  Bar($1)$0
 +            bn Foo {…} Foo { bar$1 }$0
 +            kw mut
 +            kw ref
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn skips_in_record_field_pat_name() {
 +    check_empty(
 +        r#"
 +struct Foo { bar: Bar }
 +struct Bar(u32);
 +fn outer(Foo { bar$0 }: Foo) {}
 +"#,
 +        expect![[r#"
 +            kw mut
 +            kw ref
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn completes_in_fn_param() {
 +    check_empty(
 +        r#"
 +struct Foo { bar: Bar }
 +struct Bar(u32);
 +fn foo($0) {}
 +"#,
 +        expect![[r#"
 +            st Bar
 +            st Foo
 +            bn Bar(…)  Bar($1): Bar$0
 +            bn Foo {…} Foo { bar$1 }: Foo$0
 +            kw mut
 +            kw ref
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn completes_in_closure_param() {
 +    check_empty(
 +        r#"
 +struct Foo { bar: Bar }
 +struct Bar(u32);
 +fn foo() {
 +    |$0| {};
 +}
 +"#,
 +        expect![[r#"
 +            st Bar
 +            st Foo
 +            bn Bar(…)  Bar($1)$0
 +            bn Foo {…} Foo { bar$1 }$0
 +            kw mut
 +            kw ref
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn completes_no_delims_if_existing() {
 +    check_empty(
 +        r#"
 +struct Bar(u32);
 +fn foo() {
 +    match Bar(0) {
 +        B$0(b) => {}
 +    }
 +}
 +"#,
 +        expect![[r#"
 +            st Bar
 +            kw crate::
 +            kw self::
 +        "#]],
 +    );
 +    check_empty(
 +        r#"
 +struct Foo { bar: u32 }
 +fn foo() {
 +    match (Foo { bar: 0 }) {
 +        F$0 { bar } => {}
 +    }
 +}
 +"#,
 +        expect![[r#"
 +            st Foo
 +            kw crate::
 +            kw self::
 +        "#]],
 +    );
 +    check_empty(
 +        r#"
 +enum Enum {
 +    TupleVariant(u32)
 +}
 +fn foo() {
 +    match Enum::TupleVariant(0) {
 +        Enum::T$0(b) => {}
 +    }
 +}
 +"#,
 +        expect![[r#"
-             bn RecordVariant {…} RecordVariant { field$1 }$0
++            bn TupleVariant TupleVariant
 +        "#]],
 +    );
 +    check_empty(
 +        r#"
 +enum Enum {
 +    RecordVariant { field: u32 }
 +}
 +fn foo() {
 +    match (Enum::RecordVariant { field: 0 }) {
 +        Enum::RecordV$0 { field } => {}
 +    }
 +}
 +"#,
 +        expect![[r#"
++            bn RecordVariant RecordVariant
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_enum_variant_pat() {
 +    cov_mark::check!(enum_variant_pattern_path);
 +    check_edit(
 +        "RecordVariant {…}",
 +        r#"
 +enum Enum {
 +    RecordVariant { field: u32 }
 +}
 +fn foo() {
 +    match (Enum::RecordVariant { field: 0 }) {
 +        Enum::RecordV$0
 +    }
 +}
 +"#,
 +        r#"
 +enum Enum {
 +    RecordVariant { field: u32 }
 +}
 +fn foo() {
 +    match (Enum::RecordVariant { field: 0 }) {
 +        Enum::RecordVariant { field$1 }$0
 +    }
 +}
 +"#,
 +    );
 +}
 +
 +#[test]
 +fn completes_enum_variant_pat_escape() {
 +    cov_mark::check!(enum_variant_pattern_path);
 +    check_empty(
 +        r#"
 +enum Enum {
 +    A,
 +    B { r#type: i32 },
 +    r#type,
 +    r#struct { r#type: i32 },
 +}
 +fn foo() {
 +    match (Enum::A) {
 +        $0
 +    }
 +}
 +"#,
 +        expect![[r#"
 +            en Enum
 +            bn Enum::A          Enum::A$0
 +            bn Enum::B {…}      Enum::B { r#type$1 }$0
 +            bn Enum::struct {…} Enum::r#struct { r#type$1 }$0
 +            bn Enum::type       Enum::r#type$0
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +
 +    check_empty(
 +        r#"
 +enum Enum {
 +    A,
 +    B { r#type: i32 },
 +    r#type,
 +    r#struct { r#type: i32 },
 +}
 +fn foo() {
 +    match (Enum::A) {
 +        Enum::$0
 +    }
 +}
 +"#,
 +        expect![[r#"
 +            bn A          A$0
 +            bn B {…}      B { r#type$1 }$0
 +            bn struct {…} r#struct { r#type$1 }$0
 +            bn type       r#type$0
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_associated_const() {
 +    check_empty(
 +        r#"
 +#[derive(PartialEq, Eq)]
 +struct Ty(u8);
 +
 +impl Ty {
 +    const ABC: Self = Self(0);
 +}
 +
 +fn f(t: Ty) {
 +    match t {
 +        Ty::$0 => {}
 +        _ => {}
 +    }
 +}
 +"#,
 +        expect![[r#"
 +            ct ABC const ABC: Self
 +        "#]],
 +    );
 +
 +    check_empty(
 +        r#"
 +enum MyEnum {}
 +
 +impl MyEnum {
 +    pub const A: i32 = 123;
 +    pub const B: i32 = 456;
 +}
 +
 +fn f(e: MyEnum) {
 +    match e {
 +        MyEnum::$0 => {}
 +        _ => {}
 +    }
 +}
 +"#,
 +        expect![[r#"
 +            ct A pub const A: i32
 +            ct B pub const B: i32
 +        "#]],
 +    );
 +
 +    check_empty(
 +        r#"
 +union U {
 +    i: i32,
 +    f: f32,
 +}
 +
 +impl U {
 +    pub const C: i32 = 123;
 +    pub const D: i32 = 456;
 +}
 +
 +fn f(u: U) {
 +    match u {
 +        U::$0 => {}
 +        _ => {}
 +    }
 +}
 +"#,
 +        expect![[r#"
 +            ct C pub const C: i32
 +            ct D pub const D: i32
 +        "#]],
 +    );
 +
 +    check_empty(
 +        r#"
 +#[lang = "u32"]
 +impl u32 {
 +    pub const MIN: Self = 0;
 +}
 +
 +fn f(v: u32) {
 +    match v {
 +        u32::$0
 +    }
 +}
 +        "#,
 +        expect![[r#"
 +            ct MIN pub const MIN: Self
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn in_method_param() {
 +    check_empty(
 +        r#"
 +struct Ty(u8);
 +
 +impl Ty {
 +    fn foo($0)
 +}
 +"#,
 +        expect![[r#"
 +            sp Self
 +            st Ty
 +            bn &mut self
 +            bn &self
 +            bn Self(…)   Self($1): Self$0
 +            bn Ty(…)     Ty($1): Ty$0
 +            bn mut self
 +            bn self
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +    check_empty(
 +        r#"
 +struct Ty(u8);
 +
 +impl Ty {
 +    fn foo(s$0)
 +}
 +"#,
 +        expect![[r#"
 +            sp Self
 +            st Ty
 +            bn &mut self
 +            bn &self
 +            bn Self(…)   Self($1): Self$0
 +            bn Ty(…)     Ty($1): Ty$0
 +            bn mut self
 +            bn self
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +    check_empty(
 +        r#"
 +struct Ty(u8);
 +
 +impl Ty {
 +    fn foo(s$0, foo: u8)
 +}
 +"#,
 +        expect![[r#"
 +            sp Self
 +            st Ty
 +            bn &mut self
 +            bn &self
 +            bn Self(…)   Self($1): Self$0
 +            bn Ty(…)     Ty($1): Ty$0
 +            bn mut self
 +            bn self
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +    check_empty(
 +        r#"
 +struct Ty(u8);
 +
 +impl Ty {
 +    fn foo(foo: u8, b$0)
 +}
 +"#,
 +        expect![[r#"
 +            sp Self
 +            st Ty
 +            bn Self(…) Self($1): Self$0
 +            bn Ty(…)   Ty($1): Ty$0
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +}
index ec32602fa3c2f83f95ab6f8db5b193b966068ac7,0000000000000000000000000000000000000000..f6accc68e5e80cec252e9c5c970ad819662ab81e
mode 100644,000000..100644
--- /dev/null
@@@ -1,230 -1,0 +1,229 @@@
-             tt Sized
 +use expect_test::{expect, Expect};
 +
 +use crate::tests::completion_list;
 +
 +fn check(ra_fixture: &str, expect: Expect) {
 +    let actual = completion_list(ra_fixture);
 +    expect.assert_eq(&actual);
 +}
 +
 +#[test]
 +fn without_default_impl() {
 +    check(
 +        r#"
 +struct Struct { foo: u32, bar: usize }
 +
 +fn foo() {
 +    let other = Struct {
 +        foo: 5,
 +        $0
 +    };
 +}
 +"#,
 +        expect![[r#"
 +            fd bar usize
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn record_pattern_field() {
 +    check(
 +        r#"
 +struct Struct { foo: u32, bar: u32 }
 +
 +fn foo(s: Struct) {
 +    match s {
 +        Struct { foo, $0: 92 } => (),
 +    }
 +}
 +"#,
 +        expect![[r#"
 +            fd bar u32
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn pattern_enum_variant() {
 +    check(
 +        r#"
 +enum Enum { Variant { foo: u32, bar: u32 } }
 +fn foo(e: Enum) {
 +    match e {
 +        Enum::Variant { foo, $0 } => (),
 +    }
 +}
 +"#,
 +        expect![[r#"
 +            fd bar u32
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn record_literal_field_in_macro() {
 +    check(
 +        r#"
 +macro_rules! m { ($e:expr) => { $e } }
 +struct Struct { field: u32 }
 +fn foo() {
 +    m!(Struct { fie$0 })
 +}
 +"#,
 +        expect![[r#"
 +            fd field u32
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn record_pattern_field_in_macro() {
 +    check(
 +        r"
 +macro_rules! m { ($e:expr) => { $e } }
 +struct Struct { field: u32 }
 +
 +fn foo(f: Struct) {
 +    m!(match f {
 +        Struct { f$0: 92 } => (),
 +    })
 +}
 +",
 +        expect![[r#"
 +            fd field u32
 +            kw mut
 +            kw ref
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn functional_update() {
 +    // FIXME: This should filter out all completions that do not have the type `Foo`
 +    check(
 +        r#"
 +//- minicore:default
 +struct Foo { foo1: u32, foo2: u32 }
 +impl Default for Foo {
 +    fn default() -> Self { loop {} }
 +}
 +
 +fn main() {
 +    let thing = 1;
 +    let foo = Foo { foo1: 0, foo2: 0 };
 +    let foo2 = Foo { thing, $0 }
 +}
 +"#,
 +        expect![[r#"
 +            fd ..Default::default()
 +            fd foo1                 u32
 +            fd foo2                 u32
 +        "#]],
 +    );
 +    check(
 +        r#"
 +//- minicore:default
 +struct Foo { foo1: u32, foo2: u32 }
 +impl Default for Foo {
 +    fn default() -> Self { loop {} }
 +}
 +
 +fn main() {
 +    let thing = 1;
 +    let foo = Foo { foo1: 0, foo2: 0 };
 +    let foo2 = Foo { thing, .$0 }
 +}
 +"#,
 +        expect![[r#"
 +            fd ..Default::default()
 +            sn ..
 +        "#]],
 +    );
 +    check(
 +        r#"
 +//- minicore:default
 +struct Foo { foo1: u32, foo2: u32 }
 +impl Default for Foo {
 +    fn default() -> Self { loop {} }
 +}
 +
 +fn main() {
 +    let thing = 1;
 +    let foo = Foo { foo1: 0, foo2: 0 };
 +    let foo2 = Foo { thing, ..$0 }
 +}
 +"#,
 +        expect![[r#"
 +            fd ..Default::default()
 +            fn main()               fn()
 +            lc foo                  Foo
 +            lc thing                i32
 +            md core
 +            st Foo
 +            st Foo {…}              Foo { foo1: u32, foo2: u32 }
 +            tt Default
 +            bt u32
 +            kw crate::
 +            kw self::
 +        "#]],
 +    );
 +    check(
 +        r#"
 +//- minicore:default
 +struct Foo { foo1: u32, foo2: u32 }
 +impl Default for Foo {
 +    fn default() -> Self { loop {} }
 +}
 +
 +fn main() {
 +    let thing = 1;
 +    let foo = Foo { foo1: 0, foo2: 0 };
 +    let foo2 = Foo { thing, ..Default::$0 }
 +}
 +"#,
 +        expect![[r#"
 +            fn default() (as Default) fn() -> Self
 +        "#]],
 +    );
 +}
 +
 +#[test]
 +fn empty_union_literal() {
 +    check(
 +        r#"
 +union Union { foo: u32, bar: f32 }
 +
 +fn foo() {
 +    let other = Union {
 +        $0
 +    };
 +}
 +        "#,
 +        expect![[r#"
 +            fd bar f32
 +            fd foo u32
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn dont_suggest_additional_union_fields() {
 +    check(
 +        r#"
 +union Union { foo: u32, bar: f32 }
 +
 +fn foo() {
 +    let other = Union {
 +        foo: 1,
 +        $0
 +    };
 +}
 +        "#,
 +        expect![[r#""#]],
 +    )
 +}
index ca779c2fc713e98f6022b85d1a35467579ba779e,0000000000000000000000000000000000000000..033dc99c26cf0c09acfdb2efb52a073b95b2a2f2
mode 100644,000000..100644
--- /dev/null
@@@ -1,842 -1,0 +1,895 @@@
-     )
 +//! Tests that don't fit into a specific category.
 +
 +use expect_test::{expect, Expect};
 +
 +use crate::tests::{check_edit, completion_list_no_kw};
 +
 +fn check(ra_fixture: &str, expect: Expect) {
 +    let actual = completion_list_no_kw(ra_fixture);
 +    expect.assert_eq(&actual)
 +}
 +
 +#[test]
 +fn completes_if_prefix_is_keyword() {
 +    check_edit(
 +        "wherewolf",
 +        r#"
 +fn main() {
 +    let wherewolf = 92;
 +    drop(where$0)
 +}
 +"#,
 +        r#"
 +fn main() {
 +    let wherewolf = 92;
 +    drop(wherewolf)
 +}
 +"#,
 +    )
 +}
 +
 +/// Regression test for issue #6091.
 +#[test]
 +fn correctly_completes_module_items_prefixed_with_underscore() {
 +    check_edit(
 +        "_alpha",
 +        r#"
 +fn main() {
 +    _$0
 +}
 +fn _alpha() {}
 +"#,
 +        r#"
 +fn main() {
 +    _alpha()$0
 +}
 +fn _alpha() {}
 +"#,
 +    )
 +}
 +
 +#[test]
 +fn completes_prelude() {
 +    check(
 +        r#"
 +//- /main.rs crate:main deps:std
 +fn foo() { let x: $0 }
 +
 +//- /std/lib.rs crate:std
 +pub mod prelude {
 +    pub mod rust_2018 {
 +        pub struct Option;
 +    }
 +}
 +"#,
 +        expect![[r#"
 +                md std
 +                st Option
 +                bt u32
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_prelude_macros() {
 +    check(
 +        r#"
 +//- /main.rs crate:main deps:std
 +fn f() {$0}
 +
 +//- /std/lib.rs crate:std
 +pub mod prelude {
 +    pub mod rust_2018 {
 +        pub use crate::concat;
 +    }
 +}
 +
 +mod macros {
 +    #[rustc_builtin_macro]
 +    #[macro_export]
 +    macro_rules! concat { }
 +}
 +"#,
 +        expect![[r#"
 +                fn f()        fn()
 +                ma concat!(…) macro_rules! concat
 +                md std
 +                bt u32
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_std_prelude_if_core_is_defined() {
 +    check(
 +        r#"
 +//- /main.rs crate:main deps:core,std
 +fn foo() { let x: $0 }
 +
 +//- /core/lib.rs crate:core
 +pub mod prelude {
 +    pub mod rust_2018 {
 +        pub struct Option;
 +    }
 +}
 +
 +//- /std/lib.rs crate:std deps:core
 +pub mod prelude {
 +    pub mod rust_2018 {
 +        pub struct String;
 +    }
 +}
 +"#,
 +        expect![[r#"
 +                md core
 +                md std
 +                st String
 +                bt u32
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn respects_doc_hidden() {
 +    check(
 +        r#"
 +//- /lib.rs crate:lib deps:std
 +fn f() {
 +    format_$0
 +}
 +
 +//- /std.rs crate:std
 +#[doc(hidden)]
 +#[macro_export]
 +macro_rules! format_args_nl {
 +    () => {}
 +}
 +
 +pub mod prelude {
 +    pub mod rust_2018 {}
 +}
 +            "#,
 +        expect![[r#"
 +                fn f() fn()
 +                md std
 +                bt u32
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn respects_doc_hidden_in_assoc_item_list() {
 +    check(
 +        r#"
 +//- /lib.rs crate:lib deps:std
 +struct S;
 +impl S {
 +    format_$0
 +}
 +
 +//- /std.rs crate:std
 +#[doc(hidden)]
 +#[macro_export]
 +macro_rules! format_args_nl {
 +    () => {}
 +}
 +
 +pub mod prelude {
 +    pub mod rust_2018 {}
 +}
 +            "#,
 +        expect![[r#"
 +                md std
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn associated_item_visibility() {
 +    check(
 +        r#"
 +//- /lib.rs crate:lib new_source_root:library
 +pub struct S;
 +
 +impl S {
 +    pub fn public_method() { }
 +    fn private_method() { }
 +    pub type PublicType = u32;
 +    type PrivateType = u32;
 +    pub const PUBLIC_CONST: u32 = 1;
 +    const PRIVATE_CONST: u32 = 1;
 +}
 +
 +//- /main.rs crate:main deps:lib new_source_root:local
 +fn foo() { let _ = lib::S::$0 }
 +"#,
 +        expect![[r#"
 +                ct PUBLIC_CONST    pub const PUBLIC_CONST: u32
 +                fn public_method() fn()
 +                ta PublicType      pub type PublicType = u32
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_union_associated_method() {
 +    check(
 +        r#"
 +union U {};
 +impl U { fn m() { } }
 +
 +fn foo() { let _ = U::$0 }
 +"#,
 +        expect![[r#"
 +                fn m() fn()
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_trait_associated_method_1() {
 +    check(
 +        r#"
 +trait Trait { fn m(); }
 +
 +fn foo() { let _ = Trait::$0 }
 +"#,
 +        expect![[r#"
 +                fn m() (as Trait) fn()
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_trait_associated_method_2() {
 +    check(
 +        r#"
 +trait Trait { fn m(); }
 +
 +struct S;
 +impl Trait for S {}
 +
 +fn foo() { let _ = S::$0 }
 +"#,
 +        expect![[r#"
 +                fn m() (as Trait) fn()
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_trait_associated_method_3() {
 +    check(
 +        r#"
 +trait Trait { fn m(); }
 +
 +struct S;
 +impl Trait for S {}
 +
 +fn foo() { let _ = <S as Trait>::$0 }
 +"#,
 +        expect![[r#"
 +                fn m() (as Trait) fn()
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_ty_param_assoc_ty() {
 +    check(
 +        r#"
 +trait Super {
 +    type Ty;
 +    const CONST: u8;
 +    fn func() {}
 +    fn method(&self) {}
 +}
 +
 +trait Sub: Super {
 +    type SubTy;
 +    const C2: ();
 +    fn subfunc() {}
 +    fn submethod(&self) {}
 +}
 +
 +fn foo<T: Sub>() { T::$0 }
 +"#,
 +        expect![[r#"
 +                ct C2 (as Sub)           const C2: ()
 +                ct CONST (as Super)      const CONST: u8
 +                fn func() (as Super)     fn()
 +                fn subfunc() (as Sub)    fn()
 +                ta SubTy (as Sub)        type SubTy
 +                ta Ty (as Super)         type Ty
 +                me method(…) (as Super)  fn(&self)
 +                me submethod(…) (as Sub) fn(&self)
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_self_param_assoc_ty() {
 +    check(
 +        r#"
 +trait Super {
 +    type Ty;
 +    const CONST: u8 = 0;
 +    fn func() {}
 +    fn method(&self) {}
 +}
 +
 +trait Sub: Super {
 +    type SubTy;
 +    const C2: () = ();
 +    fn subfunc() {}
 +    fn submethod(&self) {}
 +}
 +
 +struct Wrap<T>(T);
 +impl<T> Super for Wrap<T> {}
 +impl<T> Sub for Wrap<T> {
 +    fn subfunc() {
 +        // Should be able to assume `Self: Sub + Super`
 +        Self::$0
 +    }
 +}
 +"#,
 +        expect![[r#"
 +                ct C2 (as Sub)           const C2: ()
 +                ct CONST (as Super)      const CONST: u8
 +                fn func() (as Super)     fn()
 +                fn subfunc() (as Sub)    fn()
 +                ta SubTy (as Sub)        type SubTy
 +                ta Ty (as Super)         type Ty
 +                me method(…) (as Super)  fn(&self)
 +                me submethod(…) (as Sub) fn(&self)
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_type_alias() {
 +    check(
 +        r#"
 +struct S;
 +impl S { fn foo() {} }
 +type T = S;
 +impl T { fn bar() {} }
 +
 +fn main() { T::$0; }
 +"#,
 +        expect![[r#"
 +                fn bar() fn()
 +                fn foo() fn()
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_qualified_macros() {
 +    check(
 +        r#"
 +#[macro_export]
 +macro_rules! foo { () => {} }
 +
 +fn main() { let _ = crate::$0 }
 +"#,
 +        expect![[r#"
 +                fn main()  fn()
 +                ma foo!(…) macro_rules! foo
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn does_not_complete_non_fn_macros() {
 +    check(
 +        r#"
 +mod m {
 +    #[rustc_builtin_macro]
 +    pub macro Clone {}
 +}
 +
 +fn f() {m::$0}
 +"#,
 +        expect![[r#""#]],
 +    );
 +    check(
 +        r#"
 +mod m {
 +    #[rustc_builtin_macro]
 +    pub macro bench {}
 +}
 +
 +fn f() {m::$0}
 +"#,
 +        expect![[r#""#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_reexported_items_under_correct_name() {
 +    check(
 +        r#"
 +fn foo() { self::m::$0 }
 +
 +mod m {
 +    pub use super::p::wrong_fn as right_fn;
 +    pub use super::p::WRONG_CONST as RIGHT_CONST;
 +    pub use super::p::WrongType as RightType;
 +}
 +mod p {
 +    pub fn wrong_fn() {}
 +    pub const WRONG_CONST: u32 = 1;
 +    pub struct WrongType {};
 +}
 +"#,
 +        expect![[r#"
 +                ct RIGHT_CONST
 +                fn right_fn()  fn()
 +                st RightType
 +            "#]],
 +    );
 +
 +    check_edit(
 +        "RightType",
 +        r#"
 +fn foo() { self::m::$0 }
 +
 +mod m {
 +    pub use super::p::wrong_fn as right_fn;
 +    pub use super::p::WRONG_CONST as RIGHT_CONST;
 +    pub use super::p::WrongType as RightType;
 +}
 +mod p {
 +    pub fn wrong_fn() {}
 +    pub const WRONG_CONST: u32 = 1;
 +    pub struct WrongType {};
 +}
 +"#,
 +        r#"
 +fn foo() { self::m::RightType }
 +
 +mod m {
 +    pub use super::p::wrong_fn as right_fn;
 +    pub use super::p::WRONG_CONST as RIGHT_CONST;
 +    pub use super::p::WrongType as RightType;
 +}
 +mod p {
 +    pub fn wrong_fn() {}
 +    pub const WRONG_CONST: u32 = 1;
 +    pub struct WrongType {};
 +}
 +"#,
 +    );
 +}
 +
 +#[test]
 +fn completes_in_simple_macro_call() {
 +    check(
 +        r#"
 +macro_rules! m { ($e:expr) => { $e } }
 +fn main() { m!(self::f$0); }
 +fn foo() {}
 +"#,
 +        expect![[r#"
 +                fn foo()  fn()
 +                fn main() fn()
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn function_mod_share_name() {
 +    check(
 +        r#"
 +fn foo() { self::m::$0 }
 +
 +mod m {
 +    pub mod z {}
 +    pub fn z() {}
 +}
 +"#,
 +        expect![[r#"
 +                fn z() fn()
 +                md z
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_hashmap_new() {
 +    check(
 +        r#"
 +struct RandomState;
 +struct HashMap<K, V, S = RandomState> {}
 +
 +impl<K, V> HashMap<K, V, RandomState> {
 +    pub fn new() -> HashMap<K, V, RandomState> { }
 +}
 +fn foo() {
 +    HashMap::$0
 +}
 +"#,
 +        expect![[r#"
 +                fn new() fn() -> HashMap<K, V, RandomState>
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_variant_through_self() {
 +    cov_mark::check!(completes_variant_through_self);
 +    check(
 +        r#"
 +enum Foo {
 +    Bar,
 +    Baz,
 +}
 +
 +impl Foo {
 +    fn foo(self) {
 +        Self::$0
 +    }
 +}
 +"#,
 +        expect![[r#"
 +                ev Bar    Bar
 +                ev Baz    Baz
 +                me foo(…) fn(self)
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_non_exhaustive_variant_within_the_defining_crate() {
 +    check(
 +        r#"
 +enum Foo {
 +    #[non_exhaustive]
 +    Bar,
 +    Baz,
 +}
 +
 +fn foo(self) {
 +    Foo::$0
 +}
 +"#,
 +        expect![[r#"
 +                ev Bar Bar
 +                ev Baz Baz
 +            "#]],
 +    );
 +
 +    check(
 +        r#"
 +//- /main.rs crate:main deps:e
 +fn foo(self) {
 +    e::Foo::$0
 +}
 +
 +//- /e.rs crate:e
 +enum Foo {
 +    #[non_exhaustive]
 +    Bar,
 +    Baz,
 +}
 +"#,
 +        expect![[r#"
 +                ev Baz Baz
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_primitive_assoc_const() {
 +    cov_mark::check!(completes_primitive_assoc_const);
 +    check(
 +        r#"
 +//- /lib.rs crate:lib deps:core
 +fn f() {
 +    u8::$0
 +}
 +
 +//- /core.rs crate:core
 +#[lang = "u8"]
 +impl u8 {
 +    pub const MAX: Self = 255;
 +
 +    pub fn func(self) {}
 +}
 +"#,
 +        expect![[r#"
 +                ct MAX     pub const MAX: Self
 +                me func(…) fn(self)
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn completes_variant_through_alias() {
 +    cov_mark::check!(completes_variant_through_alias);
 +    check(
 +        r#"
 +enum Foo {
 +    Bar
 +}
 +type Foo2 = Foo;
 +fn main() {
 +    Foo2::$0
 +}
 +"#,
 +        expect![[r#"
 +                ev Bar Bar
 +            "#]],
 +    );
 +}
 +
 +#[test]
 +fn respects_doc_hidden2() {
 +    check(
 +        r#"
 +//- /lib.rs crate:lib deps:dep
 +fn f() {
 +    dep::$0
 +}
 +
 +//- /dep.rs crate:dep
 +#[doc(hidden)]
 +#[macro_export]
 +macro_rules! m {
 +    () => {}
 +}
 +
 +#[doc(hidden)]
 +pub fn f() {}
 +
 +#[doc(hidden)]
 +pub struct S;
 +
 +#[doc(hidden)]
 +pub mod m {}
 +            "#,
 +        expect![[r#""#]],
 +    )
 +}
 +
 +#[test]
 +fn type_anchor_empty() {
 +    check(
 +        r#"
 +trait Foo {
 +    fn foo() -> Self;
 +}
 +struct Bar;
 +impl Foo for Bar {
 +    fn foo() -> {
 +        Bar
 +    }
 +}
 +fn bar() -> Bar {
 +    <_>::$0
 +}
 +"#,
 +        expect![[r#"
 +                fn foo() (as Foo) fn() -> Self
 +            "#]],
++    );
++}
++
++#[test]
++fn type_anchor_type() {
++    check(
++        r#"
++trait Foo {
++    fn foo() -> Self;
++}
++struct Bar;
++impl Bar {
++    fn bar() {}
++}
++impl Foo for Bar {
++    fn foo() -> {
++        Bar
++    }
++}
++fn bar() -> Bar {
++    <Bar>::$0
++}
++"#,
++        expect![[r#"
++            fn bar()          fn()
++            fn foo() (as Foo) fn() -> Self
++        "#]],
++    );
++}
++
++#[test]
++fn type_anchor_type_trait() {
++    check(
++        r#"
++trait Foo {
++    fn foo() -> Self;
++}
++struct Bar;
++impl Bar {
++    fn bar() {}
++}
++impl Foo for Bar {
++    fn foo() -> {
++        Bar
++    }
++}
++fn bar() -> Bar {
++    <Bar as Foo>::$0
++}
++"#,
++        expect![[r#"
++            fn foo() (as Foo) fn() -> Self
++        "#]],
++    );
 +}
 +
 +#[test]
 +fn completes_fn_in_pub_trait_generated_by_macro() {
 +    check(
 +        r#"
 +mod other_mod {
 +    macro_rules! make_method {
 +        ($name:ident) => {
 +            fn $name(&self) {}
 +        };
 +    }
 +
 +    pub trait MyTrait {
 +        make_method! { by_macro }
 +        fn not_by_macro(&self) {}
 +    }
 +
 +    pub struct Foo {}
 +
 +    impl MyTrait for Foo {}
 +}
 +
 +fn main() {
 +    use other_mod::{Foo, MyTrait};
 +    let f = Foo {};
 +    f.$0
 +}
 +"#,
 +        expect![[r#"
 +            me by_macro() (as MyTrait) fn(&self)
 +            me not_by_macro() (as MyTrait) fn(&self)
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn completes_fn_in_pub_trait_generated_by_recursive_macro() {
 +    check(
 +        r#"
 +mod other_mod {
 +    macro_rules! make_method {
 +        ($name:ident) => {
 +            fn $name(&self) {}
 +        };
 +    }
 +
 +    macro_rules! make_trait {
 +        () => {
 +            pub trait MyTrait {
 +                make_method! { by_macro }
 +                fn not_by_macro(&self) {}
 +            }
 +        }
 +    }
 +
 +    make_trait!();
 +
 +    pub struct Foo {}
 +
 +    impl MyTrait for Foo {}
 +}
 +
 +fn main() {
 +    use other_mod::{Foo, MyTrait};
 +    let f = Foo {};
 +    f.$0
 +}
 +"#,
 +        expect![[r#"
 +            me by_macro() (as MyTrait) fn(&self)
 +            me not_by_macro() (as MyTrait) fn(&self)
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn completes_const_in_pub_trait_generated_by_macro() {
 +    check(
 +        r#"
 +mod other_mod {
 +    macro_rules! make_const {
 +        ($name:ident) => {
 +            const $name: u8 = 1;
 +        };
 +    }
 +
 +    pub trait MyTrait {
 +        make_const! { by_macro }
 +    }
 +
 +    pub struct Foo {}
 +
 +    impl MyTrait for Foo {}
 +}
 +
 +fn main() {
 +    use other_mod::{Foo, MyTrait};
 +    let f = Foo {};
 +    Foo::$0
 +}
 +"#,
 +        expect![[r#"
 +            ct by_macro (as MyTrait) pub const by_macro: u8
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn completes_locals_from_macros() {
 +    check(
 +        r#"
 +
 +macro_rules! x {
 +    ($x:ident, $expr:expr) => {
 +        let $x = 0;
 +        $expr
 +    };
 +}
 +fn main() {
 +    x! {
 +        foobar, {
 +            f$0
 +        }
 +    };
 +}
 +"#,
 +        expect![[r#"
 +            fn main() fn()
 +            lc foobar i32
 +            ma x!(…)  macro_rules! x
 +            bt u32
 +        "#]],
 +    )
 +}
 +
 +#[test]
 +fn regression_12644() {
 +    check(
 +        r#"
 +macro_rules! __rust_force_expr {
 +    ($e:expr) => {
 +        $e
 +    };
 +}
 +macro_rules! vec {
 +    ($elem:expr) => {
 +        __rust_force_expr!($elem)
 +    };
 +}
 +
 +struct Struct;
 +impl Struct {
 +    fn foo(self) {}
 +}
 +
 +fn f() {
 +    vec![Struct].$0;
 +}
 +"#,
 +        expect![[r#"
 +            me foo() fn(self)
 +        "#]],
 +    );
 +}
index d013d6f4b19ff95b0ef03e178ed3a194983ca09a,0000000000000000000000000000000000000000..3fb49b45d9888ebb7fcac3d4e4431b3f9f596e75
mode 100644,000000..100644
--- /dev/null
@@@ -1,449 -1,0 +1,449 @@@
- use hir::{InFile, Name, Semantics};
 +pub(crate) mod tags;
 +
 +mod highlights;
 +mod injector;
 +
 +mod highlight;
 +mod format;
 +mod macro_;
 +mod inject;
 +mod escape;
 +
 +mod html;
 +#[cfg(test)]
 +mod tests;
 +
-                 inject::doc_comment(hl, sema, InFile::new(file_id.into(), &node));
++use hir::{Name, Semantics};
 +use ide_db::{FxHashMap, RootDatabase};
 +use syntax::{
 +    ast, AstNode, AstToken, NodeOrToken, SyntaxKind::*, SyntaxNode, TextRange, WalkEvent, T,
 +};
 +
 +use crate::{
 +    syntax_highlighting::{
 +        escape::highlight_escape_string, format::highlight_format_string, highlights::Highlights,
 +        macro_::MacroHighlighter, tags::Highlight,
 +    },
 +    FileId, HlMod, HlTag,
 +};
 +
 +pub(crate) use html::highlight_as_html;
 +
 +#[derive(Debug, Clone, Copy)]
 +pub struct HlRange {
 +    pub range: TextRange,
 +    pub highlight: Highlight,
 +    pub binding_hash: Option<u64>,
 +}
 +
 +// Feature: Semantic Syntax Highlighting
 +//
 +// rust-analyzer highlights the code semantically.
 +// For example, `Bar` in `foo::Bar` might be colored differently depending on whether `Bar` is an enum or a trait.
 +// rust-analyzer does not specify colors directly, instead it assigns a tag (like `struct`) and a set of modifiers (like `declaration`) to each token.
 +// It's up to the client to map those to specific colors.
 +//
 +// The general rule is that a reference to an entity gets colored the same way as the entity itself.
 +// We also give special modifier for `mut` and `&mut` local variables.
 +//
 +//
 +// .Token Tags
 +//
 +// Rust-analyzer currently emits the following token tags:
 +//
 +// - For items:
 +// +
 +// [horizontal]
 +// attribute:: Emitted for attribute macros.
 +// enum:: Emitted for enums.
 +// function:: Emitted for free-standing functions.
 +// derive:: Emitted for derive macros.
 +// macro:: Emitted for function-like macros.
 +// method:: Emitted for associated functions, also knowns as methods.
 +// namespace:: Emitted for modules.
 +// struct:: Emitted for structs.
 +// trait:: Emitted for traits.
 +// typeAlias:: Emitted for type aliases and `Self` in `impl`s.
 +// union:: Emitted for unions.
 +//
 +// - For literals:
 +// +
 +// [horizontal]
 +// boolean:: Emitted for the boolean literals `true` and `false`.
 +// character:: Emitted for character literals.
 +// number:: Emitted for numeric literals.
 +// string:: Emitted for string literals.
 +// escapeSequence:: Emitted for escaped sequences inside strings like `\n`.
 +// formatSpecifier:: Emitted for format specifiers `{:?}` in `format!`-like macros.
 +//
 +// - For operators:
 +// +
 +// [horizontal]
 +// operator:: Emitted for general operators.
 +// arithmetic:: Emitted for the arithmetic operators `+`, `-`, `*`, `/`, `+=`, `-=`, `*=`, `/=`.
 +// bitwise:: Emitted for the bitwise operators `|`, `&`, `!`, `^`, `|=`, `&=`, `^=`.
 +// comparison:: Emitted for the comparison operators `>`, `<`, `==`, `>=`, `<=`, `!=`.
 +// logical:: Emitted for the logical operators `||`, `&&`, `!`.
 +//
 +// - For punctuation:
 +// +
 +// [horizontal]
 +// punctuation:: Emitted for general punctuation.
 +// attributeBracket:: Emitted for attribute invocation brackets, that is the `#[` and `]` tokens.
 +// angle:: Emitted for `<>` angle brackets.
 +// brace:: Emitted for `{}` braces.
 +// bracket:: Emitted for `[]` brackets.
 +// parenthesis:: Emitted for `()` parentheses.
 +// colon:: Emitted for the `:` token.
 +// comma:: Emitted for the `,` token.
 +// dot:: Emitted for the `.` token.
 +// semi:: Emitted for the `;` token.
 +// macroBang:: Emitted for the `!` token in macro calls.
 +//
 +// //-
 +//
 +// [horizontal]
 +// builtinAttribute:: Emitted for names to builtin attributes in attribute path, the `repr` in `#[repr(u8)]` for example.
 +// builtinType:: Emitted for builtin types like `u32`, `str` and `f32`.
 +// comment:: Emitted for comments.
 +// constParameter:: Emitted for const parameters.
 +// deriveHelper:: Emitted for derive helper attributes.
 +// enumMember:: Emitted for enum variants.
 +// generic:: Emitted for generic tokens that have no mapping.
 +// keyword:: Emitted for keywords.
 +// label:: Emitted for labels.
 +// lifetime:: Emitted for lifetimes.
 +// parameter:: Emitted for non-self function parameters.
 +// property:: Emitted for struct and union fields.
 +// selfKeyword:: Emitted for the self function parameter and self path-specifier.
 +// selfTypeKeyword:: Emitted for the Self type parameter.
 +// toolModule:: Emitted for tool modules.
 +// typeParameter:: Emitted for type parameters.
 +// unresolvedReference:: Emitted for unresolved references, names that rust-analyzer can't find the definition of.
 +// variable:: Emitted for locals, constants and statics.
 +//
 +//
 +// .Token Modifiers
 +//
 +// Token modifiers allow to style some elements in the source code more precisely.
 +//
 +// Rust-analyzer currently emits the following token modifiers:
 +//
 +// [horizontal]
 +// async:: Emitted for async functions and the `async` and `await` keywords.
 +// attribute:: Emitted for tokens inside attributes.
 +// callable:: Emitted for locals whose types implements one of the `Fn*` traits.
 +// constant:: Emitted for consts.
 +// consuming:: Emitted for locals that are being consumed when use in a function call.
 +// controlFlow:: Emitted for control-flow related tokens, this includes the `?` operator.
 +// crateRoot:: Emitted for crate names, like `serde` and `crate`.
 +// declaration:: Emitted for names of definitions, like `foo` in `fn foo() {}`.
 +// defaultLibrary:: Emitted for items from built-in crates (std, core, alloc, test and proc_macro).
 +// documentation:: Emitted for documentation comments.
 +// injected:: Emitted for doc-string injected highlighting like rust source blocks in documentation.
 +// intraDocLink:: Emitted for intra doc links in doc-strings.
 +// library:: Emitted for items that are defined outside of the current crate.
 +// mutable:: Emitted for mutable locals and statics as well as functions taking `&mut self`.
 +// public:: Emitted for items that are from the current crate and are `pub`.
 +// reference:: Emitted for locals behind a reference and functions taking `self` by reference.
 +// static:: Emitted for "static" functions, also known as functions that do not take a `self` param, as well as statics and consts.
 +// trait:: Emitted for associated trait items.
 +// unsafe:: Emitted for unsafe operations, like unsafe function calls, as well as the `unsafe` token.
 +//
 +//
 +// image::https://user-images.githubusercontent.com/48062697/113164457-06cfb980-9239-11eb-819b-0f93e646acf8.png[]
 +// image::https://user-images.githubusercontent.com/48062697/113187625-f7f50100-9250-11eb-825e-91c58f236071.png[]
 +pub(crate) fn highlight(
 +    db: &RootDatabase,
 +    file_id: FileId,
 +    range_to_highlight: Option<TextRange>,
 +    syntactic_name_ref_highlighting: bool,
 +) -> Vec<HlRange> {
 +    let _p = profile::span("highlight");
 +    let sema = Semantics::new(db);
 +
 +    // Determine the root based on the given range.
 +    let (root, range_to_highlight) = {
 +        let source_file = sema.parse(file_id);
 +        let source_file = source_file.syntax();
 +        match range_to_highlight {
 +            Some(range) => {
 +                let node = match source_file.covering_element(range) {
 +                    NodeOrToken::Node(it) => it,
 +                    NodeOrToken::Token(it) => it.parent().unwrap_or_else(|| source_file.clone()),
 +                };
 +                (node, range)
 +            }
 +            None => (source_file.clone(), source_file.text_range()),
 +        }
 +    };
 +
 +    let mut hl = highlights::Highlights::new(root.text_range());
 +    let krate = match sema.scope(&root) {
 +        Some(it) => it.krate(),
 +        None => return hl.to_vec(),
 +    };
 +    traverse(
 +        &mut hl,
 +        &sema,
 +        file_id,
 +        &root,
 +        krate,
 +        range_to_highlight,
 +        syntactic_name_ref_highlighting,
 +    );
 +    hl.to_vec()
 +}
 +
 +fn traverse(
 +    hl: &mut Highlights,
 +    sema: &Semantics<'_, RootDatabase>,
 +    file_id: FileId,
 +    root: &SyntaxNode,
 +    krate: hir::Crate,
 +    range_to_highlight: TextRange,
 +    syntactic_name_ref_highlighting: bool,
 +) {
 +    let is_unlinked = sema.to_module_def(file_id).is_none();
 +    let mut bindings_shadow_count: FxHashMap<Name, u32> = FxHashMap::default();
 +
 +    enum AttrOrDerive {
 +        Attr(ast::Item),
 +        Derive(ast::Item),
 +    }
 +
 +    impl AttrOrDerive {
 +        fn item(&self) -> &ast::Item {
 +            match self {
 +                AttrOrDerive::Attr(item) | AttrOrDerive::Derive(item) => item,
 +            }
 +        }
 +    }
 +
 +    let mut tt_level = 0;
 +    let mut attr_or_derive_item = None;
 +    let mut current_macro: Option<ast::Macro> = None;
 +    let mut macro_highlighter = MacroHighlighter::default();
 +    let mut inside_attribute = false;
 +
 +    // Walk all nodes, keeping track of whether we are inside a macro or not.
 +    // If in macro, expand it first and highlight the expanded code.
 +    for event in root.preorder_with_tokens() {
 +        use WalkEvent::{Enter, Leave};
 +
 +        let range = match &event {
 +            Enter(it) | Leave(it) => it.text_range(),
 +        };
 +
 +        // Element outside of the viewport, no need to highlight
 +        if range_to_highlight.intersect(range).is_none() {
 +            continue;
 +        }
 +
 +        // set macro and attribute highlighting states
 +        match event.clone() {
 +            Enter(NodeOrToken::Node(node)) if ast::TokenTree::can_cast(node.kind()) => {
 +                tt_level += 1;
 +            }
 +            Leave(NodeOrToken::Node(node)) if ast::TokenTree::can_cast(node.kind()) => {
 +                tt_level -= 1;
 +            }
 +            Enter(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => {
 +                inside_attribute = true
 +            }
 +            Leave(NodeOrToken::Node(node)) if ast::Attr::can_cast(node.kind()) => {
 +                inside_attribute = false
 +            }
 +
 +            Enter(NodeOrToken::Node(node)) if ast::Item::can_cast(node.kind()) => {
 +                match ast::Item::cast(node.clone()) {
 +                    Some(ast::Item::MacroRules(mac)) => {
 +                        macro_highlighter.init();
 +                        current_macro = Some(mac.into());
 +                        continue;
 +                    }
 +                    Some(ast::Item::MacroDef(mac)) => {
 +                        macro_highlighter.init();
 +                        current_macro = Some(mac.into());
 +                        continue;
 +                    }
 +                    Some(item) => {
 +                        if matches!(node.kind(), FN | CONST | STATIC) {
 +                            bindings_shadow_count.clear();
 +                        }
 +
 +                        if attr_or_derive_item.is_none() {
 +                            if sema.is_attr_macro_call(&item) {
 +                                attr_or_derive_item = Some(AttrOrDerive::Attr(item));
 +                            } else {
 +                                let adt = match item {
 +                                    ast::Item::Enum(it) => Some(ast::Adt::Enum(it)),
 +                                    ast::Item::Struct(it) => Some(ast::Adt::Struct(it)),
 +                                    ast::Item::Union(it) => Some(ast::Adt::Union(it)),
 +                                    _ => None,
 +                                };
 +                                match adt {
 +                                    Some(adt) if sema.is_derive_annotated(&adt) => {
 +                                        attr_or_derive_item =
 +                                            Some(AttrOrDerive::Derive(ast::Item::from(adt)));
 +                                    }
 +                                    _ => (),
 +                                }
 +                            }
 +                        }
 +                    }
 +                    _ => (),
 +                }
 +            }
 +            Leave(NodeOrToken::Node(node)) if ast::Item::can_cast(node.kind()) => {
 +                match ast::Item::cast(node.clone()) {
 +                    Some(ast::Item::MacroRules(mac)) => {
 +                        assert_eq!(current_macro, Some(mac.into()));
 +                        current_macro = None;
 +                        macro_highlighter = MacroHighlighter::default();
 +                    }
 +                    Some(ast::Item::MacroDef(mac)) => {
 +                        assert_eq!(current_macro, Some(mac.into()));
 +                        current_macro = None;
 +                        macro_highlighter = MacroHighlighter::default();
 +                    }
 +                    Some(item)
 +                        if attr_or_derive_item.as_ref().map_or(false, |it| *it.item() == item) =>
 +                    {
 +                        attr_or_derive_item = None;
 +                    }
 +                    _ => (),
 +                }
 +            }
 +            _ => (),
 +        }
 +
 +        let element = match event {
 +            Enter(NodeOrToken::Token(tok)) if tok.kind() == WHITESPACE => continue,
 +            Enter(it) => it,
 +            Leave(NodeOrToken::Token(_)) => continue,
 +            Leave(NodeOrToken::Node(node)) => {
 +                // Doc comment highlighting injection, we do this when leaving the node
 +                // so that we overwrite the highlighting of the doc comment itself.
++                inject::doc_comment(hl, sema, file_id, &node);
 +                continue;
 +            }
 +        };
 +
 +        if current_macro.is_some() {
 +            if let Some(tok) = element.as_token() {
 +                macro_highlighter.advance(tok);
 +            }
 +        }
 +
 +        let element = match element.clone() {
 +            NodeOrToken::Node(n) => match ast::NameLike::cast(n) {
 +                Some(n) => NodeOrToken::Node(n),
 +                None => continue,
 +            },
 +            NodeOrToken::Token(t) => NodeOrToken::Token(t),
 +        };
 +        let token = element.as_token().cloned();
 +
 +        // Descending tokens into macros is expensive even if no descending occurs, so make sure
 +        // that we actually are in a position where descending is possible.
 +        let in_macro = tt_level > 0
 +            || match attr_or_derive_item {
 +                Some(AttrOrDerive::Attr(_)) => true,
 +                Some(AttrOrDerive::Derive(_)) => inside_attribute,
 +                None => false,
 +            };
 +        let descended_element = if in_macro {
 +            // Attempt to descend tokens into macro-calls.
 +            match element {
 +                NodeOrToken::Token(token) if token.kind() != COMMENT => {
 +                    let token = match attr_or_derive_item {
 +                        Some(AttrOrDerive::Attr(_)) => {
 +                            sema.descend_into_macros_with_kind_preference(token)
 +                        }
 +                        Some(AttrOrDerive::Derive(_)) | None => {
 +                            sema.descend_into_macros_single(token)
 +                        }
 +                    };
 +                    match token.parent().and_then(ast::NameLike::cast) {
 +                        // Remap the token into the wrapping single token nodes
 +                        Some(parent) => match (token.kind(), parent.syntax().kind()) {
 +                            (T![self] | T![ident], NAME | NAME_REF) => NodeOrToken::Node(parent),
 +                            (T![self] | T![super] | T![crate] | T![Self], NAME_REF) => {
 +                                NodeOrToken::Node(parent)
 +                            }
 +                            (INT_NUMBER, NAME_REF) => NodeOrToken::Node(parent),
 +                            (LIFETIME_IDENT, LIFETIME) => NodeOrToken::Node(parent),
 +                            _ => NodeOrToken::Token(token),
 +                        },
 +                        None => NodeOrToken::Token(token),
 +                    }
 +                }
 +                e => e,
 +            }
 +        } else {
 +            element
 +        };
 +
 +        // FIXME: do proper macro def highlighting https://github.com/rust-lang/rust-analyzer/issues/6232
 +        // Skip metavariables from being highlighted to prevent keyword highlighting in them
 +        if descended_element.as_token().and_then(|t| macro_highlighter.highlight(t)).is_some() {
 +            continue;
 +        }
 +
 +        // string highlight injections, note this does not use the descended element as proc-macros
 +        // can rewrite string literals which invalidates our indices
 +        if let (Some(token), Some(descended_token)) = (token, descended_element.as_token()) {
 +            if ast::String::can_cast(token.kind()) && ast::String::can_cast(descended_token.kind())
 +            {
 +                let string = ast::String::cast(token);
 +                let string_to_highlight = ast::String::cast(descended_token.clone());
 +                if let Some((string, expanded_string)) = string.zip(string_to_highlight) {
 +                    if string.is_raw() {
 +                        if inject::ra_fixture(hl, sema, &string, &expanded_string).is_some() {
 +                            continue;
 +                        }
 +                    }
 +                    highlight_format_string(hl, &string, &expanded_string, range);
 +                    highlight_escape_string(hl, &string, range.start());
 +                }
 +            } else if ast::ByteString::can_cast(token.kind())
 +                && ast::ByteString::can_cast(descended_token.kind())
 +            {
 +                if let Some(byte_string) = ast::ByteString::cast(token) {
 +                    highlight_escape_string(hl, &byte_string, range.start());
 +                }
 +            }
 +        }
 +
 +        let element = match descended_element {
 +            NodeOrToken::Node(name_like) => highlight::name_like(
 +                sema,
 +                krate,
 +                &mut bindings_shadow_count,
 +                syntactic_name_ref_highlighting,
 +                name_like,
 +            ),
 +            NodeOrToken::Token(token) => highlight::token(sema, token).zip(Some(None)),
 +        };
 +        if let Some((mut highlight, binding_hash)) = element {
 +            if is_unlinked && highlight.tag == HlTag::UnresolvedReference {
 +                // do not emit unresolved references if the file is unlinked
 +                // let the editor do its highlighting for these tokens instead
 +                continue;
 +            }
 +            if highlight.tag == HlTag::UnresolvedReference
 +                && matches!(attr_or_derive_item, Some(AttrOrDerive::Derive(_)) if inside_attribute)
 +            {
 +                // do not emit unresolved references in derive helpers if the token mapping maps to
 +                // something unresolvable. FIXME: There should be a way to prevent that
 +                continue;
 +            }
 +            if inside_attribute {
 +                highlight |= HlMod::Attribute
 +            }
 +
 +            hl.add(HlRange { range, highlight, binding_hash });
 +        }
 +    }
 +}
index f779a985a99ae60eb9289044d604b64775532a35,0000000000000000000000000000000000000000..f376f9fda7a57799c0be9b774a81508a065d2893
mode 100644,000000..100644
--- /dev/null
@@@ -1,276 -1,0 +1,279 @@@
-     active_parameter::ActiveParameter, defs::Definition, rust_doc::is_rust_fence, SymbolKind,
 +//! "Recursive" Syntax highlighting for code in doctests and fixtures.
 +
 +use std::mem;
 +
 +use either::Either;
 +use hir::{InFile, Semantics};
 +use ide_db::{
- /// Injection of syntax highlighting of doctests.
++    active_parameter::ActiveParameter, base_db::FileId, defs::Definition, rust_doc::is_rust_fence,
++    SymbolKind,
 +};
 +use syntax::{
 +    ast::{self, AstNode, IsString, QuoteOffsets},
 +    AstToken, NodeOrToken, SyntaxNode, TextRange, TextSize,
 +};
 +
 +use crate::{
 +    doc_links::{doc_attributes, extract_definitions_from_docs, resolve_doc_path_for_def},
 +    syntax_highlighting::{highlights::Highlights, injector::Injector},
 +    Analysis, HlMod, HlRange, HlTag, RootDatabase,
 +};
 +
 +pub(super) fn ra_fixture(
 +    hl: &mut Highlights,
 +    sema: &Semantics<'_, RootDatabase>,
 +    literal: &ast::String,
 +    expanded: &ast::String,
 +) -> Option<()> {
 +    let active_parameter = ActiveParameter::at_token(sema, expanded.syntax().clone())?;
 +    if !active_parameter.ident().map_or(false, |name| name.text().starts_with("ra_fixture")) {
 +        return None;
 +    }
 +    let value = literal.value()?;
 +
 +    if let Some(range) = literal.open_quote_text_range() {
 +        hl.add(HlRange { range, highlight: HlTag::StringLiteral.into(), binding_hash: None })
 +    }
 +
 +    let mut inj = Injector::default();
 +
 +    let mut text = &*value;
 +    let mut offset: TextSize = 0.into();
 +
 +    while !text.is_empty() {
 +        let marker = "$0";
 +        let idx = text.find(marker).unwrap_or(text.len());
 +        let (chunk, next) = text.split_at(idx);
 +        inj.add(chunk, TextRange::at(offset, TextSize::of(chunk)));
 +
 +        text = next;
 +        offset += TextSize::of(chunk);
 +
 +        if let Some(next) = text.strip_prefix(marker) {
 +            if let Some(range) = literal.map_range_up(TextRange::at(offset, TextSize::of(marker))) {
 +                hl.add(HlRange { range, highlight: HlTag::Keyword.into(), binding_hash: None });
 +            }
 +
 +            text = next;
 +
 +            let marker_len = TextSize::of(marker);
 +            offset += marker_len;
 +        }
 +    }
 +
 +    let (analysis, tmp_file_id) = Analysis::from_single_file(inj.take_text());
 +
 +    for mut hl_range in analysis.highlight(tmp_file_id).unwrap() {
 +        for range in inj.map_range_up(hl_range.range) {
 +            if let Some(range) = literal.map_range_up(range) {
 +                hl_range.range = range;
 +                hl.add(hl_range);
 +            }
 +        }
 +    }
 +
 +    if let Some(range) = literal.close_quote_text_range() {
 +        hl.add(HlRange { range, highlight: HlTag::StringLiteral.into(), binding_hash: None })
 +    }
 +
 +    Some(())
 +}
 +
 +const RUSTDOC_FENCE_LENGTH: usize = 3;
 +const RUSTDOC_FENCES: [&str; 2] = ["```", "~~~"];
 +
-     InFile { file_id: src_file_id, value: node }: InFile<&SyntaxNode>,
++/// Injection of syntax highlighting of doctests and intra doc links.
 +pub(super) fn doc_comment(
 +    hl: &mut Highlights,
 +    sema: &Semantics<'_, RootDatabase>,
++    src_file_id: FileId,
++    node: &SyntaxNode,
 +) {
 +    let (attributes, def) = match doc_attributes(sema, node) {
 +        Some(it) => it,
 +        None => return,
 +    };
++    let src_file_id = src_file_id.into();
 +
 +    // Extract intra-doc links and emit highlights for them.
 +    if let Some((docs, doc_mapping)) = attributes.docs_with_rangemap(sema.db) {
 +        extract_definitions_from_docs(&docs)
 +            .into_iter()
 +            .filter_map(|(range, link, ns)| {
 +                doc_mapping.map(range).filter(|mapping| mapping.file_id == src_file_id).and_then(
 +                    |InFile { value: mapped_range, .. }| {
 +                        Some(mapped_range).zip(resolve_doc_path_for_def(sema.db, def, &link, ns))
 +                    },
 +                )
 +            })
 +            .for_each(|(range, def)| {
 +                hl.add(HlRange {
 +                    range,
 +                    highlight: module_def_to_hl_tag(def)
 +                        | HlMod::Documentation
 +                        | HlMod::Injected
 +                        | HlMod::IntraDocLink,
 +                    binding_hash: None,
 +                })
 +            });
 +    }
 +
 +    // Extract doc-test sources from the docs and calculate highlighting for them.
 +
 +    let mut inj = Injector::default();
 +    inj.add_unmapped("fn doctest() {\n");
 +
 +    let attrs_source_map = attributes.source_map(sema.db);
 +
 +    let mut is_codeblock = false;
 +    let mut is_doctest = false;
 +
 +    let mut new_comments = Vec::new();
 +    let mut string;
 +
 +    for attr in attributes.by_key("doc").attrs() {
 +        let InFile { file_id, value: src } = attrs_source_map.source_of(attr);
 +        if file_id != src_file_id {
 +            continue;
 +        }
 +        let (line, range) = match &src {
 +            Either::Left(it) => {
 +                string = match find_doc_string_in_attr(attr, it) {
 +                    Some(it) => it,
 +                    None => continue,
 +                };
 +                let text = string.text();
 +                let text_range = string.syntax().text_range();
 +                match string.quote_offsets() {
 +                    Some(QuoteOffsets { contents, .. }) => {
 +                        (&text[contents - text_range.start()], contents)
 +                    }
 +                    None => (text, text_range),
 +                }
 +            }
 +            Either::Right(comment) => {
 +                let value = comment.prefix().len();
 +                let range = comment.syntax().text_range();
 +                (
 +                    &comment.text()[value..],
 +                    TextRange::new(range.start() + TextSize::try_from(value).unwrap(), range.end()),
 +                )
 +            }
 +        };
 +
 +        let mut range_start = range.start();
 +        for line in line.split('\n') {
 +            let line_len = TextSize::from(line.len() as u32);
 +            let prev_range_start = {
 +                let next_range_start = range_start + line_len + TextSize::from(1);
 +                mem::replace(&mut range_start, next_range_start)
 +            };
 +            let mut pos = TextSize::from(0);
 +
 +            match RUSTDOC_FENCES.into_iter().find_map(|fence| line.find(fence)) {
 +                Some(idx) => {
 +                    is_codeblock = !is_codeblock;
 +                    // Check whether code is rust by inspecting fence guards
 +                    let guards = &line[idx + RUSTDOC_FENCE_LENGTH..];
 +                    let is_rust = is_rust_fence(guards);
 +                    is_doctest = is_codeblock && is_rust;
 +                    continue;
 +                }
 +                None if !is_doctest => continue,
 +                None => (),
 +            }
 +
 +            // whitespace after comment is ignored
 +            if let Some(ws) = line[pos.into()..].chars().next().filter(|c| c.is_whitespace()) {
 +                pos += TextSize::of(ws);
 +            }
 +            // lines marked with `#` should be ignored in output, we skip the `#` char
 +            if line[pos.into()..].starts_with('#') {
 +                pos += TextSize::of('#');
 +            }
 +
 +            new_comments.push(TextRange::at(prev_range_start, pos));
 +            inj.add(&line[pos.into()..], TextRange::new(pos, line_len) + prev_range_start);
 +            inj.add_unmapped("\n");
 +        }
 +    }
 +
 +    if new_comments.is_empty() {
 +        return; // no need to run an analysis on an empty file
 +    }
 +
 +    inj.add_unmapped("\n}");
 +
 +    let (analysis, tmp_file_id) = Analysis::from_single_file(inj.take_text());
 +
 +    if let Ok(ranges) = analysis.with_db(|db| super::highlight(db, tmp_file_id, None, true)) {
 +        for HlRange { range, highlight, binding_hash } in ranges {
 +            for range in inj.map_range_up(range) {
 +                hl.add(HlRange { range, highlight: highlight | HlMod::Injected, binding_hash });
 +            }
 +        }
 +    }
 +
 +    for range in new_comments {
 +        hl.add(HlRange {
 +            range,
 +            highlight: HlTag::Comment | HlMod::Documentation,
 +            binding_hash: None,
 +        });
 +    }
 +}
 +
 +fn find_doc_string_in_attr(attr: &hir::Attr, it: &ast::Attr) -> Option<ast::String> {
 +    match it.expr() {
 +        // #[doc = lit]
 +        Some(ast::Expr::Literal(lit)) => match lit.kind() {
 +            ast::LiteralKind::String(it) => Some(it),
 +            _ => None,
 +        },
 +        // #[cfg_attr(..., doc = "", ...)]
 +        None => {
 +            // We gotta hunt the string token manually here
 +            let text = attr.string_value()?;
 +            // FIXME: We just pick the first string literal that has the same text as the doc attribute
 +            // This means technically we might highlight the wrong one
 +            it.syntax()
 +                .descendants_with_tokens()
 +                .filter_map(NodeOrToken::into_token)
 +                .filter_map(ast::String::cast)
 +                .find(|string| {
 +                    string.text().get(1..string.text().len() - 1).map_or(false, |it| it == text)
 +                })
 +        }
 +        _ => None,
 +    }
 +}
 +
 +fn module_def_to_hl_tag(def: Definition) -> HlTag {
 +    let symbol = match def {
 +        Definition::Module(_) => SymbolKind::Module,
 +        Definition::Function(_) => SymbolKind::Function,
 +        Definition::Adt(hir::Adt::Struct(_)) => SymbolKind::Struct,
 +        Definition::Adt(hir::Adt::Enum(_)) => SymbolKind::Enum,
 +        Definition::Adt(hir::Adt::Union(_)) => SymbolKind::Union,
 +        Definition::Variant(_) => SymbolKind::Variant,
 +        Definition::Const(_) => SymbolKind::Const,
 +        Definition::Static(_) => SymbolKind::Static,
 +        Definition::Trait(_) => SymbolKind::Trait,
 +        Definition::TypeAlias(_) => SymbolKind::TypeAlias,
 +        Definition::BuiltinType(_) => return HlTag::BuiltinType,
 +        Definition::Macro(_) => SymbolKind::Macro,
 +        Definition::Field(_) => SymbolKind::Field,
 +        Definition::SelfType(_) => SymbolKind::Impl,
 +        Definition::Local(_) => SymbolKind::Local,
 +        Definition::GenericParam(gp) => match gp {
 +            hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
 +            hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
 +            hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
 +        },
 +        Definition::Label(_) => SymbolKind::Label,
 +        Definition::BuiltinAttr(_) => SymbolKind::BuiltinAttr,
 +        Definition::ToolModule(_) => SymbolKind::ToolModule,
 +        Definition::DeriveHelper(_) => SymbolKind::DeriveHelper,
 +    };
 +    HlTag::Symbol(symbol)
 +}
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..8a1d69816e6882aa738d0adbd23ff062c413c454
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,51 @@@
++
++<style>
++body                { margin: 0; }
++pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
++
++.lifetime           { color: #DFAF8F; font-style: italic; }
++.label              { color: #DFAF8F; font-style: italic; }
++.comment            { color: #7F9F7F; }
++.documentation      { color: #629755; }
++.intra_doc_link     { font-style: italic; }
++.injected           { opacity: 0.65 ; }
++.struct, .enum      { color: #7CB8BB; }
++.enum_variant       { color: #BDE0F3; }
++.string_literal     { color: #CC9393; }
++.field              { color: #94BFF3; }
++.function           { color: #93E0E3; }
++.function.unsafe    { color: #BC8383; }
++.trait.unsafe       { color: #BC8383; }
++.operator.unsafe    { color: #BC8383; }
++.mutable.unsafe     { color: #BC8383; text-decoration: underline; }
++.keyword.unsafe     { color: #BC8383; font-weight: bold; }
++.macro.unsafe       { color: #BC8383; }
++.parameter          { color: #94BFF3; }
++.text               { color: #DCDCCC; }
++.type               { color: #7CB8BB; }
++.builtin_type       { color: #8CD0D3; }
++.type_param         { color: #DFAF8F; }
++.attribute          { color: #94BFF3; }
++.numeric_literal    { color: #BFEBBF; }
++.bool_literal       { color: #BFE6EB; }
++.macro              { color: #94BFF3; }
++.derive             { color: #94BFF3; font-style: italic; }
++.module             { color: #AFD8AF; }
++.value_param        { color: #DCDCCC; }
++.variable           { color: #DCDCCC; }
++.format_specifier   { color: #CC696B; }
++.mutable            { text-decoration: underline; }
++.escape_sequence    { color: #94BFF3; }
++.keyword            { color: #F0DFAF; font-weight: bold; }
++.control            { font-style: italic; }
++.reference          { font-style: italic; font-weight: bold; }
++
++.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
++</style>
++<pre><code><span class="comment documentation">//! </span><span class="struct documentation injected intra_doc_link">[Struct]</span>
++<span class="comment documentation">//! This is an intra doc injection test for modules</span>
++<span class="comment documentation">//! </span><span class="struct documentation injected intra_doc_link">[Struct]</span>
++<span class="comment documentation">//! This is an intra doc injection test for modules</span>
++
++<span class="keyword">pub</span> <span class="keyword">struct</span> <span class="struct declaration public">Struct</span><span class="semicolon">;</span>
++</code></pre>
index 0000000000000000000000000000000000000000,0000000000000000000000000000000000000000..c4c3e3dc2606e5852b5813c76ba9c2bfb31f9b04
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,50 @@@
++
++<style>
++body                { margin: 0; }
++pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padding: 0.4em; }
++
++.lifetime           { color: #DFAF8F; font-style: italic; }
++.label              { color: #DFAF8F; font-style: italic; }
++.comment            { color: #7F9F7F; }
++.documentation      { color: #629755; }
++.intra_doc_link     { font-style: italic; }
++.injected           { opacity: 0.65 ; }
++.struct, .enum      { color: #7CB8BB; }
++.enum_variant       { color: #BDE0F3; }
++.string_literal     { color: #CC9393; }
++.field              { color: #94BFF3; }
++.function           { color: #93E0E3; }
++.function.unsafe    { color: #BC8383; }
++.trait.unsafe       { color: #BC8383; }
++.operator.unsafe    { color: #BC8383; }
++.mutable.unsafe     { color: #BC8383; text-decoration: underline; }
++.keyword.unsafe     { color: #BC8383; font-weight: bold; }
++.macro.unsafe       { color: #BC8383; }
++.parameter          { color: #94BFF3; }
++.text               { color: #DCDCCC; }
++.type               { color: #7CB8BB; }
++.builtin_type       { color: #8CD0D3; }
++.type_param         { color: #DFAF8F; }
++.attribute          { color: #94BFF3; }
++.numeric_literal    { color: #BFEBBF; }
++.bool_literal       { color: #BFE6EB; }
++.macro              { color: #94BFF3; }
++.derive             { color: #94BFF3; font-style: italic; }
++.module             { color: #AFD8AF; }
++.value_param        { color: #DCDCCC; }
++.variable           { color: #DCDCCC; }
++.format_specifier   { color: #CC696B; }
++.mutable            { text-decoration: underline; }
++.escape_sequence    { color: #94BFF3; }
++.keyword            { color: #F0DFAF; font-weight: bold; }
++.control            { font-style: italic; }
++.reference          { font-style: italic; font-weight: bold; }
++
++.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
++</style>
++<pre><code><span class="comment documentation">/// </span><span class="struct documentation injected intra_doc_link">[crate::foo::Struct]</span>
++<span class="comment documentation">/// This is an intra doc injection test for modules</span>
++<span class="comment documentation">/// </span><span class="struct documentation injected intra_doc_link">[crate::foo::Struct]</span>
++<span class="comment documentation">/// This is an intra doc injection test for modules</span>
++<span class="keyword">mod</span> <span class="module declaration">foo</span><span class="semicolon">;</span>
++</code></pre>
index 6ba6153178da9ce5aceedffe45add51ebc615621,0000000000000000000000000000000000000000..99be7c6648687c7bffd7640d7a1c4736b3d8a2d6
mode 100644,000000..100644
--- /dev/null
@@@ -1,1050 -1,0 +1,1096 @@@
 +use std::time::Instant;
 +
 +use expect_test::{expect_file, ExpectFile};
 +use ide_db::SymbolKind;
 +use test_utils::{bench, bench_fixture, skip_slow_tests, AssertLinear};
 +
 +use crate::{fixture, FileRange, HlTag, TextRange};
 +
 +#[test]
 +fn attributes() {
 +    check_highlighting(
 +        r#"
 +//- proc_macros: identity
 +//- minicore: derive, copy
 +#[allow(dead_code)]
 +#[rustfmt::skip]
 +#[proc_macros::identity]
 +#[derive(Copy)]
 +/// This is a doc comment
 +// This is a normal comment
 +/// This is a doc comment
 +#[derive(Copy)]
 +// This is another normal comment
 +/// This is another doc comment
 +// This is another normal comment
 +#[derive(Copy)]
 +// The reason for these being here is to test AttrIds
 +struct Foo;
 +"#,
 +        expect_file!["./test_data/highlight_attributes.html"],
 +        false,
 +    );
 +}
 +
 +#[test]
 +fn macros() {
 +    check_highlighting(
 +        r#"
 +//- proc_macros: mirror
 +proc_macros::mirror! {
 +    {
 +        ,i32 :x pub
 +        ,i32 :y pub
 +    } Foo struct
 +}
 +macro_rules! def_fn {
 +    ($($tt:tt)*) => {$($tt)*}
 +}
 +
 +def_fn! {
 +    fn bar() -> u32 {
 +        100
 +    }
 +}
 +
 +macro_rules! dont_color_me_braces {
 +    () => {0}
 +}
 +
 +macro_rules! noop {
 +    ($expr:expr) => {
 +        $expr
 +    }
 +}
 +
 +/// textually shadow previous definition
 +macro_rules! noop {
 +    ($expr:expr) => {
 +        $expr
 +    }
 +}
 +
 +macro_rules! keyword_frag {
 +    ($type:ty) => ($type)
 +}
 +
 +macro with_args($i:ident) {
 +    $i
 +}
 +
 +macro without_args {
 +    ($i:ident) => {
 +        $i
 +    }
 +}
 +
 +fn main() {
 +    println!("Hello, {}!", 92);
 +    dont_color_me_braces!();
 +    noop!(noop!(1));
 +}
 +"#,
 +        expect_file!["./test_data/highlight_macros.html"],
 +        false,
 +    );
 +}
 +
 +/// If what you want to test feels like a specific entity consider making a new test instead,
 +/// this test fixture here in fact should shrink instead of grow ideally.
 +#[test]
 +fn test_highlighting() {
 +    check_highlighting(
 +        r#"
 +//- minicore: derive, copy
 +//- /main.rs crate:main deps:foo
 +use inner::{self as inner_mod};
 +mod inner {}
 +
 +pub mod ops {
 +    #[lang = "fn_once"]
 +    pub trait FnOnce<Args> {}
 +
 +    #[lang = "fn_mut"]
 +    pub trait FnMut<Args>: FnOnce<Args> {}
 +
 +    #[lang = "fn"]
 +    pub trait Fn<Args>: FnMut<Args> {}
 +}
 +
 +struct Foo {
 +    x: u32,
 +}
 +
 +trait Bar {
 +    fn bar(&self) -> i32;
 +}
 +
 +impl Bar for Foo {
 +    fn bar(&self) -> i32 {
 +        self.x
 +    }
 +}
 +
 +impl Foo {
 +    fn baz(mut self, f: Foo) -> i32 {
 +        f.baz(self)
 +    }
 +
 +    fn qux(&mut self) {
 +        self.x = 0;
 +    }
 +
 +    fn quop(&self) -> i32 {
 +        self.x
 +    }
 +}
 +
 +use self::FooCopy::{self as BarCopy};
 +
 +#[derive(Copy)]
 +struct FooCopy {
 +    x: u32,
 +}
 +
 +impl FooCopy {
 +    fn baz(self, f: FooCopy) -> u32 {
 +        f.baz(self)
 +    }
 +
 +    fn qux(&mut self) {
 +        self.x = 0;
 +    }
 +
 +    fn quop(&self) -> u32 {
 +        self.x
 +    }
 +}
 +
 +fn str() {
 +    str();
 +}
 +
 +fn foo<'a, T>() -> T {
 +    foo::<'a, i32>()
 +}
 +
 +fn never() -> ! {
 +    loop {}
 +}
 +
 +fn const_param<const FOO: usize>() -> usize {
 +    const_param::<{ FOO }>();
 +    FOO
 +}
 +
 +use ops::Fn;
 +fn baz<F: Fn() -> ()>(f: F) {
 +    f()
 +}
 +
 +fn foobar() -> impl Copy {}
 +
 +fn foo() {
 +    let bar = foobar();
 +}
 +
 +// comment
 +fn main() {
 +    let mut x = 42;
 +    x += 1;
 +    let y = &mut x;
 +    let z = &y;
 +
 +    let Foo { x: z, y } = Foo { x: z, y };
 +
 +    y;
 +
 +    let mut foo = Foo { x, y: x };
 +    let foo2 = Foo { x, y: x };
 +    foo.quop();
 +    foo.qux();
 +    foo.baz(foo2);
 +
 +    let mut copy = FooCopy { x };
 +    copy.quop();
 +    copy.qux();
 +    copy.baz(copy);
 +
 +    let a = |x| x;
 +    let bar = Foo::baz;
 +
 +    let baz = (-42,);
 +    let baz = -baz.0;
 +
 +    let _ = !true;
 +
 +    'foo: loop {
 +        break 'foo;
 +        continue 'foo;
 +    }
 +}
 +
 +enum Option<T> {
 +    Some(T),
 +    None,
 +}
 +use Option::*;
 +
 +impl<T> Option<T> {
 +    fn and<U>(self, other: Option<U>) -> Option<(T, U)> {
 +        match other {
 +            None => unimplemented!(),
 +            Nope => Nope,
 +        }
 +    }
 +}
 +
 +async fn learn_and_sing() {
 +    let song = learn_song().await;
 +    sing_song(song).await;
 +}
 +
 +async fn async_main() {
 +    let f1 = learn_and_sing();
 +    let f2 = dance();
 +    futures::join!(f1, f2);
 +}
 +
 +fn use_foo_items() {
 +    let bob = foo::Person {
 +        name: "Bob",
 +        age: foo::consts::NUMBER,
 +    };
 +
 +    let control_flow = foo::identity(foo::ControlFlow::Continue);
 +
 +    if control_flow.should_die() {
 +        foo::die!();
 +    }
 +}
 +
 +pub enum Bool { True, False }
 +
 +impl Bool {
 +    pub const fn to_primitive(self) -> bool {
 +        true
 +    }
 +}
 +const USAGE_OF_BOOL:bool = Bool::True.to_primitive();
 +
 +trait Baz {
 +    type Qux;
 +}
 +
 +fn baz<T>(t: T)
 +where
 +    T: Baz,
 +    <T as Baz>::Qux: Bar {}
 +
 +fn gp_shadows_trait<Baz: Bar>() {
 +    Baz::bar;
 +}
 +
 +//- /foo.rs crate:foo
 +pub struct Person {
 +    pub name: &'static str,
 +    pub age: u8,
 +}
 +
 +pub enum ControlFlow {
 +    Continue,
 +    Die,
 +}
 +
 +impl ControlFlow {
 +    pub fn should_die(self) -> bool {
 +        matches!(self, ControlFlow::Die)
 +    }
 +}
 +
 +pub fn identity<T>(x: T) -> T { x }
 +
 +pub mod consts {
 +    pub const NUMBER: i64 = 92;
 +}
 +
 +macro_rules! die {
 +    () => {
 +        panic!();
 +    };
 +}
 +"#,
 +        expect_file!["./test_data/highlight_general.html"],
 +        false,
 +    );
 +}
 +
 +#[test]
 +fn test_lifetime_highlighting() {
 +    check_highlighting(
 +        r#"
 +//- minicore: derive
 +
 +#[derive()]
 +struct Foo<'a, 'b, 'c> where 'a: 'a, 'static: 'static {
 +    field: &'a (),
 +    field2: &'static (),
 +}
 +impl<'a> Foo<'_, 'a, 'static>
 +where
 +    'a: 'a,
 +    'static: 'static
 +{}
 +"#,
 +        expect_file!["./test_data/highlight_lifetimes.html"],
 +        false,
 +    );
 +}
 +
 +#[test]
 +fn test_keyword_highlighting() {
 +    check_highlighting(
 +        r#"
 +extern crate self;
 +
 +use crate;
 +use self;
 +mod __ {
 +    use super::*;
 +}
 +
 +macro_rules! void {
 +    ($($tt:tt)*) => {}
 +}
 +void!(Self);
 +struct __ where Self:;
 +fn __(_: Self) {}
 +"#,
 +        expect_file!["./test_data/highlight_keywords.html"],
 +        false,
 +    );
 +}
 +
 +#[test]
 +fn test_string_highlighting() {
 +    // The format string detection is based on macro-expansion,
 +    // thus, we have to copy the macro definition from `std`
 +    check_highlighting(
 +        r#"
 +macro_rules! println {
 +    ($($arg:tt)*) => ({
 +        $crate::io::_print($crate::format_args_nl!($($arg)*));
 +    })
 +}
 +#[rustc_builtin_macro]
 +#[macro_export]
 +macro_rules! format_args {}
 +#[rustc_builtin_macro]
 +#[macro_export]
 +macro_rules! const_format_args {}
 +#[rustc_builtin_macro]
 +#[macro_export]
 +macro_rules! format_args_nl {}
 +
 +mod panic {
 +    pub macro panic_2015 {
 +        () => (
 +            $crate::panicking::panic("explicit panic")
 +        ),
 +        ($msg:literal $(,)?) => (
 +            $crate::panicking::panic($msg)
 +        ),
 +        // Use `panic_str` instead of `panic_display::<&str>` for non_fmt_panic lint.
 +        ($msg:expr $(,)?) => (
 +            $crate::panicking::panic_str($msg)
 +        ),
 +        // Special-case the single-argument case for const_panic.
 +        ("{}", $arg:expr $(,)?) => (
 +            $crate::panicking::panic_display(&$arg)
 +        ),
 +        ($fmt:expr, $($arg:tt)+) => (
 +            $crate::panicking::panic_fmt($crate::const_format_args!($fmt, $($arg)+))
 +        ),
 +    }
 +}
 +
 +#[rustc_builtin_macro(std_panic)]
 +#[macro_export]
 +macro_rules! panic {}
 +#[rustc_builtin_macro]
 +macro_rules! assert {}
 +#[rustc_builtin_macro]
 +macro_rules! asm {}
 +
 +macro_rules! toho {
 +    () => ($crate::panic!("not yet implemented"));
 +    ($($arg:tt)+) => ($crate::panic!("not yet implemented: {}", $crate::format_args!($($arg)+)));
 +}
 +
 +fn main() {
 +    println!("Hello {{Hello}}");
 +    // from https://doc.rust-lang.org/std/fmt/index.html
 +    println!("Hello");                 // => "Hello"
 +    println!("Hello, {}!", "world");   // => "Hello, world!"
 +    println!("The number is {}", 1);   // => "The number is 1"
 +    println!("{:?}", (3, 4));          // => "(3, 4)"
 +    println!("{value}", value=4);      // => "4"
 +    println!("{} {}", 1, 2);           // => "1 2"
 +    println!("{:04}", 42);             // => "0042" with leading zerosV
 +    println!("{1} {} {0} {}", 1, 2);   // => "2 1 1 2"
 +    println!("{argument}", argument = "test");   // => "test"
 +    println!("{name} {}", 1, name = 2);          // => "2 1"
 +    println!("{a} {c} {b}", a="a", b='b', c=3);  // => "a 3 b"
 +    println!("{{{}}}", 2);                       // => "{2}"
 +    println!("Hello {:5}!", "x");
 +    println!("Hello {:1$}!", "x", 5);
 +    println!("Hello {1:0$}!", 5, "x");
 +    println!("Hello {:width$}!", "x", width = 5);
 +    println!("Hello {:<5}!", "x");
 +    println!("Hello {:-<5}!", "x");
 +    println!("Hello {:^5}!", "x");
 +    println!("Hello {:>5}!", "x");
 +    println!("Hello {:+}!", 5);
 +    println!("{:#x}!", 27);
 +    println!("Hello {:05}!", 5);
 +    println!("Hello {:05}!", -5);
 +    println!("{:#010x}!", 27);
 +    println!("Hello {0} is {1:.5}", "x", 0.01);
 +    println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
 +    println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
 +    println!("Hello {} is {:.*}",    "x", 5, 0.01);
 +    println!("Hello {} is {2:.*}",   "x", 5, 0.01);
 +    println!("Hello {} is {number:.prec$}", "x", prec = 5, number = 0.01);
 +    println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
 +    println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
 +    println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");
 +
 +    let _ = "{}"
 +    let _ = "{{}}";
 +
 +    println!("Hello {{}}");
 +    println!("{{ Hello");
 +    println!("Hello }}");
 +    println!("{{Hello}}");
 +    println!("{{ Hello }}");
 +    println!("{{Hello }}");
 +    println!("{{ Hello}}");
 +
 +    println!(r"Hello, {}!", "world");
 +
 +    // escape sequences
 +    println!("Hello\nWorld");
 +    println!("\u{48}\x65\x6C\x6C\x6F World");
 +
 +    let _ = "\x28\x28\x00\x63\n";
 +    let _ = b"\x28\x28\x00\x63\n";
 +
 +    println!("{\x41}", A = 92);
 +    println!("{ничоси}", ничоси = 92);
 +
 +    println!("{:x?} {} ", thingy, n2);
 +    panic!("{}", 0);
 +    panic!("more {}", 1);
 +    assert!(true, "{}", 1);
 +    assert!(true, "{} asdasd", 1);
 +    toho!("{}fmt", 0);
 +    asm!("mov eax, {0}");
 +    format_args!(concat!("{}"), "{}");
 +}"#,
 +        expect_file!["./test_data/highlight_strings.html"],
 +        false,
 +    );
 +}
 +
 +#[test]
 +fn test_unsafe_highlighting() {
 +    check_highlighting(
 +        r#"
 +macro_rules! id {
 +    ($($tt:tt)*) => {
 +        $($tt)*
 +    };
 +}
 +macro_rules! unsafe_deref {
 +    () => {
 +        *(&() as *const ())
 +    };
 +}
 +static mut MUT_GLOBAL: Struct = Struct { field: 0 };
 +static GLOBAL: Struct = Struct { field: 0 };
 +unsafe fn unsafe_fn() {}
 +
 +union Union {
 +    a: u32,
 +    b: f32,
 +}
 +
 +struct Struct { field: i32 }
 +impl Struct {
 +    unsafe fn unsafe_method(&self) {}
 +}
 +
 +#[repr(packed)]
 +struct Packed {
 +    a: u16,
 +}
 +
 +unsafe trait UnsafeTrait {}
 +unsafe impl UnsafeTrait for Packed {}
 +impl !UnsafeTrait for () {}
 +
 +fn unsafe_trait_bound<T: UnsafeTrait>(_: T) {}
 +
 +trait DoTheAutoref {
 +    fn calls_autoref(&self);
 +}
 +
 +impl DoTheAutoref for u16 {
 +    fn calls_autoref(&self) {}
 +}
 +
 +fn main() {
 +    let x = &5 as *const _ as *const usize;
 +    let u = Union { b: 0 };
 +
 +    id! {
 +        unsafe { unsafe_deref!() }
 +    };
 +
 +    unsafe {
 +        unsafe_deref!();
 +        id! { unsafe_deref!() };
 +
 +        // unsafe fn and method calls
 +        unsafe_fn();
 +        let b = u.b;
 +        match u {
 +            Union { b: 0 } => (),
 +            Union { a } => (),
 +        }
 +        Struct { field: 0 }.unsafe_method();
 +
 +        // unsafe deref
 +        *x;
 +
 +        // unsafe access to a static mut
 +        MUT_GLOBAL.field;
 +        GLOBAL.field;
 +
 +        // unsafe ref of packed fields
 +        let packed = Packed { a: 0 };
 +        let a = &packed.a;
 +        let ref a = packed.a;
 +        let Packed { ref a } = packed;
 +        let Packed { a: ref _a } = packed;
 +
 +        // unsafe auto ref of packed field
 +        packed.a.calls_autoref();
 +    }
 +}
 +"#,
 +        expect_file!["./test_data/highlight_unsafe.html"],
 +        false,
 +    );
 +}
 +
 +#[test]
 +fn test_highlight_doc_comment() {
 +    check_highlighting(
 +        r#"
 +//- /main.rs
 +//! This is a module to test doc injection.
 +//! ```
 +//! fn test() {}
 +//! ```
 +
 +mod outline_module;
 +
 +/// ```
 +/// let _ = "early doctests should not go boom";
 +/// ```
 +struct Foo {
 +    bar: bool,
 +}
 +
 +/// This is an impl with a code block.
 +///
 +/// ```
 +/// fn foo() {
 +///
 +/// }
 +/// ```
 +impl Foo {
 +    /// ```
 +    /// let _ = "Call me
 +    //    KILLER WHALE
 +    ///     Ishmael.";
 +    /// ```
 +    pub const bar: bool = true;
 +
 +    /// Constructs a new `Foo`.
 +    ///
 +    /// # Examples
 +    ///
 +    /// ```
 +    /// # #![allow(unused_mut)]
 +    /// let mut foo: Foo = Foo::new();
 +    /// ```
 +    pub const fn new() -> Foo {
 +        Foo { bar: true }
 +    }
 +
 +    /// `bar` method on `Foo`.
 +    ///
 +    /// # Examples
 +    ///
 +    /// ```
 +    /// use x::y;
 +    ///
 +    /// let foo = Foo::new();
 +    ///
 +    /// // calls bar on foo
 +    /// assert!(foo.bar());
 +    ///
 +    /// let bar = foo.bar || Foo::bar;
 +    ///
 +    /// /* multi-line
 +    ///        comment */
 +    ///
 +    /// let multi_line_string = "Foo
 +    ///   bar\n
 +    ///          ";
 +    ///
 +    /// ```
 +    ///
 +    /// ```rust,no_run
 +    /// let foobar = Foo::new().bar();
 +    /// ```
 +    ///
 +    /// ~~~rust,no_run
 +    /// // code block with tilde.
 +    /// let foobar = Foo::new().bar();
 +    /// ~~~
 +    ///
 +    /// ```
 +    /// // functions
 +    /// fn foo<T, const X: usize>(arg: i32) {
 +    ///     let x: T = X;
 +    /// }
 +    /// ```
 +    ///
 +    /// ```sh
 +    /// echo 1
 +    /// ```
 +    pub fn foo(&self) -> bool {
 +        true
 +    }
 +}
 +
 +/// [`Foo`](Foo) is a struct
 +/// This function is > [`all_the_links`](all_the_links) <
 +/// [`noop`](noop) is a macro below
 +/// [`Item`] is a struct in the module [`module`]
 +///
 +/// [`Item`]: module::Item
 +/// [mix_and_match]: ThisShouldntResolve
 +pub fn all_the_links() {}
 +
 +pub mod module {
 +    pub struct Item;
 +}
 +
 +/// ```
 +/// macro_rules! noop { ($expr:expr) => { $expr }}
 +/// noop!(1);
 +/// ```
 +macro_rules! noop {
 +    ($expr:expr) => {
 +        $expr
 +    }
 +}
 +
 +/// ```rust
 +/// let _ = example(&[1, 2, 3]);
 +/// ```
 +///
 +/// ```
 +/// loop {}
 +#[cfg_attr(not(feature = "false"), doc = "loop {}")]
 +#[doc = "loop {}"]
 +/// ```
 +///
 +#[cfg_attr(feature = "alloc", doc = "```rust")]
 +#[cfg_attr(not(feature = "alloc"), doc = "```ignore")]
 +/// let _ = example(&alloc::vec![1, 2, 3]);
 +/// ```
 +pub fn mix_and_match() {}
 +
 +/**
 +It is beyond me why you'd use these when you got ///
 +```rust
 +let _ = example(&[1, 2, 3]);
 +```
 +[`block_comments2`] tests these with indentation
 + */
 +pub fn block_comments() {}
 +
 +/**
 +    Really, I don't get it
 +    ```rust
 +    let _ = example(&[1, 2, 3]);
 +    ```
 +    [`block_comments`] tests these without indentation
 +*/
 +pub fn block_comments2() {}
 +
 +//- /outline_module.rs
 +//! This is an outline module whose purpose is to test that its inline attribute injection does not
 +//! spill into its parent.
 +//! ```
 +//! fn test() {}
 +//! ```
 +"#,
 +        expect_file!["./test_data/highlight_doctest.html"],
 +        false,
 +    );
 +}
 +
 +#[test]
 +fn test_extern_crate() {
 +    check_highlighting(
 +        r#"
 +//- /main.rs crate:main deps:std,alloc
 +extern crate std;
 +extern crate alloc as abc;
 +//- /std/lib.rs crate:std
 +pub struct S;
 +//- /alloc/lib.rs crate:alloc
 +pub struct A
 +"#,
 +        expect_file!["./test_data/highlight_extern_crate.html"],
 +        false,
 +    );
 +}
 +
 +#[test]
 +fn test_crate_root() {
 +    check_highlighting(
 +        r#"
 +//- minicore: iterators
 +//- /main.rs crate:main deps:foo
 +extern crate foo;
 +use core::iter;
 +
 +pub const NINETY_TWO: u8 = 92;
 +
 +use foo as foooo;
 +
 +pub(crate) fn main() {
 +    let baz = iter::repeat(92);
 +}
 +
 +mod bar {
 +    pub(in super) const FORTY_TWO: u8 = 42;
 +
 +    mod baz {
 +        use super::super::NINETY_TWO;
 +        use crate::foooo::Point;
 +
 +        pub(in super::super) const TWENTY_NINE: u8 = 29;
 +    }
 +}
 +//- /foo.rs crate:foo
 +struct Point {
 +    x: u8,
 +    y: u8,
 +}
 +
 +mod inner {
 +    pub(super) fn swap(p: crate::Point) -> crate::Point {
 +        crate::Point { x: p.y, y: p.x }
 +    }
 +}
 +"#,
 +        expect_file!["./test_data/highlight_crate_root.html"],
 +        false,
 +    );
 +}
 +
 +#[test]
 +fn test_default_library() {
 +    check_highlighting(
 +        r#"
 +//- minicore: option, iterators
 +use core::iter;
 +
 +fn main() {
 +    let foo = Some(92);
 +    let nums = iter::repeat(foo.unwrap());
 +}
 +"#,
 +        expect_file!["./test_data/highlight_default_library.html"],
 +        false,
 +    );
 +}
 +
 +#[test]
 +fn test_associated_function() {
 +    check_highlighting(
 +        r#"
 +fn not_static() {}
 +
 +struct foo {}
 +
 +impl foo {
 +    pub fn is_static() {}
 +    pub fn is_not_static(&self) {}
 +}
 +
 +trait t {
 +    fn t_is_static() {}
 +    fn t_is_not_static(&self) {}
 +}
 +
 +impl t for foo {
 +    pub fn is_static() {}
 +    pub fn is_not_static(&self) {}
 +}
 +"#,
 +        expect_file!["./test_data/highlight_assoc_functions.html"],
 +        false,
 +    )
 +}
 +
 +#[test]
 +fn test_injection() {
 +    check_highlighting(
 +        r##"
 +fn fixture(ra_fixture: &str) {}
 +
 +fn main() {
 +    fixture(r#"
 +trait Foo {
 +    fn foo() {
 +        println!("2 + 2 = {}", 4);
 +    }
 +}"#
 +    );
 +    fixture(r"
 +fn foo() {
 +    foo(\$0{
 +        92
 +    }\$0)
 +}"
 +    );
 +}
 +"##,
 +        expect_file!["./test_data/highlight_injection.html"],
 +        false,
 +    );
 +}
 +
 +#[test]
 +fn test_operators() {
 +    check_highlighting(
 +        r##"
 +fn main() {
 +    1 + 1 - 1 * 1 / 1 % 1 | 1 & 1 ! 1 ^ 1 >> 1 << 1;
 +    let mut a = 0;
 +    a += 1;
 +    a -= 1;
 +    a *= 1;
 +    a /= 1;
 +    a %= 1;
 +    a |= 1;
 +    a &= 1;
 +    a ^= 1;
 +    a >>= 1;
 +    a <<= 1;
 +}
 +"##,
 +        expect_file!["./test_data/highlight_operators.html"],
 +        false,
 +    );
 +}
 +
 +#[test]
++fn test_mod_hl_injection() {
++    check_highlighting(
++        r##"
++//- /foo.rs
++//! [Struct]
++//! This is an intra doc injection test for modules
++//! [Struct]
++//! This is an intra doc injection test for modules
++
++pub struct Struct;
++//- /lib.rs crate:foo
++/// [crate::foo::Struct]
++/// This is an intra doc injection test for modules
++/// [crate::foo::Struct]
++/// This is an intra doc injection test for modules
++mod foo;
++"##,
++        expect_file!["./test_data/highlight_module_docs_inline.html"],
++        false,
++    );
++    check_highlighting(
++        r##"
++//- /lib.rs crate:foo
++/// [crate::foo::Struct]
++/// This is an intra doc injection test for modules
++/// [crate::foo::Struct]
++/// This is an intra doc injection test for modules
++mod foo;
++//- /foo.rs
++//! [Struct]
++//! This is an intra doc injection test for modules
++//! [Struct]
++//! This is an intra doc injection test for modules
++
++pub struct Struct;
++"##,
++        expect_file!["./test_data/highlight_module_docs_outline.html"],
++        false,
++    );
++}
++
++#[test]
++#[cfg_attr(
++    all(unix, not(target_pointer_width = "64")),
++    ignore = "depends on `DefaultHasher` outputs"
++)]
 +fn test_rainbow_highlighting() {
 +    check_highlighting(
 +        r#"
 +fn main() {
 +    let hello = "hello";
 +    let x = hello.to_string();
 +    let y = hello.to_string();
 +
 +    let x = "other color please!";
 +    let y = x.to_string();
 +}
 +
 +fn bar() {
 +    let mut hello = "hello";
 +}
 +"#,
 +        expect_file!["./test_data/highlight_rainbow.html"],
 +        true,
 +    );
 +}
 +
 +#[test]
 +fn test_ranges() {
 +    let (analysis, file_id) = fixture::file(
 +        r#"
 +#[derive(Clone, Debug)]
 +struct Foo {
 +    pub x: i32,
 +    pub y: i32,
 +}
 +"#,
 +    );
 +
 +    // The "x"
 +    let highlights = &analysis
 +        .highlight_range(FileRange { file_id, range: TextRange::at(45.into(), 1.into()) })
 +        .unwrap();
 +
 +    assert_eq!(&highlights[0].highlight.to_string(), "field.declaration.public");
 +}
 +
 +#[test]
 +fn ranges_sorted() {
 +    let (analysis, file_id) = fixture::file(
 +        r#"
 +#[foo(bar = "bar")]
 +macro_rules! test {}
 +}"#
 +        .trim(),
 +    );
 +    let _ = analysis.highlight(file_id).unwrap();
 +}
 +
 +/// Highlights the code given by the `ra_fixture` argument, renders the
 +/// result as HTML, and compares it with the HTML file given as `snapshot`.
 +/// Note that the `snapshot` file is overwritten by the rendered HTML.
 +fn check_highlighting(ra_fixture: &str, expect: ExpectFile, rainbow: bool) {
 +    let (analysis, file_id) = fixture::file(ra_fixture.trim());
 +    let actual_html = &analysis.highlight_as_html(file_id, rainbow).unwrap();
 +    expect.assert_eq(actual_html)
 +}
 +
 +#[test]
 +fn benchmark_syntax_highlighting_long_struct() {
 +    if skip_slow_tests() {
 +        return;
 +    }
 +
 +    let fixture = bench_fixture::big_struct();
 +    let (analysis, file_id) = fixture::file(&fixture);
 +
 +    let hash = {
 +        let _pt = bench("syntax highlighting long struct");
 +        analysis
 +            .highlight(file_id)
 +            .unwrap()
 +            .iter()
 +            .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Struct))
 +            .count()
 +    };
 +    assert_eq!(hash, 2001);
 +}
 +
 +#[test]
 +fn syntax_highlighting_not_quadratic() {
 +    if skip_slow_tests() {
 +        return;
 +    }
 +
 +    let mut al = AssertLinear::default();
 +    while al.next_round() {
 +        for i in 6..=10 {
 +            let n = 1 << i;
 +
 +            let fixture = bench_fixture::big_struct_n(n);
 +            let (analysis, file_id) = fixture::file(&fixture);
 +
 +            let time = Instant::now();
 +
 +            let hash = analysis
 +                .highlight(file_id)
 +                .unwrap()
 +                .iter()
 +                .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Struct))
 +                .count();
 +            assert!(hash > n as usize);
 +
 +            let elapsed = time.elapsed();
 +            al.sample(n as f64, elapsed.as_millis() as f64);
 +        }
 +    }
 +}
 +
 +#[test]
 +fn benchmark_syntax_highlighting_parser() {
 +    if skip_slow_tests() {
 +        return;
 +    }
 +
 +    let fixture = bench_fixture::glorious_old_parser();
 +    let (analysis, file_id) = fixture::file(&fixture);
 +
 +    let hash = {
 +        let _pt = bench("syntax highlighting parser");
 +        analysis
 +            .highlight(file_id)
 +            .unwrap()
 +            .iter()
 +            .filter(|it| it.highlight.tag == HlTag::Symbol(SymbolKind::Function))
 +            .count()
 +    };
 +    assert_eq!(hash, 1609);
 +}
index 3c1da80edb98b08d421eb186d73bd4a0a99b163c,0000000000000000000000000000000000000000..d6a706a7cd73a82efc2dad0b97adc7ae4e9623ce
mode 100644,000000..100644
--- /dev/null
@@@ -1,60 -1,0 +1,69 @@@
-     #[allow(unused)]
 +//! limit defines a struct to enforce limits.
 +
 +#![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
 +
++#[cfg(feature = "tracking")]
 +use std::sync::atomic::AtomicUsize;
 +
 +/// Represents a struct used to enforce a numerical limit.
 +pub struct Limit {
 +    upper_bound: usize,
-         Self { upper_bound, max: AtomicUsize::new(0) }
++    #[cfg(feature = "tracking")]
 +    max: AtomicUsize,
 +}
 +
 +impl Limit {
 +    /// Creates a new limit.
 +    #[inline]
 +    pub const fn new(upper_bound: usize) -> Self {
-         Self { upper_bound, max: AtomicUsize::new(1) }
++        Self {
++            upper_bound,
++            #[cfg(feature = "tracking")]
++            max: AtomicUsize::new(0),
++        }
 +    }
 +
 +    /// Creates a new limit.
 +    #[inline]
 +    #[cfg(feature = "tracking")]
 +    pub const fn new_tracking(upper_bound: usize) -> Self {
++        Self {
++            upper_bound,
++            #[cfg(feature = "tracking")]
++            max: AtomicUsize::new(1),
++        }
 +    }
 +
 +    /// Gets the underlying numeric limit.
 +    #[inline]
 +    pub const fn inner(&self) -> usize {
 +        self.upper_bound
 +    }
 +
 +    /// Checks whether the given value is below the limit.
 +    /// Returns `Ok` when `other` is below `self`, and `Err` otherwise.
 +    #[inline]
 +    pub fn check(&self, other: usize) -> Result<(), ()> {
 +        if other > self.upper_bound {
 +            Err(())
 +        } else {
 +            #[cfg(feature = "tracking")]
 +            loop {
 +                use std::sync::atomic::Ordering;
 +                let old_max = self.max.load(Ordering::Relaxed);
 +                if other <= old_max || old_max == 0 {
 +                    break;
 +                }
 +                if self
 +                    .max
 +                    .compare_exchange_weak(old_max, other, Ordering::Relaxed, Ordering::Relaxed)
 +                    .is_ok()
 +                {
 +                    eprintln!("new max: {}", other);
 +                }
 +            }
 +
 +            Ok(())
 +        }
 +    }
 +}
index f9efcef92a610129911e6381401b7d66ce4919a8,0000000000000000000000000000000000000000..8de5d33a1936d42479470854e39bee711f1916a2
mode 100644,000000..100644
--- /dev/null
@@@ -1,132 -1,0 +1,132 @@@
-         let use_tree = matches!(p.nth(2), T![*] | T!['{']);
 +use super::*;
 +
 +pub(super) const PATH_FIRST: TokenSet =
 +    TokenSet::new(&[IDENT, T![self], T![super], T![crate], T![Self], T![:], T![<]]);
 +
 +pub(super) fn is_path_start(p: &Parser<'_>) -> bool {
 +    is_use_path_start(p) || p.at(T![<]) || p.at(T![Self])
 +}
 +
 +pub(super) fn is_use_path_start(p: &Parser<'_>) -> bool {
 +    match p.current() {
 +        IDENT | T![self] | T![super] | T![crate] => true,
 +        T![:] if p.at(T![::]) => true,
 +        _ => false,
 +    }
 +}
 +
 +pub(super) fn use_path(p: &mut Parser<'_>) {
 +    path(p, Mode::Use);
 +}
 +
 +pub(crate) fn type_path(p: &mut Parser<'_>) {
 +    path(p, Mode::Type);
 +}
 +
 +pub(super) fn expr_path(p: &mut Parser<'_>) {
 +    path(p, Mode::Expr);
 +}
 +
 +pub(crate) fn type_path_for_qualifier(
 +    p: &mut Parser<'_>,
 +    qual: CompletedMarker,
 +) -> CompletedMarker {
 +    path_for_qualifier(p, Mode::Type, qual)
 +}
 +
 +#[derive(Clone, Copy, Eq, PartialEq)]
 +enum Mode {
 +    Use,
 +    Type,
 +    Expr,
 +}
 +
 +fn path(p: &mut Parser<'_>, mode: Mode) {
 +    let path = p.start();
 +    path_segment(p, mode, true);
 +    let qual = path.complete(p, PATH);
 +    path_for_qualifier(p, mode, qual);
 +}
 +
 +fn path_for_qualifier(
 +    p: &mut Parser<'_>,
 +    mode: Mode,
 +    mut qual: CompletedMarker,
 +) -> CompletedMarker {
 +    loop {
++        let use_tree = mode == Mode::Use && matches!(p.nth(2), T![*] | T!['{']);
 +        if p.at(T![::]) && !use_tree {
 +            let path = qual.precede(p);
 +            p.bump(T![::]);
 +            path_segment(p, mode, false);
 +            let path = path.complete(p, PATH);
 +            qual = path;
 +        } else {
 +            return qual;
 +        }
 +    }
 +}
 +
 +fn path_segment(p: &mut Parser<'_>, mode: Mode, first: bool) {
 +    let m = p.start();
 +    // test qual_paths
 +    // type X = <A as B>::Output;
 +    // fn foo() { <usize as Default>::default(); }
 +    if first && p.eat(T![<]) {
 +        types::type_(p);
 +        if p.eat(T![as]) {
 +            if is_use_path_start(p) {
 +                types::path_type(p);
 +            } else {
 +                p.error("expected a trait");
 +            }
 +        }
 +        p.expect(T![>]);
 +    } else {
 +        let mut empty = true;
 +        if first {
 +            p.eat(T![::]);
 +            empty = false;
 +        }
 +        match p.current() {
 +            IDENT => {
 +                name_ref(p);
 +                opt_path_type_args(p, mode);
 +            }
 +            // test crate_path
 +            // use crate::foo;
 +            T![self] | T![super] | T![crate] | T![Self] => {
 +                let m = p.start();
 +                p.bump_any();
 +                m.complete(p, NAME_REF);
 +            }
 +            _ => {
 +                p.err_recover("expected identifier", items::ITEM_RECOVERY_SET);
 +                if empty {
 +                    // test_err empty_segment
 +                    // use crate::;
 +                    m.abandon(p);
 +                    return;
 +                }
 +            }
 +        };
 +    }
 +    m.complete(p, PATH_SEGMENT);
 +}
 +
 +fn opt_path_type_args(p: &mut Parser<'_>, mode: Mode) {
 +    match mode {
 +        Mode::Use => {}
 +        Mode::Type => {
 +            // test path_fn_trait_args
 +            // type F = Box<Fn(i32) -> ()>;
 +            if p.at(T!['(']) {
 +                params::param_list_fn_trait(p);
 +                opt_ret_type(p);
 +            } else {
 +                generic_args::opt_generic_arg_list(p, false);
 +            }
 +        }
 +        Mode::Expr => generic_args::opt_generic_arg_list(p, true),
 +    }
 +}
index 4b1858b8ed89e87c87b4e6d481911427936d7e6c,0000000000000000000000000000000000000000..4c205b9cadac3abd8311f9a7c1ae4d4f113f1b63
mode 100644,000000..100644
--- /dev/null
@@@ -1,153 -1,0 +1,160 @@@
-             let res = s
 +//! RA Proc Macro Server
 +//!
 +//! This library is able to call compiled Rust custom derive dynamic libraries on arbitrary code.
 +//! The general idea here is based on <https://github.com/fedochet/rust-proc-macro-expander>.
 +//!
 +//! But we adapt it to better fit RA needs:
 +//!
 +//! * We use `tt` for proc-macro `TokenStream` server, it is easier to manipulate and interact with
 +//!   RA than `proc-macro2` token stream.
 +//! * By **copying** the whole rustc `lib_proc_macro` code, we are able to build this with `stable`
 +//!   rustc rather than `unstable`. (Although in general ABI compatibility is still an issue)…
 +
 +#![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
 +#![cfg_attr(
 +    feature = "sysroot-abi",
 +    feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)
 +)]
 +#![allow(unreachable_pub)]
 +
 +mod dylib;
 +mod abis;
 +
 +use std::{
 +    collections::{hash_map::Entry, HashMap},
 +    env,
 +    ffi::OsString,
 +    fs,
 +    path::{Path, PathBuf},
 +    time::SystemTime,
 +};
 +
 +use proc_macro_api::{
 +    msg::{ExpandMacro, FlatTree, PanicMessage},
 +    ProcMacroKind,
 +};
 +
 +#[derive(Default)]
 +pub(crate) struct ProcMacroSrv {
 +    expanders: HashMap<(PathBuf, SystemTime), dylib::Expander>,
 +}
 +
++const EXPANDER_STACK_SIZE: usize = 8 * 1024 * 1024;
++
 +impl ProcMacroSrv {
 +    pub fn expand(&mut self, task: ExpandMacro) -> Result<FlatTree, PanicMessage> {
 +        let expander = self.expander(task.lib.as_ref()).map_err(|err| {
 +            debug_assert!(false, "should list macros before asking to expand");
 +            PanicMessage(format!("failed to load macro: {}", err))
 +        })?;
 +
 +        let prev_env = EnvSnapshot::new();
 +        for (k, v) in &task.env {
 +            env::set_var(k, v);
 +        }
 +        let prev_working_dir = match task.current_dir {
 +            Some(dir) => {
 +                let prev_working_dir = std::env::current_dir().ok();
 +                if let Err(err) = std::env::set_current_dir(&dir) {
 +                    eprintln!("Failed to set the current working dir to {}. Error: {:?}", dir, err)
 +                }
 +                prev_working_dir
 +            }
 +            None => None,
 +        };
 +
 +        let macro_body = task.macro_body.to_subtree();
 +        let attributes = task.attributes.map(|it| it.to_subtree());
 +        // FIXME: replace this with std's scoped threads once they stabilize
 +        // (then remove dependency on crossbeam)
 +        let result = crossbeam::scope(|s| {
-                 })
-                 .join();
++            let res = match s
++                .builder()
++                .stack_size(EXPANDER_STACK_SIZE)
++                .name(task.macro_name.clone())
 +                .spawn(|_| {
 +                    expander
 +                        .expand(&task.macro_name, &macro_body, attributes.as_ref())
 +                        .map(|it| FlatTree::new(&it))
++                }) {
++                Ok(handle) => handle.join(),
++                Err(e) => std::panic::resume_unwind(Box::new(e)),
++            };
 +
 +            match res {
 +                Ok(res) => res,
 +                Err(e) => std::panic::resume_unwind(e),
 +            }
 +        });
 +        let result = match result {
 +            Ok(result) => result,
 +            Err(e) => std::panic::resume_unwind(e),
 +        };
 +
 +        prev_env.rollback();
 +
 +        if let Some(dir) = prev_working_dir {
 +            if let Err(err) = std::env::set_current_dir(&dir) {
 +                eprintln!(
 +                    "Failed to set the current working dir to {}. Error: {:?}",
 +                    dir.display(),
 +                    err
 +                )
 +            }
 +        }
 +
 +        result.map_err(PanicMessage)
 +    }
 +
 +    pub(crate) fn list_macros(
 +        &mut self,
 +        dylib_path: &Path,
 +    ) -> Result<Vec<(String, ProcMacroKind)>, String> {
 +        let expander = self.expander(dylib_path)?;
 +        Ok(expander.list_macros())
 +    }
 +
 +    fn expander(&mut self, path: &Path) -> Result<&dylib::Expander, String> {
 +        let time = fs::metadata(path).and_then(|it| it.modified()).map_err(|err| {
 +            format!("Failed to get file metadata for {}: {:?}", path.display(), err)
 +        })?;
 +
 +        Ok(match self.expanders.entry((path.to_path_buf(), time)) {
 +            Entry::Vacant(v) => v.insert(dylib::Expander::new(path).map_err(|err| {
 +                format!("Cannot create expander for {}: {:?}", path.display(), err)
 +            })?),
 +            Entry::Occupied(e) => e.into_mut(),
 +        })
 +    }
 +}
 +
 +struct EnvSnapshot {
 +    vars: HashMap<OsString, OsString>,
 +}
 +
 +impl EnvSnapshot {
 +    fn new() -> EnvSnapshot {
 +        EnvSnapshot { vars: env::vars_os().collect() }
 +    }
 +
 +    fn rollback(self) {
 +        let mut old_vars = self.vars;
 +        for (name, value) in env::vars_os() {
 +            let old_value = old_vars.remove(&name);
 +            if old_value != Some(value) {
 +                match old_value {
 +                    None => env::remove_var(name),
 +                    Some(old_value) => env::set_var(name, old_value),
 +                }
 +            }
 +        }
 +        for (name, old_value) in old_vars {
 +            env::set_var(name, old_value)
 +        }
 +    }
 +}
 +
 +pub mod cli;
 +
 +#[cfg(test)]
 +mod tests;
index 0ada4b73e842d9d7f814bf71f74c9dc4441158c3,0000000000000000000000000000000000000000..5d1c013c3275b2fabf86110ec16ac13dc75e0a1f
mode 100644,000000..100644
--- /dev/null
@@@ -1,162 -1,0 +1,164 @@@
-         &mut |_, path: &AbsPath| load_proc_macro(proc_macro_client.as_ref(), path, &[]),
 +//! Loads a Cargo project into a static instance of analysis, without support
 +//! for incorporating changes.
 +use std::{path::Path, sync::Arc};
 +
 +use anyhow::Result;
 +use crossbeam_channel::{unbounded, Receiver};
 +use hir::db::DefDatabase;
 +use ide::{AnalysisHost, Change};
 +use ide_db::base_db::CrateGraph;
 +use proc_macro_api::ProcMacroServer;
 +use project_model::{CargoConfig, ProjectManifest, ProjectWorkspace};
 +use vfs::{loader::Handle, AbsPath, AbsPathBuf};
 +
 +use crate::reload::{load_proc_macro, ProjectFolders, SourceRootConfig};
 +
 +// Note: Since this type is used by external tools that use rust-analyzer as a library
 +// what otherwise would be `pub(crate)` has to be `pub` here instead.
 +pub struct LoadCargoConfig {
 +    pub load_out_dirs_from_check: bool,
 +    pub with_proc_macro: bool,
 +    pub prefill_caches: bool,
 +}
 +
 +// Note: Since this function is used by external tools that use rust-analyzer as a library
 +// what otherwise would be `pub(crate)` has to be `pub` here instead.
 +pub fn load_workspace_at(
 +    root: &Path,
 +    cargo_config: &CargoConfig,
 +    load_config: &LoadCargoConfig,
 +    progress: &dyn Fn(String),
 +) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroServer>)> {
 +    let root = AbsPathBuf::assert(std::env::current_dir()?.join(root));
 +    let root = ProjectManifest::discover_single(&root)?;
 +    let mut workspace = ProjectWorkspace::load(root, cargo_config, progress)?;
 +
 +    if load_config.load_out_dirs_from_check {
 +        let build_scripts = workspace.run_build_scripts(cargo_config, progress)?;
 +        workspace.set_build_scripts(build_scripts)
 +    }
 +
 +    load_workspace(workspace, load_config)
 +}
 +
 +// Note: Since this function is used by external tools that use rust-analyzer as a library
 +// what otherwise would be `pub(crate)` has to be `pub` here instead.
 +//
 +// The reason both, `load_workspace_at` and `load_workspace` are `pub` is that some of
 +// these tools need access to `ProjectWorkspace`, too, which `load_workspace_at` hides.
 +pub fn load_workspace(
 +    ws: ProjectWorkspace,
 +    load_config: &LoadCargoConfig,
 +) -> Result<(AnalysisHost, vfs::Vfs, Option<ProcMacroServer>)> {
 +    let (sender, receiver) = unbounded();
 +    let mut vfs = vfs::Vfs::default();
 +    let mut loader = {
 +        let loader =
 +            vfs_notify::NotifyHandle::spawn(Box::new(move |msg| sender.send(msg).unwrap()));
 +        Box::new(loader)
 +    };
 +
 +    let proc_macro_client = if load_config.with_proc_macro {
 +        let path = AbsPathBuf::assert(std::env::current_exe()?);
 +        Ok(ProcMacroServer::spawn(path, &["proc-macro"]).unwrap())
 +    } else {
 +        Err("proc macro server not started".to_owned())
 +    };
 +
 +    let crate_graph = ws.to_crate_graph(
++        &mut |_, path: &AbsPath| {
++            load_proc_macro(proc_macro_client.as_ref().map_err(|e| &**e), path, &[])
++        },
 +        &mut |path: &AbsPath| {
 +            let contents = loader.load_sync(path);
 +            let path = vfs::VfsPath::from(path.to_path_buf());
 +            vfs.set_file_contents(path.clone(), contents);
 +            vfs.file_id(&path)
 +        },
 +    );
 +
 +    let project_folders = ProjectFolders::new(&[ws], &[]);
 +    loader.set_config(vfs::loader::Config {
 +        load: project_folders.load,
 +        watch: vec![],
 +        version: 0,
 +    });
 +
 +    tracing::debug!("crate graph: {:?}", crate_graph);
 +    let host =
 +        load_crate_graph(crate_graph, project_folders.source_root_config, &mut vfs, &receiver);
 +
 +    if load_config.prefill_caches {
 +        host.analysis().parallel_prime_caches(1, |_| {})?;
 +    }
 +    Ok((host, vfs, proc_macro_client.ok()))
 +}
 +
 +fn load_crate_graph(
 +    crate_graph: CrateGraph,
 +    source_root_config: SourceRootConfig,
 +    vfs: &mut vfs::Vfs,
 +    receiver: &Receiver<vfs::loader::Message>,
 +) -> AnalysisHost {
 +    let lru_cap = std::env::var("RA_LRU_CAP").ok().and_then(|it| it.parse::<usize>().ok());
 +    let mut host = AnalysisHost::new(lru_cap);
 +    let mut analysis_change = Change::new();
 +
 +    host.raw_database_mut().set_enable_proc_attr_macros(true);
 +
 +    // wait until Vfs has loaded all roots
 +    for task in receiver {
 +        match task {
 +            vfs::loader::Message::Progress { n_done, n_total, config_version: _ } => {
 +                if n_done == n_total {
 +                    break;
 +                }
 +            }
 +            vfs::loader::Message::Loaded { files } => {
 +                for (path, contents) in files {
 +                    vfs.set_file_contents(path.into(), contents);
 +                }
 +            }
 +        }
 +    }
 +    let changes = vfs.take_changes();
 +    for file in changes {
 +        if file.exists() {
 +            let contents = vfs.file_contents(file.file_id).to_vec();
 +            if let Ok(text) = String::from_utf8(contents) {
 +                analysis_change.change_file(file.file_id, Some(Arc::new(text)))
 +            }
 +        }
 +    }
 +    let source_roots = source_root_config.partition(vfs);
 +    analysis_change.set_roots(source_roots);
 +
 +    analysis_change.set_crate_graph(crate_graph);
 +
 +    host.apply_change(analysis_change);
 +    host
 +}
 +
 +#[cfg(test)]
 +mod tests {
 +    use super::*;
 +
 +    use hir::Crate;
 +
 +    #[test]
 +    fn test_loading_rust_analyzer() {
 +        let path = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap().parent().unwrap();
 +        let cargo_config = CargoConfig::default();
 +        let load_cargo_config = LoadCargoConfig {
 +            load_out_dirs_from_check: false,
 +            with_proc_macro: false,
 +            prefill_caches: false,
 +        };
 +        let (host, _vfs, _proc_macro) =
 +            load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {}).unwrap();
 +
 +        let n_crates = Crate::all(host.raw_database()).len();
 +        // RA has quite a few crates, but the exact count doesn't matter
 +        assert!(n_crates > 20);
 +    }
 +}
index 9ae361b034e28959043b1fbd2a40298fb86a7146,0000000000000000000000000000000000000000..eaab275bc68a41724f20d928d6081e2acbded763
mode 100644,000000..100644
--- /dev/null
@@@ -1,701 -1,0 +1,705 @@@
-                                 let server_path = sysroot
-                                     .root()
-                                     .join("libexec")
-                                     .join("rust-analyzer-proc-macro-srv");
 +//! Project loading & configuration updates.
 +//!
 +//! This is quite tricky. The main problem is time and changes -- there's no
 +//! fixed "project" rust-analyzer is working with, "current project" is itself
 +//! mutable state. For example, when the user edits `Cargo.toml` by adding a new
 +//! dependency, project model changes. What's more, switching project model is
 +//! not instantaneous -- it takes time to run `cargo metadata` and (for proc
 +//! macros) `cargo check`.
 +//!
 +//! The main guiding principle here is, as elsewhere in rust-analyzer,
 +//! robustness. We try not to assume that the project model exists or is
 +//! correct. Instead, we try to provide a best-effort service. Even if the
 +//! project is currently loading and we don't have a full project model, we
 +//! still want to respond to various  requests.
 +use std::{mem, sync::Arc};
 +
 +use flycheck::{FlycheckConfig, FlycheckHandle};
 +use hir::db::DefDatabase;
 +use ide::Change;
 +use ide_db::base_db::{
 +    CrateGraph, Env, ProcMacro, ProcMacroExpander, ProcMacroExpansionError, ProcMacroKind,
 +    ProcMacroLoadResult, SourceRoot, VfsPath,
 +};
 +use proc_macro_api::{MacroDylib, ProcMacroServer};
 +use project_model::{ProjectWorkspace, WorkspaceBuildScripts};
 +use syntax::SmolStr;
 +use vfs::{file_set::FileSetConfig, AbsPath, AbsPathBuf, ChangeKind};
 +
 +use crate::{
 +    config::{Config, FilesWatcher, LinkedProject},
 +    global_state::GlobalState,
 +    lsp_ext,
 +    main_loop::Task,
 +    op_queue::Cause,
 +};
 +
 +#[derive(Debug)]
 +pub(crate) enum ProjectWorkspaceProgress {
 +    Begin,
 +    Report(String),
 +    End(Vec<anyhow::Result<ProjectWorkspace>>),
 +}
 +
 +#[derive(Debug)]
 +pub(crate) enum BuildDataProgress {
 +    Begin,
 +    Report(String),
 +    End((Arc<Vec<ProjectWorkspace>>, Vec<anyhow::Result<WorkspaceBuildScripts>>)),
 +}
 +
 +impl GlobalState {
 +    pub(crate) fn is_quiescent(&self) -> bool {
 +        !(self.fetch_workspaces_queue.op_in_progress()
 +            || self.fetch_build_data_queue.op_in_progress()
 +            || self.vfs_progress_config_version < self.vfs_config_version
 +            || self.vfs_progress_n_done < self.vfs_progress_n_total)
 +    }
 +
 +    pub(crate) fn update_configuration(&mut self, config: Config) {
 +        let _p = profile::span("GlobalState::update_configuration");
 +        let old_config = mem::replace(&mut self.config, Arc::new(config));
 +        if self.config.lru_capacity() != old_config.lru_capacity() {
 +            self.analysis_host.update_lru_capacity(self.config.lru_capacity());
 +        }
 +        if self.config.linked_projects() != old_config.linked_projects() {
 +            self.fetch_workspaces_queue.request_op("linked projects changed".to_string())
 +        } else if self.config.flycheck() != old_config.flycheck() {
 +            self.reload_flycheck();
 +        }
 +
 +        if self.analysis_host.raw_database().enable_proc_attr_macros()
 +            != self.config.expand_proc_attr_macros()
 +        {
 +            self.analysis_host
 +                .raw_database_mut()
 +                .set_enable_proc_attr_macros(self.config.expand_proc_attr_macros());
 +        }
 +    }
 +
 +    pub(crate) fn current_status(&self) -> lsp_ext::ServerStatusParams {
 +        let mut status = lsp_ext::ServerStatusParams {
 +            health: lsp_ext::Health::Ok,
 +            quiescent: self.is_quiescent(),
 +            message: None,
 +        };
 +
 +        if self.proc_macro_changed {
 +            status.health = lsp_ext::Health::Warning;
 +            status.message =
 +                Some("Reload required due to source changes of a procedural macro.".into())
 +        }
 +        if let Err(_) = self.fetch_build_data_error() {
 +            status.health = lsp_ext::Health::Warning;
 +            status.message =
 +                Some("Failed to run build scripts of some packages, check the logs.".to_string());
 +        }
 +        if !self.config.cargo_autoreload()
 +            && self.is_quiescent()
 +            && self.fetch_workspaces_queue.op_requested()
 +        {
 +            status.health = lsp_ext::Health::Warning;
 +            status.message = Some("Workspace reload required".to_string())
 +        }
 +
 +        if let Err(error) = self.fetch_workspace_error() {
 +            status.health = lsp_ext::Health::Error;
 +            status.message = Some(error)
 +        }
 +        status
 +    }
 +
 +    pub(crate) fn fetch_workspaces(&mut self, cause: Cause) {
 +        tracing::info!(%cause, "will fetch workspaces");
 +
 +        self.task_pool.handle.spawn_with_sender({
 +            let linked_projects = self.config.linked_projects();
 +            let detached_files = self.config.detached_files().to_vec();
 +            let cargo_config = self.config.cargo();
 +
 +            move |sender| {
 +                let progress = {
 +                    let sender = sender.clone();
 +                    move |msg| {
 +                        sender
 +                            .send(Task::FetchWorkspace(ProjectWorkspaceProgress::Report(msg)))
 +                            .unwrap()
 +                    }
 +                };
 +
 +                sender.send(Task::FetchWorkspace(ProjectWorkspaceProgress::Begin)).unwrap();
 +
 +                let mut workspaces = linked_projects
 +                    .iter()
 +                    .map(|project| match project {
 +                        LinkedProject::ProjectManifest(manifest) => {
 +                            project_model::ProjectWorkspace::load(
 +                                manifest.clone(),
 +                                &cargo_config,
 +                                &progress,
 +                            )
 +                        }
 +                        LinkedProject::InlineJsonProject(it) => {
 +                            project_model::ProjectWorkspace::load_inline(
 +                                it.clone(),
 +                                cargo_config.target.as_deref(),
 +                            )
 +                        }
 +                    })
 +                    .collect::<Vec<_>>();
 +
 +                if !detached_files.is_empty() {
 +                    workspaces
 +                        .push(project_model::ProjectWorkspace::load_detached_files(detached_files));
 +                }
 +
 +                tracing::info!("did fetch workspaces {:?}", workspaces);
 +                sender
 +                    .send(Task::FetchWorkspace(ProjectWorkspaceProgress::End(workspaces)))
 +                    .unwrap();
 +            }
 +        });
 +    }
 +
 +    pub(crate) fn fetch_build_data(&mut self, cause: Cause) {
 +        tracing::info!(%cause, "will fetch build data");
 +        let workspaces = Arc::clone(&self.workspaces);
 +        let config = self.config.cargo();
 +        self.task_pool.handle.spawn_with_sender(move |sender| {
 +            sender.send(Task::FetchBuildData(BuildDataProgress::Begin)).unwrap();
 +
 +            let progress = {
 +                let sender = sender.clone();
 +                move |msg| {
 +                    sender.send(Task::FetchBuildData(BuildDataProgress::Report(msg))).unwrap()
 +                }
 +            };
 +            let mut res = Vec::new();
 +            for ws in workspaces.iter() {
 +                res.push(ws.run_build_scripts(&config, &progress));
 +            }
 +            sender.send(Task::FetchBuildData(BuildDataProgress::End((workspaces, res)))).unwrap();
 +        });
 +    }
 +
 +    pub(crate) fn switch_workspaces(&mut self, cause: Cause) {
 +        let _p = profile::span("GlobalState::switch_workspaces");
 +        tracing::info!(%cause, "will switch workspaces");
 +
 +        if let Err(error_message) = self.fetch_workspace_error() {
 +            self.show_and_log_error(error_message, None);
 +            if !self.workspaces.is_empty() {
 +                // It only makes sense to switch to a partially broken workspace
 +                // if we don't have any workspace at all yet.
 +                return;
 +            }
 +        }
 +
 +        if let Err(error) = self.fetch_build_data_error() {
 +            self.show_and_log_error(
 +                "rust-analyzer failed to run build scripts".to_string(),
 +                Some(error),
 +            );
 +        }
 +
 +        let workspaces = self
 +            .fetch_workspaces_queue
 +            .last_op_result()
 +            .iter()
 +            .filter_map(|res| res.as_ref().ok().cloned())
 +            .collect::<Vec<_>>();
 +
 +        fn eq_ignore_build_data<'a>(
 +            left: &'a ProjectWorkspace,
 +            right: &'a ProjectWorkspace,
 +        ) -> bool {
 +            let key = |p: &'a ProjectWorkspace| match p {
 +                ProjectWorkspace::Cargo {
 +                    cargo,
 +                    sysroot,
 +                    rustc,
 +                    rustc_cfg,
 +                    cfg_overrides,
 +
 +                    build_scripts: _,
 +                } => Some((cargo, sysroot, rustc, rustc_cfg, cfg_overrides)),
 +                _ => None,
 +            };
 +            match (key(left), key(right)) {
 +                (Some(lk), Some(rk)) => lk == rk,
 +                _ => left == right,
 +            }
 +        }
 +
 +        let same_workspaces = workspaces.len() == self.workspaces.len()
 +            && workspaces
 +                .iter()
 +                .zip(self.workspaces.iter())
 +                .all(|(l, r)| eq_ignore_build_data(l, r));
 +
 +        if same_workspaces {
 +            let (workspaces, build_scripts) = self.fetch_build_data_queue.last_op_result();
 +            if Arc::ptr_eq(workspaces, &self.workspaces) {
 +                tracing::debug!("set build scripts to workspaces");
 +
 +                let workspaces = workspaces
 +                    .iter()
 +                    .cloned()
 +                    .zip(build_scripts)
 +                    .map(|(mut ws, bs)| {
 +                        ws.set_build_scripts(bs.as_ref().ok().cloned().unwrap_or_default());
 +                        ws
 +                    })
 +                    .collect::<Vec<_>>();
 +
 +                // Workspaces are the same, but we've updated build data.
 +                self.workspaces = Arc::new(workspaces);
 +            } else {
 +                tracing::info!("build scripts do not match the version of the active workspace");
 +                // Current build scripts do not match the version of the active
 +                // workspace, so there's nothing for us to update.
 +                return;
 +            }
 +        } else {
 +            tracing::debug!("abandon build scripts for workspaces");
 +
 +            // Here, we completely changed the workspace (Cargo.toml edit), so
 +            // we don't care about build-script results, they are stale.
 +            self.workspaces = Arc::new(workspaces)
 +        }
 +
 +        if let FilesWatcher::Client = self.config.files().watcher {
 +            let registration_options = lsp_types::DidChangeWatchedFilesRegistrationOptions {
 +                watchers: self
 +                    .workspaces
 +                    .iter()
 +                    .flat_map(|ws| ws.to_roots())
 +                    .filter(|it| it.is_local)
 +                    .flat_map(|root| {
 +                        root.include.into_iter().flat_map(|it| {
 +                            [
 +                                format!("{}/**/*.rs", it.display()),
 +                                format!("{}/**/Cargo.toml", it.display()),
 +                                format!("{}/**/Cargo.lock", it.display()),
 +                            ]
 +                        })
 +                    })
 +                    .map(|glob_pattern| lsp_types::FileSystemWatcher { glob_pattern, kind: None })
 +                    .collect(),
 +            };
 +            let registration = lsp_types::Registration {
 +                id: "workspace/didChangeWatchedFiles".to_string(),
 +                method: "workspace/didChangeWatchedFiles".to_string(),
 +                register_options: Some(serde_json::to_value(registration_options).unwrap()),
 +            };
 +            self.send_request::<lsp_types::request::RegisterCapability>(
 +                lsp_types::RegistrationParams { registrations: vec![registration] },
 +                |_, _| (),
 +            );
 +        }
 +
 +        let mut change = Change::new();
 +
 +        let files_config = self.config.files();
 +        let project_folders = ProjectFolders::new(&self.workspaces, &files_config.exclude);
 +
++        let standalone_server_name =
++            format!("rust-analyzer-proc-macro-srv{}", std::env::consts::EXE_SUFFIX);
++
 +        if self.proc_macro_clients.is_empty() {
 +            if let Some((path, args)) = self.config.proc_macro_srv() {
 +                self.proc_macro_clients = self
 +                    .workspaces
 +                    .iter()
 +                    .map(|ws| {
 +                        let mut args = args.clone();
 +                        let mut path = path.clone();
 +
 +                        if let ProjectWorkspace::Cargo { sysroot, .. } = ws {
 +                            tracing::info!("Found a cargo workspace...");
 +                            if let Some(sysroot) = sysroot.as_ref() {
 +                                tracing::info!("Found a cargo workspace with a sysroot...");
-                 let proc_macro_client = self.proc_macro_clients[idx].as_ref();
++                                let server_path =
++                                    sysroot.root().join("libexec").join(&standalone_server_name);
 +                                if std::fs::metadata(&server_path).is_ok() {
 +                                    tracing::info!(
 +                                        "And the server exists at {}",
 +                                        server_path.display()
 +                                    );
 +                                    path = server_path;
 +                                    args = vec![];
 +                                } else {
 +                                    tracing::info!(
 +                                        "And the server does not exist at {}",
 +                                        server_path.display()
 +                                    );
 +                                }
 +                            }
 +                        }
 +
 +                        tracing::info!(
 +                            "Using proc-macro server at {} with args {:?}",
 +                            path.display(),
 +                            args
 +                        );
 +                        ProcMacroServer::spawn(path.clone(), args.clone()).map_err(|err| {
 +                            let error = format!(
 +                                "Failed to run proc_macro_srv from path {}, error: {:?}",
 +                                path.display(),
 +                                err
 +                            );
 +                            tracing::error!(error);
 +                            error
 +                        })
 +                    })
 +                    .collect();
 +            }
 +        }
 +
 +        let watch = match files_config.watcher {
 +            FilesWatcher::Client => vec![],
 +            FilesWatcher::Server => project_folders.watch,
 +        };
 +        self.vfs_config_version += 1;
 +        self.loader.handle.set_config(vfs::loader::Config {
 +            load: project_folders.load,
 +            watch,
 +            version: self.vfs_config_version,
 +        });
 +
 +        // Create crate graph from all the workspaces
 +        let crate_graph = {
 +            let dummy_replacements = self.config.dummy_replacements();
 +
 +            let vfs = &mut self.vfs.write().0;
 +            let loader = &mut self.loader;
 +            let mem_docs = &self.mem_docs;
 +            let mut load = move |path: &AbsPath| {
 +                let _p = profile::span("GlobalState::load");
 +                let vfs_path = vfs::VfsPath::from(path.to_path_buf());
 +                if !mem_docs.contains(&vfs_path) {
 +                    let contents = loader.handle.load_sync(path);
 +                    vfs.set_file_contents(vfs_path.clone(), contents);
 +                }
 +                let res = vfs.file_id(&vfs_path);
 +                if res.is_none() {
 +                    tracing::warn!("failed to load {}", path.display())
 +                }
 +                res
 +            };
 +
 +            let mut crate_graph = CrateGraph::default();
 +            for (idx, ws) in self.workspaces.iter().enumerate() {
-     server: Result<&ProcMacroServer, &String>,
++                let proc_macro_client = match self.proc_macro_clients.get(idx) {
++                    Some(res) => res.as_ref().map_err(|e| &**e),
++                    None => Err("Proc macros are disabled"),
++                };
 +                let mut load_proc_macro = move |crate_name: &str, path: &AbsPath| {
 +                    load_proc_macro(
 +                        proc_macro_client,
 +                        path,
 +                        dummy_replacements.get(crate_name).map(|v| &**v).unwrap_or_default(),
 +                    )
 +                };
 +                crate_graph.extend(ws.to_crate_graph(&mut load_proc_macro, &mut load));
 +            }
 +            crate_graph
 +        };
 +        change.set_crate_graph(crate_graph);
 +
 +        self.source_root_config = project_folders.source_root_config;
 +
 +        self.analysis_host.apply_change(change);
 +        self.process_changes();
 +        self.reload_flycheck();
 +        tracing::info!("did switch workspaces");
 +    }
 +
 +    fn fetch_workspace_error(&self) -> Result<(), String> {
 +        let mut buf = String::new();
 +
 +        for ws in self.fetch_workspaces_queue.last_op_result() {
 +            if let Err(err) = ws {
 +                stdx::format_to!(buf, "rust-analyzer failed to load workspace: {:#}\n", err);
 +            }
 +        }
 +
 +        if buf.is_empty() {
 +            return Ok(());
 +        }
 +
 +        Err(buf)
 +    }
 +
 +    fn fetch_build_data_error(&self) -> Result<(), String> {
 +        let mut buf = String::new();
 +
 +        for ws in &self.fetch_build_data_queue.last_op_result().1 {
 +            match ws {
 +                Ok(data) => match data.error() {
 +                    Some(stderr) => stdx::format_to!(buf, "{:#}\n", stderr),
 +                    _ => (),
 +                },
 +                // io errors
 +                Err(err) => stdx::format_to!(buf, "{:#}\n", err),
 +            }
 +        }
 +
 +        if buf.is_empty() {
 +            Ok(())
 +        } else {
 +            Err(buf)
 +        }
 +    }
 +
 +    fn reload_flycheck(&mut self) {
 +        let _p = profile::span("GlobalState::reload_flycheck");
 +        let config = match self.config.flycheck() {
 +            Some(it) => it,
 +            None => {
 +                self.flycheck = Vec::new();
 +                self.diagnostics.clear_check();
 +                return;
 +            }
 +        };
 +
 +        let sender = self.flycheck_sender.clone();
 +        self.flycheck = self
 +            .workspaces
 +            .iter()
 +            .enumerate()
 +            .filter_map(|(id, w)| match w {
 +                ProjectWorkspace::Cargo { cargo, .. } => Some((id, cargo.workspace_root())),
 +                ProjectWorkspace::Json { project, .. } => {
 +                    // Enable flychecks for json projects if a custom flycheck command was supplied
 +                    // in the workspace configuration.
 +                    match config {
 +                        FlycheckConfig::CustomCommand { .. } => Some((id, project.path())),
 +                        _ => None,
 +                    }
 +                }
 +                ProjectWorkspace::DetachedFiles { .. } => None,
 +            })
 +            .map(|(id, root)| {
 +                let sender = sender.clone();
 +                FlycheckHandle::spawn(
 +                    id,
 +                    Box::new(move |msg| sender.send(msg).unwrap()),
 +                    config.clone(),
 +                    root.to_path_buf(),
 +                )
 +            })
 +            .collect();
 +    }
 +}
 +
 +#[derive(Default)]
 +pub(crate) struct ProjectFolders {
 +    pub(crate) load: Vec<vfs::loader::Entry>,
 +    pub(crate) watch: Vec<usize>,
 +    pub(crate) source_root_config: SourceRootConfig,
 +}
 +
 +impl ProjectFolders {
 +    pub(crate) fn new(
 +        workspaces: &[ProjectWorkspace],
 +        global_excludes: &[AbsPathBuf],
 +    ) -> ProjectFolders {
 +        let mut res = ProjectFolders::default();
 +        let mut fsc = FileSetConfig::builder();
 +        let mut local_filesets = vec![];
 +
 +        for root in workspaces.iter().flat_map(|ws| ws.to_roots()) {
 +            let file_set_roots: Vec<VfsPath> =
 +                root.include.iter().cloned().map(VfsPath::from).collect();
 +
 +            let entry = {
 +                let mut dirs = vfs::loader::Directories::default();
 +                dirs.extensions.push("rs".into());
 +                dirs.include.extend(root.include);
 +                dirs.exclude.extend(root.exclude);
 +                for excl in global_excludes {
 +                    if dirs
 +                        .include
 +                        .iter()
 +                        .any(|incl| incl.starts_with(excl) || excl.starts_with(incl))
 +                    {
 +                        dirs.exclude.push(excl.clone());
 +                    }
 +                }
 +
 +                vfs::loader::Entry::Directories(dirs)
 +            };
 +
 +            if root.is_local {
 +                res.watch.push(res.load.len());
 +            }
 +            res.load.push(entry);
 +
 +            if root.is_local {
 +                local_filesets.push(fsc.len());
 +            }
 +            fsc.add_file_set(file_set_roots)
 +        }
 +
 +        let fsc = fsc.build();
 +        res.source_root_config = SourceRootConfig { fsc, local_filesets };
 +
 +        res
 +    }
 +}
 +
 +#[derive(Default, Debug)]
 +pub(crate) struct SourceRootConfig {
 +    pub(crate) fsc: FileSetConfig,
 +    pub(crate) local_filesets: Vec<usize>,
 +}
 +
 +impl SourceRootConfig {
 +    pub(crate) fn partition(&self, vfs: &vfs::Vfs) -> Vec<SourceRoot> {
 +        let _p = profile::span("SourceRootConfig::partition");
 +        self.fsc
 +            .partition(vfs)
 +            .into_iter()
 +            .enumerate()
 +            .map(|(idx, file_set)| {
 +                let is_local = self.local_filesets.contains(&idx);
 +                if is_local {
 +                    SourceRoot::new_local(file_set)
 +                } else {
 +                    SourceRoot::new_library(file_set)
 +                }
 +            })
 +            .collect()
 +    }
 +}
 +
 +/// Load the proc-macros for the given lib path, replacing all expanders whose names are in `dummy_replace`
 +/// with an identity dummy expander.
 +pub(crate) fn load_proc_macro(
++    server: Result<&ProcMacroServer, &str>,
 +    path: &AbsPath,
 +    dummy_replace: &[Box<str>],
 +) -> ProcMacroLoadResult {
 +    let res: Result<Vec<_>, String> = (|| {
 +        let dylib = MacroDylib::new(path.to_path_buf())
 +            .map_err(|io| format!("Proc-macro dylib loading failed: {io}"))?;
 +        let server = server.map_err(ToOwned::to_owned)?;
 +        let vec = server.load_dylib(dylib).map_err(|e| format!("{e}"))?;
 +        if vec.is_empty() {
 +            return Err("proc macro library returned no proc macros".to_string());
 +        }
 +        Ok(vec
 +            .into_iter()
 +            .map(|expander| expander_to_proc_macro(expander, dummy_replace))
 +            .collect())
 +    })();
 +    return match res {
 +        Ok(proc_macros) => {
 +            tracing::info!(
 +                "Loaded proc-macros for {}: {:?}",
 +                path.display(),
 +                proc_macros.iter().map(|it| it.name.clone()).collect::<Vec<_>>()
 +            );
 +            Ok(proc_macros)
 +        }
 +        Err(e) => {
 +            tracing::warn!("proc-macro loading for {} failed: {e}", path.display());
 +            Err(e)
 +        }
 +    };
 +
 +    fn expander_to_proc_macro(
 +        expander: proc_macro_api::ProcMacro,
 +        dummy_replace: &[Box<str>],
 +    ) -> ProcMacro {
 +        let name = SmolStr::from(expander.name());
 +        let kind = match expander.kind() {
 +            proc_macro_api::ProcMacroKind::CustomDerive => ProcMacroKind::CustomDerive,
 +            proc_macro_api::ProcMacroKind::FuncLike => ProcMacroKind::FuncLike,
 +            proc_macro_api::ProcMacroKind::Attr => ProcMacroKind::Attr,
 +        };
 +        let expander: Arc<dyn ProcMacroExpander> =
 +            if dummy_replace.iter().any(|replace| &**replace == name) {
 +                Arc::new(DummyExpander)
 +            } else {
 +                Arc::new(Expander(expander))
 +            };
 +        ProcMacro { name, kind, expander }
 +    }
 +
 +    #[derive(Debug)]
 +    struct Expander(proc_macro_api::ProcMacro);
 +
 +    impl ProcMacroExpander for Expander {
 +        fn expand(
 +            &self,
 +            subtree: &tt::Subtree,
 +            attrs: Option<&tt::Subtree>,
 +            env: &Env,
 +        ) -> Result<tt::Subtree, ProcMacroExpansionError> {
 +            let env = env.iter().map(|(k, v)| (k.to_string(), v.to_string())).collect();
 +            match self.0.expand(subtree, attrs, env) {
 +                Ok(Ok(subtree)) => Ok(subtree),
 +                Ok(Err(err)) => Err(ProcMacroExpansionError::Panic(err.0)),
 +                Err(err) => Err(ProcMacroExpansionError::System(err.to_string())),
 +            }
 +        }
 +    }
 +
 +    /// Dummy identity expander, used for proc-macros that are deliberately ignored by the user.
 +    #[derive(Debug)]
 +    struct DummyExpander;
 +
 +    impl ProcMacroExpander for DummyExpander {
 +        fn expand(
 +            &self,
 +            subtree: &tt::Subtree,
 +            _: Option<&tt::Subtree>,
 +            _: &Env,
 +        ) -> Result<tt::Subtree, ProcMacroExpansionError> {
 +            Ok(subtree.clone())
 +        }
 +    }
 +}
 +
 +pub(crate) fn should_refresh_for_change(path: &AbsPath, change_kind: ChangeKind) -> bool {
 +    const IMPLICIT_TARGET_FILES: &[&str] = &["build.rs", "src/main.rs", "src/lib.rs"];
 +    const IMPLICIT_TARGET_DIRS: &[&str] = &["src/bin", "examples", "tests", "benches"];
 +    let file_name = path.file_name().unwrap_or_default();
 +
 +    if file_name == "Cargo.toml" || file_name == "Cargo.lock" {
 +        return true;
 +    }
 +    if change_kind == ChangeKind::Modify {
 +        return false;
 +    }
 +    if path.extension().unwrap_or_default() != "rs" {
 +        if (file_name == "config.toml" || file_name == "config")
 +            && path.parent().map(|parent| parent.as_ref().ends_with(".cargo")) == Some(true)
 +        {
 +            return true;
 +        }
 +        return false;
 +    }
 +    if IMPLICIT_TARGET_FILES.iter().any(|it| path.as_ref().ends_with(it)) {
 +        return true;
 +    }
 +    let parent = match path.parent() {
 +        Some(it) => it,
 +        None => return false,
 +    };
 +    if IMPLICIT_TARGET_DIRS.iter().any(|it| parent.as_ref().ends_with(it)) {
 +        return true;
 +    }
 +    if file_name == "main.rs" {
 +        let grand_parent = match parent.parent() {
 +            Some(it) => it,
 +            None => return false,
 +        };
 +        if IMPLICIT_TARGET_DIRS.iter().any(|it| grand_parent.as_ref().ends_with(it)) {
 +            return true;
 +        }
 +    }
 +    false
 +}
index cf90ba64cff1ab5ba6e41e3e7c9246698a21fc11,0000000000000000000000000000000000000000..63309a155219e55ebec99bcfd3b416ede648df38
mode 100644,000000..100644
--- /dev/null
@@@ -1,4810 -1,0 +1,4806 @@@
-     pub fn iterable(&self) -> Option<Expr> { support::child(&self.syntax) }
 +//! Generated by `sourcegen_ast`, do not edit by hand.
 +
 +#![allow(non_snake_case)]
 +use crate::{
 +    ast::{self, support, AstChildren, AstNode},
 +    SyntaxKind::{self, *},
 +    SyntaxNode, SyntaxToken, T,
 +};
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Name {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl Name {
 +    pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
 +    pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct NameRef {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl NameRef {
 +    pub fn ident_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ident]) }
 +    pub fn self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![self]) }
 +    pub fn super_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![super]) }
 +    pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
 +    pub fn Self_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![Self]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Lifetime {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl Lifetime {
 +    pub fn lifetime_ident_token(&self) -> Option<SyntaxToken> {
 +        support::token(&self.syntax, T![lifetime_ident])
 +    }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Path {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl Path {
 +    pub fn qualifier(&self) -> Option<Path> { support::child(&self.syntax) }
 +    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
 +    pub fn segment(&self) -> Option<PathSegment> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct PathSegment {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl PathSegment {
 +    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
 +    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
 +    pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
 +    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
 +    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
 +    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
 +    pub fn path_type(&self) -> Option<PathType> { support::child(&self.syntax) }
 +    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
 +    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct GenericArgList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl GenericArgList {
 +    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
 +    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
 +    pub fn generic_args(&self) -> AstChildren<GenericArg> { support::children(&self.syntax) }
 +    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ParamList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ParamList {
 +    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
 +    pub fn self_param(&self) -> Option<SelfParam> { support::child(&self.syntax) }
 +    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
 +    pub fn params(&self) -> AstChildren<Param> { support::children(&self.syntax) }
 +    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 +    pub fn pipe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![|]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RetType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl RetType {
 +    pub fn thin_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![->]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct PathType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl PathType {
 +    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TypeArg {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl TypeArg {
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct AssocTypeArg {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasTypeBounds for AssocTypeArg {}
 +impl AssocTypeArg {
 +    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
 +    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
 +    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +    pub fn const_arg(&self) -> Option<ConstArg> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct LifetimeArg {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl LifetimeArg {
 +    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ConstArg {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ConstArg {
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct GenericParamList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl GenericParamList {
 +    pub fn l_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![<]) }
 +    pub fn generic_params(&self) -> AstChildren<GenericParam> { support::children(&self.syntax) }
 +    pub fn r_angle_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![>]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TypeBoundList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl TypeBoundList {
 +    pub fn bounds(&self) -> AstChildren<TypeBound> { support::children(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MacroCall {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for MacroCall {}
 +impl ast::HasDocComments for MacroCall {}
 +impl MacroCall {
 +    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 +    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
 +    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Attr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl Attr {
 +    pub fn pound_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![#]) }
 +    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
 +    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
 +    pub fn meta(&self) -> Option<Meta> { support::child(&self.syntax) }
 +    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TokenTree {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl TokenTree {
 +    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
 +    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 +    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
 +    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 +    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
 +    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MacroItems {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasModuleItem for MacroItems {}
 +impl MacroItems {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MacroStmts {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl MacroStmts {
 +    pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct SourceFile {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for SourceFile {}
 +impl ast::HasModuleItem for SourceFile {}
 +impl ast::HasDocComments for SourceFile {}
 +impl SourceFile {
 +    pub fn shebang_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![shebang]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Const {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Const {}
 +impl ast::HasName for Const {}
 +impl ast::HasVisibility for Const {}
 +impl ast::HasDocComments for Const {}
 +impl Const {
 +    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
 +    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
 +    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
 +    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 +    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Enum {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Enum {}
 +impl ast::HasName for Enum {}
 +impl ast::HasVisibility for Enum {}
 +impl ast::HasGenericParams for Enum {}
 +impl ast::HasDocComments for Enum {}
 +impl Enum {
 +    pub fn enum_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![enum]) }
 +    pub fn variant_list(&self) -> Option<VariantList> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ExternBlock {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for ExternBlock {}
 +impl ast::HasDocComments for ExternBlock {}
 +impl ExternBlock {
 +    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 +    pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
 +    pub fn extern_item_list(&self) -> Option<ExternItemList> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ExternCrate {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for ExternCrate {}
 +impl ast::HasVisibility for ExternCrate {}
 +impl ast::HasDocComments for ExternCrate {}
 +impl ExternCrate {
 +    pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
 +    pub fn crate_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![crate]) }
 +    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
 +    pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Fn {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Fn {}
 +impl ast::HasName for Fn {}
 +impl ast::HasVisibility for Fn {}
 +impl ast::HasGenericParams for Fn {}
 +impl ast::HasDocComments for Fn {}
 +impl Fn {
 +    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
 +    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
 +    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
 +    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 +    pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
 +    pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) }
 +    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
 +    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
 +    pub fn body(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Impl {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Impl {}
 +impl ast::HasVisibility for Impl {}
 +impl ast::HasGenericParams for Impl {}
 +impl ast::HasDocComments for Impl {}
 +impl Impl {
 +    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
 +    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 +    pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
 +    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
 +    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
 +    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
 +    pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MacroRules {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for MacroRules {}
 +impl ast::HasName for MacroRules {}
 +impl ast::HasVisibility for MacroRules {}
 +impl ast::HasDocComments for MacroRules {}
 +impl MacroRules {
 +    pub fn macro_rules_token(&self) -> Option<SyntaxToken> {
 +        support::token(&self.syntax, T![macro_rules])
 +    }
 +    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
 +    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MacroDef {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for MacroDef {}
 +impl ast::HasName for MacroDef {}
 +impl ast::HasVisibility for MacroDef {}
 +impl ast::HasDocComments for MacroDef {}
 +impl MacroDef {
 +    pub fn macro_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![macro]) }
 +    pub fn args(&self) -> Option<TokenTree> { support::child(&self.syntax) }
 +    pub fn body(&self) -> Option<TokenTree> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Module {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Module {}
 +impl ast::HasName for Module {}
 +impl ast::HasVisibility for Module {}
 +impl ast::HasDocComments for Module {}
 +impl Module {
 +    pub fn mod_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mod]) }
 +    pub fn item_list(&self) -> Option<ItemList> { support::child(&self.syntax) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Static {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Static {}
 +impl ast::HasName for Static {}
 +impl ast::HasVisibility for Static {}
 +impl ast::HasDocComments for Static {}
 +impl Static {
 +    pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
 +    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
 +    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 +    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Struct {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Struct {}
 +impl ast::HasName for Struct {}
 +impl ast::HasVisibility for Struct {}
 +impl ast::HasGenericParams for Struct {}
 +impl ast::HasDocComments for Struct {}
 +impl Struct {
 +    pub fn struct_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![struct]) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +    pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Trait {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Trait {}
 +impl ast::HasName for Trait {}
 +impl ast::HasVisibility for Trait {}
 +impl ast::HasGenericParams for Trait {}
 +impl ast::HasTypeBounds for Trait {}
 +impl ast::HasDocComments for Trait {}
 +impl Trait {
 +    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 +    pub fn auto_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![auto]) }
 +    pub fn trait_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![trait]) }
 +    pub fn assoc_item_list(&self) -> Option<AssocItemList> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TypeAlias {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for TypeAlias {}
 +impl ast::HasName for TypeAlias {}
 +impl ast::HasVisibility for TypeAlias {}
 +impl ast::HasGenericParams for TypeAlias {}
 +impl ast::HasTypeBounds for TypeAlias {}
 +impl ast::HasDocComments for TypeAlias {}
 +impl TypeAlias {
 +    pub fn default_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![default]) }
 +    pub fn type_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![type]) }
 +    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Union {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Union {}
 +impl ast::HasName for Union {}
 +impl ast::HasVisibility for Union {}
 +impl ast::HasGenericParams for Union {}
 +impl ast::HasDocComments for Union {}
 +impl Union {
 +    pub fn union_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![union]) }
 +    pub fn record_field_list(&self) -> Option<RecordFieldList> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Use {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Use {}
 +impl ast::HasVisibility for Use {}
 +impl ast::HasDocComments for Use {}
 +impl Use {
 +    pub fn use_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![use]) }
 +    pub fn use_tree(&self) -> Option<UseTree> { support::child(&self.syntax) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Visibility {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl Visibility {
 +    pub fn pub_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![pub]) }
 +    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
 +    pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
 +    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 +    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ItemList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for ItemList {}
 +impl ast::HasModuleItem for ItemList {}
 +impl ItemList {
 +    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
 +    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Rename {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasName for Rename {}
 +impl Rename {
 +    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
 +    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct UseTree {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl UseTree {
 +    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 +    pub fn coloncolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![::]) }
 +    pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
 +    pub fn use_tree_list(&self) -> Option<UseTreeList> { support::child(&self.syntax) }
 +    pub fn rename(&self) -> Option<Rename> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct UseTreeList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl UseTreeList {
 +    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
 +    pub fn use_trees(&self) -> AstChildren<UseTree> { support::children(&self.syntax) }
 +    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Abi {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl Abi {
 +    pub fn extern_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![extern]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct WhereClause {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl WhereClause {
 +    pub fn where_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![where]) }
 +    pub fn predicates(&self) -> AstChildren<WherePred> { support::children(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct BlockExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for BlockExpr {}
 +impl BlockExpr {
 +    pub fn label(&self) -> Option<Label> { support::child(&self.syntax) }
 +    pub fn try_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![try]) }
 +    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 +    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
 +    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
 +    pub fn stmt_list(&self) -> Option<StmtList> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct SelfParam {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for SelfParam {}
 +impl ast::HasName for SelfParam {}
 +impl SelfParam {
 +    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
 +    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 +    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
 +    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Param {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Param {}
 +impl Param {
 +    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 +    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +    pub fn dotdotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![...]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RecordFieldList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl RecordFieldList {
 +    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
 +    pub fn fields(&self) -> AstChildren<RecordField> { support::children(&self.syntax) }
 +    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TupleFieldList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl TupleFieldList {
 +    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
 +    pub fn fields(&self) -> AstChildren<TupleField> { support::children(&self.syntax) }
 +    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RecordField {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for RecordField {}
 +impl ast::HasName for RecordField {}
 +impl ast::HasVisibility for RecordField {}
 +impl ast::HasDocComments for RecordField {}
 +impl RecordField {
 +    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TupleField {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for TupleField {}
 +impl ast::HasVisibility for TupleField {}
 +impl ast::HasDocComments for TupleField {}
 +impl TupleField {
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct VariantList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl VariantList {
 +    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
 +    pub fn variants(&self) -> AstChildren<Variant> { support::children(&self.syntax) }
 +    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Variant {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Variant {}
 +impl ast::HasName for Variant {}
 +impl ast::HasVisibility for Variant {}
 +impl ast::HasDocComments for Variant {}
 +impl Variant {
 +    pub fn field_list(&self) -> Option<FieldList> { support::child(&self.syntax) }
 +    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct AssocItemList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for AssocItemList {}
 +impl AssocItemList {
 +    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
 +    pub fn assoc_items(&self) -> AstChildren<AssocItem> { support::children(&self.syntax) }
 +    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ExternItemList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for ExternItemList {}
 +impl ExternItemList {
 +    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
 +    pub fn extern_items(&self) -> AstChildren<ExternItem> { support::children(&self.syntax) }
 +    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ConstParam {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for ConstParam {}
 +impl ast::HasName for ConstParam {}
 +impl ConstParam {
 +    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
 +    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 +    pub fn default_val(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct LifetimeParam {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for LifetimeParam {}
 +impl ast::HasTypeBounds for LifetimeParam {}
 +impl LifetimeParam {
 +    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TypeParam {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for TypeParam {}
 +impl ast::HasName for TypeParam {}
 +impl ast::HasTypeBounds for TypeParam {}
 +impl TypeParam {
 +    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 +    pub fn default_type(&self) -> Option<Type> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct WherePred {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasTypeBounds for WherePred {}
 +impl WherePred {
 +    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
 +    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
 +    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Meta {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl Meta {
 +    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 +    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn token_tree(&self) -> Option<TokenTree> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ExprStmt {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ExprStmt {
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct LetStmt {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for LetStmt {}
 +impl LetStmt {
 +    pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
 +    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 +    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 +    pub fn initializer(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn let_else(&self) -> Option<LetElse> { support::child(&self.syntax) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct LetElse {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl LetElse {
 +    pub fn else_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![else]) }
 +    pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ArrayExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for ArrayExpr {}
 +impl ArrayExpr {
 +    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
 +    pub fn exprs(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct AwaitExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for AwaitExpr {}
 +impl AwaitExpr {
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
 +    pub fn await_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![await]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct BinExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for BinExpr {}
 +impl BinExpr {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct BoxExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for BoxExpr {}
 +impl BoxExpr {
 +    pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct BreakExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for BreakExpr {}
 +impl BreakExpr {
 +    pub fn break_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![break]) }
 +    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct CallExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for CallExpr {}
 +impl ast::HasArgList for CallExpr {}
 +impl CallExpr {
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct CastExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for CastExpr {}
 +impl CastExpr {
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn as_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![as]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ClosureExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for ClosureExpr {}
 +impl ClosureExpr {
 +    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
 +    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
 +    pub fn static_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![static]) }
 +    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
 +    pub fn move_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![move]) }
 +    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
 +    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
 +    pub fn body(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ContinueExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for ContinueExpr {}
 +impl ContinueExpr {
 +    pub fn continue_token(&self) -> Option<SyntaxToken> {
 +        support::token(&self.syntax, T![continue])
 +    }
 +    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct FieldExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for FieldExpr {}
 +impl FieldExpr {
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
 +    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ForExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for ForExpr {}
 +impl ForExpr {
 +    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
 +    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 +    pub fn in_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![in]) }
-     pub fn condition(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct IfExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for IfExpr {}
 +impl IfExpr {
 +    pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
-     pub fn condition(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn else_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![else]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct IndexExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for IndexExpr {}
 +impl IndexExpr {
 +    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
 +    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Literal {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for Literal {}
 +impl Literal {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct LoopExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for LoopExpr {}
 +impl ast::HasLoopBody for LoopExpr {}
 +impl LoopExpr {
 +    pub fn loop_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![loop]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MacroExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl MacroExpr {
 +    pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MatchExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for MatchExpr {}
 +impl MatchExpr {
 +    pub fn match_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![match]) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn match_arm_list(&self) -> Option<MatchArmList> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MethodCallExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for MethodCallExpr {}
 +impl ast::HasArgList for MethodCallExpr {}
 +impl MethodCallExpr {
 +    pub fn receiver(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn dot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![.]) }
 +    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
 +    pub fn generic_arg_list(&self) -> Option<GenericArgList> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ParenExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for ParenExpr {}
 +impl ParenExpr {
 +    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct PathExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for PathExpr {}
 +impl PathExpr {
 +    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct PrefixExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for PrefixExpr {}
 +impl PrefixExpr {
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RangeExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for RangeExpr {}
 +impl RangeExpr {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RecordExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl RecordExpr {
 +    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 +    pub fn record_expr_field_list(&self) -> Option<RecordExprFieldList> {
 +        support::child(&self.syntax)
 +    }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RefExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for RefExpr {}
 +impl RefExpr {
 +    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
 +    pub fn raw_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![raw]) }
 +    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
 +    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ReturnExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for ReturnExpr {}
 +impl ReturnExpr {
 +    pub fn return_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![return]) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TryExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for TryExpr {}
 +impl TryExpr {
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TupleExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for TupleExpr {}
 +impl TupleExpr {
 +    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
 +    pub fn fields(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
 +    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct WhileExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for WhileExpr {}
 +impl WhileExpr {
 +    pub fn while_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![while]) }
-     pub fn condition(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct YieldExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for YieldExpr {}
 +impl YieldExpr {
 +    pub fn yield_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![yield]) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct LetExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for LetExpr {}
 +impl LetExpr {
 +    pub fn let_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![let]) }
 +    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 +    pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct UnderscoreExpr {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for UnderscoreExpr {}
 +impl UnderscoreExpr {
 +    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct StmtList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for StmtList {}
 +impl StmtList {
 +    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
 +    pub fn statements(&self) -> AstChildren<Stmt> { support::children(&self.syntax) }
 +    pub fn tail_expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct Label {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl Label {
 +    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 +    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RecordExprFieldList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for RecordExprFieldList {}
 +impl RecordExprFieldList {
 +    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
 +    pub fn fields(&self) -> AstChildren<RecordExprField> { support::children(&self.syntax) }
 +    pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
 +    pub fn spread(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RecordExprField {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for RecordExprField {}
 +impl RecordExprField {
 +    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
 +    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ArgList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ArgList {
 +    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
 +    pub fn args(&self) -> AstChildren<Expr> { support::children(&self.syntax) }
 +    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MatchArmList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for MatchArmList {}
 +impl MatchArmList {
 +    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
 +    pub fn arms(&self) -> AstChildren<MatchArm> { support::children(&self.syntax) }
 +    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MatchArm {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for MatchArm {}
 +impl MatchArm {
 +    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 +    pub fn guard(&self) -> Option<MatchGuard> { support::child(&self.syntax) }
 +    pub fn fat_arrow_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=>]) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn comma_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![,]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MatchGuard {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl MatchGuard {
 +    pub fn if_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![if]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ArrayType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ArrayType {
 +    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +    pub fn semicolon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![;]) }
 +    pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
 +    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct DynTraitType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl DynTraitType {
 +    pub fn dyn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![dyn]) }
 +    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct FnPtrType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl FnPtrType {
 +    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
 +    pub fn async_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![async]) }
 +    pub fn unsafe_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![unsafe]) }
 +    pub fn abi(&self) -> Option<Abi> { support::child(&self.syntax) }
 +    pub fn fn_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![fn]) }
 +    pub fn param_list(&self) -> Option<ParamList> { support::child(&self.syntax) }
 +    pub fn ret_type(&self) -> Option<RetType> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ForType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ForType {
 +    pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
 +    pub fn generic_param_list(&self) -> Option<GenericParamList> { support::child(&self.syntax) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ImplTraitType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ImplTraitType {
 +    pub fn impl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![impl]) }
 +    pub fn type_bound_list(&self) -> Option<TypeBoundList> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct InferType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl InferType {
 +    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MacroType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl MacroType {
 +    pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct NeverType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl NeverType {
 +    pub fn excl_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![!]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ParenType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ParenType {
 +    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct PtrType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl PtrType {
 +    pub fn star_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![*]) }
 +    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
 +    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RefType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl RefType {
 +    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
 +    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 +    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct SliceType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl SliceType {
 +    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TupleType {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl TupleType {
 +    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
 +    pub fn fields(&self) -> AstChildren<Type> { support::children(&self.syntax) }
 +    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TypeBound {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl TypeBound {
 +    pub fn lifetime(&self) -> Option<Lifetime> { support::child(&self.syntax) }
 +    pub fn question_mark_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![?]) }
 +    pub fn tilde_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![~]) }
 +    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
 +    pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct IdentPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for IdentPat {}
 +impl ast::HasName for IdentPat {}
 +impl IdentPat {
 +    pub fn ref_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![ref]) }
 +    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
 +    pub fn at_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![@]) }
 +    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct BoxPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl BoxPat {
 +    pub fn box_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![box]) }
 +    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RestPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for RestPat {}
 +impl RestPat {
 +    pub fn dotdot_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![..]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct LiteralPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl LiteralPat {
 +    pub fn literal(&self) -> Option<Literal> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct MacroPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl MacroPat {
 +    pub fn macro_call(&self) -> Option<MacroCall> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct OrPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl OrPat {
 +    pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ParenPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ParenPat {
 +    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
 +    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 +    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct PathPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl PathPat {
 +    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct WildcardPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl WildcardPat {
 +    pub fn underscore_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![_]) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RangePat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl RangePat {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RecordPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl RecordPat {
 +    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 +    pub fn record_pat_field_list(&self) -> Option<RecordPatFieldList> {
 +        support::child(&self.syntax)
 +    }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RefPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl RefPat {
 +    pub fn amp_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![&]) }
 +    pub fn mut_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![mut]) }
 +    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct SlicePat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl SlicePat {
 +    pub fn l_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['[']) }
 +    pub fn pats(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
 +    pub fn r_brack_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![']']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TuplePat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl TuplePat {
 +    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
 +    pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
 +    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct TupleStructPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl TupleStructPat {
 +    pub fn path(&self) -> Option<Path> { support::child(&self.syntax) }
 +    pub fn l_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['(']) }
 +    pub fn fields(&self) -> AstChildren<Pat> { support::children(&self.syntax) }
 +    pub fn r_paren_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![')']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct ConstBlockPat {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ConstBlockPat {
 +    pub fn const_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![const]) }
 +    pub fn block_expr(&self) -> Option<BlockExpr> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RecordPatFieldList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl RecordPatFieldList {
 +    pub fn l_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['{']) }
 +    pub fn fields(&self) -> AstChildren<RecordPatField> { support::children(&self.syntax) }
 +    pub fn rest_pat(&self) -> Option<RestPat> { support::child(&self.syntax) }
 +    pub fn r_curly_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T!['}']) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct RecordPatField {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for RecordPatField {}
 +impl RecordPatField {
 +    pub fn name_ref(&self) -> Option<NameRef> { support::child(&self.syntax) }
 +    pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
 +    pub fn pat(&self) -> Option<Pat> { support::child(&self.syntax) }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub enum GenericArg {
 +    TypeArg(TypeArg),
 +    AssocTypeArg(AssocTypeArg),
 +    LifetimeArg(LifetimeArg),
 +    ConstArg(ConstArg),
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub enum Type {
 +    ArrayType(ArrayType),
 +    DynTraitType(DynTraitType),
 +    FnPtrType(FnPtrType),
 +    ForType(ForType),
 +    ImplTraitType(ImplTraitType),
 +    InferType(InferType),
 +    MacroType(MacroType),
 +    NeverType(NeverType),
 +    ParenType(ParenType),
 +    PathType(PathType),
 +    PtrType(PtrType),
 +    RefType(RefType),
 +    SliceType(SliceType),
 +    TupleType(TupleType),
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub enum Expr {
 +    ArrayExpr(ArrayExpr),
 +    AwaitExpr(AwaitExpr),
 +    BinExpr(BinExpr),
 +    BlockExpr(BlockExpr),
 +    BoxExpr(BoxExpr),
 +    BreakExpr(BreakExpr),
 +    CallExpr(CallExpr),
 +    CastExpr(CastExpr),
 +    ClosureExpr(ClosureExpr),
 +    ContinueExpr(ContinueExpr),
 +    FieldExpr(FieldExpr),
 +    ForExpr(ForExpr),
 +    IfExpr(IfExpr),
 +    IndexExpr(IndexExpr),
 +    Literal(Literal),
 +    LoopExpr(LoopExpr),
 +    MacroExpr(MacroExpr),
 +    MacroStmts(MacroStmts),
 +    MatchExpr(MatchExpr),
 +    MethodCallExpr(MethodCallExpr),
 +    ParenExpr(ParenExpr),
 +    PathExpr(PathExpr),
 +    PrefixExpr(PrefixExpr),
 +    RangeExpr(RangeExpr),
 +    RecordExpr(RecordExpr),
 +    RefExpr(RefExpr),
 +    ReturnExpr(ReturnExpr),
 +    TryExpr(TryExpr),
 +    TupleExpr(TupleExpr),
 +    WhileExpr(WhileExpr),
 +    YieldExpr(YieldExpr),
 +    LetExpr(LetExpr),
 +    UnderscoreExpr(UnderscoreExpr),
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub enum Item {
 +    Const(Const),
 +    Enum(Enum),
 +    ExternBlock(ExternBlock),
 +    ExternCrate(ExternCrate),
 +    Fn(Fn),
 +    Impl(Impl),
 +    MacroCall(MacroCall),
 +    MacroRules(MacroRules),
 +    MacroDef(MacroDef),
 +    Module(Module),
 +    Static(Static),
 +    Struct(Struct),
 +    Trait(Trait),
 +    TypeAlias(TypeAlias),
 +    Union(Union),
 +    Use(Use),
 +}
 +impl ast::HasAttrs for Item {}
 +impl ast::HasDocComments for Item {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub enum Stmt {
 +    ExprStmt(ExprStmt),
 +    Item(Item),
 +    LetStmt(LetStmt),
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub enum Pat {
 +    IdentPat(IdentPat),
 +    BoxPat(BoxPat),
 +    RestPat(RestPat),
 +    LiteralPat(LiteralPat),
 +    MacroPat(MacroPat),
 +    OrPat(OrPat),
 +    ParenPat(ParenPat),
 +    PathPat(PathPat),
 +    WildcardPat(WildcardPat),
 +    RangePat(RangePat),
 +    RecordPat(RecordPat),
 +    RefPat(RefPat),
 +    SlicePat(SlicePat),
 +    TuplePat(TuplePat),
 +    TupleStructPat(TupleStructPat),
 +    ConstBlockPat(ConstBlockPat),
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub enum FieldList {
 +    RecordFieldList(RecordFieldList),
 +    TupleFieldList(TupleFieldList),
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub enum Adt {
 +    Enum(Enum),
 +    Struct(Struct),
 +    Union(Union),
 +}
 +impl ast::HasAttrs for Adt {}
 +impl ast::HasDocComments for Adt {}
 +impl ast::HasGenericParams for Adt {}
 +impl ast::HasName for Adt {}
 +impl ast::HasVisibility for Adt {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub enum AssocItem {
 +    Const(Const),
 +    Fn(Fn),
 +    MacroCall(MacroCall),
 +    TypeAlias(TypeAlias),
 +}
 +impl ast::HasAttrs for AssocItem {}
 +impl ast::HasDocComments for AssocItem {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub enum ExternItem {
 +    Fn(Fn),
 +    MacroCall(MacroCall),
 +    Static(Static),
 +    TypeAlias(TypeAlias),
 +}
 +impl ast::HasAttrs for ExternItem {}
 +impl ast::HasDocComments for ExternItem {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub enum GenericParam {
 +    ConstParam(ConstParam),
 +    LifetimeParam(LifetimeParam),
 +    TypeParam(TypeParam),
 +}
 +impl ast::HasAttrs for GenericParam {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct AnyHasArgList {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasArgList for AnyHasArgList {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct AnyHasAttrs {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasAttrs for AnyHasAttrs {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct AnyHasDocComments {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasDocComments for AnyHasDocComments {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct AnyHasGenericParams {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasGenericParams for AnyHasGenericParams {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct AnyHasLoopBody {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasLoopBody for AnyHasLoopBody {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct AnyHasModuleItem {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasModuleItem for AnyHasModuleItem {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct AnyHasName {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasName for AnyHasName {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct AnyHasTypeBounds {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasTypeBounds for AnyHasTypeBounds {}
 +
 +#[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +pub struct AnyHasVisibility {
 +    pub(crate) syntax: SyntaxNode,
 +}
 +impl ast::HasVisibility for AnyHasVisibility {}
 +impl AstNode for Name {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == NAME }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for NameRef {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == NAME_REF }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Lifetime {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Path {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for PathSegment {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_SEGMENT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for GenericArgList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_ARG_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ParamList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RetType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RET_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for PathType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TypeArg {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ARG }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for AssocTypeArg {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_TYPE_ARG }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for LifetimeArg {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_ARG }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ConstArg {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_ARG }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for GenericParamList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == GENERIC_PARAM_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TypeBoundList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MacroCall {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_CALL }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Attr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == ATTR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TokenTree {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TOKEN_TREE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MacroItems {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_ITEMS }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MacroStmts {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_STMTS }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for SourceFile {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == SOURCE_FILE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Const {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Enum {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == ENUM }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ExternBlock {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_BLOCK }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ExternCrate {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_CRATE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Fn {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == FN }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Impl {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MacroRules {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_RULES }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MacroDef {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_DEF }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Module {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MODULE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Static {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == STATIC }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Struct {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == STRUCT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Trait {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TRAIT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TypeAlias {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_ALIAS }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Union {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == UNION }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Use {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == USE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Visibility {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == VISIBILITY }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ItemList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == ITEM_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Rename {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RENAME }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for UseTree {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for UseTreeList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == USE_TREE_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Abi {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == ABI }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for WhereClause {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_CLAUSE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for BlockExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == BLOCK_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for SelfParam {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == SELF_PARAM }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Param {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == PARAM }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RecordFieldList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TupleFieldList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RecordField {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_FIELD }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TupleField {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_FIELD }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for VariantList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Variant {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == VARIANT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for AssocItemList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == ASSOC_ITEM_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ExternItemList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == EXTERN_ITEM_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ConstParam {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_PARAM }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for LifetimeParam {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == LIFETIME_PARAM }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TypeParam {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_PARAM }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for WherePred {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == WHERE_PRED }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Meta {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == META }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ExprStmt {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == EXPR_STMT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for LetStmt {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == LET_STMT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for LetElse {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == LET_ELSE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ArrayExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for AwaitExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == AWAIT_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for BinExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == BIN_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for BoxExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for BreakExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == BREAK_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for CallExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == CALL_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for CastExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == CAST_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ClosureExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == CLOSURE_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ContinueExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == CONTINUE_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for FieldExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == FIELD_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ForExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for IfExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == IF_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for IndexExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == INDEX_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Literal {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for LoopExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == LOOP_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MacroExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MatchExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MethodCallExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == METHOD_CALL_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ParenExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for PathExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for PrefixExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == PREFIX_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RangeExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RecordExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RefExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == REF_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ReturnExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RETURN_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TryExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TRY_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TupleExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for WhileExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == WHILE_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for YieldExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == YIELD_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for LetExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == LET_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for UnderscoreExpr {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == UNDERSCORE_EXPR }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for StmtList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == STMT_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for Label {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == LABEL }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RecordExprFieldList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RecordExprField {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_EXPR_FIELD }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ArgList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == ARG_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MatchArmList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MatchArm {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_ARM }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MatchGuard {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MATCH_GUARD }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ArrayType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == ARRAY_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for DynTraitType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == DYN_TRAIT_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for FnPtrType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == FN_PTR_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ForType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == FOR_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ImplTraitType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == IMPL_TRAIT_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for InferType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == INFER_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MacroType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for NeverType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == NEVER_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ParenType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for PtrType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == PTR_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RefType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == REF_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for SliceType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TupleType {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_TYPE }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TypeBound {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TYPE_BOUND }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for IdentPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == IDENT_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for BoxPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == BOX_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RestPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == REST_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for LiteralPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == LITERAL_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for MacroPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == MACRO_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for OrPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == OR_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ParenPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == PAREN_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for PathPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == PATH_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for WildcardPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == WILDCARD_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RangePat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RANGE_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RecordPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RefPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == REF_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for SlicePat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == SLICE_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TuplePat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for TupleStructPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == TUPLE_STRUCT_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for ConstBlockPat {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == CONST_BLOCK_PAT }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RecordPatFieldList {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD_LIST }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AstNode for RecordPatField {
 +    fn can_cast(kind: SyntaxKind) -> bool { kind == RECORD_PAT_FIELD }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        if Self::can_cast(syntax.kind()) {
 +            Some(Self { syntax })
 +        } else {
 +            None
 +        }
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl From<TypeArg> for GenericArg {
 +    fn from(node: TypeArg) -> GenericArg { GenericArg::TypeArg(node) }
 +}
 +impl From<AssocTypeArg> for GenericArg {
 +    fn from(node: AssocTypeArg) -> GenericArg { GenericArg::AssocTypeArg(node) }
 +}
 +impl From<LifetimeArg> for GenericArg {
 +    fn from(node: LifetimeArg) -> GenericArg { GenericArg::LifetimeArg(node) }
 +}
 +impl From<ConstArg> for GenericArg {
 +    fn from(node: ConstArg) -> GenericArg { GenericArg::ConstArg(node) }
 +}
 +impl AstNode for GenericArg {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            TYPE_ARG | ASSOC_TYPE_ARG | LIFETIME_ARG | CONST_ARG => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        let res = match syntax.kind() {
 +            TYPE_ARG => GenericArg::TypeArg(TypeArg { syntax }),
 +            ASSOC_TYPE_ARG => GenericArg::AssocTypeArg(AssocTypeArg { syntax }),
 +            LIFETIME_ARG => GenericArg::LifetimeArg(LifetimeArg { syntax }),
 +            CONST_ARG => GenericArg::ConstArg(ConstArg { syntax }),
 +            _ => return None,
 +        };
 +        Some(res)
 +    }
 +    fn syntax(&self) -> &SyntaxNode {
 +        match self {
 +            GenericArg::TypeArg(it) => &it.syntax,
 +            GenericArg::AssocTypeArg(it) => &it.syntax,
 +            GenericArg::LifetimeArg(it) => &it.syntax,
 +            GenericArg::ConstArg(it) => &it.syntax,
 +        }
 +    }
 +}
 +impl From<ArrayType> for Type {
 +    fn from(node: ArrayType) -> Type { Type::ArrayType(node) }
 +}
 +impl From<DynTraitType> for Type {
 +    fn from(node: DynTraitType) -> Type { Type::DynTraitType(node) }
 +}
 +impl From<FnPtrType> for Type {
 +    fn from(node: FnPtrType) -> Type { Type::FnPtrType(node) }
 +}
 +impl From<ForType> for Type {
 +    fn from(node: ForType) -> Type { Type::ForType(node) }
 +}
 +impl From<ImplTraitType> for Type {
 +    fn from(node: ImplTraitType) -> Type { Type::ImplTraitType(node) }
 +}
 +impl From<InferType> for Type {
 +    fn from(node: InferType) -> Type { Type::InferType(node) }
 +}
 +impl From<MacroType> for Type {
 +    fn from(node: MacroType) -> Type { Type::MacroType(node) }
 +}
 +impl From<NeverType> for Type {
 +    fn from(node: NeverType) -> Type { Type::NeverType(node) }
 +}
 +impl From<ParenType> for Type {
 +    fn from(node: ParenType) -> Type { Type::ParenType(node) }
 +}
 +impl From<PathType> for Type {
 +    fn from(node: PathType) -> Type { Type::PathType(node) }
 +}
 +impl From<PtrType> for Type {
 +    fn from(node: PtrType) -> Type { Type::PtrType(node) }
 +}
 +impl From<RefType> for Type {
 +    fn from(node: RefType) -> Type { Type::RefType(node) }
 +}
 +impl From<SliceType> for Type {
 +    fn from(node: SliceType) -> Type { Type::SliceType(node) }
 +}
 +impl From<TupleType> for Type {
 +    fn from(node: TupleType) -> Type { Type::TupleType(node) }
 +}
 +impl AstNode for Type {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            ARRAY_TYPE | DYN_TRAIT_TYPE | FN_PTR_TYPE | FOR_TYPE | IMPL_TRAIT_TYPE | INFER_TYPE
 +            | MACRO_TYPE | NEVER_TYPE | PAREN_TYPE | PATH_TYPE | PTR_TYPE | REF_TYPE
 +            | SLICE_TYPE | TUPLE_TYPE => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        let res = match syntax.kind() {
 +            ARRAY_TYPE => Type::ArrayType(ArrayType { syntax }),
 +            DYN_TRAIT_TYPE => Type::DynTraitType(DynTraitType { syntax }),
 +            FN_PTR_TYPE => Type::FnPtrType(FnPtrType { syntax }),
 +            FOR_TYPE => Type::ForType(ForType { syntax }),
 +            IMPL_TRAIT_TYPE => Type::ImplTraitType(ImplTraitType { syntax }),
 +            INFER_TYPE => Type::InferType(InferType { syntax }),
 +            MACRO_TYPE => Type::MacroType(MacroType { syntax }),
 +            NEVER_TYPE => Type::NeverType(NeverType { syntax }),
 +            PAREN_TYPE => Type::ParenType(ParenType { syntax }),
 +            PATH_TYPE => Type::PathType(PathType { syntax }),
 +            PTR_TYPE => Type::PtrType(PtrType { syntax }),
 +            REF_TYPE => Type::RefType(RefType { syntax }),
 +            SLICE_TYPE => Type::SliceType(SliceType { syntax }),
 +            TUPLE_TYPE => Type::TupleType(TupleType { syntax }),
 +            _ => return None,
 +        };
 +        Some(res)
 +    }
 +    fn syntax(&self) -> &SyntaxNode {
 +        match self {
 +            Type::ArrayType(it) => &it.syntax,
 +            Type::DynTraitType(it) => &it.syntax,
 +            Type::FnPtrType(it) => &it.syntax,
 +            Type::ForType(it) => &it.syntax,
 +            Type::ImplTraitType(it) => &it.syntax,
 +            Type::InferType(it) => &it.syntax,
 +            Type::MacroType(it) => &it.syntax,
 +            Type::NeverType(it) => &it.syntax,
 +            Type::ParenType(it) => &it.syntax,
 +            Type::PathType(it) => &it.syntax,
 +            Type::PtrType(it) => &it.syntax,
 +            Type::RefType(it) => &it.syntax,
 +            Type::SliceType(it) => &it.syntax,
 +            Type::TupleType(it) => &it.syntax,
 +        }
 +    }
 +}
 +impl From<ArrayExpr> for Expr {
 +    fn from(node: ArrayExpr) -> Expr { Expr::ArrayExpr(node) }
 +}
 +impl From<AwaitExpr> for Expr {
 +    fn from(node: AwaitExpr) -> Expr { Expr::AwaitExpr(node) }
 +}
 +impl From<BinExpr> for Expr {
 +    fn from(node: BinExpr) -> Expr { Expr::BinExpr(node) }
 +}
 +impl From<BlockExpr> for Expr {
 +    fn from(node: BlockExpr) -> Expr { Expr::BlockExpr(node) }
 +}
 +impl From<BoxExpr> for Expr {
 +    fn from(node: BoxExpr) -> Expr { Expr::BoxExpr(node) }
 +}
 +impl From<BreakExpr> for Expr {
 +    fn from(node: BreakExpr) -> Expr { Expr::BreakExpr(node) }
 +}
 +impl From<CallExpr> for Expr {
 +    fn from(node: CallExpr) -> Expr { Expr::CallExpr(node) }
 +}
 +impl From<CastExpr> for Expr {
 +    fn from(node: CastExpr) -> Expr { Expr::CastExpr(node) }
 +}
 +impl From<ClosureExpr> for Expr {
 +    fn from(node: ClosureExpr) -> Expr { Expr::ClosureExpr(node) }
 +}
 +impl From<ContinueExpr> for Expr {
 +    fn from(node: ContinueExpr) -> Expr { Expr::ContinueExpr(node) }
 +}
 +impl From<FieldExpr> for Expr {
 +    fn from(node: FieldExpr) -> Expr { Expr::FieldExpr(node) }
 +}
 +impl From<ForExpr> for Expr {
 +    fn from(node: ForExpr) -> Expr { Expr::ForExpr(node) }
 +}
 +impl From<IfExpr> for Expr {
 +    fn from(node: IfExpr) -> Expr { Expr::IfExpr(node) }
 +}
 +impl From<IndexExpr> for Expr {
 +    fn from(node: IndexExpr) -> Expr { Expr::IndexExpr(node) }
 +}
 +impl From<Literal> for Expr {
 +    fn from(node: Literal) -> Expr { Expr::Literal(node) }
 +}
 +impl From<LoopExpr> for Expr {
 +    fn from(node: LoopExpr) -> Expr { Expr::LoopExpr(node) }
 +}
 +impl From<MacroExpr> for Expr {
 +    fn from(node: MacroExpr) -> Expr { Expr::MacroExpr(node) }
 +}
 +impl From<MacroStmts> for Expr {
 +    fn from(node: MacroStmts) -> Expr { Expr::MacroStmts(node) }
 +}
 +impl From<MatchExpr> for Expr {
 +    fn from(node: MatchExpr) -> Expr { Expr::MatchExpr(node) }
 +}
 +impl From<MethodCallExpr> for Expr {
 +    fn from(node: MethodCallExpr) -> Expr { Expr::MethodCallExpr(node) }
 +}
 +impl From<ParenExpr> for Expr {
 +    fn from(node: ParenExpr) -> Expr { Expr::ParenExpr(node) }
 +}
 +impl From<PathExpr> for Expr {
 +    fn from(node: PathExpr) -> Expr { Expr::PathExpr(node) }
 +}
 +impl From<PrefixExpr> for Expr {
 +    fn from(node: PrefixExpr) -> Expr { Expr::PrefixExpr(node) }
 +}
 +impl From<RangeExpr> for Expr {
 +    fn from(node: RangeExpr) -> Expr { Expr::RangeExpr(node) }
 +}
 +impl From<RecordExpr> for Expr {
 +    fn from(node: RecordExpr) -> Expr { Expr::RecordExpr(node) }
 +}
 +impl From<RefExpr> for Expr {
 +    fn from(node: RefExpr) -> Expr { Expr::RefExpr(node) }
 +}
 +impl From<ReturnExpr> for Expr {
 +    fn from(node: ReturnExpr) -> Expr { Expr::ReturnExpr(node) }
 +}
 +impl From<TryExpr> for Expr {
 +    fn from(node: TryExpr) -> Expr { Expr::TryExpr(node) }
 +}
 +impl From<TupleExpr> for Expr {
 +    fn from(node: TupleExpr) -> Expr { Expr::TupleExpr(node) }
 +}
 +impl From<WhileExpr> for Expr {
 +    fn from(node: WhileExpr) -> Expr { Expr::WhileExpr(node) }
 +}
 +impl From<YieldExpr> for Expr {
 +    fn from(node: YieldExpr) -> Expr { Expr::YieldExpr(node) }
 +}
 +impl From<LetExpr> for Expr {
 +    fn from(node: LetExpr) -> Expr { Expr::LetExpr(node) }
 +}
 +impl From<UnderscoreExpr> for Expr {
 +    fn from(node: UnderscoreExpr) -> Expr { Expr::UnderscoreExpr(node) }
 +}
 +impl AstNode for Expr {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            ARRAY_EXPR | AWAIT_EXPR | BIN_EXPR | BLOCK_EXPR | BOX_EXPR | BREAK_EXPR | CALL_EXPR
 +            | CAST_EXPR | CLOSURE_EXPR | CONTINUE_EXPR | FIELD_EXPR | FOR_EXPR | IF_EXPR
 +            | INDEX_EXPR | LITERAL | LOOP_EXPR | MACRO_EXPR | MACRO_STMTS | MATCH_EXPR
 +            | METHOD_CALL_EXPR | PAREN_EXPR | PATH_EXPR | PREFIX_EXPR | RANGE_EXPR
 +            | RECORD_EXPR | REF_EXPR | RETURN_EXPR | TRY_EXPR | TUPLE_EXPR | WHILE_EXPR
 +            | YIELD_EXPR | LET_EXPR | UNDERSCORE_EXPR => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        let res = match syntax.kind() {
 +            ARRAY_EXPR => Expr::ArrayExpr(ArrayExpr { syntax }),
 +            AWAIT_EXPR => Expr::AwaitExpr(AwaitExpr { syntax }),
 +            BIN_EXPR => Expr::BinExpr(BinExpr { syntax }),
 +            BLOCK_EXPR => Expr::BlockExpr(BlockExpr { syntax }),
 +            BOX_EXPR => Expr::BoxExpr(BoxExpr { syntax }),
 +            BREAK_EXPR => Expr::BreakExpr(BreakExpr { syntax }),
 +            CALL_EXPR => Expr::CallExpr(CallExpr { syntax }),
 +            CAST_EXPR => Expr::CastExpr(CastExpr { syntax }),
 +            CLOSURE_EXPR => Expr::ClosureExpr(ClosureExpr { syntax }),
 +            CONTINUE_EXPR => Expr::ContinueExpr(ContinueExpr { syntax }),
 +            FIELD_EXPR => Expr::FieldExpr(FieldExpr { syntax }),
 +            FOR_EXPR => Expr::ForExpr(ForExpr { syntax }),
 +            IF_EXPR => Expr::IfExpr(IfExpr { syntax }),
 +            INDEX_EXPR => Expr::IndexExpr(IndexExpr { syntax }),
 +            LITERAL => Expr::Literal(Literal { syntax }),
 +            LOOP_EXPR => Expr::LoopExpr(LoopExpr { syntax }),
 +            MACRO_EXPR => Expr::MacroExpr(MacroExpr { syntax }),
 +            MACRO_STMTS => Expr::MacroStmts(MacroStmts { syntax }),
 +            MATCH_EXPR => Expr::MatchExpr(MatchExpr { syntax }),
 +            METHOD_CALL_EXPR => Expr::MethodCallExpr(MethodCallExpr { syntax }),
 +            PAREN_EXPR => Expr::ParenExpr(ParenExpr { syntax }),
 +            PATH_EXPR => Expr::PathExpr(PathExpr { syntax }),
 +            PREFIX_EXPR => Expr::PrefixExpr(PrefixExpr { syntax }),
 +            RANGE_EXPR => Expr::RangeExpr(RangeExpr { syntax }),
 +            RECORD_EXPR => Expr::RecordExpr(RecordExpr { syntax }),
 +            REF_EXPR => Expr::RefExpr(RefExpr { syntax }),
 +            RETURN_EXPR => Expr::ReturnExpr(ReturnExpr { syntax }),
 +            TRY_EXPR => Expr::TryExpr(TryExpr { syntax }),
 +            TUPLE_EXPR => Expr::TupleExpr(TupleExpr { syntax }),
 +            WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }),
 +            YIELD_EXPR => Expr::YieldExpr(YieldExpr { syntax }),
 +            LET_EXPR => Expr::LetExpr(LetExpr { syntax }),
 +            UNDERSCORE_EXPR => Expr::UnderscoreExpr(UnderscoreExpr { syntax }),
 +            _ => return None,
 +        };
 +        Some(res)
 +    }
 +    fn syntax(&self) -> &SyntaxNode {
 +        match self {
 +            Expr::ArrayExpr(it) => &it.syntax,
 +            Expr::AwaitExpr(it) => &it.syntax,
 +            Expr::BinExpr(it) => &it.syntax,
 +            Expr::BlockExpr(it) => &it.syntax,
 +            Expr::BoxExpr(it) => &it.syntax,
 +            Expr::BreakExpr(it) => &it.syntax,
 +            Expr::CallExpr(it) => &it.syntax,
 +            Expr::CastExpr(it) => &it.syntax,
 +            Expr::ClosureExpr(it) => &it.syntax,
 +            Expr::ContinueExpr(it) => &it.syntax,
 +            Expr::FieldExpr(it) => &it.syntax,
 +            Expr::ForExpr(it) => &it.syntax,
 +            Expr::IfExpr(it) => &it.syntax,
 +            Expr::IndexExpr(it) => &it.syntax,
 +            Expr::Literal(it) => &it.syntax,
 +            Expr::LoopExpr(it) => &it.syntax,
 +            Expr::MacroExpr(it) => &it.syntax,
 +            Expr::MacroStmts(it) => &it.syntax,
 +            Expr::MatchExpr(it) => &it.syntax,
 +            Expr::MethodCallExpr(it) => &it.syntax,
 +            Expr::ParenExpr(it) => &it.syntax,
 +            Expr::PathExpr(it) => &it.syntax,
 +            Expr::PrefixExpr(it) => &it.syntax,
 +            Expr::RangeExpr(it) => &it.syntax,
 +            Expr::RecordExpr(it) => &it.syntax,
 +            Expr::RefExpr(it) => &it.syntax,
 +            Expr::ReturnExpr(it) => &it.syntax,
 +            Expr::TryExpr(it) => &it.syntax,
 +            Expr::TupleExpr(it) => &it.syntax,
 +            Expr::WhileExpr(it) => &it.syntax,
 +            Expr::YieldExpr(it) => &it.syntax,
 +            Expr::LetExpr(it) => &it.syntax,
 +            Expr::UnderscoreExpr(it) => &it.syntax,
 +        }
 +    }
 +}
 +impl From<Const> for Item {
 +    fn from(node: Const) -> Item { Item::Const(node) }
 +}
 +impl From<Enum> for Item {
 +    fn from(node: Enum) -> Item { Item::Enum(node) }
 +}
 +impl From<ExternBlock> for Item {
 +    fn from(node: ExternBlock) -> Item { Item::ExternBlock(node) }
 +}
 +impl From<ExternCrate> for Item {
 +    fn from(node: ExternCrate) -> Item { Item::ExternCrate(node) }
 +}
 +impl From<Fn> for Item {
 +    fn from(node: Fn) -> Item { Item::Fn(node) }
 +}
 +impl From<Impl> for Item {
 +    fn from(node: Impl) -> Item { Item::Impl(node) }
 +}
 +impl From<MacroCall> for Item {
 +    fn from(node: MacroCall) -> Item { Item::MacroCall(node) }
 +}
 +impl From<MacroRules> for Item {
 +    fn from(node: MacroRules) -> Item { Item::MacroRules(node) }
 +}
 +impl From<MacroDef> for Item {
 +    fn from(node: MacroDef) -> Item { Item::MacroDef(node) }
 +}
 +impl From<Module> for Item {
 +    fn from(node: Module) -> Item { Item::Module(node) }
 +}
 +impl From<Static> for Item {
 +    fn from(node: Static) -> Item { Item::Static(node) }
 +}
 +impl From<Struct> for Item {
 +    fn from(node: Struct) -> Item { Item::Struct(node) }
 +}
 +impl From<Trait> for Item {
 +    fn from(node: Trait) -> Item { Item::Trait(node) }
 +}
 +impl From<TypeAlias> for Item {
 +    fn from(node: TypeAlias) -> Item { Item::TypeAlias(node) }
 +}
 +impl From<Union> for Item {
 +    fn from(node: Union) -> Item { Item::Union(node) }
 +}
 +impl From<Use> for Item {
 +    fn from(node: Use) -> Item { Item::Use(node) }
 +}
 +impl AstNode for Item {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL | MACRO_CALL | MACRO_RULES
 +            | MACRO_DEF | MODULE | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        let res = match syntax.kind() {
 +            CONST => Item::Const(Const { syntax }),
 +            ENUM => Item::Enum(Enum { syntax }),
 +            EXTERN_BLOCK => Item::ExternBlock(ExternBlock { syntax }),
 +            EXTERN_CRATE => Item::ExternCrate(ExternCrate { syntax }),
 +            FN => Item::Fn(Fn { syntax }),
 +            IMPL => Item::Impl(Impl { syntax }),
 +            MACRO_CALL => Item::MacroCall(MacroCall { syntax }),
 +            MACRO_RULES => Item::MacroRules(MacroRules { syntax }),
 +            MACRO_DEF => Item::MacroDef(MacroDef { syntax }),
 +            MODULE => Item::Module(Module { syntax }),
 +            STATIC => Item::Static(Static { syntax }),
 +            STRUCT => Item::Struct(Struct { syntax }),
 +            TRAIT => Item::Trait(Trait { syntax }),
 +            TYPE_ALIAS => Item::TypeAlias(TypeAlias { syntax }),
 +            UNION => Item::Union(Union { syntax }),
 +            USE => Item::Use(Use { syntax }),
 +            _ => return None,
 +        };
 +        Some(res)
 +    }
 +    fn syntax(&self) -> &SyntaxNode {
 +        match self {
 +            Item::Const(it) => &it.syntax,
 +            Item::Enum(it) => &it.syntax,
 +            Item::ExternBlock(it) => &it.syntax,
 +            Item::ExternCrate(it) => &it.syntax,
 +            Item::Fn(it) => &it.syntax,
 +            Item::Impl(it) => &it.syntax,
 +            Item::MacroCall(it) => &it.syntax,
 +            Item::MacroRules(it) => &it.syntax,
 +            Item::MacroDef(it) => &it.syntax,
 +            Item::Module(it) => &it.syntax,
 +            Item::Static(it) => &it.syntax,
 +            Item::Struct(it) => &it.syntax,
 +            Item::Trait(it) => &it.syntax,
 +            Item::TypeAlias(it) => &it.syntax,
 +            Item::Union(it) => &it.syntax,
 +            Item::Use(it) => &it.syntax,
 +        }
 +    }
 +}
 +impl From<ExprStmt> for Stmt {
 +    fn from(node: ExprStmt) -> Stmt { Stmt::ExprStmt(node) }
 +}
 +impl From<Item> for Stmt {
 +    fn from(node: Item) -> Stmt { Stmt::Item(node) }
 +}
 +impl From<LetStmt> for Stmt {
 +    fn from(node: LetStmt) -> Stmt { Stmt::LetStmt(node) }
 +}
 +impl From<IdentPat> for Pat {
 +    fn from(node: IdentPat) -> Pat { Pat::IdentPat(node) }
 +}
 +impl From<BoxPat> for Pat {
 +    fn from(node: BoxPat) -> Pat { Pat::BoxPat(node) }
 +}
 +impl From<RestPat> for Pat {
 +    fn from(node: RestPat) -> Pat { Pat::RestPat(node) }
 +}
 +impl From<LiteralPat> for Pat {
 +    fn from(node: LiteralPat) -> Pat { Pat::LiteralPat(node) }
 +}
 +impl From<MacroPat> for Pat {
 +    fn from(node: MacroPat) -> Pat { Pat::MacroPat(node) }
 +}
 +impl From<OrPat> for Pat {
 +    fn from(node: OrPat) -> Pat { Pat::OrPat(node) }
 +}
 +impl From<ParenPat> for Pat {
 +    fn from(node: ParenPat) -> Pat { Pat::ParenPat(node) }
 +}
 +impl From<PathPat> for Pat {
 +    fn from(node: PathPat) -> Pat { Pat::PathPat(node) }
 +}
 +impl From<WildcardPat> for Pat {
 +    fn from(node: WildcardPat) -> Pat { Pat::WildcardPat(node) }
 +}
 +impl From<RangePat> for Pat {
 +    fn from(node: RangePat) -> Pat { Pat::RangePat(node) }
 +}
 +impl From<RecordPat> for Pat {
 +    fn from(node: RecordPat) -> Pat { Pat::RecordPat(node) }
 +}
 +impl From<RefPat> for Pat {
 +    fn from(node: RefPat) -> Pat { Pat::RefPat(node) }
 +}
 +impl From<SlicePat> for Pat {
 +    fn from(node: SlicePat) -> Pat { Pat::SlicePat(node) }
 +}
 +impl From<TuplePat> for Pat {
 +    fn from(node: TuplePat) -> Pat { Pat::TuplePat(node) }
 +}
 +impl From<TupleStructPat> for Pat {
 +    fn from(node: TupleStructPat) -> Pat { Pat::TupleStructPat(node) }
 +}
 +impl From<ConstBlockPat> for Pat {
 +    fn from(node: ConstBlockPat) -> Pat { Pat::ConstBlockPat(node) }
 +}
 +impl AstNode for Pat {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            IDENT_PAT | BOX_PAT | REST_PAT | LITERAL_PAT | MACRO_PAT | OR_PAT | PAREN_PAT
 +            | PATH_PAT | WILDCARD_PAT | RANGE_PAT | RECORD_PAT | REF_PAT | SLICE_PAT
 +            | TUPLE_PAT | TUPLE_STRUCT_PAT | CONST_BLOCK_PAT => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        let res = match syntax.kind() {
 +            IDENT_PAT => Pat::IdentPat(IdentPat { syntax }),
 +            BOX_PAT => Pat::BoxPat(BoxPat { syntax }),
 +            REST_PAT => Pat::RestPat(RestPat { syntax }),
 +            LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }),
 +            MACRO_PAT => Pat::MacroPat(MacroPat { syntax }),
 +            OR_PAT => Pat::OrPat(OrPat { syntax }),
 +            PAREN_PAT => Pat::ParenPat(ParenPat { syntax }),
 +            PATH_PAT => Pat::PathPat(PathPat { syntax }),
 +            WILDCARD_PAT => Pat::WildcardPat(WildcardPat { syntax }),
 +            RANGE_PAT => Pat::RangePat(RangePat { syntax }),
 +            RECORD_PAT => Pat::RecordPat(RecordPat { syntax }),
 +            REF_PAT => Pat::RefPat(RefPat { syntax }),
 +            SLICE_PAT => Pat::SlicePat(SlicePat { syntax }),
 +            TUPLE_PAT => Pat::TuplePat(TuplePat { syntax }),
 +            TUPLE_STRUCT_PAT => Pat::TupleStructPat(TupleStructPat { syntax }),
 +            CONST_BLOCK_PAT => Pat::ConstBlockPat(ConstBlockPat { syntax }),
 +            _ => return None,
 +        };
 +        Some(res)
 +    }
 +    fn syntax(&self) -> &SyntaxNode {
 +        match self {
 +            Pat::IdentPat(it) => &it.syntax,
 +            Pat::BoxPat(it) => &it.syntax,
 +            Pat::RestPat(it) => &it.syntax,
 +            Pat::LiteralPat(it) => &it.syntax,
 +            Pat::MacroPat(it) => &it.syntax,
 +            Pat::OrPat(it) => &it.syntax,
 +            Pat::ParenPat(it) => &it.syntax,
 +            Pat::PathPat(it) => &it.syntax,
 +            Pat::WildcardPat(it) => &it.syntax,
 +            Pat::RangePat(it) => &it.syntax,
 +            Pat::RecordPat(it) => &it.syntax,
 +            Pat::RefPat(it) => &it.syntax,
 +            Pat::SlicePat(it) => &it.syntax,
 +            Pat::TuplePat(it) => &it.syntax,
 +            Pat::TupleStructPat(it) => &it.syntax,
 +            Pat::ConstBlockPat(it) => &it.syntax,
 +        }
 +    }
 +}
 +impl From<RecordFieldList> for FieldList {
 +    fn from(node: RecordFieldList) -> FieldList { FieldList::RecordFieldList(node) }
 +}
 +impl From<TupleFieldList> for FieldList {
 +    fn from(node: TupleFieldList) -> FieldList { FieldList::TupleFieldList(node) }
 +}
 +impl AstNode for FieldList {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            RECORD_FIELD_LIST | TUPLE_FIELD_LIST => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        let res = match syntax.kind() {
 +            RECORD_FIELD_LIST => FieldList::RecordFieldList(RecordFieldList { syntax }),
 +            TUPLE_FIELD_LIST => FieldList::TupleFieldList(TupleFieldList { syntax }),
 +            _ => return None,
 +        };
 +        Some(res)
 +    }
 +    fn syntax(&self) -> &SyntaxNode {
 +        match self {
 +            FieldList::RecordFieldList(it) => &it.syntax,
 +            FieldList::TupleFieldList(it) => &it.syntax,
 +        }
 +    }
 +}
 +impl From<Enum> for Adt {
 +    fn from(node: Enum) -> Adt { Adt::Enum(node) }
 +}
 +impl From<Struct> for Adt {
 +    fn from(node: Struct) -> Adt { Adt::Struct(node) }
 +}
 +impl From<Union> for Adt {
 +    fn from(node: Union) -> Adt { Adt::Union(node) }
 +}
 +impl AstNode for Adt {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            ENUM | STRUCT | UNION => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        let res = match syntax.kind() {
 +            ENUM => Adt::Enum(Enum { syntax }),
 +            STRUCT => Adt::Struct(Struct { syntax }),
 +            UNION => Adt::Union(Union { syntax }),
 +            _ => return None,
 +        };
 +        Some(res)
 +    }
 +    fn syntax(&self) -> &SyntaxNode {
 +        match self {
 +            Adt::Enum(it) => &it.syntax,
 +            Adt::Struct(it) => &it.syntax,
 +            Adt::Union(it) => &it.syntax,
 +        }
 +    }
 +}
 +impl From<Const> for AssocItem {
 +    fn from(node: Const) -> AssocItem { AssocItem::Const(node) }
 +}
 +impl From<Fn> for AssocItem {
 +    fn from(node: Fn) -> AssocItem { AssocItem::Fn(node) }
 +}
 +impl From<MacroCall> for AssocItem {
 +    fn from(node: MacroCall) -> AssocItem { AssocItem::MacroCall(node) }
 +}
 +impl From<TypeAlias> for AssocItem {
 +    fn from(node: TypeAlias) -> AssocItem { AssocItem::TypeAlias(node) }
 +}
 +impl AstNode for AssocItem {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            CONST | FN | MACRO_CALL | TYPE_ALIAS => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        let res = match syntax.kind() {
 +            CONST => AssocItem::Const(Const { syntax }),
 +            FN => AssocItem::Fn(Fn { syntax }),
 +            MACRO_CALL => AssocItem::MacroCall(MacroCall { syntax }),
 +            TYPE_ALIAS => AssocItem::TypeAlias(TypeAlias { syntax }),
 +            _ => return None,
 +        };
 +        Some(res)
 +    }
 +    fn syntax(&self) -> &SyntaxNode {
 +        match self {
 +            AssocItem::Const(it) => &it.syntax,
 +            AssocItem::Fn(it) => &it.syntax,
 +            AssocItem::MacroCall(it) => &it.syntax,
 +            AssocItem::TypeAlias(it) => &it.syntax,
 +        }
 +    }
 +}
 +impl From<Fn> for ExternItem {
 +    fn from(node: Fn) -> ExternItem { ExternItem::Fn(node) }
 +}
 +impl From<MacroCall> for ExternItem {
 +    fn from(node: MacroCall) -> ExternItem { ExternItem::MacroCall(node) }
 +}
 +impl From<Static> for ExternItem {
 +    fn from(node: Static) -> ExternItem { ExternItem::Static(node) }
 +}
 +impl From<TypeAlias> for ExternItem {
 +    fn from(node: TypeAlias) -> ExternItem { ExternItem::TypeAlias(node) }
 +}
 +impl AstNode for ExternItem {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            FN | MACRO_CALL | STATIC | TYPE_ALIAS => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        let res = match syntax.kind() {
 +            FN => ExternItem::Fn(Fn { syntax }),
 +            MACRO_CALL => ExternItem::MacroCall(MacroCall { syntax }),
 +            STATIC => ExternItem::Static(Static { syntax }),
 +            TYPE_ALIAS => ExternItem::TypeAlias(TypeAlias { syntax }),
 +            _ => return None,
 +        };
 +        Some(res)
 +    }
 +    fn syntax(&self) -> &SyntaxNode {
 +        match self {
 +            ExternItem::Fn(it) => &it.syntax,
 +            ExternItem::MacroCall(it) => &it.syntax,
 +            ExternItem::Static(it) => &it.syntax,
 +            ExternItem::TypeAlias(it) => &it.syntax,
 +        }
 +    }
 +}
 +impl From<ConstParam> for GenericParam {
 +    fn from(node: ConstParam) -> GenericParam { GenericParam::ConstParam(node) }
 +}
 +impl From<LifetimeParam> for GenericParam {
 +    fn from(node: LifetimeParam) -> GenericParam { GenericParam::LifetimeParam(node) }
 +}
 +impl From<TypeParam> for GenericParam {
 +    fn from(node: TypeParam) -> GenericParam { GenericParam::TypeParam(node) }
 +}
 +impl AstNode for GenericParam {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            CONST_PARAM | LIFETIME_PARAM | TYPE_PARAM => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        let res = match syntax.kind() {
 +            CONST_PARAM => GenericParam::ConstParam(ConstParam { syntax }),
 +            LIFETIME_PARAM => GenericParam::LifetimeParam(LifetimeParam { syntax }),
 +            TYPE_PARAM => GenericParam::TypeParam(TypeParam { syntax }),
 +            _ => return None,
 +        };
 +        Some(res)
 +    }
 +    fn syntax(&self) -> &SyntaxNode {
 +        match self {
 +            GenericParam::ConstParam(it) => &it.syntax,
 +            GenericParam::LifetimeParam(it) => &it.syntax,
 +            GenericParam::TypeParam(it) => &it.syntax,
 +        }
 +    }
 +}
 +impl AnyHasArgList {
 +    #[inline]
 +    pub fn new<T: ast::HasArgList>(node: T) -> AnyHasArgList {
 +        AnyHasArgList { syntax: node.syntax().clone() }
 +    }
 +}
 +impl AstNode for AnyHasArgList {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            CALL_EXPR | METHOD_CALL_EXPR => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        Self::can_cast(syntax.kind()).then(|| AnyHasArgList { syntax })
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AnyHasAttrs {
 +    #[inline]
 +    pub fn new<T: ast::HasAttrs>(node: T) -> AnyHasAttrs {
 +        AnyHasAttrs { syntax: node.syntax().clone() }
 +    }
 +}
 +impl AstNode for AnyHasAttrs {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            MACRO_CALL
 +            | SOURCE_FILE
 +            | CONST
 +            | ENUM
 +            | EXTERN_BLOCK
 +            | EXTERN_CRATE
 +            | FN
 +            | IMPL
 +            | MACRO_RULES
 +            | MACRO_DEF
 +            | MODULE
 +            | STATIC
 +            | STRUCT
 +            | TRAIT
 +            | TYPE_ALIAS
 +            | UNION
 +            | USE
 +            | ITEM_LIST
 +            | BLOCK_EXPR
 +            | SELF_PARAM
 +            | PARAM
 +            | RECORD_FIELD
 +            | TUPLE_FIELD
 +            | VARIANT
 +            | ASSOC_ITEM_LIST
 +            | EXTERN_ITEM_LIST
 +            | CONST_PARAM
 +            | LIFETIME_PARAM
 +            | TYPE_PARAM
 +            | LET_STMT
 +            | ARRAY_EXPR
 +            | AWAIT_EXPR
 +            | BIN_EXPR
 +            | BOX_EXPR
 +            | BREAK_EXPR
 +            | CALL_EXPR
 +            | CAST_EXPR
 +            | CLOSURE_EXPR
 +            | CONTINUE_EXPR
 +            | FIELD_EXPR
 +            | FOR_EXPR
 +            | IF_EXPR
 +            | INDEX_EXPR
 +            | LITERAL
 +            | LOOP_EXPR
 +            | MATCH_EXPR
 +            | METHOD_CALL_EXPR
 +            | PAREN_EXPR
 +            | PATH_EXPR
 +            | PREFIX_EXPR
 +            | RANGE_EXPR
 +            | REF_EXPR
 +            | RETURN_EXPR
 +            | TRY_EXPR
 +            | TUPLE_EXPR
 +            | WHILE_EXPR
 +            | YIELD_EXPR
 +            | LET_EXPR
 +            | UNDERSCORE_EXPR
 +            | STMT_LIST
 +            | RECORD_EXPR_FIELD_LIST
 +            | RECORD_EXPR_FIELD
 +            | MATCH_ARM_LIST
 +            | MATCH_ARM
 +            | IDENT_PAT
 +            | REST_PAT
 +            | RECORD_PAT_FIELD => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        Self::can_cast(syntax.kind()).then(|| AnyHasAttrs { syntax })
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AnyHasDocComments {
 +    #[inline]
 +    pub fn new<T: ast::HasDocComments>(node: T) -> AnyHasDocComments {
 +        AnyHasDocComments { syntax: node.syntax().clone() }
 +    }
 +}
 +impl AstNode for AnyHasDocComments {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            MACRO_CALL | SOURCE_FILE | CONST | ENUM | EXTERN_BLOCK | EXTERN_CRATE | FN | IMPL
 +            | MACRO_RULES | MACRO_DEF | MODULE | STATIC | STRUCT | TRAIT | TYPE_ALIAS | UNION
 +            | USE | RECORD_FIELD | TUPLE_FIELD | VARIANT => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        Self::can_cast(syntax.kind()).then(|| AnyHasDocComments { syntax })
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AnyHasGenericParams {
 +    #[inline]
 +    pub fn new<T: ast::HasGenericParams>(node: T) -> AnyHasGenericParams {
 +        AnyHasGenericParams { syntax: node.syntax().clone() }
 +    }
 +}
 +impl AstNode for AnyHasGenericParams {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            ENUM | FN | IMPL | STRUCT | TRAIT | TYPE_ALIAS | UNION => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        Self::can_cast(syntax.kind()).then(|| AnyHasGenericParams { syntax })
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AnyHasLoopBody {
 +    #[inline]
 +    pub fn new<T: ast::HasLoopBody>(node: T) -> AnyHasLoopBody {
 +        AnyHasLoopBody { syntax: node.syntax().clone() }
 +    }
 +}
 +impl AstNode for AnyHasLoopBody {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            FOR_EXPR | LOOP_EXPR | WHILE_EXPR => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        Self::can_cast(syntax.kind()).then(|| AnyHasLoopBody { syntax })
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AnyHasModuleItem {
 +    #[inline]
 +    pub fn new<T: ast::HasModuleItem>(node: T) -> AnyHasModuleItem {
 +        AnyHasModuleItem { syntax: node.syntax().clone() }
 +    }
 +}
 +impl AstNode for AnyHasModuleItem {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            MACRO_ITEMS | SOURCE_FILE | ITEM_LIST => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        Self::can_cast(syntax.kind()).then(|| AnyHasModuleItem { syntax })
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AnyHasName {
 +    #[inline]
 +    pub fn new<T: ast::HasName>(node: T) -> AnyHasName {
 +        AnyHasName { syntax: node.syntax().clone() }
 +    }
 +}
 +impl AstNode for AnyHasName {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            CONST | ENUM | FN | MACRO_RULES | MACRO_DEF | MODULE | STATIC | STRUCT | TRAIT
 +            | TYPE_ALIAS | UNION | RENAME | SELF_PARAM | RECORD_FIELD | VARIANT | CONST_PARAM
 +            | TYPE_PARAM | IDENT_PAT => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        Self::can_cast(syntax.kind()).then(|| AnyHasName { syntax })
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AnyHasTypeBounds {
 +    #[inline]
 +    pub fn new<T: ast::HasTypeBounds>(node: T) -> AnyHasTypeBounds {
 +        AnyHasTypeBounds { syntax: node.syntax().clone() }
 +    }
 +}
 +impl AstNode for AnyHasTypeBounds {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            ASSOC_TYPE_ARG | TRAIT | TYPE_ALIAS | LIFETIME_PARAM | TYPE_PARAM | WHERE_PRED => true,
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        Self::can_cast(syntax.kind()).then(|| AnyHasTypeBounds { syntax })
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl AnyHasVisibility {
 +    #[inline]
 +    pub fn new<T: ast::HasVisibility>(node: T) -> AnyHasVisibility {
 +        AnyHasVisibility { syntax: node.syntax().clone() }
 +    }
 +}
 +impl AstNode for AnyHasVisibility {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        match kind {
 +            CONST | ENUM | EXTERN_CRATE | FN | IMPL | MACRO_RULES | MACRO_DEF | MODULE | STATIC
 +            | STRUCT | TRAIT | TYPE_ALIAS | UNION | USE | RECORD_FIELD | TUPLE_FIELD | VARIANT => {
 +                true
 +            }
 +            _ => false,
 +        }
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        Self::can_cast(syntax.kind()).then(|| AnyHasVisibility { syntax })
 +    }
 +    fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +}
 +impl std::fmt::Display for GenericArg {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Type {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Expr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Item {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Stmt {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Pat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for FieldList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Adt {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for AssocItem {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ExternItem {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for GenericParam {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Name {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for NameRef {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Lifetime {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Path {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for PathSegment {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for GenericArgList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ParamList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RetType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for PathType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TypeArg {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for AssocTypeArg {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for LifetimeArg {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ConstArg {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for GenericParamList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TypeBoundList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MacroCall {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Attr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TokenTree {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MacroItems {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MacroStmts {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for SourceFile {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Const {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Enum {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ExternBlock {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ExternCrate {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Fn {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Impl {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MacroRules {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MacroDef {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Module {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Static {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Struct {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Trait {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TypeAlias {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Union {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Use {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Visibility {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ItemList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Rename {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for UseTree {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for UseTreeList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Abi {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for WhereClause {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for BlockExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for SelfParam {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Param {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RecordFieldList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TupleFieldList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RecordField {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TupleField {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for VariantList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Variant {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for AssocItemList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ExternItemList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ConstParam {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for LifetimeParam {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TypeParam {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for WherePred {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Meta {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ExprStmt {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for LetStmt {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for LetElse {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ArrayExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for AwaitExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for BinExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for BoxExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for BreakExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for CallExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for CastExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ClosureExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ContinueExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for FieldExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ForExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for IfExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for IndexExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Literal {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for LoopExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MacroExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MatchExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MethodCallExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ParenExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for PathExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for PrefixExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RangeExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RecordExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RefExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ReturnExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TryExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TupleExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for WhileExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for YieldExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for LetExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for UnderscoreExpr {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for StmtList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for Label {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RecordExprFieldList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RecordExprField {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ArgList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MatchArmList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MatchArm {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MatchGuard {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ArrayType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for DynTraitType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for FnPtrType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ForType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ImplTraitType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for InferType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MacroType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for NeverType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ParenType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for PtrType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RefType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for SliceType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TupleType {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TypeBound {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for IdentPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for BoxPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RestPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for LiteralPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for MacroPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for OrPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ParenPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for PathPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for WildcardPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RangePat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RecordPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RefPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for SlicePat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TuplePat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for TupleStructPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for ConstBlockPat {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RecordPatFieldList {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
 +impl std::fmt::Display for RecordPatField {
 +    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +        std::fmt::Display::fmt(self.syntax(), f)
 +    }
 +}
index b143df1f83f2ae3a2aa26dad048cd1fedc5c0492,0000000000000000000000000000000000000000..bb92c51e9a90ed766bce24344f8ddeeb2337ed8c
mode 100644,000000..100644
--- /dev/null
@@@ -1,837 -1,0 +1,875 @@@
 +//! Various extension methods to ast Nodes, which are hard to code-generate.
 +//! Extensions for various expressions live in a sibling `expr_extensions` module.
 +//!
 +//! These methods should only do simple, shallow tasks related to the syntax of the node itself.
 +
 +use std::{borrow::Cow, fmt, iter::successors};
 +
 +use itertools::Itertools;
 +use parser::SyntaxKind;
 +use rowan::{GreenNodeData, GreenTokenData};
 +
 +use crate::{
 +    ast::{self, support, AstNode, AstToken, HasAttrs, HasGenericParams, HasName, SyntaxNode},
 +    NodeOrToken, SmolStr, SyntaxElement, SyntaxToken, TokenText, T,
 +};
 +
 +impl ast::Lifetime {
 +    pub fn text(&self) -> TokenText<'_> {
 +        text_of_first_token(self.syntax())
 +    }
 +}
 +
 +impl ast::Name {
 +    pub fn text(&self) -> TokenText<'_> {
 +        text_of_first_token(self.syntax())
 +    }
 +}
 +
 +impl ast::NameRef {
 +    pub fn text(&self) -> TokenText<'_> {
 +        text_of_first_token(self.syntax())
 +    }
 +
 +    pub fn as_tuple_field(&self) -> Option<usize> {
 +        self.text().parse().ok()
 +    }
 +
 +    pub fn token_kind(&self) -> SyntaxKind {
 +        self.syntax().first_token().map_or(SyntaxKind::ERROR, |it| it.kind())
 +    }
 +}
 +
 +fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> {
 +    fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData {
 +        green_ref.children().next().and_then(NodeOrToken::into_token).unwrap()
 +    }
 +
 +    match node.green() {
 +        Cow::Borrowed(green_ref) => TokenText::borrowed(first_token(green_ref).text()),
 +        Cow::Owned(green) => TokenText::owned(first_token(&green).to_owned()),
 +    }
 +}
 +
 +impl ast::HasModuleItem for ast::StmtList {}
 +
 +impl ast::BlockExpr {
 +    // FIXME: remove all these methods, they belong to ast::StmtList
 +    pub fn statements(&self) -> impl Iterator<Item = ast::Stmt> {
 +        self.stmt_list().into_iter().flat_map(|it| it.statements())
 +    }
 +    pub fn tail_expr(&self) -> Option<ast::Expr> {
 +        self.stmt_list()?.tail_expr()
 +    }
 +}
 +
 +#[derive(Debug, PartialEq, Eq, Clone)]
 +pub enum Macro {
 +    MacroRules(ast::MacroRules),
 +    MacroDef(ast::MacroDef),
 +}
 +
 +impl From<ast::MacroRules> for Macro {
 +    fn from(it: ast::MacroRules) -> Self {
 +        Macro::MacroRules(it)
 +    }
 +}
 +
 +impl From<ast::MacroDef> for Macro {
 +    fn from(it: ast::MacroDef) -> Self {
 +        Macro::MacroDef(it)
 +    }
 +}
 +
 +impl AstNode for Macro {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        matches!(kind, SyntaxKind::MACRO_RULES | SyntaxKind::MACRO_DEF)
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        let res = match syntax.kind() {
 +            SyntaxKind::MACRO_RULES => Macro::MacroRules(ast::MacroRules { syntax }),
 +            SyntaxKind::MACRO_DEF => Macro::MacroDef(ast::MacroDef { syntax }),
 +            _ => return None,
 +        };
 +        Some(res)
 +    }
 +    fn syntax(&self) -> &SyntaxNode {
 +        match self {
 +            Macro::MacroRules(it) => it.syntax(),
 +            Macro::MacroDef(it) => it.syntax(),
 +        }
 +    }
 +}
 +
 +impl HasName for Macro {
 +    fn name(&self) -> Option<ast::Name> {
 +        match self {
 +            Macro::MacroRules(mac) => mac.name(),
 +            Macro::MacroDef(mac) => mac.name(),
 +        }
 +    }
 +}
 +
 +impl HasAttrs for Macro {}
 +
 +impl From<ast::AssocItem> for ast::Item {
 +    fn from(assoc: ast::AssocItem) -> Self {
 +        match assoc {
 +            ast::AssocItem::Const(it) => ast::Item::Const(it),
 +            ast::AssocItem::Fn(it) => ast::Item::Fn(it),
 +            ast::AssocItem::MacroCall(it) => ast::Item::MacroCall(it),
 +            ast::AssocItem::TypeAlias(it) => ast::Item::TypeAlias(it),
 +        }
 +    }
 +}
 +
 +#[derive(Debug, Copy, Clone, PartialEq, Eq)]
 +pub enum AttrKind {
 +    Inner,
 +    Outer,
 +}
 +
 +impl AttrKind {
 +    /// Returns `true` if the attr_kind is [`Inner`](Self::Inner).
 +    pub fn is_inner(&self) -> bool {
 +        matches!(self, Self::Inner)
 +    }
 +
 +    /// Returns `true` if the attr_kind is [`Outer`](Self::Outer).
 +    pub fn is_outer(&self) -> bool {
 +        matches!(self, Self::Outer)
 +    }
 +}
 +
 +impl ast::Attr {
 +    pub fn as_simple_atom(&self) -> Option<SmolStr> {
 +        let meta = self.meta()?;
 +        if meta.eq_token().is_some() || meta.token_tree().is_some() {
 +            return None;
 +        }
 +        self.simple_name()
 +    }
 +
 +    pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> {
 +        let tt = self.meta()?.token_tree()?;
 +        Some((self.simple_name()?, tt))
 +    }
 +
 +    pub fn simple_name(&self) -> Option<SmolStr> {
 +        let path = self.meta()?.path()?;
 +        match (path.segment(), path.qualifier()) {
 +            (Some(segment), None) => Some(segment.syntax().first_token()?.text().into()),
 +            _ => None,
 +        }
 +    }
 +
 +    pub fn kind(&self) -> AttrKind {
 +        match self.excl_token() {
 +            Some(_) => AttrKind::Inner,
 +            None => AttrKind::Outer,
 +        }
 +    }
 +
 +    pub fn path(&self) -> Option<ast::Path> {
 +        self.meta()?.path()
 +    }
 +
 +    pub fn expr(&self) -> Option<ast::Expr> {
 +        self.meta()?.expr()
 +    }
 +
 +    pub fn token_tree(&self) -> Option<ast::TokenTree> {
 +        self.meta()?.token_tree()
 +    }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq)]
 +pub enum PathSegmentKind {
 +    Name(ast::NameRef),
 +    Type { type_ref: Option<ast::Type>, trait_ref: Option<ast::PathType> },
 +    SelfTypeKw,
 +    SelfKw,
 +    SuperKw,
 +    CrateKw,
 +}
 +
 +impl ast::PathSegment {
 +    pub fn parent_path(&self) -> ast::Path {
 +        self.syntax()
 +            .parent()
 +            .and_then(ast::Path::cast)
 +            .expect("segments are always nested in paths")
 +    }
 +
 +    pub fn crate_token(&self) -> Option<SyntaxToken> {
 +        self.name_ref().and_then(|it| it.crate_token())
 +    }
 +
 +    pub fn self_token(&self) -> Option<SyntaxToken> {
 +        self.name_ref().and_then(|it| it.self_token())
 +    }
 +
 +    pub fn self_type_token(&self) -> Option<SyntaxToken> {
 +        self.name_ref().and_then(|it| it.Self_token())
 +    }
 +
 +    pub fn super_token(&self) -> Option<SyntaxToken> {
 +        self.name_ref().and_then(|it| it.super_token())
 +    }
 +
 +    pub fn kind(&self) -> Option<PathSegmentKind> {
 +        let res = if let Some(name_ref) = self.name_ref() {
 +            match name_ref.token_kind() {
 +                T![Self] => PathSegmentKind::SelfTypeKw,
 +                T![self] => PathSegmentKind::SelfKw,
 +                T![super] => PathSegmentKind::SuperKw,
 +                T![crate] => PathSegmentKind::CrateKw,
 +                _ => PathSegmentKind::Name(name_ref),
 +            }
 +        } else {
 +            match self.syntax().first_child_or_token()?.kind() {
 +                T![<] => {
 +                    // <T> or <T as Trait>
 +                    // T is any TypeRef, Trait has to be a PathType
 +                    let mut type_refs =
 +                        self.syntax().children().filter(|node| ast::Type::can_cast(node.kind()));
 +                    let type_ref = type_refs.next().and_then(ast::Type::cast);
 +                    let trait_ref = type_refs.next().and_then(ast::PathType::cast);
 +                    PathSegmentKind::Type { type_ref, trait_ref }
 +                }
 +                _ => return None,
 +            }
 +        };
 +        Some(res)
 +    }
 +}
 +
 +impl ast::Path {
 +    pub fn parent_path(&self) -> Option<ast::Path> {
 +        self.syntax().parent().and_then(ast::Path::cast)
 +    }
 +
 +    pub fn as_single_segment(&self) -> Option<ast::PathSegment> {
 +        match self.qualifier() {
 +            Some(_) => None,
 +            None => self.segment(),
 +        }
 +    }
 +
 +    pub fn as_single_name_ref(&self) -> Option<ast::NameRef> {
 +        match self.qualifier() {
 +            Some(_) => None,
 +            None => self.segment()?.name_ref(),
 +        }
 +    }
 +
 +    pub fn first_qualifier_or_self(&self) -> ast::Path {
 +        successors(Some(self.clone()), ast::Path::qualifier).last().unwrap()
 +    }
 +
 +    pub fn first_segment(&self) -> Option<ast::PathSegment> {
 +        self.first_qualifier_or_self().segment()
 +    }
 +
 +    pub fn segments(&self) -> impl Iterator<Item = ast::PathSegment> + Clone {
 +        successors(self.first_segment(), |p| {
 +            p.parent_path().parent_path().and_then(|p| p.segment())
 +        })
 +    }
 +
 +    pub fn qualifiers(&self) -> impl Iterator<Item = ast::Path> + Clone {
 +        successors(self.qualifier(), |p| p.qualifier())
 +    }
 +
 +    pub fn top_path(&self) -> ast::Path {
 +        let mut this = self.clone();
 +        while let Some(path) = this.parent_path() {
 +            this = path;
 +        }
 +        this
 +    }
 +}
 +
 +impl ast::Use {
 +    pub fn is_simple_glob(&self) -> bool {
 +        self.use_tree().map_or(false, |use_tree| {
 +            use_tree.use_tree_list().is_none() && use_tree.star_token().is_some()
 +        })
 +    }
 +}
 +
 +impl ast::UseTree {
 +    pub fn is_simple_path(&self) -> bool {
 +        self.use_tree_list().is_none() && self.star_token().is_none()
 +    }
 +}
 +
 +impl ast::UseTreeList {
 +    pub fn parent_use_tree(&self) -> ast::UseTree {
 +        self.syntax()
 +            .parent()
 +            .and_then(ast::UseTree::cast)
 +            .expect("UseTreeLists are always nested in UseTrees")
 +    }
 +
 +    pub fn has_inner_comment(&self) -> bool {
 +        self.syntax()
 +            .children_with_tokens()
 +            .filter_map(|it| it.into_token())
 +            .find_map(ast::Comment::cast)
 +            .is_some()
 +    }
 +}
 +
 +impl ast::Impl {
 +    pub fn self_ty(&self) -> Option<ast::Type> {
 +        match self.target() {
 +            (Some(t), None) | (_, Some(t)) => Some(t),
 +            _ => None,
 +        }
 +    }
 +
 +    pub fn trait_(&self) -> Option<ast::Type> {
 +        match self.target() {
 +            (Some(t), Some(_)) => Some(t),
 +            _ => None,
 +        }
 +    }
 +
 +    fn target(&self) -> (Option<ast::Type>, Option<ast::Type>) {
 +        let mut types = support::children(self.syntax());
 +        let first = types.next();
 +        let second = types.next();
 +        (first, second)
 +    }
 +
 +    pub fn for_trait_name_ref(name_ref: &ast::NameRef) -> Option<ast::Impl> {
 +        let this = name_ref.syntax().ancestors().find_map(ast::Impl::cast)?;
 +        if this.trait_()?.syntax().text_range().start() == name_ref.syntax().text_range().start() {
 +            Some(this)
 +        } else {
 +            None
 +        }
 +    }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq)]
 +pub enum StructKind {
 +    Record(ast::RecordFieldList),
 +    Tuple(ast::TupleFieldList),
 +    Unit,
 +}
 +
 +impl StructKind {
 +    fn from_node<N: AstNode>(node: &N) -> StructKind {
 +        if let Some(nfdl) = support::child::<ast::RecordFieldList>(node.syntax()) {
 +            StructKind::Record(nfdl)
 +        } else if let Some(pfl) = support::child::<ast::TupleFieldList>(node.syntax()) {
 +            StructKind::Tuple(pfl)
 +        } else {
 +            StructKind::Unit
 +        }
 +    }
 +}
 +
 +impl ast::Struct {
 +    pub fn kind(&self) -> StructKind {
 +        StructKind::from_node(self)
 +    }
 +}
 +
 +impl ast::RecordExprField {
 +    pub fn for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordExprField> {
 +        let candidate = Self::for_name_ref(field_name)?;
 +        if candidate.field_name().as_ref() == Some(field_name) {
 +            Some(candidate)
 +        } else {
 +            None
 +        }
 +    }
 +
 +    pub fn for_name_ref(name_ref: &ast::NameRef) -> Option<ast::RecordExprField> {
 +        let syn = name_ref.syntax();
 +        syn.parent()
 +            .and_then(ast::RecordExprField::cast)
 +            .or_else(|| syn.ancestors().nth(4).and_then(ast::RecordExprField::cast))
 +    }
 +
 +    /// Deals with field init shorthand
 +    pub fn field_name(&self) -> Option<ast::NameRef> {
 +        if let Some(name_ref) = self.name_ref() {
 +            return Some(name_ref);
 +        }
 +        if let ast::Expr::PathExpr(expr) = self.expr()? {
 +            let path = expr.path()?;
 +            let segment = path.segment()?;
 +            let name_ref = segment.name_ref()?;
 +            if path.qualifier().is_none() {
 +                return Some(name_ref);
 +            }
 +        }
 +        None
 +    }
 +}
 +
 +#[derive(Debug, Clone)]
 +pub enum NameLike {
 +    NameRef(ast::NameRef),
 +    Name(ast::Name),
 +    Lifetime(ast::Lifetime),
 +}
 +
 +impl NameLike {
 +    pub fn as_name_ref(&self) -> Option<&ast::NameRef> {
 +        match self {
 +            NameLike::NameRef(name_ref) => Some(name_ref),
 +            _ => None,
 +        }
 +    }
 +    pub fn as_lifetime(&self) -> Option<&ast::Lifetime> {
 +        match self {
 +            NameLike::Lifetime(lifetime) => Some(lifetime),
 +            _ => None,
 +        }
 +    }
 +    pub fn text(&self) -> TokenText<'_> {
 +        match self {
 +            NameLike::NameRef(name_ref) => name_ref.text(),
 +            NameLike::Name(name) => name.text(),
 +            NameLike::Lifetime(lifetime) => lifetime.text(),
 +        }
 +    }
 +}
 +
 +impl ast::AstNode for NameLike {
 +    fn can_cast(kind: SyntaxKind) -> bool {
 +        matches!(kind, SyntaxKind::NAME | SyntaxKind::NAME_REF | SyntaxKind::LIFETIME)
 +    }
 +    fn cast(syntax: SyntaxNode) -> Option<Self> {
 +        let res = match syntax.kind() {
 +            SyntaxKind::NAME => NameLike::Name(ast::Name { syntax }),
 +            SyntaxKind::NAME_REF => NameLike::NameRef(ast::NameRef { syntax }),
 +            SyntaxKind::LIFETIME => NameLike::Lifetime(ast::Lifetime { syntax }),
 +            _ => return None,
 +        };
 +        Some(res)
 +    }
 +    fn syntax(&self) -> &SyntaxNode {
 +        match self {
 +            NameLike::NameRef(it) => it.syntax(),
 +            NameLike::Name(it) => it.syntax(),
 +            NameLike::Lifetime(it) => it.syntax(),
 +        }
 +    }
 +}
 +
 +const _: () = {
 +    use ast::{Lifetime, Name, NameRef};
 +    stdx::impl_from!(NameRef, Name, Lifetime for NameLike);
 +};
 +
 +#[derive(Debug, Clone, PartialEq)]
 +pub enum NameOrNameRef {
 +    Name(ast::Name),
 +    NameRef(ast::NameRef),
 +}
 +
 +impl fmt::Display for NameOrNameRef {
 +    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
 +        match self {
 +            NameOrNameRef::Name(it) => fmt::Display::fmt(it, f),
 +            NameOrNameRef::NameRef(it) => fmt::Display::fmt(it, f),
 +        }
 +    }
 +}
 +
 +impl NameOrNameRef {
 +    pub fn text(&self) -> TokenText<'_> {
 +        match self {
 +            NameOrNameRef::Name(name) => name.text(),
 +            NameOrNameRef::NameRef(name_ref) => name_ref.text(),
 +        }
 +    }
 +}
 +
 +impl ast::RecordPatField {
 +    pub fn for_field_name_ref(field_name: &ast::NameRef) -> Option<ast::RecordPatField> {
 +        let candidate = field_name.syntax().parent().and_then(ast::RecordPatField::cast)?;
 +        match candidate.field_name()? {
 +            NameOrNameRef::NameRef(name_ref) if name_ref == *field_name => Some(candidate),
 +            _ => None,
 +        }
 +    }
 +
 +    pub fn for_field_name(field_name: &ast::Name) -> Option<ast::RecordPatField> {
 +        let candidate =
 +            field_name.syntax().ancestors().nth(2).and_then(ast::RecordPatField::cast)?;
 +        match candidate.field_name()? {
 +            NameOrNameRef::Name(name) if name == *field_name => Some(candidate),
 +            _ => None,
 +        }
 +    }
 +
 +    pub fn parent_record_pat(&self) -> ast::RecordPat {
 +        self.syntax().ancestors().find_map(ast::RecordPat::cast).unwrap()
 +    }
 +
 +    /// Deals with field init shorthand
 +    pub fn field_name(&self) -> Option<NameOrNameRef> {
 +        if let Some(name_ref) = self.name_ref() {
 +            return Some(NameOrNameRef::NameRef(name_ref));
 +        }
 +        match self.pat() {
 +            Some(ast::Pat::IdentPat(pat)) => {
 +                let name = pat.name()?;
 +                Some(NameOrNameRef::Name(name))
 +            }
 +            Some(ast::Pat::BoxPat(pat)) => match pat.pat() {
 +                Some(ast::Pat::IdentPat(pat)) => {
 +                    let name = pat.name()?;
 +                    Some(NameOrNameRef::Name(name))
 +                }
 +                _ => None,
 +            },
 +            _ => None,
 +        }
 +    }
 +}
 +
 +impl ast::Variant {
 +    pub fn parent_enum(&self) -> ast::Enum {
 +        self.syntax()
 +            .parent()
 +            .and_then(|it| it.parent())
 +            .and_then(ast::Enum::cast)
 +            .expect("EnumVariants are always nested in Enums")
 +    }
 +    pub fn kind(&self) -> StructKind {
 +        StructKind::from_node(self)
 +    }
 +}
 +
 +impl ast::Item {
 +    pub fn generic_param_list(&self) -> Option<ast::GenericParamList> {
 +        ast::AnyHasGenericParams::cast(self.syntax().clone())?.generic_param_list()
 +    }
 +}
 +
 +#[derive(Debug, Clone, PartialEq, Eq)]
 +pub enum FieldKind {
 +    Name(ast::NameRef),
 +    Index(SyntaxToken),
 +}
 +
 +impl ast::FieldExpr {
 +    pub fn index_token(&self) -> Option<SyntaxToken> {
 +        self.syntax
 +            .children_with_tokens()
 +            // FIXME: Accepting floats here to reject them in validation later
 +            .find(|c| c.kind() == SyntaxKind::INT_NUMBER || c.kind() == SyntaxKind::FLOAT_NUMBER)
 +            .as_ref()
 +            .and_then(SyntaxElement::as_token)
 +            .cloned()
 +    }
 +
 +    pub fn field_access(&self) -> Option<FieldKind> {
 +        match self.name_ref() {
 +            Some(nr) => Some(FieldKind::Name(nr)),
 +            None => self.index_token().map(FieldKind::Index),
 +        }
 +    }
 +}
 +
 +pub struct SlicePatComponents {
 +    pub prefix: Vec<ast::Pat>,
 +    pub slice: Option<ast::Pat>,
 +    pub suffix: Vec<ast::Pat>,
 +}
 +
 +impl ast::SlicePat {
 +    pub fn components(&self) -> SlicePatComponents {
 +        let mut args = self.pats().peekable();
 +        let prefix = args
 +            .peeking_take_while(|p| match p {
 +                ast::Pat::RestPat(_) => false,
 +                ast::Pat::IdentPat(bp) => !matches!(bp.pat(), Some(ast::Pat::RestPat(_))),
 +                ast::Pat::RefPat(rp) => match rp.pat() {
 +                    Some(ast::Pat::RestPat(_)) => false,
 +                    Some(ast::Pat::IdentPat(bp)) => !matches!(bp.pat(), Some(ast::Pat::RestPat(_))),
 +                    _ => true,
 +                },
 +                _ => true,
 +            })
 +            .collect();
 +        let slice = args.next();
 +        let suffix = args.collect();
 +
 +        SlicePatComponents { prefix, slice, suffix }
 +    }
 +}
 +
 +impl ast::IdentPat {
 +    pub fn is_simple_ident(&self) -> bool {
 +        self.at_token().is_none()
 +            && self.mut_token().is_none()
 +            && self.ref_token().is_none()
 +            && self.pat().is_none()
 +    }
 +}
 +
 +#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 +pub enum SelfParamKind {
 +    /// self
 +    Owned,
 +    /// &self
 +    Ref,
 +    /// &mut self
 +    MutRef,
 +}
 +
 +impl ast::SelfParam {
 +    pub fn kind(&self) -> SelfParamKind {
 +        if self.amp_token().is_some() {
 +            if self.mut_token().is_some() {
 +                SelfParamKind::MutRef
 +            } else {
 +                SelfParamKind::Ref
 +            }
 +        } else {
 +            SelfParamKind::Owned
 +        }
 +    }
 +}
 +
 +#[derive(Clone, Debug, PartialEq, Eq, Hash)]
 +pub enum TypeBoundKind {
 +    /// Trait
 +    PathType(ast::PathType),
 +    /// for<'a> ...
 +    ForType(ast::ForType),
 +    /// 'a
 +    Lifetime(ast::Lifetime),
 +}
 +
 +impl ast::TypeBound {
 +    pub fn kind(&self) -> TypeBoundKind {
 +        if let Some(path_type) = support::children(self.syntax()).next() {
 +            TypeBoundKind::PathType(path_type)
 +        } else if let Some(for_type) = support::children(self.syntax()).next() {
 +            TypeBoundKind::ForType(for_type)
 +        } else if let Some(lifetime) = self.lifetime() {
 +            TypeBoundKind::Lifetime(lifetime)
 +        } else {
 +            unreachable!()
 +        }
 +    }
 +}
 +
 +#[derive(Debug, Clone)]
 +pub enum TypeOrConstParam {
 +    Type(ast::TypeParam),
 +    Const(ast::ConstParam),
 +}
 +
 +impl TypeOrConstParam {
 +    pub fn name(&self) -> Option<ast::Name> {
 +        match self {
 +            TypeOrConstParam::Type(x) => x.name(),
 +            TypeOrConstParam::Const(x) => x.name(),
 +        }
 +    }
 +}
 +
 +pub enum VisibilityKind {
 +    In(ast::Path),
 +    PubCrate,
 +    PubSuper,
 +    PubSelf,
 +    Pub,
 +}
 +
 +impl ast::Visibility {
 +    pub fn kind(&self) -> VisibilityKind {
 +        match self.path() {
 +            Some(path) => {
 +                if let Some(segment) =
 +                    path.as_single_segment().filter(|it| it.coloncolon_token().is_none())
 +                {
 +                    if segment.crate_token().is_some() {
 +                        return VisibilityKind::PubCrate;
 +                    } else if segment.super_token().is_some() {
 +                        return VisibilityKind::PubSuper;
 +                    } else if segment.self_token().is_some() {
 +                        return VisibilityKind::PubSelf;
 +                    }
 +                }
 +                VisibilityKind::In(path)
 +            }
 +            None => VisibilityKind::Pub,
 +        }
 +    }
 +}
 +
 +impl ast::LifetimeParam {
 +    pub fn lifetime_bounds(&self) -> impl Iterator<Item = SyntaxToken> {
 +        self.syntax()
 +            .children_with_tokens()
 +            .filter_map(|it| it.into_token())
 +            .skip_while(|x| x.kind() != T![:])
 +            .filter(|it| it.kind() == T![lifetime_ident])
 +    }
 +}
 +
 +impl ast::Module {
 +    /// Returns the parent ast::Module, this is different than the semantic parent in that this only
 +    /// considers parent declarations in the AST
 +    pub fn parent(&self) -> Option<ast::Module> {
 +        self.syntax().ancestors().nth(2).and_then(ast::Module::cast)
 +    }
 +}
 +
 +impl ast::RangePat {
 +    pub fn start(&self) -> Option<ast::Pat> {
 +        self.syntax()
 +            .children_with_tokens()
 +            .take_while(|it| !(it.kind() == T![..] || it.kind() == T![..=]))
 +            .filter_map(|it| it.into_node())
 +            .find_map(ast::Pat::cast)
 +    }
 +
 +    pub fn end(&self) -> Option<ast::Pat> {
 +        self.syntax()
 +            .children_with_tokens()
 +            .skip_while(|it| !(it.kind() == T![..] || it.kind() == T![..=]))
 +            .filter_map(|it| it.into_node())
 +            .find_map(ast::Pat::cast)
 +    }
 +}
 +
 +impl ast::TokenTree {
 +    pub fn token_trees_and_tokens(
 +        &self,
 +    ) -> impl Iterator<Item = NodeOrToken<ast::TokenTree, SyntaxToken>> {
 +        self.syntax().children_with_tokens().filter_map(|not| match not {
 +            NodeOrToken::Node(node) => ast::TokenTree::cast(node).map(NodeOrToken::Node),
 +            NodeOrToken::Token(t) => Some(NodeOrToken::Token(t)),
 +        })
 +    }
 +
 +    pub fn left_delimiter_token(&self) -> Option<SyntaxToken> {
 +        self.syntax()
 +            .first_child_or_token()?
 +            .into_token()
 +            .filter(|it| matches!(it.kind(), T!['{'] | T!['('] | T!['[']))
 +    }
 +
 +    pub fn right_delimiter_token(&self) -> Option<SyntaxToken> {
 +        self.syntax()
 +            .last_child_or_token()?
 +            .into_token()
 +            .filter(|it| matches!(it.kind(), T!['}'] | T![')'] | T![']']))
 +    }
 +
 +    pub fn parent_meta(&self) -> Option<ast::Meta> {
 +        self.syntax().parent().and_then(ast::Meta::cast)
 +    }
 +}
 +
 +impl ast::Meta {
 +    pub fn parent_attr(&self) -> Option<ast::Attr> {
 +        self.syntax().parent().and_then(ast::Attr::cast)
 +    }
 +}
 +
 +impl ast::GenericArgList {
 +    pub fn lifetime_args(&self) -> impl Iterator<Item = ast::LifetimeArg> {
 +        self.generic_args().filter_map(|arg| match arg {
 +            ast::GenericArg::LifetimeArg(it) => Some(it),
 +            _ => None,
 +        })
 +    }
 +}
 +
 +impl ast::GenericParamList {
 +    pub fn lifetime_params(&self) -> impl Iterator<Item = ast::LifetimeParam> {
 +        self.generic_params().filter_map(|param| match param {
 +            ast::GenericParam::LifetimeParam(it) => Some(it),
 +            ast::GenericParam::TypeParam(_) | ast::GenericParam::ConstParam(_) => None,
 +        })
 +    }
 +    pub fn type_or_const_params(&self) -> impl Iterator<Item = ast::TypeOrConstParam> {
 +        self.generic_params().filter_map(|param| match param {
 +            ast::GenericParam::TypeParam(it) => Some(ast::TypeOrConstParam::Type(it)),
 +            ast::GenericParam::LifetimeParam(_) => None,
 +            ast::GenericParam::ConstParam(it) => Some(ast::TypeOrConstParam::Const(it)),
 +        })
 +    }
 +}
 +
++impl ast::ForExpr {
++    pub fn iterable(&self) -> Option<ast::Expr> {
++        // If the iterable is a BlockExpr, check if the body is missing.
++        // If it is assume the iterable is the expression that is missing instead.
++        let mut exprs = support::children(self.syntax());
++        let first = exprs.next();
++        match first {
++            Some(ast::Expr::BlockExpr(_)) => exprs.next().and(first),
++            first => first,
++        }
++    }
++}
++
 +impl ast::HasLoopBody for ast::ForExpr {
 +    fn loop_body(&self) -> Option<ast::BlockExpr> {
 +        let mut exprs = support::children(self.syntax());
 +        let first = exprs.next();
 +        let second = exprs.next();
 +        second.or(first)
 +    }
 +}
 +
++impl ast::WhileExpr {
++    pub fn condition(&self) -> Option<ast::Expr> {
++        // If the condition is a BlockExpr, check if the body is missing.
++        // If it is assume the condition is the expression that is missing instead.
++        let mut exprs = support::children(self.syntax());
++        let first = exprs.next();
++        match first {
++            Some(ast::Expr::BlockExpr(_)) => exprs.next().and(first),
++            first => first,
++        }
++    }
++}
++
 +impl ast::HasLoopBody for ast::WhileExpr {
 +    fn loop_body(&self) -> Option<ast::BlockExpr> {
 +        let mut exprs = support::children(self.syntax());
 +        let first = exprs.next();
 +        let second = exprs.next();
 +        second.or(first)
 +    }
 +}
 +
 +impl ast::HasAttrs for ast::AnyHasDocComments {}
 +
 +impl From<ast::Adt> for ast::Item {
 +    fn from(it: ast::Adt) -> Self {
 +        match it {
 +            ast::Adt::Enum(it) => ast::Item::Enum(it),
 +            ast::Adt::Struct(it) => ast::Item::Struct(it),
 +            ast::Adt::Union(it) => ast::Item::Union(it),
 +        }
 +    }
 +}
++
++impl ast::IfExpr {
++    pub fn condition(&self) -> Option<ast::Expr> {
++        support::child(&self.syntax)
++    }
++}
++
++impl ast::MatchGuard {
++    pub fn condition(&self) -> Option<ast::Expr> {
++        support::child(&self.syntax)
++    }
++}
index 4cfb8075cb155c5a47677701d8a50cc2c0938b28,0000000000000000000000000000000000000000..6d2766225103f7b0aa2406a99939031a973b7274
mode 100644,000000..100644
--- /dev/null
@@@ -1,860 -1,0 +1,862 @@@
 +//! This module generates AST datatype used by rust-analyzer.
 +//!
 +//! Specifically, it generates the `SyntaxKind` enum and a number of newtype
 +//! wrappers around `SyntaxNode` which implement `syntax::AstNode`.
 +
 +use std::{
 +    collections::{BTreeSet, HashSet},
 +    fmt::Write,
 +};
 +
 +use itertools::Itertools;
 +use proc_macro2::{Punct, Spacing};
 +use quote::{format_ident, quote};
 +use ungrammar::{Grammar, Rule};
 +
 +use crate::tests::ast_src::{
 +    AstEnumSrc, AstNodeSrc, AstSrc, Cardinality, Field, KindsSrc, KINDS_SRC,
 +};
 +
 +#[test]
 +fn sourcegen_ast() {
 +    let syntax_kinds = generate_syntax_kinds(KINDS_SRC);
 +    let syntax_kinds_file =
 +        sourcegen::project_root().join("crates/parser/src/syntax_kind/generated.rs");
 +    sourcegen::ensure_file_contents(syntax_kinds_file.as_path(), &syntax_kinds);
 +
 +    let grammar =
 +        include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/rust.ungram")).parse().unwrap();
 +    let ast = lower(&grammar);
 +
 +    let ast_tokens = generate_tokens(&ast);
 +    let ast_tokens_file =
 +        sourcegen::project_root().join("crates/syntax/src/ast/generated/tokens.rs");
 +    sourcegen::ensure_file_contents(ast_tokens_file.as_path(), &ast_tokens);
 +
 +    let ast_nodes = generate_nodes(KINDS_SRC, &ast);
 +    let ast_nodes_file = sourcegen::project_root().join("crates/syntax/src/ast/generated/nodes.rs");
 +    sourcegen::ensure_file_contents(ast_nodes_file.as_path(), &ast_nodes);
 +}
 +
 +fn generate_tokens(grammar: &AstSrc) -> String {
 +    let tokens = grammar.tokens.iter().map(|token| {
 +        let name = format_ident!("{}", token);
 +        let kind = format_ident!("{}", to_upper_snake_case(token));
 +        quote! {
 +            #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +            pub struct #name {
 +                pub(crate) syntax: SyntaxToken,
 +            }
 +            impl std::fmt::Display for #name {
 +                fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +                    std::fmt::Display::fmt(&self.syntax, f)
 +                }
 +            }
 +            impl AstToken for #name {
 +                fn can_cast(kind: SyntaxKind) -> bool { kind == #kind }
 +                fn cast(syntax: SyntaxToken) -> Option<Self> {
 +                    if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
 +                }
 +                fn syntax(&self) -> &SyntaxToken { &self.syntax }
 +            }
 +        }
 +    });
 +
 +    sourcegen::add_preamble(
 +        "sourcegen_ast",
 +        sourcegen::reformat(
 +            quote! {
 +                use crate::{SyntaxKind::{self, *}, SyntaxToken, ast::AstToken};
 +                #(#tokens)*
 +            }
 +            .to_string(),
 +        ),
 +    )
 +    .replace("#[derive", "\n#[derive")
 +}
 +
 +fn generate_nodes(kinds: KindsSrc<'_>, grammar: &AstSrc) -> String {
 +    let (node_defs, node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
 +        .nodes
 +        .iter()
 +        .map(|node| {
 +            let name = format_ident!("{}", node.name);
 +            let kind = format_ident!("{}", to_upper_snake_case(&node.name));
 +            let traits = node
 +                .traits
 +                .iter()
 +                .filter(|trait_name| {
 +                    // Loops have two expressions so this might collide, therefor manual impl it
 +                    node.name != "ForExpr" && node.name != "WhileExpr"
 +                        || trait_name.as_str() != "HasLoopBody"
 +                })
 +                .map(|trait_name| {
 +                    let trait_name = format_ident!("{}", trait_name);
 +                    quote!(impl ast::#trait_name for #name {})
 +                });
 +
 +            let methods = node.fields.iter().map(|field| {
 +                let method_name = field.method_name();
 +                let ty = field.ty();
 +
 +                if field.is_many() {
 +                    quote! {
 +                        pub fn #method_name(&self) -> AstChildren<#ty> {
 +                            support::children(&self.syntax)
 +                        }
 +                    }
 +                } else if let Some(token_kind) = field.token_kind() {
 +                    quote! {
 +                        pub fn #method_name(&self) -> Option<#ty> {
 +                            support::token(&self.syntax, #token_kind)
 +                        }
 +                    }
 +                } else {
 +                    quote! {
 +                        pub fn #method_name(&self) -> Option<#ty> {
 +                            support::child(&self.syntax)
 +                        }
 +                    }
 +                }
 +            });
 +            (
 +                quote! {
 +                    #[pretty_doc_comment_placeholder_workaround]
 +                    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +                    pub struct #name {
 +                        pub(crate) syntax: SyntaxNode,
 +                    }
 +
 +                    #(#traits)*
 +
 +                    impl #name {
 +                        #(#methods)*
 +                    }
 +                },
 +                quote! {
 +                    impl AstNode for #name {
 +                        fn can_cast(kind: SyntaxKind) -> bool {
 +                            kind == #kind
 +                        }
 +                        fn cast(syntax: SyntaxNode) -> Option<Self> {
 +                            if Self::can_cast(syntax.kind()) { Some(Self { syntax }) } else { None }
 +                        }
 +                        fn syntax(&self) -> &SyntaxNode { &self.syntax }
 +                    }
 +                },
 +            )
 +        })
 +        .unzip();
 +
 +    let (enum_defs, enum_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
 +        .enums
 +        .iter()
 +        .map(|en| {
 +            let variants: Vec<_> = en.variants.iter().map(|var| format_ident!("{}", var)).collect();
 +            let name = format_ident!("{}", en.name);
 +            let kinds: Vec<_> = variants
 +                .iter()
 +                .map(|name| format_ident!("{}", to_upper_snake_case(&name.to_string())))
 +                .collect();
 +            let traits = en.traits.iter().map(|trait_name| {
 +                let trait_name = format_ident!("{}", trait_name);
 +                quote!(impl ast::#trait_name for #name {})
 +            });
 +
 +            let ast_node = if en.name == "Stmt" {
 +                quote! {}
 +            } else {
 +                quote! {
 +                    impl AstNode for #name {
 +                        fn can_cast(kind: SyntaxKind) -> bool {
 +                            match kind {
 +                                #(#kinds)|* => true,
 +                                _ => false,
 +                            }
 +                        }
 +                        fn cast(syntax: SyntaxNode) -> Option<Self> {
 +                            let res = match syntax.kind() {
 +                                #(
 +                                #kinds => #name::#variants(#variants { syntax }),
 +                                )*
 +                                _ => return None,
 +                            };
 +                            Some(res)
 +                        }
 +                        fn syntax(&self) -> &SyntaxNode {
 +                            match self {
 +                                #(
 +                                #name::#variants(it) => &it.syntax,
 +                                )*
 +                            }
 +                        }
 +                    }
 +                }
 +            };
 +
 +            (
 +                quote! {
 +                    #[pretty_doc_comment_placeholder_workaround]
 +                    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +                    pub enum #name {
 +                        #(#variants(#variants),)*
 +                    }
 +
 +                    #(#traits)*
 +                },
 +                quote! {
 +                    #(
 +                        impl From<#variants> for #name {
 +                            fn from(node: #variants) -> #name {
 +                                #name::#variants(node)
 +                            }
 +                        }
 +                    )*
 +                    #ast_node
 +                },
 +            )
 +        })
 +        .unzip();
 +
 +    let (any_node_defs, any_node_boilerplate_impls): (Vec<_>, Vec<_>) = grammar
 +        .nodes
 +        .iter()
 +        .flat_map(|node| node.traits.iter().map(move |t| (t, node)))
 +        .into_group_map()
 +        .into_iter()
 +        .sorted_by_key(|(k, _)| *k)
 +        .map(|(trait_name, nodes)| {
 +            let name = format_ident!("Any{}", trait_name);
 +            let trait_name = format_ident!("{}", trait_name);
 +            let kinds: Vec<_> = nodes
 +                .iter()
 +                .map(|name| format_ident!("{}", to_upper_snake_case(&name.name.to_string())))
 +                .collect();
 +
 +            (
 +                quote! {
 +                    #[pretty_doc_comment_placeholder_workaround]
 +                    #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 +                    pub struct #name {
 +                        pub(crate) syntax: SyntaxNode,
 +                    }
 +                    impl ast::#trait_name for #name {}
 +                },
 +                quote! {
 +                    impl #name {
 +                        #[inline]
 +                        pub fn new<T: ast::#trait_name>(node: T) -> #name {
 +                            #name {
 +                                syntax: node.syntax().clone()
 +                            }
 +                        }
 +                    }
 +                    impl AstNode for #name {
 +                        fn can_cast(kind: SyntaxKind) -> bool {
 +                            match kind {
 +                                #(#kinds)|* => true,
 +                                _ => false,
 +                            }
 +                        }
 +                        fn cast(syntax: SyntaxNode) -> Option<Self> {
 +                            Self::can_cast(syntax.kind()).then(|| #name { syntax })
 +                        }
 +                        fn syntax(&self) -> &SyntaxNode {
 +                            &self.syntax
 +                        }
 +                    }
 +                },
 +            )
 +        })
 +        .unzip();
 +
 +    let enum_names = grammar.enums.iter().map(|it| &it.name);
 +    let node_names = grammar.nodes.iter().map(|it| &it.name);
 +
 +    let display_impls =
 +        enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| {
 +            quote! {
 +                impl std::fmt::Display for #name {
 +                    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
 +                        std::fmt::Display::fmt(self.syntax(), f)
 +                    }
 +                }
 +            }
 +        });
 +
 +    let defined_nodes: HashSet<_> = node_names.collect();
 +
 +    for node in kinds
 +        .nodes
 +        .iter()
 +        .map(|kind| to_pascal_case(kind))
 +        .filter(|name| !defined_nodes.iter().any(|&it| it == name))
 +    {
 +        drop(node)
 +        // FIXME: restore this
 +        // eprintln!("Warning: node {} not defined in ast source", node);
 +    }
 +
 +    let ast = quote! {
 +        #![allow(non_snake_case)]
 +        use crate::{
 +            SyntaxNode, SyntaxToken, SyntaxKind::{self, *},
 +            ast::{self, AstNode, AstChildren, support},
 +            T,
 +        };
 +
 +        #(#node_defs)*
 +        #(#enum_defs)*
 +        #(#any_node_defs)*
 +        #(#node_boilerplate_impls)*
 +        #(#enum_boilerplate_impls)*
 +        #(#any_node_boilerplate_impls)*
 +        #(#display_impls)*
 +    };
 +
 +    let ast = ast.to_string().replace("T ! [", "T![");
 +
 +    let mut res = String::with_capacity(ast.len() * 2);
 +
 +    let mut docs =
 +        grammar.nodes.iter().map(|it| &it.doc).chain(grammar.enums.iter().map(|it| &it.doc));
 +
 +    for chunk in ast.split("# [pretty_doc_comment_placeholder_workaround] ") {
 +        res.push_str(chunk);
 +        if let Some(doc) = docs.next() {
 +            write_doc_comment(doc, &mut res);
 +        }
 +    }
 +
 +    let res = sourcegen::add_preamble("sourcegen_ast", sourcegen::reformat(res));
 +    res.replace("#[derive", "\n#[derive")
 +}
 +
 +fn write_doc_comment(contents: &[String], dest: &mut String) {
 +    for line in contents {
 +        writeln!(dest, "///{}", line).unwrap();
 +    }
 +}
 +
 +fn generate_syntax_kinds(grammar: KindsSrc<'_>) -> String {
 +    let (single_byte_tokens_values, single_byte_tokens): (Vec<_>, Vec<_>) = grammar
 +        .punct
 +        .iter()
 +        .filter(|(token, _name)| token.len() == 1)
 +        .map(|(token, name)| (token.chars().next().unwrap(), format_ident!("{}", name)))
 +        .unzip();
 +
 +    let punctuation_values = grammar.punct.iter().map(|(token, _name)| {
 +        if "{}[]()".contains(token) {
 +            let c = token.chars().next().unwrap();
 +            quote! { #c }
 +        } else {
 +            let cs = token.chars().map(|c| Punct::new(c, Spacing::Joint));
 +            quote! { #(#cs)* }
 +        }
 +    });
 +    let punctuation =
 +        grammar.punct.iter().map(|(_token, name)| format_ident!("{}", name)).collect::<Vec<_>>();
 +
 +    let x = |&name| match name {
 +        "Self" => format_ident!("SELF_TYPE_KW"),
 +        name => format_ident!("{}_KW", to_upper_snake_case(name)),
 +    };
 +    let full_keywords_values = grammar.keywords;
 +    let full_keywords = full_keywords_values.iter().map(x);
 +
 +    let contextual_keywords_values = &grammar.contextual_keywords;
 +    let contextual_keywords = contextual_keywords_values.iter().map(x);
 +
 +    let all_keywords_values = grammar
 +        .keywords
 +        .iter()
 +        .chain(grammar.contextual_keywords.iter())
 +        .copied()
 +        .collect::<Vec<_>>();
 +    let all_keywords_idents = all_keywords_values.iter().map(|kw| format_ident!("{}", kw));
 +    let all_keywords = all_keywords_values.iter().map(x).collect::<Vec<_>>();
 +
 +    let literals =
 +        grammar.literals.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();
 +
 +    let tokens = grammar.tokens.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();
 +
 +    let nodes = grammar.nodes.iter().map(|name| format_ident!("{}", name)).collect::<Vec<_>>();
 +
 +    let ast = quote! {
 +        #![allow(bad_style, missing_docs, unreachable_pub)]
 +        /// The kind of syntax node, e.g. `IDENT`, `USE_KW`, or `STRUCT`.
 +        #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 +        #[repr(u16)]
 +        pub enum SyntaxKind {
 +            // Technical SyntaxKinds: they appear temporally during parsing,
 +            // but never end up in the final tree
 +            #[doc(hidden)]
 +            TOMBSTONE,
 +            #[doc(hidden)]
 +            EOF,
 +            #(#punctuation,)*
 +            #(#all_keywords,)*
 +            #(#literals,)*
 +            #(#tokens,)*
 +            #(#nodes,)*
 +
 +            // Technical kind so that we can cast from u16 safely
 +            #[doc(hidden)]
 +            __LAST,
 +        }
 +        use self::SyntaxKind::*;
 +
 +        impl SyntaxKind {
 +            pub fn is_keyword(self) -> bool {
 +                match self {
 +                    #(#all_keywords)|* => true,
 +                    _ => false,
 +                }
 +            }
 +
 +            pub fn is_punct(self) -> bool {
 +                match self {
 +                    #(#punctuation)|* => true,
 +                    _ => false,
 +                }
 +            }
 +
 +            pub fn is_literal(self) -> bool {
 +                match self {
 +                    #(#literals)|* => true,
 +                    _ => false,
 +                }
 +            }
 +
 +            pub fn from_keyword(ident: &str) -> Option<SyntaxKind> {
 +                let kw = match ident {
 +                    #(#full_keywords_values => #full_keywords,)*
 +                    _ => return None,
 +                };
 +                Some(kw)
 +            }
 +
 +            pub fn from_contextual_keyword(ident: &str) -> Option<SyntaxKind> {
 +                let kw = match ident {
 +                    #(#contextual_keywords_values => #contextual_keywords,)*
 +                    _ => return None,
 +                };
 +                Some(kw)
 +            }
 +
 +            pub fn from_char(c: char) -> Option<SyntaxKind> {
 +                let tok = match c {
 +                    #(#single_byte_tokens_values => #single_byte_tokens,)*
 +                    _ => return None,
 +                };
 +                Some(tok)
 +            }
 +        }
 +
 +        #[macro_export]
 +        macro_rules! T {
 +            #([#punctuation_values] => { $crate::SyntaxKind::#punctuation };)*
 +            #([#all_keywords_idents] => { $crate::SyntaxKind::#all_keywords };)*
 +            [lifetime_ident] => { $crate::SyntaxKind::LIFETIME_IDENT };
 +            [ident] => { $crate::SyntaxKind::IDENT };
 +            [shebang] => { $crate::SyntaxKind::SHEBANG };
 +        }
 +        pub use T;
 +    };
 +
 +    sourcegen::add_preamble("sourcegen_ast", sourcegen::reformat(ast.to_string()))
 +}
 +
 +fn to_upper_snake_case(s: &str) -> String {
 +    let mut buf = String::with_capacity(s.len());
 +    let mut prev = false;
 +    for c in s.chars() {
 +        if c.is_ascii_uppercase() && prev {
 +            buf.push('_')
 +        }
 +        prev = true;
 +
 +        buf.push(c.to_ascii_uppercase());
 +    }
 +    buf
 +}
 +
 +fn to_lower_snake_case(s: &str) -> String {
 +    let mut buf = String::with_capacity(s.len());
 +    let mut prev = false;
 +    for c in s.chars() {
 +        if c.is_ascii_uppercase() && prev {
 +            buf.push('_')
 +        }
 +        prev = true;
 +
 +        buf.push(c.to_ascii_lowercase());
 +    }
 +    buf
 +}
 +
 +fn to_pascal_case(s: &str) -> String {
 +    let mut buf = String::with_capacity(s.len());
 +    let mut prev_is_underscore = true;
 +    for c in s.chars() {
 +        if c == '_' {
 +            prev_is_underscore = true;
 +        } else if prev_is_underscore {
 +            buf.push(c.to_ascii_uppercase());
 +            prev_is_underscore = false;
 +        } else {
 +            buf.push(c.to_ascii_lowercase());
 +        }
 +    }
 +    buf
 +}
 +
 +fn pluralize(s: &str) -> String {
 +    format!("{}s", s)
 +}
 +
 +impl Field {
 +    fn is_many(&self) -> bool {
 +        matches!(self, Field::Node { cardinality: Cardinality::Many, .. })
 +    }
 +    fn token_kind(&self) -> Option<proc_macro2::TokenStream> {
 +        match self {
 +            Field::Token(token) => {
 +                let token: proc_macro2::TokenStream = token.parse().unwrap();
 +                Some(quote! { T![#token] })
 +            }
 +            _ => None,
 +        }
 +    }
 +    fn method_name(&self) -> proc_macro2::Ident {
 +        match self {
 +            Field::Token(name) => {
 +                let name = match name.as_str() {
 +                    ";" => "semicolon",
 +                    "->" => "thin_arrow",
 +                    "'{'" => "l_curly",
 +                    "'}'" => "r_curly",
 +                    "'('" => "l_paren",
 +                    "')'" => "r_paren",
 +                    "'['" => "l_brack",
 +                    "']'" => "r_brack",
 +                    "<" => "l_angle",
 +                    ">" => "r_angle",
 +                    "=" => "eq",
 +                    "!" => "excl",
 +                    "*" => "star",
 +                    "&" => "amp",
 +                    "_" => "underscore",
 +                    "." => "dot",
 +                    ".." => "dotdot",
 +                    "..." => "dotdotdot",
 +                    "..=" => "dotdoteq",
 +                    "=>" => "fat_arrow",
 +                    "@" => "at",
 +                    ":" => "colon",
 +                    "::" => "coloncolon",
 +                    "#" => "pound",
 +                    "?" => "question_mark",
 +                    "," => "comma",
 +                    "|" => "pipe",
 +                    "~" => "tilde",
 +                    _ => name,
 +                };
 +                format_ident!("{}_token", name)
 +            }
 +            Field::Node { name, .. } => {
 +                if name == "type" {
 +                    format_ident!("ty")
 +                } else {
 +                    format_ident!("{}", name)
 +                }
 +            }
 +        }
 +    }
 +    fn ty(&self) -> proc_macro2::Ident {
 +        match self {
 +            Field::Token(_) => format_ident!("SyntaxToken"),
 +            Field::Node { ty, .. } => format_ident!("{}", ty),
 +        }
 +    }
 +}
 +
 +fn lower(grammar: &Grammar) -> AstSrc {
 +    let mut res = AstSrc {
 +        tokens: "Whitespace Comment String ByteString IntNumber FloatNumber Char Byte Ident"
 +            .split_ascii_whitespace()
 +            .map(|it| it.to_string())
 +            .collect::<Vec<_>>(),
 +        ..Default::default()
 +    };
 +
 +    let nodes = grammar.iter().collect::<Vec<_>>();
 +
 +    for &node in &nodes {
 +        let name = grammar[node].name.clone();
 +        let rule = &grammar[node].rule;
 +        match lower_enum(grammar, rule) {
 +            Some(variants) => {
 +                let enum_src = AstEnumSrc { doc: Vec::new(), name, traits: Vec::new(), variants };
 +                res.enums.push(enum_src);
 +            }
 +            None => {
 +                let mut fields = Vec::new();
 +                lower_rule(&mut fields, grammar, None, rule);
 +                res.nodes.push(AstNodeSrc { doc: Vec::new(), name, traits: Vec::new(), fields });
 +            }
 +        }
 +    }
 +
 +    deduplicate_fields(&mut res);
 +    extract_enums(&mut res);
 +    extract_struct_traits(&mut res);
 +    extract_enum_traits(&mut res);
 +    res
 +}
 +
 +fn lower_enum(grammar: &Grammar, rule: &Rule) -> Option<Vec<String>> {
 +    let alternatives = match rule {
 +        Rule::Alt(it) => it,
 +        _ => return None,
 +    };
 +    let mut variants = Vec::new();
 +    for alternative in alternatives {
 +        match alternative {
 +            Rule::Node(it) => variants.push(grammar[*it].name.clone()),
 +            Rule::Token(it) if grammar[*it].name == ";" => (),
 +            _ => return None,
 +        }
 +    }
 +    Some(variants)
 +}
 +
 +fn lower_rule(acc: &mut Vec<Field>, grammar: &Grammar, label: Option<&String>, rule: &Rule) {
 +    if lower_comma_list(acc, grammar, label, rule) {
 +        return;
 +    }
 +
 +    match rule {
 +        Rule::Node(node) => {
 +            let ty = grammar[*node].name.clone();
 +            let name = label.cloned().unwrap_or_else(|| to_lower_snake_case(&ty));
 +            let field = Field::Node { name, ty, cardinality: Cardinality::Optional };
 +            acc.push(field);
 +        }
 +        Rule::Token(token) => {
 +            assert!(label.is_none());
 +            let mut name = grammar[*token].name.clone();
 +            if name != "int_number" && name != "string" {
 +                if "[]{}()".contains(&name) {
 +                    name = format!("'{}'", name);
 +                }
 +                let field = Field::Token(name);
 +                acc.push(field);
 +            }
 +        }
 +        Rule::Rep(inner) => {
 +            if let Rule::Node(node) = &**inner {
 +                let ty = grammar[*node].name.clone();
 +                let name = label.cloned().unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty)));
 +                let field = Field::Node { name, ty, cardinality: Cardinality::Many };
 +                acc.push(field);
 +                return;
 +            }
 +            panic!("unhandled rule: {:?}", rule)
 +        }
 +        Rule::Labeled { label: l, rule } => {
 +            assert!(label.is_none());
 +            let manually_implemented = matches!(
 +                l.as_str(),
 +                "lhs"
 +                    | "rhs"
 +                    | "then_branch"
 +                    | "else_branch"
 +                    | "start"
 +                    | "end"
 +                    | "op"
 +                    | "index"
 +                    | "base"
 +                    | "value"
 +                    | "trait"
 +                    | "self_ty"
++                    | "iterable"
++                    | "condition"
 +            );
 +            if manually_implemented {
 +                return;
 +            }
 +            lower_rule(acc, grammar, Some(l), rule);
 +        }
 +        Rule::Seq(rules) | Rule::Alt(rules) => {
 +            for rule in rules {
 +                lower_rule(acc, grammar, label, rule)
 +            }
 +        }
 +        Rule::Opt(rule) => lower_rule(acc, grammar, label, rule),
 +    }
 +}
 +
 +// (T (',' T)* ','?)
 +fn lower_comma_list(
 +    acc: &mut Vec<Field>,
 +    grammar: &Grammar,
 +    label: Option<&String>,
 +    rule: &Rule,
 +) -> bool {
 +    let rule = match rule {
 +        Rule::Seq(it) => it,
 +        _ => return false,
 +    };
 +    let (node, repeat, trailing_comma) = match rule.as_slice() {
 +        [Rule::Node(node), Rule::Rep(repeat), Rule::Opt(trailing_comma)] => {
 +            (node, repeat, trailing_comma)
 +        }
 +        _ => return false,
 +    };
 +    let repeat = match &**repeat {
 +        Rule::Seq(it) => it,
 +        _ => return false,
 +    };
 +    match repeat.as_slice() {
 +        [comma, Rule::Node(n)] if comma == &**trailing_comma && n == node => (),
 +        _ => return false,
 +    }
 +    let ty = grammar[*node].name.clone();
 +    let name = label.cloned().unwrap_or_else(|| pluralize(&to_lower_snake_case(&ty)));
 +    let field = Field::Node { name, ty, cardinality: Cardinality::Many };
 +    acc.push(field);
 +    true
 +}
 +
 +fn deduplicate_fields(ast: &mut AstSrc) {
 +    for node in &mut ast.nodes {
 +        let mut i = 0;
 +        'outer: while i < node.fields.len() {
 +            for j in 0..i {
 +                let f1 = &node.fields[i];
 +                let f2 = &node.fields[j];
 +                if f1 == f2 {
 +                    node.fields.remove(i);
 +                    continue 'outer;
 +                }
 +            }
 +            i += 1;
 +        }
 +    }
 +}
 +
 +fn extract_enums(ast: &mut AstSrc) {
 +    for node in &mut ast.nodes {
 +        for enm in &ast.enums {
 +            let mut to_remove = Vec::new();
 +            for (i, field) in node.fields.iter().enumerate() {
 +                let ty = field.ty().to_string();
 +                if enm.variants.iter().any(|it| it == &ty) {
 +                    to_remove.push(i);
 +                }
 +            }
 +            if to_remove.len() == enm.variants.len() {
 +                node.remove_field(to_remove);
 +                let ty = enm.name.clone();
 +                let name = to_lower_snake_case(&ty);
 +                node.fields.push(Field::Node { name, ty, cardinality: Cardinality::Optional });
 +            }
 +        }
 +    }
 +}
 +
 +fn extract_struct_traits(ast: &mut AstSrc) {
 +    let traits: &[(&str, &[&str])] = &[
 +        ("HasAttrs", &["attrs"]),
 +        ("HasName", &["name"]),
 +        ("HasVisibility", &["visibility"]),
 +        ("HasGenericParams", &["generic_param_list", "where_clause"]),
 +        ("HasTypeBounds", &["type_bound_list", "colon_token"]),
 +        ("HasModuleItem", &["items"]),
 +        ("HasLoopBody", &["label", "loop_body"]),
 +        ("HasArgList", &["arg_list"]),
 +    ];
 +
 +    for node in &mut ast.nodes {
 +        for (name, methods) in traits {
 +            extract_struct_trait(node, name, methods);
 +        }
 +    }
 +
 +    let nodes_with_doc_comments = [
 +        "SourceFile",
 +        "Fn",
 +        "Struct",
 +        "Union",
 +        "RecordField",
 +        "TupleField",
 +        "Enum",
 +        "Variant",
 +        "Trait",
 +        "Module",
 +        "Static",
 +        "Const",
 +        "TypeAlias",
 +        "Impl",
 +        "ExternBlock",
 +        "ExternCrate",
 +        "MacroCall",
 +        "MacroRules",
 +        "MacroDef",
 +        "Use",
 +    ];
 +
 +    for node in &mut ast.nodes {
 +        if nodes_with_doc_comments.contains(&&*node.name) {
 +            node.traits.push("HasDocComments".into());
 +        }
 +    }
 +}
 +
 +fn extract_struct_trait(node: &mut AstNodeSrc, trait_name: &str, methods: &[&str]) {
 +    let mut to_remove = Vec::new();
 +    for (i, field) in node.fields.iter().enumerate() {
 +        let method_name = field.method_name().to_string();
 +        if methods.iter().any(|&it| it == method_name) {
 +            to_remove.push(i);
 +        }
 +    }
 +    if to_remove.len() == methods.len() {
 +        node.traits.push(trait_name.to_string());
 +        node.remove_field(to_remove);
 +    }
 +}
 +
 +fn extract_enum_traits(ast: &mut AstSrc) {
 +    for enm in &mut ast.enums {
 +        if enm.name == "Stmt" {
 +            continue;
 +        }
 +        let nodes = &ast.nodes;
 +        let mut variant_traits = enm
 +            .variants
 +            .iter()
 +            .map(|var| nodes.iter().find(|it| &it.name == var).unwrap())
 +            .map(|node| node.traits.iter().cloned().collect::<BTreeSet<_>>());
 +
 +        let mut enum_traits = match variant_traits.next() {
 +            Some(it) => it,
 +            None => continue,
 +        };
 +        for traits in variant_traits {
 +            enum_traits = enum_traits.intersection(&traits).cloned().collect();
 +        }
 +        enm.traits = enum_traits.into_iter().collect();
 +    }
 +}
 +
 +impl AstNodeSrc {
 +    fn remove_field(&mut self, to_remove: Vec<usize>) {
 +        to_remove.into_iter().rev().for_each(|idx| {
 +            self.fields.remove(idx);
 +        });
 +    }
 +}
index 468f2b9e981fe29851a793c0fa412ed7718d378c,0000000000000000000000000000000000000000..76bbd1e91889e8267f4eb74c8fd4ed10e2ab5dd4
mode 100644,000000..100644
--- /dev/null
@@@ -1,265 -1,0 +1,266 @@@
- Additionally, it assumes that the remote for `rust-analyzer` is called `upstream` (I use `origin` to point to my fork).
 +# Contributing Quick Start
 +
 +rust-analyzer is an ordinary Rust project, which is organized as a Cargo workspace, builds on stable and doesn't depend on C libraries.
 +So, just
 +
 +```
 +$ cargo test
 +```
 +
 +should be enough to get you started!
 +
 +To learn more about how rust-analyzer works, see [./architecture.md](./architecture.md).
 +It also explains the high-level layout of the source code.
 +Do skim through that document.
 +
 +We also publish rustdoc docs to pages: https://rust-lang.github.io/rust-analyzer/ide/.
 +Note though, that the internal documentation is very incomplete.
 +
 +Various organizational and process issues are discussed in this document.
 +
 +# Getting in Touch
 +
 +rust-analyzer is a part of the [RLS-2.0 working
 +group](https://github.com/rust-lang/compiler-team/tree/6a769c13656c0a6959ebc09e7b1f7c09b86fb9c0/working-groups/rls-2.0).
 +Discussion happens in this Zulip stream:
 +
 +https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frust-analyzer
 +
 +# Issue Labels
 +
 +* [good-first-issue](https://github.com/rust-lang/rust-analyzer/labels/good%20first%20issue)
 +  are good issues to get into the project.
 +* [E-has-instructions](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-has-instructions)
 +  issues have links to the code in question and tests.
 +* [Broken Window](https://github.com/rust-lang/rust-analyzer/issues?q=is:issue+is:open+label:%22Broken+Window%22)
 +  are issues which are not necessarily critical by themselves, but which should be fixed ASAP regardless, to avoid accumulation of technical debt.
 +* [E-easy](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy),
 +  [E-medium](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-medium),
 +  [E-hard](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-hard),
 +  [E-unknown](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AE-unknown),
 +  labels are *estimates* for how hard would be to write a fix. Each triaged issue should have one of these labels.
 +* [S-actionable](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AS-actionable) and
 +  [S-unactionable](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3AS-unactionable)
 +  specify if there are concrete steps to resolve or advance an issue. Roughly, actionable issues need only work to be fixed,
 +  while unactionable ones are blocked either on user feedback (providing a reproducible example), or on larger architectural
 +  work or decisions. This classification is descriptive, not prescriptive, and might be wrong: Any unactionable issue might have a simple fix that we missed.
 +  Each triaged issue should have one of these labels.
 +* [fun](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%3Afun)
 +  is for cool, but probably hard stuff.
 +* [Design](https://github.com/rust-lang/rust-analyzer/issues?q=is%3Aopen+is%3Aissue+label%Design)
 +  is for moderate/large scale architecture discussion.
 +  Also a kind of fun.
 +  These issues should generally include a link to a Zulip discussion thread.
 +
 +# Code Style & Review Process
 +
 +Do see [./style.md](./style.md).
 +
 +# Cookbook
 +
 +## CI
 +
 +We use GitHub Actions for CI.
 +Most of the things, including formatting, are checked by `cargo test`.
 +If `cargo test` passes locally, that's a good sign that CI will be green as well.
 +The only exception is that some long-running tests are skipped locally by default.
 +Use `env RUN_SLOW_TESTS=1 cargo test` to run the full suite.
 +
 +We use bors to enforce the [not rocket science](https://graydon2.dreamwidth.org/1597.html) rule.
 +
 +## Launching rust-analyzer
 +
 +Debugging the language server can be tricky.
 +LSP is rather chatty, so driving it from the command line is not really feasible, driving it via VS Code requires interacting with two processes.
 +
 +For this reason, the best way to see how rust-analyzer works is to **find a relevant test and execute it**.
 +VS Code & Emacs include an action for running a single test.
 +
 +Launching a VS Code instance with a locally built language server is also possible.
 +There's **"Run Extension (Debug Build)"** launch configuration for this in VS Code.
 +
 +In general, I use one of the following workflows for fixing bugs and implementing features:
 +
 +If the problem concerns only internal parts of rust-analyzer (i.e. I don't need to touch the `rust-analyzer` crate or TypeScript code), there is a unit-test for it.
 +So, I use **Rust Analyzer: Run** action in VS Code to run this single test, and then just do printf-driven development/debugging.
 +As a sanity check after I'm done, I use `cargo xtask install --server` and **Reload Window** action in VS Code to verify that the thing works as I expect.
 +
 +If the problem concerns only the VS Code extension, I use **Run Installed Extension** launch configuration from `launch.json`.
 +Notably, this uses the usual `rust-analyzer` binary from `PATH`.
 +For this, it is important to have the following in your `settings.json` file:
 +```json
 +{
 +    "rust-analyzer.server.path": "rust-analyzer"
 +}
 +```
 +After I am done with the fix, I use `cargo xtask install --client` to try the new extension for real.
 +
 +If I need to fix something in the `rust-analyzer` crate, I feel sad because it's on the boundary between the two processes, and working there is slow.
 +I usually just `cargo xtask install --server` and poke changes from my live environment.
 +Note that this uses `--release`, which is usually faster overall, because loading stdlib into debug version of rust-analyzer takes a lot of time.
 +To speed things up, sometimes I open a temporary hello-world project which has `"rust-analyzer.cargo.noSysroot": true` in `.code/settings.json`.
 +This flag causes rust-analyzer to skip loading the sysroot, which greatly reduces the amount of things rust-analyzer needs to do, and makes printf's more useful.
 +Note that you should only use the `eprint!` family of macros for debugging: stdout is used for LSP communication, and `print!` would break it.
 +
 +If I need to fix something simultaneously in the server and in the client, I feel even more sad.
 +I don't have a specific workflow for this case.
 +
 +Additionally, I use `cargo run --release -p rust-analyzer -- analysis-stats path/to/some/rust/crate` to run a batch analysis.
 +This is primarily useful for performance optimizations, or for bug minimization.
 +
 +## TypeScript Tests
 +
 +If you change files under `editors/code` and would like to run the tests and linter, install npm and run:
 +
 +```bash
 +cd editors/code
 +npm ci
 +npm run lint
 +```
 +## How to ...
 +
 +* ... add an assist? [#7535](https://github.com/rust-lang/rust-analyzer/pull/7535)
 +* ... add a new protocol extension? [#4569](https://github.com/rust-lang/rust-analyzer/pull/4569)
 +* ... add a new configuration option? [#7451](https://github.com/rust-lang/rust-analyzer/pull/7451)
 +* ... add a new completion? [#6964](https://github.com/rust-lang/rust-analyzer/pull/6964)
 +* ... allow new syntax in the parser? [#7338](https://github.com/rust-lang/rust-analyzer/pull/7338)
 +
 +## Logging
 +
 +Logging is done by both rust-analyzer and VS Code, so it might be tricky to figure out where logs go.
 +
 +Inside rust-analyzer, we use the [`tracing`](https://docs.rs/tracing/) crate for logging,
 +and [`tracing-subscriber`](https://docs.rs/tracing-subscriber) for logging frontend.
 +By default, log goes to stderr, but the stderr itself is processed by VS Code.
 +`--log-file <PATH>` CLI argument allows logging to file.
 +Setting the `RA_LOG_FILE=<PATH>` environment variable will also log to file, it will also override `--log-file`.
 +
 +To see stderr in the running VS Code instance, go to the "Output" tab of the panel and select `rust-analyzer`.
 +This shows `eprintln!` as well.
 +Note that `stdout` is used for the actual protocol, so `println!` will break things.
 +
 +To log all communication between the server and the client, there are two choices:
 +
 +* You can log on the server side, by running something like
 +  ```
 +  env RA_LOG=lsp_server=debug code .
 +  ```
 +* You can log on the client side, by enabling `"rust-analyzer.trace.server": "verbose"` workspace setting.
 +  These logs are shown in a separate tab in the output and could be used with LSP inspector.
 +  Kudos to [@DJMcNab](https://github.com/DJMcNab) for setting this awesome infra up!
 +
 +
 +There are also several VS Code commands which might be of interest:
 +
 +* `Rust Analyzer: Status` shows some memory-usage statistics.
 +
 +* `Rust Analyzer: Syntax Tree` shows syntax tree of the current file/selection.
 +
 +* `Rust Analyzer: View Hir` shows the HIR expressions within the function containing the cursor.
 +
 +  You can hover over syntax nodes in the opened text file to see the appropriate
 +  rust code that it refers to and the rust editor will also highlight the proper
 +  text range.
 +
 +  If you trigger Go to Definition in the inspected Rust source file,
 +  the syntax tree read-only editor should scroll to and select the
 +  appropriate syntax node token.
 +
 +  ![demo](https://user-images.githubusercontent.com/36276403/78225773-6636a480-74d3-11ea-9d9f-1c9d42da03b0.png)
 +
 +## Profiling
 +
 +We have a built-in hierarchical profiler, you can enable it by using `RA_PROFILE` env-var:
 +
 +```
 +RA_PROFILE=*             // dump everything
 +RA_PROFILE=foo|bar|baz   // enabled only selected entries
 +RA_PROFILE=*@3>10        // dump everything, up to depth 3, if it takes more than 10 ms
 +```
 +
 +In particular, I have `export RA_PROFILE='*>10'` in my shell profile.
 +
 +We also have a "counting" profiler which counts number of instances of popular structs.
 +It is enabled by `RA_COUNT=1`.
 +
 +To measure time for from-scratch analysis, use something like this:
 +
 +```
 +$ cargo run --release -p rust-analyzer -- analysis-stats ../chalk/
 +```
 +
 +For measuring time of incremental analysis, use either of these:
 +
 +```
 +$ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --highlight ../chalk/chalk-engine/src/logic.rs
 +$ cargo run --release -p rust-analyzer -- analysis-bench ../chalk/ --complete ../chalk/chalk-engine/src/logic.rs:94:0
 +```
 +
 +Look for `fn benchmark_xxx` tests for a quick way to reproduce performance problems.
 +
 +## Release Process
 +
 +Release process is handled by `release`, `dist` and `promote` xtasks, `release` being the main one.
 +
 +`release` assumes that you have checkouts of `rust-analyzer`, `rust-analyzer.github.io`, and `rust-lang/rust` in the same directory:
 +
 +```
 +./rust-analyzer
 +./rust-analyzer.github.io
 +./rust-rust-analyzer  # Note the name!
 +```
 +
-      * pushes VS Code extension to the marketplace
++The remote for `rust-analyzer` must be called `upstream` (I use `origin` to point to my fork).
++In addition, for `xtask promote` (see below), `rust-rust-analyzer` must have a `rust-analyzer` remote pointing to this repository on GitHub.
 +
 +`release` calls the GitHub API calls to scrape pull request comments and categorize them in the changelog.
 +This step uses the `curl` and `jq` applications, which need to be available in `PATH`.
 +Finally, you need to obtain a GitHub personal access token and set the `GITHUB_TOKEN` environment variable.
 +
 +Release steps:
 +
 +1. Set the `GITHUB_TOKEN` environment variable.
 +2. Inside rust-analyzer, run `cargo xtask release`. This will:
 +   * checkout the `release` branch
 +   * reset it to `upstream/nightly`
 +   * push it to `upstream`. This triggers GitHub Actions which:
 +     * runs `cargo xtask dist` to package binaries and VS Code extension
 +     * makes a GitHub release
- 6. Inside `rust-analyzer`, run `cargo xtask promote` -- this will create a PR to rust-lang/rust updating rust-analyzer's submodule.
++     * publishes the VS Code extension to the marketplace
 +   * call the GitHub API for PR details
 +   * create a new changelog in `rust-analyzer.github.io`
 +3. While the release is in progress, fill in the changelog
 +4. Commit & push the changelog
 +5. Tweet
++6. Inside `rust-analyzer`, run `cargo xtask promote` -- this will create a PR to rust-lang/rust updating rust-analyzer's subtree.
 +   Self-approve the PR.
 +
 +If the GitHub Actions release fails because of a transient problem like a timeout, you can re-run the job from the Actions console.
 +If it fails because of something that needs to be fixed, remove the release tag (if needed), fix the problem, then start over.
 +Make sure to remove the new changelog post created when running `cargo xtask release` a second time.
 +
 +We release "nightly" every night automatically and promote the latest nightly to "stable" manually, every week.
 +
 +We don't do "patch" releases, unless something truly egregious comes up.
 +To do a patch release, cherry-pick the fix on top of the current `release` branch and push the branch.
 +There's no need to write a changelog for a patch release, it's OK to include the notes about the fix into the next weekly one.
 +Note: we tag releases by dates, releasing a patch release on the same day should work (by overwriting a tag), but I am not 100% sure.
 +
 +## Permissions
 +
 +There are three sets of people with extra permissions:
 +
 +* rust-analyzer GitHub organization [**admins**](https://github.com/orgs/rust-analyzer/people?query=role:owner) (which include current t-compiler leads).
 +  Admins have full access to the org.
 +* [**review**](https://github.com/orgs/rust-analyzer/teams/review) team in the organization.
 +  Reviewers have `r+` access to all of organization's repositories and publish rights on crates.io.
 +  They also have direct commit access, but all changes should via bors queue.
 +  It's ok to self-approve if you think you know what you are doing!
 +  bors should automatically sync the permissions.
 +  Feel free to request a review or assign any PR to a reviewer with the relevant expertise to bring the work to their attention.
 +  Don't feel pressured to review assigned PRs though.
 +  If you don't feel like reviewing for whatever reason, someone else will pick the review up!
 +* [**triage**](https://github.com/orgs/rust-analyzer/teams/triage) team in the organization.
 +  This team can label and close issues.
 +
 +Note that at the time being you need to be a member of the org yourself to view the links.
index 1c5fc64c2417e993b4f09f50f5269c3f58609b06,0000000000000000000000000000000000000000..17ada5156407e99b3e416303382f4b0ba0da64df
mode 100644,000000..100644
--- /dev/null
@@@ -1,102 -1,0 +1,96 @@@
-         cmd!(sh, "git submodule update --recursive").run()?;
 +mod changelog;
 +
 +use xshell::{cmd, Shell};
 +
 +use crate::{date_iso, flags, is_release_tag, project_root};
 +
 +impl flags::Release {
 +    pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
 +        if !self.dry_run {
 +            cmd!(sh, "git switch release").run()?;
 +            cmd!(sh, "git fetch upstream --tags --force").run()?;
 +            cmd!(sh, "git reset --hard tags/nightly").run()?;
 +            // The `release` branch sometimes has a couple of cherry-picked
 +            // commits for patch releases. If that's the case, just overwrite
 +            // it. As we are setting `release` branch to an up-to-date `nightly`
 +            // tag, this shouldn't be problematic in general.
 +            //
 +            // Note that, as we tag releases, we don't worry about "losing"
 +            // commits -- they'll be kept alive by the tag. More generally, we
 +            // don't care about historic releases all that much, it's fine even
 +            // to delete old tags.
 +            cmd!(sh, "git push --force").run()?;
 +        }
 +
 +        // Generates bits of manual.adoc.
 +        cmd!(sh, "cargo test -p ide-assists -p ide-diagnostics -p rust-analyzer -- sourcegen_")
 +            .run()?;
 +
 +        let website_root = project_root().join("../rust-analyzer.github.io");
 +        {
 +            let _dir = sh.push_dir(&website_root);
 +            cmd!(sh, "git switch src").run()?;
 +            cmd!(sh, "git pull").run()?;
 +        }
 +        let changelog_dir = website_root.join("./thisweek/_posts");
 +
 +        let today = date_iso(sh)?;
 +        let commit = cmd!(sh, "git rev-parse HEAD").read()?;
 +        let changelog_n = sh
 +            .read_dir(changelog_dir.as_path())?
 +            .into_iter()
 +            .filter_map(|p| p.file_stem().map(|s| s.to_string_lossy().to_string()))
 +            .filter_map(|s| s.splitn(5, '-').last().map(|n| n.replace('-', ".")))
 +            .filter_map(|s| s.parse::<f32>().ok())
 +            .map(|n| 1 + n.floor() as usize)
 +            .max()
 +            .unwrap_or_default();
 +
 +        for adoc in [
 +            "manual.adoc",
 +            "generated_assists.adoc",
 +            "generated_config.adoc",
 +            "generated_diagnostic.adoc",
 +            "generated_features.adoc",
 +        ] {
 +            let src = project_root().join("./docs/user/").join(adoc);
 +            let dst = website_root.join(adoc);
 +
 +            let contents = sh.read_file(src)?;
 +            sh.write_file(dst, contents)?;
 +        }
 +
 +        let tags = cmd!(sh, "git tag --list").read()?;
 +        let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap();
 +
 +        let contents = changelog::get_changelog(sh, changelog_n, &commit, prev_tag, &today)?;
 +        let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n));
 +        sh.write_file(&path, &contents)?;
 +
 +        Ok(())
 +    }
 +}
 +
 +impl flags::Promote {
 +    pub(crate) fn run(self, sh: &Shell) -> anyhow::Result<()> {
 +        let _dir = sh.push_dir("../rust-rust-analyzer");
 +        cmd!(sh, "git switch master").run()?;
 +        cmd!(sh, "git fetch upstream").run()?;
 +        cmd!(sh, "git reset --hard upstream/master").run()?;
-         {
-             let _dir = sh.push_dir("src/tools/rust-analyzer");
-             cmd!(sh, "git fetch origin").run()?;
-             cmd!(sh, "git reset --hard origin/release").run()?;
-         }
-         cmd!(sh, "git add src/tools/rust-analyzer").run()?;
-         cmd!(sh, "git commit -m':arrow_up: rust-analyzer'").run()?;
 +
 +        let date = date_iso(sh)?;
 +        let branch = format!("rust-analyzer-{date}");
 +        cmd!(sh, "git switch -c {branch}").run()?;
++        cmd!(sh, "git subtree pull -P src/tools/rust-analyzer rust-analyzer master").run()?;
++
 +        if !self.dry_run {
 +            cmd!(sh, "git push -u origin {branch}").run()?;
 +            cmd!(
 +                sh,
 +                "xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost"
 +            )
 +            .run()?;
 +        }
 +        Ok(())
 +    }
 +}