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

Skip too complex guards #570

Merged
merged 10 commits into from
Oct 11, 2024
Merged

Conversation

erszcz
Copy link
Collaborator

@erszcz erszcz commented Sep 17, 2024

This PR skips processing functions which use complex guards in order to make Gradualizer more convenient for everyday use, based on the fact that such complex guards aren't handled properly yet. It's important to underline that this PR doesn't lead to fewer or inferior warnings, since the warnings that are skipped could only be false positives anyway, due to incorrect/missing parameter refinement.

This enables Gradualizer users to more conveniently use the tool on "random", i.e. Gradualizer-unaware, projects, thanks to fewer false positives being raised. The PR also contains examples of refactoring (some) unhandled Erlang constructs into equivalent ones that are already handled completely by the tool.

Gradualizer developers can see which Erlang constructs and what guards would be worth handling next. We can also see that with this change some assertions can be dropped from Gradualizer code, yet maintaining that the tool can self-check.

Since too complex guards lead to skipping a function altogether now,
this condition is redundant.
Dropping it allows exhaustiveness checking to benefit from the simple
refinements from guards that are supported.
Copy link
Collaborator

@xxdavid xxdavid left a comment

Choose a reason for hiding this comment

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

Hi again! I am also for lowering the number of false positives in cases our code is not smart enough yet. To be honest, I am not really sure of the scope/implications of the changes in this PR though. Do I understand it correctly that all functions that contain any guard other than a single is_TYPE/1 (such as is_integer/1) guard are now skipped (as refine_vars_by_mismatching_clause/3 throws the {skip, too_complex_guards} tuple?

src/typechecker.hrl Show resolved Hide resolved
@erszcz
Copy link
Collaborator Author

erszcz commented Oct 10, 2024

Do I understand it correctly that all functions that contain any guard other than a single is_TYPE/1 (such as is_integer/1) guard are now skipped (as refine_vars_by_mismatching_clause/3 throws the {skip, too_complex_guards} tuple?

Yes. I don't really see a better way to make the usability reasonable and at the same time not spend significant time on code which would just override the argument types to any() in presence of too complex guards. It's still possible to avoid skipping by refactoring code to use just patterns or simple guards, thanks to verbose logging.

Proper tackling of complex guards requires two things: precise inference of types based on all operators (e.g. binary + might currently "refine" to a broader type, see #572) and negative types. Neither is already available, so I think reaching for the lowest-hanging fruit is just to skip too complex syntax, yet be useful otherwise.

@erszcz erszcz merged commit c44e393 into josefs:master Oct 11, 2024
5 checks passed
@erszcz erszcz deleted the skip-too-complex-guards branch October 11, 2024 11:47
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

Successfully merging this pull request may close these issues.

2 participants