/** * The type a position expects, and the report a position that expected nothing * earns: the contextual type of a collection literal, of a record literal, of * an awaited operand and of a `??` subject, and D85 rule 207's rule that an * empty collection which never learns what it holds is reported where the hole * was made. * * D115 §三: these were the contextual-type family and the unsettled-collection * family, seventeen private and protected methods of `Analyzer`. They belong * together because they are the two halves of one question: what does this * position say the value holds, and what happens when nothing does. */ import { type BindingPattern, type Expression } from "../../ast.ts"; import { type Diagnostic } from "../../diagnostic.ts"; import { type Span } from "../../source.ts"; import { type ValueType } from "../../types.ts"; import { type Binding } from "../scopes.ts"; /** * CO-I15: the declaration an empty collection is being declared into — the * name the author wrote and the word they declared it with. */ export interface EmptyCollectionTarget { readonly name: string; readonly keyword: "const" | "let"; } /** What contextual typing and the unsettled-collection rule asks of the analyzer that hosts it, and nothing more. */ export interface ContextualTypingHost { annotationFreeHeads: number; readonly bindingHoleCauses: Map>; readonly contextualAssignments: Map; readonly deferredConvergenceReports: { readonly report: Diagnostic; readonly resultKey: string; readonly causes: ReadonlySet; }[]; readonly diagnostics: Diagnostic[]; expandAliases(type: ValueType, seen?: ReadonlySet): ValueType; fieldsOf(identity: string): ReadonlyMap | null; readonly functionResultKeys: Map; readonly importBindings: ReadonlyMap; inferExpression(expression: Expression, contextualType?: ValueType): ValueType; readonly inferredExpressionTypes: Map; isAssignableHere(actual: ValueType, expected: ValueType): boolean; lookup(name: string): Binding | null; readonly primitiveNames: Set; readonly reportedCollectionHoles: Set; readonly reportedResultHoles: Set; readonly scopes: Map[]; } export declare class ContextualTyping { private readonly host; constructor(host: ContextualTypingHost); contextualCollectionType(type: ValueType): Extract | null; /** * D114 item ①: what an `await` says to the expression it awaits. A position * that expects `T` is awaiting something that produces `Promise`, and a * position that expects nothing keeps expecting nothing — silence has to stay * silence, because section 8's empty-collection rule reads this same channel * and `await []` must go on saying exactly what it said. */ awaitedOperandContext(contextualType: ValueType): ValueType; /** * D114 0.28.0 A-I1: the *subject* of `??` stands in the position the * annotation names, exactly as its fallback does. `const xs: List = * empty() ?? []` settled the empty literal on the right and left the generic * call on the left at `List` — one `??` under one annotation * answering two ways, while both arms of a ternary already receive it. The * subject may be null, so what it is offered is the optional spelling of the * expected type; every reader of a contextual type looks through `optional` * already (section 8's empty-collection rule and the type-argument seed * both do). Every other operator's operands stay context-free: `??` is the * one whose subject the position's own type reaches. */ coalescingSubjectContext(operator: string, contextualType: ValueType): ValueType; coalescingFallbackContext(left: ValueType, contextualType: ValueType): ValueType; contextualObjectType(type: ValueType, expression?: Extract): Extract | null; private contextualObjectDiscriminantsMatch; contextuallyAssignable(actual: ValueType, expected: ValueType, valueSpan: Span): boolean; private knownEnumSingleton; widenAggregateSingleton(type: ValueType): ValueType; inferAnnotationFreeHead(expression: Expression): ValueType; inAnnotationFreeHead(): boolean; /** * D85 rule 207: an empty collection's element type must be settled where the * collection is written — by an annotation, a contextual type, or the * constructor's own arguments. Nothing infers it from a later mutation, so a * binding left with no source is reported at the construction rather than * kept as `unknown` for a following line to fill in. * * The value written at this position is not always the construction itself. * A ternary arm, a list element or its spread, a record-literal field, a * `??` fallback, a receiver and an argument all become part of the value the * name holds, so each is its own settling position and each reports at its * own `[]`. What stops the walk is the value, not the syntax: it descends * only while `carriesUnsettledCollection` still sees the hole in the type * arriving here, so `print(Set().size)` and `const n = Set().size` stay * legal per rule 208 — neither of those names holds a collection — while a * spread whose `unknown` the merge absorbs (`["x", ...[]]`) leaves nothing * to report. A sibling settles nothing for its neighbour: `[["a"], []]` * merges through `unionOf`, so the union still carries the hole and the * empty `[]` reports on its own. * * Returns whether it reported, so the caller can hand the name `invalidType` * instead of the hole. Rule 209 requires one mistake to be reported once, * and `List` reaching a later line is what produces the second, * contradicting report the ruling exists to delete. */ requireSettledCollectionElement(initializer: Expression, declared: ValueType, annotated: boolean, target?: EmptyCollectionTarget | null): boolean; /** * CO-I15: the empty-collection sentence, written for the declaration it is * standing on. * * `const names = []` used to be answered with `write 'let items: List * = []'` — a binding the author did not write, a keyword they did not use, * and an element type nobody at the site named. The binding and the keyword * are on record here, so they are quoted; the element type is the one thing * the compiler genuinely does not know, so it stays visibly a blank rather * than borrowing `string` and reading as an answer. */ private emptyCollectionAdvice; private reportUnsettledCollection; private isFreshUnresolvedCollection; /** * D85 rule 209: where the value at this position came from, when it came * from a hole VEL4039 already reported. The answer is two-part because a * callee can be declared after its caller: `true` is a hole already on * record, and `causes` are the local results that make this position a hole * too if theirs turn out to be one. * * Only a name and a call to a local name are modelled — the two shapes an * author writes between an empty collection and the `return` that publishes * it. Anything else contributes nothing, so an unmodelled position keeps the * report it has today rather than losing one. */ collectResultHoleSources(expression: Expression, causes: Set): boolean; /** * D85 rule 209: a name bound to a reported hole carries it, so `const a = []` * followed by `return a` is the same one mistake `return []` is. Only an * unannotated `const`/`let` of a single name carries anything: an annotation * settles the construction, and a destructuring pattern takes the hole apart * rather than passing it on. */ recordBindingHoleSource(pattern: BindingPattern, initializer: Expression, reported: boolean): void; /** * D85 rule 209: delete the convergence report of every function whose result * is invalid only because a hole VEL4039 already explained reached it through * a local call. The set grows until it stops growing, because a chain of * forwarding functions is still one mistake however long it is — and a cycle * with no empty collection anywhere in it never enters the set, so a genuine * convergence failure still reports on both of its halves. */ resolveDeferredConvergenceReports(): void; } //# sourceMappingURL=contextual.d.ts.map