Skip to content

Fix isorecursive canonicalization #5269

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 1 commit into from
Nov 17, 2022
Merged

Fix isorecursive canonicalization #5269

merged 1 commit into from
Nov 17, 2022

Conversation

tlively
Copy link
Member

@tlively tlively commented Nov 17, 2022

Fixes a longstanding problem with isorecursive canonicalization that only showed
up in MacOS and occasionally Windows builds. The problem was that
RecGroupEquator was not quite correct in the presence of self-references in
rec groups. Specifically, RecGroupEquator did not differentiate between
instances of the same type appearing across two rec groups where the type was a
self-reference in one group but not in the other.

The reason this only showed up occasionally on some platforms was that this bug
could only cause incorrect behavior if two groups that would incorrectly be
compared as equal were hashed into the same bucket of a hash map. Apparently the
hash map used on Linux never hashes the two problematic groups into the same
bucket.

Fixes a longstanding problem with isorecursive canonicalization that only showed
up in MacOS and occasionally Windows builds. The problem was that
`RecGroupEquator` was not quite correct in the presence of self-references in
rec groups. Specifically, `RecGroupEquator` did not differentiate between
instances of the same type appearing across two rec groups where the type was a
self-reference in one group but not in the other.

The reason this only showed up occasionally on some platforms was that this bug
could only cause incorrect behavior if two groups that would incorrectly be
compared as equal were hashed into the same bucket of a hash map. Apparently the
hash map used on Linux never hashes the two problematic groups into the same
bucket.
@tlively tlively requested a review from kripken November 17, 2022 00:45
@tlively
Copy link
Member Author

tlively commented Nov 17, 2022

Current dependencies on/for this PR:

This comment was auto-generated by Graphite.

return groupA == groupB || (groupA == newGroup && groupB == otherGroup);
bool selfRefA = groupA == newGroup;
bool selfRefB = groupB == otherGroup;
return (selfRefA && selfRefB) || (!selfRefA && !selfRefB && groupA == groupB);
Copy link
Member

Choose a reason for hiding this comment

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

I've forgotten how this code works, sorry. Is newGroup a new group being built that is being compared to an existing group otherGroup? How can groupA/B not match those two, why would we be comparing types not from the groups at all, when comparing newGroup/otherGroup?

I couldn't find code comments explaining how the class RecGroupEquator is used - are they somewhere else than on the class itself?

Copy link
Member Author

Choose a reason for hiding this comment

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

I've forgotten how this code works, sorry. Is newGroup a new group being built that is being compared to an existing group otherGroup?

Yes, exactly.

How can groupA/B not match those two, why would we be comparing types not from the groups at all, when comparing newGroup/otherGroup?

Because we might be comparing heap types that are used in newGroup and otherGroup (e.g. because structs defined in those groups contain reference to the heap types), but are defined in some arbitrary different previous groups. We're trying to compare the "shapes" of newGroup and otherGroup, and how they reference other groups is part of that "shape."

I couldn't find code comments explaining how the class RecGroupEquator is used - are they somewhere else than on the class itself?

There are some additional comments on RecGroupStructure and RecGroupStore.

Copy link
Member

Choose a reason for hiding this comment

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

Got it, thanks!

Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

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

lgtm (I assume my remaining question is a small misunderstanding on my part)

Can we add a test for this?

@tlively
Copy link
Member Author

tlively commented Nov 17, 2022

Can we add a test for this?

This would be difficult since RecGroupEquator is not a public API, but rather an implementation detail of equirecursive type canonicalization. I did re-enable the existing unit test for canonicalizing recursive isorecursive types. That test used to be extremely flaky on Mac and now it shouldn't be, so maybe that's enough testing?

@kripken
Copy link
Member

kripken commented Nov 17, 2022

sgtm, a re-enabled flaky test that is now stable seems enough.

@tlively tlively merged commit 5f5c702 into main Nov 17, 2022
@tlively tlively deleted the fix-isorec-canon branch November 17, 2022 21:30
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