Tracking of `super()` call in constructor is wrong
https://github.com/dudykr/stc/blob/273356f921c6152b5a45c41527923a86361ebe13/crates/stc_ts_type_checker/tests/conformance/es6/classDeclaration/superCallBeforeThisAccessing1.ts#L9-L12
The code above should pass, but currently, stc fails to validate it.
The validation logic for it lives at
https://github.com/dudykr/stc/blob/273356f921c6152b5a45c41527923a86361ebe13/crates/stc_ts_file_analyzer/src/analyzer/scope/mod.rs#L663-L681
Not sure why doesn't it work, though.
Can I try to fix this one? 😁
Of course, thank you!
I think that ploblem is reorder logic.
This code flow is next
// origin
class D extends Base {
private _t: any;
constructor() {
super(i);
var s = {
t: this._t
}
var i = Factory.create(s);
}
}
// reorder
class D extends Base {
private _t: any;
constructor() {
var s = {
t: this._t
}
var i = Factory.create(s);
super(i);
}
}
//tsc
class D extends Base {
private _t: any;
constructor() {
var s, i;
super(i); // i value is undefined, type is undefinable
var s = {
t: this._t
}
var i = Factory.create(s);
}
}
Hello, how's it going! I think, STC seems to validate all hoisted variables by var keywords, at the beginning of function.
First of all, to help our understanding, here's some other examples.
- more simplified version of above example (same error)
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
super(s);
let s = {
t: this._t
}
}
}
- tsc hoisting rules
// error case
function A() {
console.log(a) // Error: Variable 'a' is used before being assigned.
var a: number
}
// non error case
function B() {
console.log(a)
var a: number | undefined
}
https://github.com/dudykr/stc/blob/3bee2888c6033ce859296ddf62fc06ccca883701/crates/stc_ts_file_analyzer/src/analyzer/hoisting/mod.rs#L46
on this line, STC always validates all hoisted variables.
could you please give me more information about this issue?
If it's a problem of reordering, we can add some code to https://github.com/dudykr/stc/blob/3bee2888c6033ce859296ddf62fc06ccca883701/crates/stc_ts_ordering/src/stmt.rs#L24-L29
It seems that the 'reorder' function is working as intended. However, what I am trying to convey is that, for certain Var::Decl related tasks, we need to first declare and register types to a certain extent, and then iterate through the entire block sequentially.
so example
class D extends Base {
private _t: any;
constructor() {
var s, i;
// declare_var `s, i` with subset of undefined
// when this example, Factory create return type declared any, we shouldn't know s type
// maybe, i declared any, s declared undefined or temp object literal
super(i); // i value is undefined, type is undefinable
var s = {
t: this._t
} // Overwriting the type after declaration
var i = Factory.create(s); // Overwriting the type after declaration
}
}
There are much more complex test cases, but feel free to give it a try
I have looked at other test cases, but I don't see any for more complex cases. What cases are you concerned about?
declare var Factory: {create: <T>(arg:T) => T};
class Base {
constructor(c) { }
}
class D extends Base {
private _t;
constructor() {
super(i); // error Variable 'i' is used before being assigned.(2454)
var s = {
t: this._t
}
var i = Factory.create(s);
}
}
class E extends Base {
private _t;
constructor() {
let x = {
j: this._t, // error 'super' must be called before accessing 'this' in the constructor of a derived class
}
super(undefined);
}
}
class F extends Base {
private _t;
constructor() {
let x = () => { this._t };
x(); // no error; we only check super is called before this when the container is a constructor
this._t; // error 'super' must be called before accessing 'this' in the constructor of a derived class
super(undefined);
}
}
If all the rhs expressions of var are checked, eventually the following code and result will be the same:
class D extends Base {
private _t;
constructor() {
let s = {
t: this._t // error 'super' must be called before accessing 'this' in the constructor of a derived class.(17009)
}
let i = Factory.create(s);
super(i);
}
}
That's why an error occurs.
I'm not sure about the way to validate declarations partially. Any ideas?
If you're only going to fix this issue, you're delaying the parameter check when you check the function's return value