/** * `match`: what one arm's pattern proves, what it covers, and whether the arms * together cover the subject's whole domain. * * D114 R1d: `match` is the language's largest single construct — the statement * handler, the per-arm pass, the pattern walk, the coverage ledger, and the * exhaustiveness report came to roughly seven hundred lines inside `analyzer.ts`. * They answer one question and live in one collaborator the analyzer owns as * `this.matching`. The block-exit predicates (`blockAlwaysReturns` and its two * siblings) travel with them: their only readers are the arms, which need to * know whether an arm's facts reach the code after the match. */ import { type Expression, type MatchPattern, type Statement, type TypeReference } from "../ast.ts"; import { type ClassInfo } from "../contracts.ts"; import { type Diagnostic, type DiagnosticFix } from "../diagnostic.ts"; import { type Span } from "../source.ts"; import { type EnumInfo, type ValueType } from "../types.ts"; import { type FlowFacts, type FlowFactInvalidations, type FlowFactsSnapshot } from "./flow/facts.ts"; import { type FlowMerge } from "./flow/merge.ts"; import { type Narrowing } from "./flow/narrowing.ts"; import { type LoweringRecorder } from "./lowering-recorder.ts"; import { type MatchCoverageRules } from "./match-coverage.ts"; import { type Binding, type BuiltinTypeNamePosition } from "./scopes.ts"; /** What a `match` has proved covered so far, carried from one branch to the next. */ export interface MatchCoverage { readonly continuingInvalidations: FlowFactInvalidations[]; readonly continuingFacts: ReadonlyMap[]; readonly fallthroughInvalidations: FlowFactInvalidations[]; readonly coveredValues: Set; readonly coveredEnumMembers: Set; readonly guardedEnumMembers: Set; readonly coveredTypes: ValueType[]; readonly coveredListLengths: Set; coveredListMinimum: number | null; universalCovered: boolean; fallthroughType: ValueType; fallthroughNarrowings: ReadonlyMap; /** * D114 F4: an arm's pattern was refused — it answered `invalidType` — so this * match has no coverage verdict to give. The refusal is already reported at * the arm that earned it; exhaustiveness and redundancy are questions about * arms that mean something, and one of these does not yet. */ armRefused: boolean; /** * The redundancy reports (VEL4014) the arms decided, held until every arm is * walked. A refusal in a *later* arm suspends the verdict for the arms before * it as well, so these are issued from `reportMatchCoverage` — where the * whole match's verdict is issued — rather than from the arm that decided one. */ readonly redundancy: Diagnostic[]; } /** Everything the match cluster asks of the analyzer that hosts it. */ export interface MatchAnalysisHost { readonly coverage: MatchCoverageRules; isAssignableHere(actual: ValueType, expected: ValueType): boolean; allowBareGenericClassName(reference: TypeReference): void; analyzeStatements(statements: readonly Statement[]): void; applyNarrowings(narrowed: ReadonlyMap, narrowingSpan: Span): void; readonly classes: Map; declareBinding(name: string, mutable: boolean, type: ValueType, declarationSpan: Span, internal?: boolean, declaredType?: ValueType, importSource?: string, typeNamePosition?: BuiltinTypeNamePosition): void; readonly diagnostics: Diagnostic[]; enterScope(): void; readonly enums: Map; equalityMayCompareNaN(type: ValueType): boolean; equalityOperandMayBeNaN(expression: Expression, type: ValueType): boolean; erasedClassCheckType(source: ValueType, checked: ValueType): ValueType; exitScope(): void; expandAliases(type: ValueType, seen?: ReadonlySet): ValueType; readonly flowFacts: FlowFacts; readonly flowMerge: FlowMerge; inferExpression(expression: Expression, contextualType?: ValueType): ValueType; readonly inferredExpressionTypes: Map; lookup(name: string): Binding | null; readonly lowering: LoweringRecorder; /** D114 F4: the matches (by statement start) one of whose arms was refused. */ readonly matchesWithRefusedArm: Set; readonly namedTypes: Map>; readonly narrowing: Narrowing; readonly primitiveNames: Set; readonlyDataViewOf(type: ValueType): ValueType; rejectErasedRuntimeCheck(checked: ValueType, errorSpan: Span): boolean; resolveAnnotation(reference: TypeReference | null): ValueType; readonly semanticBindingEntryOwners: Map; readonly typeAliases: Map; typeError(message: string, errorSpan: Span, fix?: DiagnosticFix): void; validateTypeReference(reference: TypeReference, resolve?: (reference: TypeReference) => ValueType): boolean; } export declare class MatchAnalysis { private readonly host; constructor(host: MatchAnalysisHost); analyzeMatchStatement(statement: Extract): void; /** One `case` arm: what its pattern proves, what its guard adds, and what its body leaves. */ analyzeMatchBranch(statement: Extract, branch: Extract["cases"][number], matched: ValueType, flowBaseline: FlowFactsSnapshot, visibleAtMatch: number, coverage: MatchCoverage): void; /** The pattern half of one arm: its bindings, its narrowings, and what it adds to the coverage. */ creditMatchPatternCoverage(statement: Extract, branch: Extract["cases"][number], matched: ValueType, flowBaseline: FlowFactsSnapshot, coverage: MatchCoverage): { readonly branchReachable: boolean; readonly bindings: ReadonlyMap; readonly patternNarrowings: ReadonlyMap; readonly patternSurviving: ReadonlyMap; readonly rootPattern: MatchPattern; }; /** After every arm: whether the match is exhaustive, and what survives it. */ reportMatchCoverage(statement: Extract, matched: ValueType, flowBaseline: FlowFactsSnapshot, visibleAtMatch: number, coverage: MatchCoverage): void; /** The arms do not cover the subject: which enum members, or which fallback, is missing. */ private reportMissingMatchArms; analyzeMatchPattern(pattern: MatchPattern, input: ValueType, bindings: Map): ValueType; /** `case Type:` — the erased-check refusals, the narrowed subject, and the capture it may bind. */ private analyzeMatchTypePattern; matchLocationNarrowing(expression: Expression, type: ValueType): ReadonlyMap; retargetNarrowings(source: ReadonlyMap, type: ValueType): ReadonlyMap; matchFallthroughType(input: ValueType, pattern: MatchPattern): ValueType; unwrapMatchAs(pattern: MatchPattern): MatchPattern; addMatchBinding(bindings: Map, name: string, type: ValueType, bindingSpan: Span): void; narrowMatchType(input: ValueType, rawChecked: ValueType): ValueType; } //# sourceMappingURL=matching.d.ts.map