Rust

[languages.rust]           # off unless the table is written
include = ["**/*.rs"]      # the default
ignore_unresolved = ["generated::*"]   # paths not to warn about
Option
includeGlobs of the files to scan.
ignore_unresolvedName patterns of the paths that are expected not to resolve, so are not reported as unresolved, such as a module that a macro declares.

Packages

Every Cargo package of the project is a crate, which pkg: selects by its package name, so pkg:zenith_lang_* selects the crates whose names start with zenith_lang_. zenith asks Cargo for the crates, with cargo metadata --no-deps --offline, which reads the manifests but resolves no versions and never touches the network. Without Cargo, or when it fails, zenith reads the Cargo.toml files itself and finds each crate's targets the way Cargo does.

Each target of a crate is the root of a module tree: its library, its binaries, its tests, benchmarks and examples, and its build script. The other targets of a crate use its library by its name.

Imports

Every import is a value import. Each use declaration imports each of its leaves, so use a::{b, c::d} imports a::b and a::c::d, and a glob imports the path before it. So does an extern crate, and so does a path in code that starts with crate, self, super, :: or the name of a crate or module, such as zenith_lang_js::JS written without a use. A use path that starts with a name that another use or an extern crate brought into scope imports what the name stands for: after use smoltcp::socket::tcp;, use tcp::State; imports smoltcp::socket::tcp::State. mod a; declares a module but doesn't import it. zenith-ignore comments work as // or /* */ comments.

The tokens of a macro call or an attribute aren't parsed as code, so zenith reads the paths in them: vec![crate::a::b()] imports crate::a::b. A path that starts at a macro variable, such as $crate::a or $module::a, or at an interpolation, which macros like quote! write as #krate::a, imports nothing. Nor does a path in the body of quote!, quote_spanned!, parse_quote! or parse_quote_spanned!, whatever path names the macro: the body is code that a procedural macro generates for the crates that use it, so its paths are theirs, not imports of the macro's crate.

Files are parsed with rust-analyzer's parser, in the edition of their crate, which Cargo or the crate's Cargo.toml gives (and Rust 2015 if it gives none). A file in no crate is parsed in the latest edition.

Resolution

A path imports the file of the last module on it: a.rs or a/mod.rs for the module a, in the module tree of the importing file's target. The rest of the path is items in that file. The file is spelt as the module is, even where names ignore case, as they do by default on macOS and Windows, so crate::Config is the type Config in the crate root, not the module in config.rs. A crate's own dependencies, from its [dependencies], [dev-dependencies] and [build-dependencies], including renamed ones and those that workspace = true takes from the workspace, are the crates that its code may name.

ImportedNode
a module of the projectcrates/api/src/store.rsIts file. A dependency that is a crate of the project resolves into the module tree of its library.
another cratecrate:serdeNamed by its package.
the standard libraryrust:stdstd, core, alloc, proc_macro and test.

An inline mod a { } block is part of its file, so a path into it, used or not, imports nothing. #[path] attributes are not followed, and a file doesn't import itself. A raw identifier names what it spells: r#false is the module false. A path that starts with the name of a tool, such as clippy::too_many_lines in an #[allow] or rustfmt::skip, is the tool's attribute or lint, and imports nothing unless a crate or module has the name.