import type { AgencyNode, FunctionCall, VariableType } from "../types.js"; import type { BlockType } from "../types/typeHints.js"; import type { DiagnosticName } from "./diagnostics.js"; /** * Which diagnostic a type mismatch becomes, at the three sites a decorated * def's mistakes reach (docs/dev/language/decorators.md). * * A decorator tag lowers to a call with the def's body as its block, so a * wrong tag argument, a body return that does not fit the block, and a * decorator whose return does not fit the def are all caught by the * ordinary call and return checks. Those checks would name the synthesized * call. This table gives each site a second entry that names the decorator * and the def, used when the call carries `decorator`. * * @budgeted(cost: "x") argument: decoratorArgType * def f(): number { declaredReturn: decoratorReturnMismatch * saveDraft(5) draft: decoratorDraftType * return 5 blockReturn: decoratorBodyReturn * } * * With stacked tags (`@a @b def f`), `return b(...)` sits in `a`'s block, so * a block return whose value is itself a decorator's call is the two * decorators disagreeing, not the body: the `stacked` entry. * * The table only names the entry. The sites still decide whether there is a * mismatch and where it is reported. */ export type MismatchSite = "argument" | "blockReturn" | "declaredReturn" | "draft"; export type MismatchInput = { site: MismatchSite; /** argument: the call. blockReturn and draft: the call that owns the * block. declaredReturn: the returned value, when it is a call. */ owner: FunctionCall | undefined; /** The checked value. */ value: AgencyNode; /** The plain entry's own params: `actual` and `expected`, plus `fn` and * `param` for an argument and `context` for a return. */ params: Record; }; /** A registry entry and the params to render it with. */ export type MismatchEntry = { name: DiagnosticName; params: Record; }; export declare function mismatchEntry(input: MismatchInput): MismatchEntry; /** * The type a `saveDraft(value)` must fit. A draft is the value of the frame * it is saved in. A decorated body is the decorator's block, so its draft is * the block's value and must fit the block slot's return type (`any` when * the slot is untyped); the def's declared type is what the decorator * returns, which is a different thing. Anywhere else, including the block of * an ordinary call such as a guard, the draft fits the scope's return type, * as a `return` does. * * `blockOwner` is the call that owns the innermost block around the draft, * and `blockSlot` that call's block parameter type, if any. */ export declare function draftTarget(blockOwner: FunctionCall | undefined, blockSlot: BlockType | undefined, scopeReturnType: VariableType | null | undefined): VariableType | null | undefined;