규칙 8.17
8장, 함수와 진입점 테스트
A local function (a const that holds an arrow function or a function expression, or a function declaration, written inside a function’s body) is a function of the module named after the body that declares it (surface §14), and it may read and write the variables of the functions around it, as a TypeScript closure does.
A name its body reads is looked up as TypeScript looks it up, from the innermost block outward; one that lands on a let, a const or a parameter of a function around it is a capture, which the emitted function takes as a parameter ahead of its own and which every call of it passes: by value while neither it nor a local function it calls writes the variable, and by reference once one does; a const keeps its constant, so a loop it bounds is still counted (Rule 7.5).
A whole write to a captured value parameter shares the local copy of Rule 8.8 with the
enclosing body and every other closure; its reference never reaches the enclosing caller.
A Ref<T> parameter must not be captured (Rule 8.25), and a variable a local function writes
counts as a reference in Rule 8.25’s check of the call that passes it.
this in an arrow function is the object of the method around it, captured the same way, and the class the call names in a static member (Rule 8.13).
A write through a capture follows the variable’s own declaration: a let may be written, a const only through what it holds and only when its initializer built the value (Rule 6.10), and a whole-rebound value parameter through its mutable local copy (Rule 8.8).
A function declaration may be called anywhere in its block, as TypeScript hoists it, and a local function may be declared in a generic function, once for each of its instances.
A call of a local function at a point where a variable it captures is not declared yet must be refused, since TypeScript throws there; so must a function named where a value is read (held in a variable, returned, compared or chosen at run time), there being no function value, other than as an argument of a parameter that takes a function (Rule 8.18).
A function named as the callback of a fold (any(xs, isBig), zip(xs, ys, f)) passes what it captures to every call the fold makes.
규칙 본문과 그 아래 항목은 설계 문서에 적힌 컴파일러 원문이라 한국어 페이지에서도 영어로 둡니다.
근거
a function is no value here: nothing can return one, store one or choose one at run time, so every call of a local function is written inside the scope that declares it, where every variable it reads is in scope too. Passing those variables at each call is all a closure’s environment holds, and passing a written one by reference is what makes the write visible to the function around it and to the next call, as it is in TypeScript. A call is where TypeScript would read a variable that is not declared yet, so that is where the refusal stands. Before this rule a local function that read a name from the function around it was refused, with the parameter to add instead.
출처
ECMAScript function environment records (a closure reads the binding, not a copy of it), FunctionDeclarationInstantiation (a function declaration is instantiated before its block runs), let and const declarations (a binding may not be read before its declaration is evaluated) and arrow functions (this is the enclosing one); Rule 6.10; Rule 8.8; Rule 8.10; Rule 8.13; surface §14.
검증 방식
테스트로 확인합니다. 테스트나 게이트 스크립트, CI 워크플로가 이 규칙을 가리키고, 아래 파일 가운데 하나라도 규칙을 더는 가리키지 않으면 추적 검사가 실패합니다.
컴파일러가 이 규칙을 적용하는 곳을 규칙이 직접 적은 내용입니다.
TS8022 UNKNOWN_NAME for a call before a captured variable’s declaration ("f" reads "y", which is not declared yet where "f" is called: a let or a const is not there before its declaration, and TypeScript throws. Call "f" after "y" is declared.), TS8099 for a function named as a value ("f" is a function, and a shader has no function values: nothing at run time can hold one, return one or choose between two. Call it where its value is needed, "f(...)".), TS8018 ASSIGN_TARGET and TS8005 CONST_ASSIGN for a write through a parameter or a const; pinned by src/compiler/ts/closures.test.ts, which holds WGSL, GLSL ES 3.00, the CPU oracle, the codegen and the debugger to one value for each form; examples/closures.shade.ts in the compile gate.
커밋 c66579bf에서 이 규칙을 확인하는 파일입니다. 파일마다 규칙을 처음 가리키는 줄로 연결했습니다.
설명하는 절
커밋 c66579bf의 표면 문서에서 이 규칙을 설명하는 절입니다.
적용하는 오류 코드
규칙이 Enforced by 항목에서 가리키는 진단 코드와, 레지스트리 설명에서 이 규칙을 가리키는 진단 코드입니다.
-
TS8005CONST_ASSIGN const나 읽기 전용 리소스처럼 바뀔 수 없는 이름에 값을 대입합니다.-
TS8018ASSIGN_TARGET - An assignment or
++/--target that is not a writable place, such as a temporary or an input that has no writable value local. -
TS8022UNKNOWN_NAME - Reference to a name TypeShade cannot resolve (identifier, struct field, or struct shape) that is not a function call (
UNKNOWN_FN) or a type name (UNKNOWN_TYPE), in a body a call lowers or in one no call lowers; a name the library declares for TypeScript's own use (Object,Math,Symbol), or the file declares as an enum, a namespace, a class or a type, read as a value says what it is. -
TS8099UNSUPPORTED UNSUPPORTED(TS8099) is the one deliberate exception to "sequential": it is the catch-all for a diagnostic whose site does not yet deserve its own code, so it stays parked past the sequential range instead of at its head.
함께 보기
소스
커밋 c66579bf의 규칙 원문:
docs/language-design.md:783(설계 문서)reqs/rules/RULE-0817.md(추적 항목)