google / google/closure-compiler
Factory generated constructors are not detected as pure
- Dominant language
- JavaScript
- Stars
- 7.7k
- Forks
- 1.2k
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 6
Description
In most cases, GCC is able to figure out if a constructor is pure. As an example, consider the `Vec` class, which is a 2 dimensional vector.
```javascript
/** @interface */
class IVec {
/** @const {number} */
x;
/** @const {number} */
y;
}
/** @implements {IVec} */
class Vec {
/**
* @param {number} x
* @param {number} y
*/
constructor(x, y) {
/** @const {number} */
this.x = x;
/** @const {number} */
this.y = y;
}
}
new Vec(2, 2);
```
When compiled, this will produce no code, since the constructor is correctly determined to be pure.
When the class is generated through a factory, this inference does not seem to work. Consider for instance a factory which generates a class of points on a certain ray. Using this factory, we create a class `DiagonalVec`, which is the set of points with x=y.
```javascript
/** @interface */
class IVec {
/** @const {number} */
x;
/** @const {number} */
y;
}
/**
* @param {number} slope
* @return {function(new:IVec, number)}
*/
const fixedSlopeFactory = (slope) => /** @implements {IVec} */ class {
/** @param {number} x */
constructor(x) {
/** @const {number} */
this.x = x;
/** @const {number} */
this.y = slope * x;
}
}
/** @const {function(new:IVec, number)} */
const DiagonalVec = fixedSlopeFactory(1);
new DiagonalVec(2);
```
Now if we compile this using
```shell
bun google-closure-compiler -O ADVANCED --js a.js --jscomp_error strictCheckTypes --jscomp_error reportUnknownTypes --language_in UNSTABLE
```
the compiler outputs `new ((b=>class{constructor(a){this.x=a;this.y=b*a}})(1))(2);` In particular, the factory generated constructor was not proven to be pure.
How can I make the compiler figure this out, potentially using unsafe annotations such as `@pureOrBreakMyCode` ?
Contributor guide
Assessment
This issue has not been assessed yet.