Skip to content

Java: Improve algorithm for subtyping of parameterized types. #7088

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

Merged
merged 3 commits into from
Nov 17, 2021

Conversation

aschackmull
Copy link
Contributor

This drastically improves performance when there are many instantiations of generic types with 3 or more type variables. One observed case improved from 85 minutes to less than one minute.

@aschackmull aschackmull added the no-change-note-required This PR does not need a change note label Nov 9, 2021
@aschackmull aschackmull requested a review from a team as a code owner November 9, 2021 14:52
@github-actions github-actions bot added the Java label Nov 9, 2021
@aschackmull aschackmull requested a review from hvitved November 15, 2021 12:03
Comment on lines +171 to +173
typePrefixContains(pragma[only_bind_into](pps0), pragma[only_bind_into](ppt0)) and
pps = TTypeParam(pragma[only_bind_into](pps0), t) and
ppt = TTypeParam(ppt0, t)
Copy link
Contributor

Choose a reason for hiding this comment

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

Worth commenting what the load of pragmas intend to achieve? It looks like you want:

Take all TTypeParam(ppt0, t)
Join with all TTypeParam(pps0, t)
Restrict by typePrefixContains(pps0, ppt0)

?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, that join order would be horrible (and isn't what the pragmas describe). There are two instances of canonical pragma use. The only_bind_into on pps0 means "don't join on this" and the set of only_bind_into on all the columns of typePrefixContains is the canonical use saying "put this predicate first in the pipeline". So this should be entirely standard pragma use.

Copy link
Contributor

Choose a reason for hiding this comment

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

Right, I was reading the pragma as if it was only_bind_out. Oops.

ParameterizedPrefix ppt, ParameterizedPrefix ppt0, RefType s
) {
exists(GenericType g, int n, RefType t |
ppt.split(g, ppt0, t, n) and
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
ppt.split(g, ppt0, t, n) and
// Implies ppt = TTypeParam(ppt0, t)
ppt.split(g, ppt0, t, n) and

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's in the qldoc of split. Do you think it should be repeated here?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes, because it enables the reader to understand the whole of this predicate in one go without referring elsewhere

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

exists(ParameterizedPrefix pps0 |
typePrefixContains(pps0, ppt0) and
pps = TTypeParam(pps0, s) and
s instanceof Wildcard
Copy link
Contributor

Choose a reason for hiding this comment

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

Surprising not see the wildcard condition in the algorithm outline at line 150

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's because it's semantically irrelevant. It's just a piece of manual magic implied by typeArgumentContains(_, s, t, _).

Copy link
Contributor

Choose a reason for hiding this comment

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

In that case suggest adding // manual magic to make clear that's all this is doing

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Comment on lines 271 to 273
private predicate subtypeStarMagic1(RefType t) { t = any(Wildcard w).getUpperBound().getType() }

private predicate subtypeStarMagic2(RefType t) { t = any(Wildcard w).getLowerBound().getType() }
Copy link
Contributor

Choose a reason for hiding this comment

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

Call them getAWildcardUpper/LowerBound?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We could... But they really are pieces manual magic, so I thought these names were clearer.

Copy link
Contributor

Choose a reason for hiding this comment

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

Similar to s instanceof Wildcard above suggest naming them for what they are and using // manual magic to signal intent

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@aschackmull aschackmull force-pushed the java/parameterized-subtyping branch from c22813b to 76606b5 Compare November 16, 2021 15:11
@smowton
Copy link
Contributor

smowton commented Nov 16, 2021

Added a commit to fix manuel-magic https://en.wikipedia.org/wiki/Manuel_(Fawlty_Towers)

@aschackmull aschackmull merged commit 1645fcf into github:main Nov 17, 2021
@aschackmull aschackmull deleted the java/parameterized-subtyping branch November 17, 2021 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Java no-change-note-required This PR does not need a change note
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants