Skip to main content

Crate brink_analyzer

Crate brink_analyzer 

Source
Expand description

Cross-file semantic analysis for inkle’s ink narrative scripting language.

The analyzer merges per-file SymbolManifests from brink-ir into a unified SymbolIndex, then runs validation passes (name resolution, duplicate detection, type checking). Both brink-compiler and brink-lsp consume the analysis result.

Structs§

AnalysisOptions
Tooling options for analysis: the registered host manifest and the severity policy for its external checks. Defaults to no manifest.
AnalysisResult
The output of cross-file semantic analysis.
AnalyzerTablesOwned
Owned form of brink_ir::lir::AnalyzerTables (issue #1527) — every analyzer side-table LIR lowering reads, held by value instead of by the borrowed references AnalyzerTables itself carries. A caller builds one of these (via assemble_analyzer_tables) and then borrows its fields into an AnalyzerTables at the lowering call site, exactly as brink-db’s two salsa queries already borrow their own owned UfcsLookup/CoalesceLookup locals.
BodyTypes
The full inferred picture of one def’s body: params, every local (params ∪ temps) by name, and the return type. A superset of InferredSigsignatures is the firewall-facing projection, bodies is what a hover/diagnostic consumer (TM-5) wants.
CallGraph
A directed call graph over inferable definitions.
CoalesceChain
Every step of one or-coalescing chain, innermost first.
CoalesceStep
The recorded types of one or step, in the left-associative order the grammar builds.
CueHarvest
One @NAME cue’s harvest record: every occurrence project-wide, in no particular merge order (a completion consumer sorts as it needs).
Def
One inferable definition: its own id, declaring file, declared params, and body.
DirectCallArgMismatch
One statically-checkable argument-type mismatch recorded at any of three producer sites whose callee resolves straight to a known def via known_sigs — so its declared parameter types are already fully known at the site — unlike the T1c call-through-a-value case ValueCallFact exists for:
EffectAtoms
The raw per-definition atoms harvested from one body walk — the inputs the solve_scc_effects fixpoint closes over. reads/writes/calls are the direct atoms this body emits; direct_calls are the inferable (knot/stitch) callees whose rows must be joined in transitively; creates_fn_values are the targets this body creates fn values for (Fork A, issue #1726 — structural, fed into the call graph alongside direct_calls); opaque records that the body performed a call through a function value whose reaching values were not all created in-project (or another effects-opaque construct), forcing the pessimal floor.
EffectRow
A static summary of the atomic effects a definition (and everything it transitively calls) may perform — the spec §2 “row”. Unordered sets over a finite per-project lattice, so join is a monotone least-upper-bound and the per-SCC fixpoint terminates without widening.
FieldAssignMismatch
One statically-checkable type mismatch at a dotted struct-field assignment target (issue #1900, split from #1864/#1877 — PR #1899’s own check_declared_assign_target explicitly excludes a multi-segment target, since a dotted target’s declared type is its root’s shape, not the field’s).
FileId
Opaque identifier for a source file within a multi-file project.
FnRow
The effect row riding a Ty::Fndocs/effects-spec.md §5 (“rows ride the unifier — the heap answer”), issue #1680 step 3.
HarvestIndex
The project-wide harvest index (issue #2114): every @NAME cue payload and every inline-markup span kind/attribute name, keyed by name so completion crosses files — the compiler-side sibling of crate::SymbolIndex.
HarvestNames
Range-free completion projection of a HarvestIndex (issue #2134).
HarvestSite
One occurrence of a harvested name — lets a completion consumer answer “where is this used”, not just “does this name exist”.
ImportScope
Per-file import context threaded into resolution (M-2d, docs/modules-spec.md §2; issue #790) so a bare reference with multiple cross-module candidates binds to the module this file actually imports — “names cross module boundaries only via import” — rather than to the flat duplicate-winner.
InferenceResult
The whole-project inference result (mirrors AnalysisResult’s shape: one pure function over already-computed inputs, callable directly or wrapped as a salsa query).
InferredSig
A def’s inferred signature: positional param types (declaration order) plus a return type. The generalized, per-def result of a body’s fixpoint solve — what a caller reads (never the caller reading the callee’s body directly; that’s the firewall).
LambdaAnnotationMismatch
One incompatibility between a lambda’s own written annotation (a param’s : T or the lambda’s : R return annotation) and its body-derived type (issue #1994, RULED 2026-08-01, closing #1932: “the written annotation takes priority… an incompatible body is an eager error at the lambda, not a deferred surprise at the call site”).
LambdaEscapeSlot
One lambda-body param or body-declared temp, ready for the same Unknown-escape (E065) / Conflicted-escape (E066) treatment strict::check_def already gives a top-level def’s own params/ locals (issue #1770: “lambda bodies are invisible to strict-mode escape checking… give lambda bodies a per-lambda frame”).
LintPolicy
The resolved [lints] policy (issue #1160): per-code severity overrides plus the blanket deny-warnings flag. Bundled as its own small, cheaply-PartialEq-comparable value — rather than as two loose scalars — so brink-db’s severity-partitioning call sites can share one narrow salsa projection the same way TypePolicy already does (see brink-db’s type_policy_query/lint_policy_query doc comments for the cutoff argument).
NodeKey
Identity of one HIR node for side-table purposes: the file it lives in plus its source range.
ProjectConfig
ProtocolImplDecl
One protocol impl registration: “function implements protocol for the declared STRUCT named type_name”. Programmatic v1 (see the module doc) — the future source spelling lowers into this same shape.
ResolvedModule
A file’s resolved module (M-1, docs/modules-spec.md §1/§5).
ResolvedParam
A merged parameter: name (from the ink declaration) and resolved type.
ResolvedType
A resolved type reference: the written name, its base type (if resolvable), and any closed-domain constraint (from a semantic type definition).
SccGraph
scc_graph’s output: the dependency-ordered component membership plus the condensation DAG’s adjacency, keyed by each component’s stable id — its own minimum member (FG-2, issue #631’s scc_membership() query; SccId is a plain DefinitionId in brink-db’s query layer, per the design doc’s “already the sort key in graph.rs” note).
ShapeInfo
One declared struct shape: fields in declaration order, name -> declared type (Ty::Unknown if the field’s own annotation doesn’t resolve — e.g. an unrecognized type name, already flagged elsewhere by annotations::check’s E061).
ShapeTable
declared_shapes’ referrer-scoped lookup table — see that function’s doc for the coexistence story this exists to resolve correctly.
SideTable
A (node → payload) side channel: analysis verdicts recorded beside the HIR rather than written into it (D2 — the HIR stays immutable).
Sig
Per-declaration signature summary (phase-0 stub).
SpanHarvest
One markup span kind’s harvest record.
SpanNames
One markup span kind’s range-free completion record — see HarvestNames.
SymbolMeta
Per-symbol merged metadata (docs, types, values), surfaced to the IDE and used by the call-site checks. Keyed by the symbol’s DefinitionId on the AnalysisResult. For externals this merges inline docs with the registered host manifest; knots/stitches carry inline docs only; VAR/CONST add an inferred initializer value.
TypedAssignMismatch
One statically-checkable type mismatch at a declaration-initializer or assignment site against an already-known declared type (issue #1877) — the ~ temp/plain-assignment sibling of DirectCallArgMismatch, which covers only direct-call arguments.
UfcsArgMismatch
One statically-checkable argument-type mismatch at a UFCS-desugared free function call (recv.name(args)name(recv, args)) — issue #1881, the UFCS sibling of infer::DirectCallArgMismatch (#1864/PR #1875, direct calls) and infer::TypedAssignMismatch (#1877/PR #1899, declaration initializers and assignments). Reported by [check_strict] as E063, the same code the other two siblings use — no new code minted for this position (docs/t1c-spec.md §8’s “existing TM-3 machinery” posture, extended here rather than a parallel checker).
UfcsCallArgs
One UFCS-desugared call site’s (recv.name(args)name(recv, args)) written-argument types (issue #1881) — the receiver itself is not included here (its type is already known directly to ufcs::UfcsVisitor, this fact’s sole consumer, from receiver-type resolution). Recorded unconditionally at every multi-segment, value-resolving call this pass walks (see body::InferPass::infer_call’s own doc for why it cannot check anything against a UFCS receiver directly) — this is the raw per-argument type data brink_analyzer::ufcs’s own resolution pass needs to complete its own argument-type check against the desugared free function’s already-known declared param types (InferenceResult::signatures, keyed by the target), without a second expression-type inference pass over the same body.
ValueCallFact
One statically-checkable fact about a call through a function value (T1c, docs/t1c-spec.md §4 — “under types = strict, calls through function values are statically checked”).
ValueMeta
Initializer-derived metadata for a VAR or CONST declaration. Purely presentational — ink variables are dynamically retyped at runtime, so this never drives diagnostics.

Enums§

CoalesceError
Why an coalesce application is ill-typed (NS-A1, F19).
CoalesceShape
Which of infer::ty::coalesce’s three outcomes one or step took — the shape question LIR lowering asks, answered from types instead of syntax.
Dialect
Compiler dialect: gates T1b brink-extension syntax. Default StrictInk — divergence from the oracle-anchored ink subset is a visible, one-time, per-project choice (docs/t1b-surface-spec.md §1).
ExternalCheckSeverity
Severity policy for manifest-driven external checks. Configurable as a compiler/IDE flag; defaults to Error (a registered manifest is binding).
InferredType
The type of a VAR/CONST initializer literal. Deliberately separate from the host-manifest BaseType vocabulary — Divert/List are ink runtime concepts that must not leak into the manifest serialization schema.
LintLevel
A [lints] table entry’s severity (issue #1160) — mirrors Rust’s own [lints] levels. Warn is every diagnostic code’s implicit level when [lints] doesn’t mention it, so it doubles as this type’s Default.
Protocol
One entry of the closed protocol registry (stdlib-spec §9.6). The enum is the registry: adding an entry is a compiler change by construction.
SemanticTypeDiagnosticSeverity
Severity policy for unknown-semantic-type diagnostics (E040), parallel to ExternalCheckSeverity. Configurable as a compiler/IDE flag; defaults to Tolerant — the #339/#527 default-tolerant path, where an unresolved semantic type is only diagnosed once a HostManifest is registered. Raising it to Error opts back into strict checking (E040 fires for any unresolved type even with no manifest registered) — e.g. so a host can catch typo’d semantic-type tags before wiring up a full manifest (#532).
Ty
A type in the checker’s universe (typed-mode-spec §2).
TypePolicy
types project policy (docs/typed-mode-spec.md §1). Gradual is the pre-flip behavior — Unknown unifies with anything, annotations are optional seasoning, and the strict checks do not run. Strict requires dialect = brink.
UfcsVerdict
What one recv.name(args) call site resolved to (D2’s “node → resolved target”). Consumed by LIR lowering — which of the two code shapes to emit — and by IDE hover/go-to-def, which needs the real target rather than the receiver the ResolutionMap records for the callee path.
ValueCallKind
What a ValueCallFact observed. Strict mode maps these onto the existing TM-3 machinery — escape codes for unresolved callees, the typed-mismatch code for known-type disagreements — rather than minting parallel codes (docs/t1c-spec.md §8).

Functions§

analyze
Run cross-file semantic analysis with default options (no host manifest).
analyze_with_options
analyze with explicit tooling options — same test-fixture status and same deliberately absent module/nativeness parameters (see analyze).
annotation_mismatches
Compare each def’s annotated param/return types (Sig, declaration-only) against the same def’s body-inferred types (InferenceResult, from infer_project/the composed call_edgessolve_scc path) and report a disagreement. Advisory-only (E063 is a warning) — severity policy for strict mode is TM-3’s call, not this one’s.
assemble_analyzer_tables
Assemble every analyzer side-table LIR lowering needs, from scratch, in one whole-project pass — the one path a caller with no salsa layer of its own must use (issue #1528).
assignable
Is a value of type source legal in a slot declared target?
await_condition_callees
Every DefinitionId called (directly) from any await condition in hir, resolved through resolutions. The salsa path (brink-db‘s await_purity_diagnostics_query) uses this to fetch exactly those defs’ memoized per-def effect rows — the incremental analogue of the monolithic path handing check the whole-project crate::infer::effects_project table. A callee that resolves to a non-inferable symbol (an EXTERNAL, a VAR fn-value) simply has no per-def row; check handles it via the same resolution it does here, so the two paths agree.
await_purity_diagnostics
Check every await condition in hir against the whole-project effect rows rows (docs/flow-suspension-spec.md §3/§5). Returns an E105 for each condition that is not effect-free (read-only).
call_edges
Pass 1, exposed per one definition (FG-2, issue #631 — call_edges(def)). Computes exactly what [build_call_graph]’s loop body computes for one def: infer this def’s body with known_sigs empty (every call resolves Unknown; only the set of resolved call targets is kept, matching the design doc’s explicit “keep reusing infer_def_body and discard types, as today” allowance for this query). Returns an empty set for an unknown/non-inferable def id — same “absent data reads as empty, never panics” contract as the rest of this module.
call_site_metas
Project the external-kind entries of an enrichment map to a name-keyed map for the call-site checks (issue #750 / FG-3 completion). Range-free by construction (SymbolMeta carries no spans), so brink-db can put an Eq-cutoff memo between the (often-invalidated, full-ranged-index- reading) enrichment pass and every file’s call-site walk — the resolution_index playbook.
check_annotations
Semantic diagnostics on annotation content: unknown type names (E061). Brink-dialect-only (see module doc). manifest: the registered host manifest, if any — T1d-2’s Handle<K> vocabulary source (None degrades to an empty handle-kind set, same posture as every other manifest-driven check).
check_anonymous_stateful
Run the lint over one already-lowered file’s HirFile. Both lower_file (ink) and lower_native_file (native) in brink-db call this per file — see the module doc’s “Wiring” section.
check_native_choice_dead_end
Run the lint over one native file’s already-lowered HirFile. Only meaningful for HIR the native frontend produced — never call this against ink-produced HIR (see the module doc’s “Native-only” section).
check_protocol_impls
Validate registered protocol impls: shape against the protocol’s signature (E115) and inferred effect row against the protocol’s contract (E114). Returns all diagnostics; an impl that fails a shape check is not row-checked (the E102-before-E103 posture — don’t stack a second diagnostic on an impl that can’t even be resolved).
check_reserved_names
Check one file for author declarations of the reserved protocol method names (E113, hard error). Brink-dialect-only — the caller (per_file_diagnostics) gates the call, mirroring the annotation- content precedent: under strict-ink there is no protocol registry and vanilla ink identifiers stay untouched.
coalesce
The or-coalescing TYPING rule (NS-A1; docs/stdlib-phase-c-findings.md F19’s recommendation, implemented as ruled by wave A1’s scope):
coalesce_lir_lookup
Translate a CoalesceTable into brink-ir’s own lowering-facing mirror — the one translation point between the two crates (issue #1471), exactly as crate::ufcs_lir_lookup is for the UFCS table.
coalesce_types
The B1 or-coalescing typing side table for a project (issue #1492): the chain root → per-step operand/result types channel LIR lowering reads to choose a chain’s code shape — “inner stays Option” vs “unwrap at the end” — instead of re-deriving the answer from syntax it cannot see through (a call’s return type, a VAR’s declared type).
collect_external_sigs
Declaration-derived EXTERNAL signatures (issue #786, docs/t1d-spec.md §3: “a binding declared to take Handle<AudioInstance> rejects a Handle<Timer> argument at compile time” under types = strict; issue #805 widens this to the manifest’s full scalar-semantic-type vocabulary and to inline-doc-only bindings).
comparator_callees
Every DefinitionId named as a statically-named-function callback (#fn(target) literal, or the native bare-name spelling) of a pure-callback verb call in hir, resolved through resolutions and index. The salsa path (brink-db‘s comparator_contract_diagnostics_query) uses this to fetch exactly those defs’ memoized per-def effect rows — the incremental analogue of the monolithic path handing check the whole-project effects_project table (the await_condition_callees shape).
comparator_contract_diagnostics
Check every pure-callback verb call in hir (see [callback_arg_index]) whose callback is a statically-named function — an inline #fn(target) literal (ink/brink), or the sigil-free native bare-name spelling (.brink, issue #1862/#1887: map(items, double)) — against the whole-project effect rows. Returns an E119 for each callback whose row provably exceeds pure·silent.
conventions_confinement_diagnostics
Run the confinement/unconfigured E169 checks (conventions_module_diagnostics/conventions_unconfigured_diagnostics) for a caller with no live ProjectDb to ask per-file — the off-db analysis road (issue #2335: IdeSnapshot::analyze/session.analysis(), reached through [crate::analyze_with_modules], this function’s one caller).
conventions_module_diagnostics
Diagnose every claiming handler declared in hir when this file is not the project’s configured conventions module.
conventions_pointer_unresolvable_diagnostics
Diagnose every claiming handler declared in hir when the project’s [project] conventions pointer is well-formed (path-shaped) but resolves to no real file in the project (issue #2320) — a typo’d, moved, or deleted target, or a pointer whose minted module does not match any file’s real module because the brink.toml declaring it was discovered at a nested key (the issue’s own brink-web case). The message blames the mismatch, not the author: either side of it may be the one that’s wrong.
conventions_unconfigured_diagnostics
Diagnose every claiming handler declared in hir when the project has no conventions module configured at all (issue #2289, part 2 of the 2026-08-05 ruling — see this module’s own doc, “What IS now enforced”).
declared_shapes
Every declared STRUCT shape in the project — a referrer-scoped lookup table (issue #2241).
def_body
Find one inferable def’s own params + body from a declaring-file-scoped HIR slice alone (FG-2.1, issue #638, Ruling 2b — backs brink-db’s per-def def_body_query(def) projection, the inference_index_query precedent applied to bodies). A thin filter over the same [collect_defs] walk call_edges/solve_scc already used project-wide, scoped here to exactly def’s declaring file so the salsa wrapper records a read-edge on only that file’s lowered_query — not every project file’s. Returns owned data (Vec<Param>/Block both Clone) since the salsa caller stores the result in a long-lived memo, past the borrow of any one lowered_query call.
def_effect_atoms
T2-1 (docs/effects-spec.md §2/§4, issue #860 — def_effect_atoms(def)). One def’s raw effect atoms: the read set (VAR/CONST globals read), the write set (assignment targets resolving to a VAR/CONST), the call-kind set (EXTERNAL names directly called), the inferable direct-call edges the effect fixpoint follows, the fn-value creation targets (Fork A, issue #1726 — EffectAtoms::creates_fn_values), and whether the body calls through a function value it cannot trace (→ pessimal). Harvested by the exact same body walk referenced_globals/call_edges drive — the read set here is FG-2.1’s referenced_globals, and the direct-call edges are call_edges’s set — so no new walk shape is introduced, only the per-def atom bundle T2 needs assembled from one pass.
effect_atom_name
The author-facing name of one effect-row atom.
effective_severity
The severity a diagnostic code should actually be reported at, given the project’s types policy and resolved [lints] policy — the single seam every diagnostic-partitioning site must call instead of the raw brink_ir::DiagnosticCode::severity default.
effects_assertion_defs
Every def carrying a #@effects(…) assertion in hir, paired with the DefinitionId the exceedance check needs its row for — the seam a salsa caller uses to fetch exactly those rows (and no others) via the per-def effects(def) query, keeping unannotated projects inference-free.
effects_assertion_diagnostics
Check every knot/stitch’s #@effects(…) assertion in hir against rows — that def’s inferred EffectRow, however the caller computed it: the whole-project pure crate::effects_project for the analyzer’s monolithic path, or, for the salsa-memoized production path, a small map built from individual per-def effects(def) queries (only for the defs that actually carry an assertion, preserving the advisory/lazy invariant — an unannotated project never triggers effect inference at all).
effects_project
T2-1 (docs/effects-spec.md §4, issue #860 — the whole-project effect row table). Mirrors infer_project’s shape for effects: harvest every inferable def’s atoms, build the same call graph off the direct-call edges, solve every SCC batch in condensation order with solve_scc_effects (accumulating each finalized batch’s rows as known_rows for its successors). A pure function of already-computed inputs — the direct-call pure-function callers and the property tests use it; brink-db’s per-SCC effects_scc_query reproduces the same fold incrementally.
erase_fn_rows
Rewrite every Ty::Fn anywhere inside ty to carry the top FnRow — the canonical form used to compare two types modulo their effect rows. Recurses through every structural variant so a row nested inside array<fn(): int> or fn(fn(): int): int is erased too.
external_meta_diagnostics
The index-driven half of the external-check family (issue #750 / FG-3 completion): host-manifest enrichment + checks for EXTERNALs ([external_check::analyze_externals] — arity E039, unknown semantic types E040) followed by knot/stitch doc enrichment ([external_check::enrich_callables], same E040 vocabulary), in exactly that order for both the diagnostics and the symbol_meta merge. Reads the index and the merged inline docs only — never any file’s HIR — which is what lets brink-db memoize it separately from the per-file HIR walks (file_value_meta / file_call_site_diagnostics).
file_call_site_diagnostics
One file’s external call-site literal checks (E041 type mismatch, E042 closed domain) — the per-file slice of [external_check::check_call_sites] (issue #750 / FG-3 completion). The checker only ever reads the file it is visiting plus the name-keyed external metas, so the per-file split is behavior-neutral; the caller owns both the ExternalCheckSeverity gate and the file-order concatenation the single whole-project walk produced.
file_value_meta
One file’s VAR/CONST/LIST initializer/doc enrichment (issue #750 / FG-3 completion — the per-file slice of [external_check::infer_value_meta], which whole_project_diagnostics used to run as one loop over every file’s HIR). Purely presentational — never produces diagnostics. A declaration’s initializer lives in exactly one file, so the per-file split is behavior-neutral: the whole-project result is the file-order merge of the per-file maps (later files overwrite on the — deliberately deterministic — duplicate-name id collision, exactly as the single loop did). Reads no symbol ranges from index (only by_name + kind), so a range-zeroed index projection serves it.
finish_analysis
Assemble the final AnalysisResult from the already-computed layer-2 pieces (index + per-file resolutions), running the remaining passes: per-file diagnostic contributors (per_file_diagnostics) for every file, then the whole-project contributors (whole_project_diagnostics).
harvest
Build the project-wide harvest index from every file’s HIR, upgrading any markup span kind the host manifest declares.
hir_has_await
Cheap structural scan: does any knot/stitch body in hir contain an await suspension point? The laziness gate for the whole-project purity pass — an await-free project never triggers effect inference for this pass, mirroring the #@effects exceedance pass’s own laziness gate.
hir_has_comparator_site
Cheap structural scan: does any knot/stitch body in hir contain a pure-callback verb call whose callback is an inline #fn(…) literal, or (native files only) a bare-name reference that might be one? The laziness gate for the whole-project pass — a project without such a site never triggers effect inference here, mirroring the #@effects and await-purity gates.
infer_project
Infer types for every knot/stitch body across the whole project.
inferable_defs
Every inferable (knot/stitch) definition’s id in the project (FG-2, issue #631). A cheap structural scan — needs the whole project’s HIR to enumerate every def’s body. Superseded, for brink-db’s per-def/per-SCC query wiring, by inferable_defs_from_index (FG-2.1, issue #638, Ruling 2b — the same id set, sourced from the index alone, no HIR read); kept for direct pure-function callers (e.g. infer_project) and as the equivalence anchor inferable_defs_from_index_matches_hir_derived_set pins.
inferable_defs_from_index
The same inferable (knot/stitch) def id set as inferable_defs, read directly off the index’s SymbolKind — no HIR (FG-2.1, issue #638, Ruling 2b: “inferable comes from an index-sourced inferable_defs_query (dep = inference_index_query, not HIR)”). A knot/stitch symbol is always indexed at exactly the same moment its hir.knots entry is lowered (lower_single_knot/lower_top_level), so filtering index.symbols by kind here is output-identical to walking every file’s HIR the way inferable_defs does — pinned by inferable_defs_from_index_matches_hir_derived_set.
is_path_shaped_conventions_pointer
Whether a [project] conventions pointer names a project-relative path to a .brink conventions module, as opposed to a bare built-in preset name (docs/prose-dialect-spec.md §3.4’s “either shape” pointer mechanism). A path either contains a directory separator or ends in the .brink extension; a bare word (no separator, no extension) is a preset name.
is_reserved_protocol_name
Whether name is a reserved protocol method name (F6, ruled 2026-07-19): display, compare, or next.
iterate_element_ty
The element type for binds when iterating iterable — the checker side of the closed builtin iterable set, unified under the registry (stdlib-spec §9.6: “for is the only v1 consumer”). Arrays iterate values; maps iterate keys in insertion order (docs/t1b-surface-spec.md §2). Everything else is not iterable v1 — None (the caller falls back to Unknown; the runtime faults NotIndexable, conservatively carried in the faults row dimension).
iterate_val_ty
The value type bound by for k, v in m’s second binding (B2, issue #1461, docs/stdlib-spec.md §5/§9’s F10 ruling — two-binding map iteration is the pair story entries() never got). Only maps have a “value at key”; arrays and ranges iterate a single element with no paired value, so they’re not represented here at all — a caller (infer::body’s BlockStmt::For arm) falls back to Ty::Unknown for anything this returns None for, the same permissive-at-compile posture iterate_element_ty’s own callers already rely on.
local_signature
The per-file locals path signature itself cannot take (issue #530).
module_diagnostics
The M-2 module import + visibility checks (docs/modules-spec.md §2/§4/§7): import well-formedness and cross-module #@private reference enforcement. Purely additive — every trigger needs an IMPORT/#@private/#@public construct absent from the pre-modules world, so the oracle/tier1 corpus is untouched. Genuinely whole-project (reads every file’s HIR plus the project-wide resolutions to walk cross-module references), so it stays a whole-project pass in brink-db’s decomposed whole_project_diagnostics_query rather than gaining a per-file split here (issue #750 / FG-3 completion rebase note; a per-file slice is possible FG-4-era work if module churn is ever hot).
native_strict_only_error
The B0.9 native strict-only enforcement point (docs/b0-sequencing.md §B0.9’s “the strict-only ruling’s enforcement point”, issue #1342; decision-log 2026-07-19 “Typing posture ruled”: “the native surface is strict-only — types = strict is a property of the dialect, not a project knob; gradual typing does not exist on the native surface”).
no_world_reads_diagnostics
Diagnose every @[convention] handler declared in hir whose transitive call closure reaches a world-reading (Query) or unclassified (Plain) EXTERNAL.
per_file_diagnostics
Per-file diagnostic contributors (issue #632 / FG-3, docs/fine-grained-salsa-proposal.md §1 item 4): structural validation, the dialect gate, and (brink dialect only) annotation-content checks — the three passes finish_analysis used to run as whole-project loops (validate::validate/dialect_gate::check/annotations::check, each internally iterating every file) even though none of them actually reads another file’s state:
project_has_coalesce
Cheap structural scan: does any expression in hir coalesce? The laziness gate for [resolve]’s caller — a project with no or-coalescing anywhere (every ink-dialect project, by construction: InfixOp::Coalesce is native-lowering-only) never triggers whole-project inference on this pass’s account, mirroring crate::project_has_ufcs_call’s own shape.
project_has_ufcs_call
Cheap structural scan: does any call in hir have a multi-segment callee path? The laziness gate for resolve’s caller — a project (every ink project, by construction; see the module doc) with no dotted-callee call never triggers whole-project inference on this pass’s account, mirroring whole_project_diagnostics’ own needs_effects gate.
project_inline_docs
Collect inline /// docs across all files, keyed by (kind, declared name) — the project-wide doc merge feeding the external/callable/value enrichment passes. Exposed as its own seam (issue #750 / FG-3 completion) so brink-db can memoize it behind an Eq-cutoff query: DocBlock carries no ranges, so any edit that leaves every /// block’s parsed content intact backdates the memo even though the pass reads every file’s manifest.
ref_assignable
Is a value of type source legal as the argument bound to a ref parameter declared target?
referenced_globals
Pass 1b, exposed per one definition (FG-2.1, issue #638, Ruling 1 — referenced_globals(def), the same per-def body-facts family as call_edges). The VAR/CONST global ids def’s body references, recorded by [body::BodyResult::referenced_globals] regardless of whether a real globals map was supplied — this call passes an empty one, exactly call_edges’s “discard the computed types, keep the structural fact” shape. brink-db resolves each returned id via signature_query and hands the walk a small narrow BTreeMap before the real solve runs (two walks: this scan, then solve_scc — see the spec’s Ruling 1 tradeoff note). Also the per-def global read set a future T2 effect row needs — named and shaped for that reuse now, no speculative machinery added.
resolve
Resolve one file’s references against the project-wide symbol index.
resolve_annotation
Resolve a parsed type annotation into the checker’s Ty universe.
resolve_type_policy
THE types-default resolution function (issue #1127, decision-log 2026-07-19 “Typing posture ruled”). An explicit types = … — a CLI --types flag, a brink.toml [project] types key, an editor/LSP API call — always wins. When the project never says, the default is keyed on the dialect:
resolve_ufcs_calls
Resolve every UFCS-shaped call in the project, returning the verdict side table plus the diagnostics the four outcomes above produce.
scc_graph
Partition graph into SCCs and compute the condensation DAG in one pass (FG-2, issue #631). [topo_order] is now a thin projection of this (.order) kept for its own existing tests/callers; scc_membership_query is the new consumer that needs the adjacency too.
signature
Compute the signature stub for one definition.
solve_scc
Solve exactly one SCC batch (FG-2, issue #631 — solve_scc(SccId)).
solve_scc_effects
Solve one SCC batch’s effect-row fixpoint (spec §4 — the same per-SCC join TM-1’s type solver runs, lifted to the effect lattice). Lifts infer::solve_one_batch’s shape: known_rows must already carry the finalized row of every def outside batch that a member calls (every condensation-predecessor SCC’s rows); atoms carries every batch member’s harvested EffectAtoms.
strict_diagnostics
The strict typed-mode pass (docs/typed-mode-spec.md §1/§9-step-3), extracted from whole_project_diagnostics’s body (issue #750 / FG-3 completion) so brink-db can run it without also paying for the external-check family’s inputs. Returns empty under types = gradual — byte-identical, forever.
symbol_index
Build the project-wide declaration index from per-file symbol manifests.
symbol_index_with_modules
The merged symbol index with DefinitionIds qualified by each file’s declared module (M-1, docs/modules-spec.md §5).
ufcs_lir_lookup
Translate a UfcsTable into brink-ir’s own lowering-facing mirror (brink_ir::lir::UfcsLookup/UfcsVerdict) — issue #1506’s one conversion point, so the UfcsVerdictbrink_ir::lir::UfcsVerdict mapping lives in exactly one place rather than once per caller. brink-ir sits below this crate in the crate graph (this crate depends on brink-ir, never the reverse), so it cannot provide this itself — see brink_ir::lir::UfcsVerdict’s own doc. Every LIR-lowering caller shares this: brink-db’s ufcs_resolution_query (the production path) and assemble_analyzer_tables — the salsa-free path used by brink-test-harness (corpus::compile_and_explore_from_brink_native) and any other caller with no salsa layer of its own to memoize the table in.
ufcs_resolution
The B3a UFCS verdict side table for a project (issue #1482, D2): the node → resolved target channel LIR lowering reads to choose between emitting a call through a field’s value and emitting the desugared free call name(recv, args), and that IDE hover/go-to-def reads to name the real target of a method-call-shaped site.
unify
Unify (join) two observed types for the same slot.
unify_all
Fold unify over an iterator of observed types, starting from Ty::Unknown (the identity). Used for collection-literal element joins (spec §5: #[1, 2.0] is Array<float>) and for folding multiple observations of the same local/return slot across a body.
validate_admission
Run every §4.2 admission check over one file’s already-lowered (HirFile, SymbolManifest) pair.
validate_native_accept_list
Run the B0.9 accept-list over one native file’s already-lowered HirFile. Non-suppressible, mirroring crate::validate_admission — callers must not route the result through apply_suppressions. Only meaningful for HIR the native frontend produced; never call this against ink-produced HIR (see the module doc).
whole_project_diagnostics
Whole-project diagnostic contributors that genuinely need cross-file state (issue #632 / FG-3 design doc §1), now composed of the same per-pass seams brink-db’s decomposed queries wrap (issue #750 / FG-3 completion) — module_diagnostics, strict_diagnostics, external_meta_diagnostics, per-file file_value_meta, and per-file file_call_site_diagnostics behind call_site_metas — in exactly the pre-split order, so the query-composed result is identical to this monolithic one by construction (pinned by query_equivalence.rs).

Type Aliases§

CoalesceTable
Every or-coalescing chain’s recorded typing, keyed at the chain root (see the module doc for why not per step).
ModuleMap
Map from file to its resolved module. Absent entries (and undeclared modules) hash by bare name — byte-identical to the pre-modules scheme.
ResolutionMap
Maps reference use-sites to their resolved definitions, with file provenance.
UfcsTable
Every UFCS call site’s verdict for one project.