Rule 8.10
Chapter 8, Functions and entry points Test
A method that writes its object (assigns to this or to a field, a component or an element of it, applies ++ or -- to one, or calls such a method or reads such a getter on this, on a field, a component or an element of it whatever class that field is, or through super) must take the object by reference, and may return a value like any other method; a base’s body that a class calls through super and that writes its object takes it by reference too, and so does the copy of a method that takes a function (Rule 8.18) when a function handed over writes the variable the call is on.
Its receiver must be a place a function may write: a let local, a const local whose initializer built its value (Rule 6.10), a module variable, a storage element, or this inside a constructor or another such method, or a field or an element of one of those.
A receiver that is a parameter, a const whose value something else may hold, or a value nothing holds must be refused with the remedy, as must a call of such a method that returns nothing where a value is expected.
A method whose every return is return this returns its object, and a chain of calls on what it returns that is the whole of a call statement, of a declaration’s initializer or of a return (v.setX(1.).setY(2.)) must run each call but the last as a statement of its own, in source order, on the place the chain starts from, found once before the first call (an index it is reached through is read into a let), a new at the root being held in a temporary; inside a larger expression what such a method returns is a copy, and a call on it that writes its object must be refused with the remedy.
The rule text and the parts under it are the compiler's own English, as the design document writes them.
Rationale
WGSL takes a place as a pointer and GLSL ES 3.00 as an inout parameter, and either leaves the return free for a value, so a generator’s next() can advance its state and return the draw as TypeScript’s own method does; the rule that such a method returns nothing belonged to the protocol that returned the struct itself, which the reference replaced. A base’s body called through super changes the object of the body that called it, which hands its own reference on. A function handed to a method may write the very object the method runs on (this.each((i) => { this.total += … })), which in TypeScript is one object, so the copy takes it by the one reference both use. A field of this is part of this, so this.body.step(dt) writes this when step writes its object, whichever class declares step; before this a method that did so was refused as one that reads its object only. return this hands back a struct, which is a value: where a chain is the whole statement it can run on the place itself, which is TypeScript’s meaning, and where it is not, the copy is all there is, which is right for a read and wrong for a write.
Derives from
Reference and Pointer Types; Function Calls; GLSL ES 3.00 §6.1.1 (“Evaluation of an inout parameter results in both a value and an l-value”); ECMAScript the super keyword; surface §26 (design #86 step 2).
How it is verified
Checked by a test. A test, a gate script or a CI workflow names this rule, and the traceability check fails when a file listed below stops naming it.
Where the rule says the compiler enforces it:
TS8035 CLASS_MEMBER for each refusal ("Gen.next" changes its object, and "r" is a const whose value may be one something else holds, which TypeScript would change with it and a copy here would not. Declare it with let to change a copy, or call it on the value itself.; "V.setY" changes its object, and inside this expression it would change the copy "v.setX(3.)" hands back. Make the chain a statement of its own, or call each method on the object itself.), pinned by src/compiler/ts/class-methods.test.ts and src/compiler/ts/class-syntax.test.ts, which also hold the three CPU paths to one value for a method that changes its object and returns one, a base’s body called through super that writes its object, a chain, and a method that writes its object through a field of another class, three levels deep; src/compiler/ts/higher-order.test.ts, which holds them to one value for the copy of a method whose function writes the object the call is on; src/compiler/ts/inout-params.test.ts; examples/orbit-inout.shade.ts, examples/particle-step.shade.ts, examples/rng-method.shade.ts, examples/class-builder.shade.ts and examples/class-parts.shade.ts in the compile gate.
The files that verify it at commit 26de7be8, each at the first line that names the rule:
Explained in
The sections of the surface document that explain this rule, at commit 26de7be8:
Error codes that enforce it
The diagnostic codes the rule names under Enforced by, or whose registry text names the rule:
See also
Source
The rule at commit 26de7be8:
docs/language-design.md:716(the design document)reqs/rules/RULE-0810.md(its traceability item)