/** * Coverage: whether one pattern can match a type, whether it covers the whole * of it, and what a set of arms has covered between them. * * D114 R1d: split out of `./matching.ts` during the move, which came to 882 * lines as one file — over the 800-line budget of D115 §一.1. The split is the * one the construct already has: `./matching.ts` walks an arm and binds its * names, and this file answers the yes/no questions that walk asks. The three * block-exit predicates live here because their only readers are those * questions and the arm that asks whether its facts reach past the match. */ import { type Expression, type MatchPattern, type MatchValue, type Statement, type TypeReference } from "../ast.ts"; import { type EnumInfo, type ValueType } from "../types.ts"; import { type ClassRegistry } from "./classes/registry.ts"; import { type Narrowing } from "./flow/narrowing.ts"; import { type LoweringRecorder } from "./lowering-recorder.ts"; /** Everything the match cluster asks of the analyzer that hosts it. */ export interface MatchCoverageHost { isAssignableHere(actual: ValueType, expected: ValueType): boolean; readonly classRegistry: ClassRegistry; readonly enums: Map; expandAliases(type: ValueType, seen?: ReadonlySet): ValueType; fieldsOf(identity: string): ReadonlyMap | null; readonly inferredExpressionTypes: Map; inferredOrAnalyze(expression: Expression): ValueType; isSubclassOf(className: string, base: string): boolean; readonly lowering: LoweringRecorder; /** D114 F4: the matches (by statement start) one of whose arms was refused. */ readonly matchesWithRefusedArm: ReadonlySet; readonly narrowing: Narrowing; readonly nonFallthroughWhileStatements: Set; readonlyDataViewOf(type: ValueType): ValueType; readonlyFieldsOf(identity: string): ReadonlySet | null; resolveAnnotation(reference: TypeReference | null): ValueType; } export declare class MatchCoverageRules { private readonly host; constructor(host: MatchCoverageHost); matchPatternCoversWholeType(pattern: MatchPattern, input: ValueType): boolean; matchPatternIsIrrefutable(pattern: MatchPattern): boolean; matchPatternCoversType(pattern: MatchPattern, input: ValueType): boolean; matchListCandidates(input: ValueType): ValueType[]; matchObjectCandidates(input: ValueType): ValueType[]; matchObjectField(candidate: ValueType, property: string): ValueType | null; matchPatternMayMatchType(pattern: MatchPattern, input: ValueType): boolean; matchObjectRestType(candidates: readonly ValueType[], selected: ReadonlySet): ValueType; matchLiteralCompatible(matched: ValueType, literal: ValueType): boolean; matchValueKey(value: MatchValue): string; matchValueDisplay(value: MatchValue): string; /** * D45 rule 77: how a match over a class subject can be closed. A subclass * instance still satisfies its base pattern, so a base tail proves the match * exhaustive; an extern class check may fail at runtime, so only the wildcard * proves an extern subject, and a union of classes has to be covered member * by member. * * D114 0.28.0 B-I1: the pattern the advice names is the *bare* class. A * subject that names its arguments used to be dropped into the template * whole — `end with 'case Shape:'` — and that is the one spelling * VEL4022 refuses, because type arguments are erased and cannot be checked. */ classFallbackAdvice(subject: ValueType): string; matchTypesOverlap(left: ValueType, right: ValueType, seen?: Set): boolean; /** C3: totality is about runtime shapes; field and container write permissions do not affect a match. */ runtimeTypeCovers(input: ValueType, checked: ValueType, seen?: Set): boolean; /** * D114 0.28.0 B-D1: whether a *bare* generic class pattern can match a class * subject. D77 rule 194 item 2 admits the bare name in exactly two positions * — `is Stack` and `case Stack:` — because the check is `instanceof`, which * says nothing about the arguments; the pattern therefore stands for every * instantiation of that class. `is Round` was accepted on a `Shape` * subject and `case Round:` was refused as "can never match", because * assignability compares the *applications*, and `Round extends Shape` * has no application until an argument is named. The relation the erased * check proves is between the two declarations, so that is what is asked, in * both directions — a subclass pattern on a base subject and a base pattern * on a subclass subject are the two ways one instantiation can be the other. * * An applied pattern never reaches here: VEL4022 refuses `case Round:` * before the comparison. A bare *non-generic* class keeps the ordinary * assignability route, which already decides it exactly. */ bareGenericClassReaches(subject: ValueType, pattern: ValueType): boolean; runtimeTypeCheckMayExecute(input: ValueType, checkedInput: ValueType): boolean; matchTypeFullyCovered(target: ValueType, coveredTypes: readonly ValueType[], coveredValues: ReadonlySet, coveredEnumMembers: ReadonlySet, coveredListLengths: ReadonlySet, coveredListMinimum: number | null): boolean; enumMemberCoverageKey(identity: string, member: string): string; /** ENM-I5: enum members reached through a type pattern (parenthesized singletons, unions of them) credit member coverage. */ creditEnumMemberCoverage(checked: ValueType, covered: Set): void; /** ENM-I6: the enum behind a match subject - bare or optional - that carries the exhaustiveness contract. */ enumMatchSubject(matched: ValueType): { readonly target: Extract; readonly optional: boolean; } | null; /** The class arms of a match subject: the type itself, or the class members of its optional/union spellings. */ classArmsOf(expanded: ValueType): Extract[]; blockAlwaysReturns(statements: readonly Statement[]): boolean; statementAlwaysExitsBlock(statement: Statement): boolean; blockAlwaysExits(statements: readonly Statement[]): boolean; } //# sourceMappingURL=match-coverage.d.ts.map