규칙 7.5
7장, 표현식과 문 테스트
A for loop must be counted: an i32 or u32 induction variable, a constant step, and an exit that compares the induction variable to a bound; the start and the bound may be runtime values, the loop body must not write the bound, and the step must move the variable toward the bound. A runtime bound must be compared with <, <=, > or >=, and a multiplicative step with a runtime start or bound must be a whole factor of 2 or more. A header whose start and bound are constants must reach its bound within the induction type’s range. An induction variable with no annotation is an i32, or a u32 when its initializer is a non-negative integer literal and the bound it is compared with is a u32; that is the integer type the position declares for Rule 5.1. A while loop is an open loop and may have any bool condition; a while whose condition is constantly true must have a break or a return in its body. No limit is placed on a trip count. A for…of over an array (array<T, N>, or a runtime-sized storage array) is a counted loop over the array’s indices, from 0 to its length; its variable is a const or a let holding a copy of the element, and the array must be a name, or a member or index path to one. A for…in must be refused.
규칙 본문과 그 아래 항목은 설계 문서에 적힌 컴파일러 원문이라 한국어 페이지에서도 영어로 둡니다.
근거
both targets accept a runtime bound and an open loop (#203 measured each on Tint and on ANGLE), and a program over data loops over a count it learns at run time. The analyses of roadmap items 15, 18 and 21 need a counted shape, a step whose direction is known and a bound the body does not move; none of them needs the bound to be a literal (#203). What a counted for promises a reader is exactly that shape, so a loop that ends some other way is written as a while, which says so. for (let i = 0; i < data.length; i++) is the loop a TypeScript author writes first, and data.length is a u32: a counter that stayed i32 would make it a comparison of two integer types the author never wrote. for (const x of xs) is the other loop a TypeScript author writes over data: its trip count is the array’s length, which the body cannot change (WGSL has no array that grows), so it is a counted loop with nothing left to check. for…in enumerates an object’s keys, which a shader value does not have. Roadmap item 15 is the first to read it: the IR for carries the counted fact the front end proved (counted, absent on a while, which is a for over a counter it made), and the proof of a kernel function’s loops takes it from there (Rule 8.22).
출처
Loop Statement, For Statement, While Statement; surface §17; #203.
검증 방식
테스트로 확인합니다. 테스트나 게이트 스크립트, CI 워크플로가 이 규칙을 가리키고, 아래 파일 가운데 하나라도 규칙을 더는 가리키지 않으면 추적 검사가 실패합니다.
컴파일러가 이 규칙을 적용하는 곳을 규칙이 직접 적은 내용입니다.
TS8006 LOOP_BOUND (an exit that is not a comparison with a bound; an && exit, named by the clause that is not its bound; == or != against a runtime bound; a multiplicative step with a runtime start or bound that is not a whole factor of 2 or more; a bound the body writes; a constant header that leaves its type), TS8007 LOOP_INFINITE (a step away from the bound, or one that never moves the variable; a constant header that never exits; a for with no condition; while (true), or a while whose condition folds to true from constants through !, &&, || and comparisons, a float compared only over literals and module constants that f32 holds exactly, with nothing that leaves it), TS8008 LOOP_INDUCTION (an update that is none of the counted forms, one sentence whatever its operator, including a compound assignment to a member or an element; i = i + c is i += c spelled out, its sum typed as in a body), TS8003 for a while condition that is not a bool, as for an if or a for condition, with the comparison with zero or the any/all that says a number’s or a vector of bools’ truthiness (lowerWhile); lowerFor in src/compiler/ts/lower/control.ts, which leaves an error for every for it does not lower, so a refused loop is never dropped from the module; pinned by src/compiler/ts/runtime-loop-bound.test.ts and src/compiler/ts/loop-shapes.test.ts, and by examples/loops-over-data.shade.ts on the compile gate. What is not checked is in Appendix B.
커밋 c66579bf에서 이 규칙을 확인하는 파일입니다. 파일마다 규칙을 처음 가리키는 줄로 연결했습니다.
설명하는 절
커밋 c66579bf의 표면 문서에서 이 규칙을 설명하는 절입니다.
적용하는 오류 코드
규칙이 Enforced by 항목에서 가리키는 진단 코드와, 레지스트리 설명에서 이 규칙을 가리키는 진단 코드입니다.
-
TS8003TYPE_MISMATCH - 연산자나 조건, 선언, 반환, 인자처럼 두 값이 만나는 자리에서 타입이 서로 맞지 않거나, 컴파일러가 접는 상수를 WGSL이 거부합니다. 31을 넘는 시프트 양, 0인 제수, 서로 엇갈린 clamp 경계, 범위를 넘는 f32 값이 그렇습니다.
-
TS8006LOOP_BOUND - 컴파일러가 종료를 증명할 수 없는
for루프입니다. 카운터를 경계와 비교하지 않거나, 본문이 경계를 씁니다. -
TS8007LOOP_INFINITE - 끝나지 않는 것이 확실한 루프입니다.
break나return이 없는데 조건이true인while, 또는 카운터를 경계에서 멀어지게 하는 증가입니다. 조건은 그대로 썼든 상수만으로 계산했든 같습니다. -
TS8008LOOP_INDUCTION for루프의 카운터가i32나u32타입의let하나가 아니거나, 갱신이 상수만큼 움직이지 않습니다.
함께 보기
소스
커밋 c66579bf의 규칙 원문:
docs/language-design.md:563(설계 문서)reqs/rules/RULE-0705.md(추적 항목)