-
-
Notifications
You must be signed in to change notification settings - Fork 679
feat: add type narrow to support better type check #2352
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add type narrow to support better type check #2352
Conversation
1795f6f to
df38498
Compare
|
When I thought about narrowing in the past, the mechanism I had in mind was to add a new |
I have not found |
|
By the way, we should not support narrow type for variant like class A {}
class B extends A {
foo(): void {}
}
class C {
v: A = new A();
}
let c = new C();
let d = c;
c.v = new B();
if (c.v instanceof B) {
d.v = new A(); // c.v has changed, but compiler don't know
c.v.foo();
} |
This reverts commit df38498.
d.v = new A(); // c.v has changed, but compiler don't knowwell. that's problem on TS. I guess they are fixed this later. I see no reason to refuse it if we can handle this case correctly |
|
Quite similar to why nullability checks are limited to locals. Also applies to narrowing if we don't want to run into unsoundness. ...
let cv = c.v;
if (cv instanceof B) {
// works
} |
…t/add-type-narrow
|
Btw such flow mechanics is quite typical: var thenFlow = flow.fork();
this.currentFlow = thenFlow;
thenFlow.inheritNarrowedTypeIfTrue(condExpr);I'm wondering could we add some method for Flow which include this routine? class Flow {
...
toBranch(condExpr: Expression, ifTrue: bool): Flow {
var other = this.fork();
if (ifTrue) {
other.inheritNarrowedTypeIfTrue(condExpr);
} else {
other.inheritNarrowedTypeIfFalse(condExpr);
}
return other;
}
}And later simplify to: this.currentFlow = flow.toBranch(condExpr, true);Not sure about naming. Probably you could call all of this better |
|
@dcodeIO Could this feature merge? |
| pendingElements.delete(dummy); | ||
| flow.freeScopedDummyLocal(name); | ||
|
|
||
| initType = this.currentType; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Due to compiling with Constraincts.CONV_IMPLICIT, I think initType is always the same as type here. Sure that the additional initType variable is needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider this testcase. Actually initType and type are not always the same in nullable
export function testInit(a: Ref): void {
let c: Ref | null = requireNonNull(a);
if (isNullable(c)) ERROR("should be non-nullable");
}
|
@dcodeIO Could you kindly review this PR? |
|
I'm having a hard time reviewing the PR, and would like to suggest to split it up a little. As a start, there has been the refactoring from From there on it gets a little tricky, as I am not confident about having an out-of-line |
Yes, I will split it into several PR. But it needs some time because I am preparing my graduation thesis now😄 |
No description provided.