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

no-useless-return has a false negative with try/catch #7481

Closed
not-an-aardvark opened this issue Oct 29, 2016 · 14 comments · Fixed by #16996
Closed

no-useless-return has a false negative with try/catch #7481

not-an-aardvark opened this issue Oct 29, 2016 · 14 comments · Fixed by #16996
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion bug ESLint is working incorrectly rule Relates to ESLint's core rules
Projects

Comments

@not-an-aardvark
Copy link
Member

Tell us about your environment

  • ESLint Version: 3.9.0
  • Node Version: 6.9.1
  • npm Version: 3.10.8

What parser (default, Babel-ESLint, etc.) are you using?

default

Please show your full configuration:

rules:
  no-useless-return: error

What did you do? Please include the actual source code causing the issue.

function foo() {
  try {
    return;
  } catch (err) {
    foo();
  }
}

What did you expect to happen?

This should report an error, because the return statement can be safely removed.

What actually happened? Please include the actual, raw output from ESLint.

No error.

@not-an-aardvark not-an-aardvark added bug ESLint is working incorrectly rule Relates to ESLint's core rules accepted There is consensus among the team that this change meets the criteria for inclusion labels Oct 29, 2016
@mysticatea
Copy link
Member

mysticatea commented Oct 30, 2016

Thank you for this issue.

In fact, this is caused by the current code path analyzer.
Since the analyzer cannot know the places which throw exceptions, it generates 2 code paths which go to the catch block from both the first statement and the last statement in the try block (edit: and from throw statements).
But in this case, the return; statement throws no exception clearly. I will investigate to improve the code path.

@mysticatea mysticatea self-assigned this Oct 30, 2016
@not-an-aardvark
Copy link
Member Author

When linting this code:

try { a; b; c; } catch (e) {}

I got this code path:

DOT
digraph {
node[shape=box,style="rounded,filled",fillcolor=white];
initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25];
final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25];
s1_1[label="Program\nTryStatement\nBlockStatement\nExpressionStatement\nIdentifier (a)\nIdentifier:exit (a)"];
s1_2[label="ExpressionStatement\nIdentifier (b)\nExpressionStatement\nIdentifier (c)\nExpressionStatement:exit\nIdentifier:exit (b)\nExpressionStatement:exit\nIdentifier:exit (c)\nExpressionStatement:exit\nBlockStatement:exit"];
s1_4[label="TryStatement:exit\nProgram:exit"];
s1_3[label="CatchClause\nIdentifier (e)\nBlockStatement\nIdentifier:exit (e)\nBlockStatement:exit\nCatchClause:exit"];
initial->s1_1->s1_2->s1_4;
s1_1->s1_3->s1_4->final;
}
Image


But I expected to get something like this:

DOT
digraph {
node[shape=box,style="rounded,filled",fillcolor=white];
initial[label="",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25];
final[label="",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25];
s1_1[label="Program\nTryStatement\nBlockStatement\nExpressionStatement\nIdentifier (a)"];
s1_2[label="Identifier:exit (a)\nExpressionStatement:exit\nExpressionStatement\nIdentifier (b)"];
s1_3[label="Identifier:exit (b)\nExpressionStatement:exit\nExpressionStatement\nIdentifier (c)"];
s1_4[label="Identifier:exit (c)\nExpressionStatement:exit\nBlockStatement:exit"];
s1_5[label="CatchClause\nIdentifier (e)\nBlockStatement\nIdentifier:exit (e)\nBlockStatement:exit\nCatchClause:exit"];
s1_6[label="TryStatement:exit\nProgram:exit"];
initial->s1_1->s1_2->s1_3->s1_4->s1_6;
s1_1->s1_5->s1_6->final;
s1_2->s1_5;
s1_3->s1_5;
}
Image


Is it intentional that each try statement only contains one error point (and one exit point at the end), rather than having an exit point for every possible error?

@mysticatea
Copy link
Member

Yes, it's intentional because I thought that making every throwable path is too many. #3559 (comment)

I'm sorry for I have not done this.

@not-an-aardvark
Copy link
Member Author

not-an-aardvark commented Feb 7, 2018

I see, that makes sense.

  • Do you think it would still be too many paths if we used scope analysis to avoid impossible ReferenceErrors? (It might still be complex because we would have to keep track of TDZ references.)
  • As a smaller fix for this issue, maybe we could avoid adding the edge to the CatchClause if the TryStatement has no throwable paths.

@mysticatea
Copy link
Member

It makes sense if we avoid making throwable path at references which never throw.
If we make every throwable path, I think we should measure impact to performance.

@not-an-aardvark
Copy link
Member Author

Actually, I suppose the second solution wouldn't resolve this issue because something like this would still report an error:

try {
  foo();
  return;
} catch (err) {
  foo();
}

@nzakas
Copy link
Member

nzakas commented Oct 4, 2018

@mysticatea @not-an-aardvark are either of you interested in addressing this?

@kaicataldo kaicataldo added Hacktoberfest Recommended issue for those participating in Hacktoberfest https://hacktoberfest.digitalocean.com/ help wanted The team would welcome a contribution from the community for this issue labels Oct 1, 2019
@kaicataldo kaicataldo removed the Hacktoberfest Recommended issue for those participating in Hacktoberfest https://hacktoberfest.digitalocean.com/ label Nov 19, 2019
@kaicataldo
Copy link
Member

Friendly ping

@guilhermejcgois
Copy link

guilhermejcgois commented Nov 25, 2022

I have free time until 1st december, can I go for it @mysticatea ? Any tip will be very appreciate 😄

Taking a look into this issue seems that in the current version we still have it, adding the example of @not-an-aardvark and no-useless-return.js#L308-L329 cause the test to fail

@nzakas
Copy link
Member

nzakas commented Nov 25, 2022

@guilhermejcgois they have long since left the project. You are welcome to pick this up.

guilhermejcgois added a commit to guilhermejcgois/eslint that referenced this issue Nov 27, 2022
Promote up the useless returns in BlockStatement inside TryStatement
when ESLint is going up in the tree during traversing the AST.

Fixes eslint#7481
guilhermejcgois added a commit to guilhermejcgois/eslint that referenced this issue Nov 27, 2022
Promote up the useless returns in BlockStatement inside TryStatement
when ESLint is going up in the tree during traversing the AST.

Fixes eslint#7481
guilhermejcgois added a commit to guilhermejcgois/eslint that referenced this issue Nov 27, 2022
Promote up the useless returns in BlockStatement inside TryStatement
when ESLint is going up in the tree during traversing the AST.

Fixes eslint#7481
@eslint-github-bot eslint-github-bot bot added the auto closed The bot closed this issue label Dec 26, 2022
@eslint-github-bot
Copy link

Unfortunately, it looks like there wasn't enough interest from the team
or community to implement this change. While we wish we'd be able to
accommodate everyone's requests, we do need to prioritize. We've found
that accepted issues failing to be implemented after 90 days tend to
never be implemented, and as such, we close those issues.
This doesn't mean the idea isn't interesting or useful, just that it's
not something the team can commit to.

Thanks for contributing to ESLint and we appreciate your understanding.

@ljharb
Copy link
Sponsor Contributor

ljharb commented Dec 26, 2022

This has an open PR, #16693

@mdjermanovic mdjermanovic removed help wanted The team would welcome a contribution from the community for this issue auto closed The bot closed this issue labels Dec 26, 2022
@mdjermanovic mdjermanovic added this to Needs Triage in Triage via automation Dec 26, 2022
@mdjermanovic mdjermanovic moved this from Needs Triage to Pull Request Opened in Triage Dec 26, 2022
@mdjermanovic mdjermanovic reopened this Dec 26, 2022
Triage automation moved this from Pull Request Opened to Evaluating Dec 26, 2022
@sam3k
Copy link
Contributor

sam3k commented Feb 25, 2023

Update:

  • This might be the actual opened PR? #16593
  • We're waiting to hear from @guilhermejcgois on one last edge case that needs to be addressed in the PR

@nzakas
Copy link
Member

nzakas commented Mar 1, 2023

Looks like we will need help finishing up the PR for this.

@eslint-github-bot eslint-github-bot bot locked and limited conversation to collaborators Nov 20, 2023
@eslint-github-bot eslint-github-bot bot added the archived due to age This issue has been archived; please open a new issue for any further discussion label Nov 20, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
accepted There is consensus among the team that this change meets the criteria for inclusion archived due to age This issue has been archived; please open a new issue for any further discussion bug ESLint is working incorrectly rule Relates to ESLint's core rules
Projects
Archived in project
Triage
Evaluating
8 participants