-
Notifications
You must be signed in to change notification settings - Fork 12.6k
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
fix(44466): Fixes parsing contextual keyword casts as arrow functions #49029
fix(44466): Fixes parsing contextual keyword casts as arrow functions #49029
Conversation
Can you use the test provided in the #49021?
// @declaration: true
let readonly: any = undefined;
let override: any = undefined;
let out: any = undefined;
let declare: any = undefined;
export const a = (readonly as number);
export const b = (override as number);
export const c = (out as number);
export const d = (declare as number); |
@typescript-bot pack this |
Heya @DanielRosenwasser, I've started to run the diff-based community code test suite on this PR at 3dd9ef4. You can monitor the build here. Update: The results are in! |
Heya @DanielRosenwasser, I've started to run the parallelized Definitely Typed test suite on this PR at 3dd9ef4. You can monitor the build here. |
Heya @DanielRosenwasser, I've started to run the perf test suite on this PR at 3dd9ef4. You can monitor the build here. Update: The results are in! |
Heya @DanielRosenwasser, I've started to run the extended test suite on this PR at 3dd9ef4. You can monitor the build here. |
Heya @DanielRosenwasser, I've started to run the tarball bundle task on this PR at 3dd9ef4. You can monitor the build here. |
@DanielRosenwasser done |
@DanielRosenwasser |
@@ -4538,6 +4538,10 @@ namespace ts { | |||
// isn't actually allowed, but we want to treat it as a lambda so we can provide | |||
// a good error message. | |||
if (isModifierKind(second) && second !== SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsIdentifier)) { |
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.
The fact that nextTokenIsIdentifier
checks for async
and yield
itself makes me feel like there should be some sort of context for as
, rather than special casing, but like you said on #44466 (comment), I'm not entirely certain that there's another expression that can behave like this.
This whole "does this look like an arrow function" is effectively a heuristic and continues to bite us (see: #16241), so I think it's likely ok to disable this heuristic here like you've done.
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.
I think the other option is reworking this along the lines Daniel suggested earlier in #44466, but looking for a matched close paren followed by an arrow? But doing that leaves a lot of lookahead for errors to accumulate, and you're not guaranteed to find the matching paren, much less the arrow itself.
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.
Yeah, I think that this fix is good as-is; this block (as commented above) is to do better error recovery if someone writes code like (foo number) => ...
, which is guaranteed to fail to parse later. The likelihood of that broken code appearing and someone legitimately naming a type as
seems very, very low, so I'm happy with just not having recovery in this case.
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.
I suppose though, that one could write a test that is (foo as) => 1234
or something, and see if you should actually return TriState.Unknown
here instead.
Or, that this should be a lookAhead
in the if statement before the code you've added (the "isn't actually allowed" one), to better fit with the heuristic.
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.
I have tested both, and they both pass the tests in the PR, though they all differ on a test like:
let out: any = undefined;
type as = any;
export const e = (declare as) => 1234;
With the two lookahead versions, you get an emitted exports.e = declare;
, but with Unknown
, it actually tries to parse that broken code as an arrow function again and complains about the modifier, and emits:
var e = function (as) { return 1234; };
exports.e = e;
Maybe that's better in the error case, preserving the recovery?
@DanielRosenwasser curious as to what you think; I'm not convinced it matters either way if both fix the bug, just an esoteric recovery.
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.
I think this is an okay fix; however, if we add satisfies
(or any other new infix keyword) then we'll have another similar bug in the future.
@DanielRosenwasser Here they are:Comparison Report - main..49029
System
Hosts
Scenarios
Developer Information: |
@@ -4538,6 +4538,10 @@ namespace ts { | |||
// isn't actually allowed, but we want to treat it as a lambda so we can provide | |||
// a good error message. | |||
if (isModifierKind(second) && second !== SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsIdentifier)) { |
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.
Yeah, I think that this fix is good as-is; this block (as commented above) is to do better error recovery if someone writes code like (foo number) => ...
, which is guaranteed to fail to parse later. The likelihood of that broken code appearing and someone legitimately naming a type as
seems very, very low, so I'm happy with just not having recovery in this case.
@typescript-bot pack this |
Heya @DanielRosenwasser, I've started to run the tarball bundle task on this PR at e9d39bd. You can monitor the build here. |
I'm going to cherry-pick this manually. |
No I'm not, I accidentally merged instead of sqaushed. @typescript-bot cherry-pick this to release-4.7 |
Heya @DanielRosenwasser, I've started to run the task to cherry-pick this into |
Hey @DanielRosenwasser, I couldn't open a PR with the cherry-pick. (You can check the log here). You may need to squash and pick this PR into release-4.7 manually. |
I guess I am 🙄 |
Fixes #44466
Fixes #49021