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

if containing only return is dropped #1585

Closed
Conduitry opened this issue Aug 28, 2017 · 9 comments
Closed

if containing only return is dropped #1585

Conduitry opened this issue Aug 28, 2017 · 9 comments

Comments

@Conduitry
Copy link
Contributor

Regression in 0.49.

function foo(x) {
	if (x) {
		return y;
	}
	bar();
}

foo(z);

produces

function foo(x) {
	bar();
}

foo(z);
@kzc
Copy link
Contributor

kzc commented Aug 28, 2017

Patch below fixes this particular issue with no test regressions:

--- a/src/ast/Node.js
+++ b/src/ast/Node.js
@@ -30,7 +30,7 @@ export default class Node {
        }
 
        hasEffects () {
-               return this.included || this.someChild( child => child.hasEffects() );
+               return this.included || this.someChild( child => child.shouldBeIncluded() );
        }
 
        hasEffectsWhenAssigned () {

@lukastaegert Does that match your intention?

@lukastaegert
Copy link
Member

You are right, but if you change the logic here, then any function that only contains a return statement will be kept as well even though it clearly has no side-effects.
The reason is that return statements have no effects but .shouldBeIncluded() when they are encountered. I though this was enough, but apparently it is knot :)

I'm looking into this now, thanks to @Conduitry for this quick observation! If do not find a good solution soon, your patch is at least a working fix.

@kzc
Copy link
Contributor

kzc commented Aug 28, 2017

You are right, but if you change the logic here, then any function that only contains a return statement will be kept as well even though it clearly has no side-effects.

Not the case. 16 tests like the following still pass with the patch:

var x = true ? foo () : bar();

function foo () {
	return 'should be removed, because x is unused';
}

https://github.com/rollup/rollup/blob/master/test/form/samples/side-effect-q/main.js

@lukastaegert
Copy link
Member

You are absolutely right, I just saw this myself! Nevertheless, let me check if it is not better to change the logic of the return statement instead.

@lukastaegert
Copy link
Member

Ok, I understand it now, the reason your fix works is because the algorithm that determines if function calls have effects is the custom logic here that I was planning to replace on my next pull request. In so far, there is no reason not to do it this way for now, I will just have to find a better solution when I actually start refactoring this code :) I will push a new pull request with new tests in a second.

@lukastaegert
Copy link
Member

Ah, again, it is not that easy. This is not removed now though it should have been:

function isRemoved ( x ) {
	if ( x ) {
		return 2;
	}
	return 1;
}

isRemoved( true );

Back to the drawing board.

@kzc
Copy link
Contributor

kzc commented Aug 28, 2017

It's better to err on the side of caution. Dropping necessary code is far worse than including unnecessary code.

@lukastaegert
Copy link
Member

I totally agree. But I think I have a good solution now, should take a few minutes, though :)
My idea is to add an options object to .hasEffects...(options) calls which I wanted to add at some later point anyways. This will tell the algorithm if we are checking nested function calls for effects or not. In the first case, we ignore the effects of return statements, in the other case we don't.

@lukastaegert
Copy link
Member

Should be fixed in a nice way by #1586.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants