-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Mark (bigint|number).toString(radix) nosideeffects (fixes #4169) #4308
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3668,6 +3668,16 @@ public void testCallCache_propagatesSideEffects() { | |
| }); | ||
| } | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What we're missing is a test case to confirm that the call will not be considered pure when the I think we should have that before I try to run this through extensive testing. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just for learning: So you mean that if the compiler knows for sure that its numerical, the call can be removed. And if it does not know for sure (any type) its kept? Why wouldn't we say that toString will always only have the purpose to output a string and if anyone calls another function toString, its an idiot? Thanks.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, we may be way overly cautious here. Instead of if (assumeKnownBuiltinsArePure
&& OBJECT_METHODS_WITHOUT_SIDEEFFECTS.contains(callee.getString())
&& (callNode.hasOneChild() || isNumericToStringCall(callee))) {maybe one can decide the call to be pure if its a built-in with 0 arguments or if (assumeKnownBuiltinsArePure
&& OBJECT_METHODS_WITHOUT_SIDEEFFECTS.contains(callee.getString())
&& (callNode.hasOneChild() || "toString".equals(callee.getString()))) {Whichever is the desired behavior, I can change the code to that.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OK, I did a bit of historical digging with the intent of finding out whether the The answer was "no". This condition was there when the logic was first added in 2010, and never had a comment attached to say why it was there. I assume it was just an extra signal to be sure that the I'll point out that So, I'll suggest 3 options for you.
Options 2 and 3 assume you would also remove the type-checking code, of course. Number 3 keeps the logic the simplest, but adds a new risk of breaking code using user-written Number 2 adds very little risk, so I'd be inclined to go with that one. I think I prefer both of those options over number 1 now that I've had more time to reflect on it, because they're simpler and don't require type information. But, if you decide to add tests, I'm still OK with merging it.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Awesome, thanks a lot! I'll get to this later today. Let me research this better but I remember seeing toString() pure assumption in other tools as well (oxc, Uglify). If so, that may make 3 safer than it initially seems: most things that can be broken by this have already been broken & likely fixed. Re: eliminating
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @brad4d I implemented Option 2 with minimal changes. Can you take another look? Though, it could be nice to rearrange test callNode.isNoSideEffectsCall() |
||
| @Test | ||
| public void testToStringWithRadixIsPure() { | ||
| assertPureCallsMarked("var x = {}; x.toString(16);", ImmutableList.of("x.toString")); | ||
| } | ||
|
|
||
| @Test | ||
| public void testOptionalChainToStringWithRadixIsPure() { | ||
| assertPureCallsMarked("var x = {}; x?.toString(16);", ImmutableList.of("x?.toString")); | ||
| } | ||
|
|
||
| @Test | ||
| public void testDynamicImport() { | ||
| ignoreWarnings(DiagnosticGroups.MODULE_LOAD); | ||
|
|
||
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.
What we're missing is a test case to confirm that the call will not be eliminated when the
thisobject is not numerical.I think we should have that before I try to run this through extensive testing.