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

Revertible thunks as function II: fix recursive overriding #940

Merged
merged 12 commits into from
Dec 1, 2022

Conversation

yannham
Copy link
Member

@yannham yannham commented Nov 23, 2022

Revertible thunks are functions

Closes #908.

Follow-up of #924: bring the presentation of revertible thunks as just functions memoization devices to its logical conclusion by providing helper to explicitly rebuild the represented function and apply it. This explicit application was required to fix recursive overriding in the general case, see #908. Now, the implementation faithfully expresses general merging of recursive fields as common_field = fun self => (left_field self) & (right_field self), when recursive record fields are understood as functions of self (representing the ambient record).

Revertible thunks representation

This PR also reworks the representation of revertible thunks. They used to store the cached data as an Rc<Closure>, initialized as soon as the revertible thunks was initialized. This doesn't model revertible thunks faithfully: the cached value should be owned (as it is for normal thunks), and as long as the revertible thunks hasn't be "patched" (or, when seen as a function, applied), the cached value is meaningless and may contain free variables, id est unbound identifiers.

The cached value should never be used before full initialization. This PR sets the cached value to be an Option<Closure>, and to panic if it used before initialization. It also ensures that initialization is done only once. The previous implementation wouldn't complain about such violation. Note that we have no choice to perform the construction of a revertible thunks in two steps, and thus observe a transitory state where the cached value is not initialized, because we are potentially building cyclic values. However, if the implementation is correct, the state where the cached value is set to None shouldn't really be observable.

@yannham yannham changed the title Refactor/revthunks are functions 2 Revertible thunks as function II: fix recursive overriding Nov 23, 2022
@github-actions github-actions bot temporarily deployed to pull request November 23, 2022 17:39 Inactive
@github-actions github-actions bot temporarily deployed to pull request November 24, 2022 13:37 Inactive
@github-actions github-actions bot temporarily deployed to pull request November 24, 2022 14:33 Inactive
@github-actions github-actions bot temporarily deployed to pull request November 24, 2022 14:59 Inactive
@yannham yannham force-pushed the refactor/revthunks-are-functions-2 branch from 41639fa to b5818dd Compare November 24, 2022 17:54
@github-actions github-actions bot temporarily deployed to pull request November 24, 2022 17:58 Inactive
@yannham yannham marked this pull request as ready for review November 24, 2022 18:04
src/eval/lazy.rs Outdated Show resolved Hide resolved
src/eval/lazy.rs Outdated Show resolved Hide resolved
src/eval/lazy.rs Outdated Show resolved Hide resolved
src/eval/lazy.rs Outdated Show resolved Hide resolved
src/eval/lazy.rs Outdated Show resolved Hide resolved
src/eval/lazy.rs Outdated Show resolved Hide resolved
@github-actions github-actions bot temporarily deployed to pull request November 24, 2022 18:13 Inactive
@github-actions github-actions bot temporarily deployed to pull request November 24, 2022 18:36 Inactive
src/eval/lazy.rs Outdated Show resolved Hide resolved
src/eval/lazy.rs Outdated Show resolved Hide resolved
@github-actions github-actions bot temporarily deployed to pull request November 25, 2022 10:25 Inactive
src/eval/merge.rs Outdated Show resolved Hide resolved
src/eval/merge.rs Outdated Show resolved Hide resolved
src/eval/merge.rs Outdated Show resolved Hide resolved
@github-actions github-actions bot temporarily deployed to pull request November 25, 2022 10:32 Inactive
@github-actions github-actions bot temporarily deployed to pull request November 25, 2022 10:37 Inactive
Copy link
Contributor

@vkleen vkleen left a comment

Choose a reason for hiding this comment

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

I've just found some more typos in the comments. The logic seems good, as far as I can tell 👍

src/eval/lazy.rs Outdated Show resolved Hide resolved
src/eval/lazy.rs Outdated Show resolved Hide resolved
src/eval/lazy.rs Outdated Show resolved Hide resolved
src/eval/lazy.rs Outdated Show resolved Hide resolved
src/eval/merge.rs Outdated Show resolved Hide resolved
src/eval/merge.rs Outdated Show resolved Hide resolved
src/eval/merge.rs Outdated Show resolved Hide resolved
src/eval/merge.rs Outdated Show resolved Hide resolved
@github-actions github-actions bot temporarily deployed to pull request November 25, 2022 13:46 Inactive
Copy link
Contributor

@matthew-healy matthew-healy left a comment

Choose a reason for hiding this comment

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

As far as I can tell, this looks good, though I have to say my mental model for exactly what's going on & how it all fits together isn't great and as such I don't feel qualified to give an approving review.

I left one or two small comments but just for minor things. I don't think they need to block merging.

src/eval/lazy.rs Show resolved Hide resolved
src/eval/lazy.rs Outdated Show resolved Hide resolved
src/eval/lazy.rs Outdated Show resolved Hide resolved
yannham and others added 11 commits November 30, 2022 16:59
Revertible thunks used Rc<Closure> for the cached data. But when the
revertible thunk is first created, the cached data aren't meaningful and
can't be used as it is (it has free variables which need to be bound).
This change better reflects this reality by using an Option, and by
panicking in some illegal patterns (using the cached term before the
revertible thunk is properly constructed or trying to build the cached
data multiple times). Previously, we would silently accept such
operations with the risk of getting spurious unbound variable errors
later on.
Some multistep overriding patterns weren't handled correctly broken (see
#908). Revertible thunks are to be
understood as function, and the previous implementation was trying to
away with actually introducing explicit function and application, by
patching directly the environment of expressions with free variables.
The examples presented in #908 makes it clear that this simplification
doesn't work for all cases: this commit fixes the issue by introducing
explicit functions and applications in the general case of merging two
record fields, instead of relying on environment patching.
Co-authored-by: Viktor Kleen <viktor.kleen@tweag.io>
@yannham yannham force-pushed the refactor/revthunks-are-functions-2 branch from a9f17bd to bcec8a5 Compare November 30, 2022 16:01
@github-actions github-actions bot temporarily deployed to pull request November 30, 2022 16:04 Inactive
@yannham yannham force-pushed the refactor/revthunks-are-functions-2 branch from bcec8a5 to 1e18dfb Compare December 1, 2022 09:15
@github-actions github-actions bot temporarily deployed to pull request December 1, 2022 09:18 Inactive
@yannham yannham merged commit b192634 into master Dec 1, 2022
@yannham yannham deleted the refactor/revthunks-are-functions-2 branch December 1, 2022 10:40
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.

Recursive overriding is nonassociative
3 participants