Skip to content
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 class name references #55262

Merged
merged 2 commits into from Aug 5, 2023
Merged

Fix class name references #55262

merged 2 commits into from Aug 5, 2023

Conversation

rbuckton
Copy link
Member

@rbuckton rbuckton commented Aug 4, 2023

This fixes our emit for references to a class name inside of a class body when down-level emit moves the member containing the reference outside of the class body. This is necessary to preserve the "double bind" semantics of class names, where references to a class name inside of a class body are not affected when the reference to the class outside of the class body is changed.

We generally emit members outside of a class body when downleveling static fields, class static blocks, and private methods/accessors.

Fixes #54607

@typescript-bot typescript-bot added Author: Team For Milestone Bug PRs that fix a bug with a specific milestone labels Aug 4, 2023
Comment on lines -1073 to +1072
YieldExpression,
YieldExpression
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you know what you ran which did this? Was it organize imports? Something else? Hoping to get to the bottom of these so we can be consistent (or, I guess formatting will prevent that).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably organize imports.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, just tested running organize on checker.ts and this didn't happen, even when reordering things, really odd.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it was a result of running Organize Imports to remove an unused import. I just checked locally and that does remove the trailing ,.

@jakebailey
Copy link
Member

(Abusing this PR slightly to make sure RWC is working; this PR touches emit so it should produce a diff)

@typescript-bot test this

@typescript-bot
Copy link
Collaborator

typescript-bot commented Aug 4, 2023

Heya @jakebailey, I've started to run the extended test suite on this PR at 9868cdb. You can monitor the build here.

@@ -1070,7 +1069,7 @@ import {
WhileStatement,
WideningContext,
WithStatement,
YieldExpression,
YieldExpression
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
YieldExpression
YieldExpression,

Well, in any case, probably best to leave it until we can figure out what's happening. This is of course a nit (still looking at the PR)

Copy link
Member

@jakebailey jakebailey left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems correct to me though it's a little hard for me to be sure staring at the emit output 😄

Comment on lines -6025 to -6026
ClassWithBodyScopedClassBinding = 1 << 16, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 1 << 17, // Binding to a decorated class inside of the class's body.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we shift the other bits down or is it no big deal to leave them empty until later?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a driveby cleanup, right? I don't see any removal of BodyScopedClassBinding in the rest of the PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All references to BodyScopedClassBinding were removed in a prior PR, but I neglected to remove the flag. I can fix up the bits used as well.

Copy link
Member

@sandersn sandersn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems good, although I have a few questions. And the emit changes Testing123_1 -> Testing123 are unexpected to me, so worth double-checking.

Comment on lines -6025 to -6026
ClassWithBodyScopedClassBinding = 1 << 16, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 1 << 17, // Binding to a decorated class inside of the class's body.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a driveby cleanup, right? I don't see any removal of BodyScopedClassBinding in the rest of the PR.

break;
}

while (container.kind !== SyntaxKind.SourceFile && container.parent !== declaration) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as I read it, this while loop is semantically equivalent to the old one. Am I missing anything?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, they are equivalent, but I feel this is a bit easier to read and reason over.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, the new one is much easier to read.

@@ -27964,38 +27963,20 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {

let declaration = localOrExportSymbol.valueDeclaration;
if (declaration && localOrExportSymbol.flags & SymbolFlags.Class) {
// Due to the emit for class decorators, any reference to the class from inside of the class body
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To check my understanding: before, the _a reference was only generated for ClassExpressions and decorated classes. Now it happens for any class declaration/expression that references itself in its body. Is that correct?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We won't always generate the reference, but now we will always set the flag. It's just that the cases where we need the flag set were no longer restricted to the cases mentioned in the comment.

@@ -24,5 +24,5 @@ let Testing123 = Testing123_1 = class Testing123 {
exports.Testing123 = Testing123;
Testing123.prop1 = Testing123_1.prop0;
exports.Testing123 = Testing123 = Testing123_1 = __decorate([
Something({ v: () => Testing123_1 })
Something({ v: () => Testing123 })
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand how this diff happened. I assume it's because of the first block in the checker getting deleted, but I thought the edit to the second block would cause the reference to still get generated as Testing123_1.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Testing123_1 represents the class binding inside the class body, however a class decorator is evaluated outside of the class body, so it was pointing to the wrong reference prior to this change.

@rbuckton rbuckton merged commit b1c4dc4 into main Aug 5, 2023
18 checks passed
@rbuckton rbuckton deleted the fix-class-name-references branch August 5, 2023 00:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Author: Team For Milestone Bug PRs that fix a bug with a specific milestone
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Incorrect transpilation of class name references in static contexts
4 participants