-
Notifications
You must be signed in to change notification settings - Fork 12
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
types: introduce TypeInner
making Type
the only public "incomplete Simplicity type" type
#233
Merged
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This avoids passing `hint` through all the layers of recursion, but more importantly, constructs the actual error from a `Context` rather than from a `LockedContext`. In the next commit, we will need extra information to do this, and not want our context to be locked at the time.
We will want to change how types are constructed and this will minimize the future diff.
We will need this elsewhere in the next commit.
Merged
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Reviewed 15d69b2 Looks great. I left some comments.
We have the Bound::sum and Bound::product constructors which check whether the proposed children of the bound are complete, and if so, construct a complete bound. If not, they construct an incomplete one. This check involves calling Bound::final_data which locks the context and then inspects the bound. This limits our freedom of movement to call these constructors because we need to make sure that the context isn't already locked. Better to pull this logic into Context where it can keep track of locking.
We want to make the `Bound` type private to the types module, because it is conceptually an implementation detail of the type inferenece algorithm. It has a weird mutual recursion with `Type` that shouldn't be exposed in the public API. It will also become a problem in a later commit when we change it to be mutually recursive with a new `TypeInner` type instead. For a couple reasons: 1. `TypeInner` is a private type, so if `Bound` contains it, then `Bound` would need to hide its internals which is impossible for an enum. So we would need a `BoundInner` in addition to `TypeInner`, which would be a real pain to understand. 2. Neither `TypeInner` nor `Bound` will hold a reference to an inference context. This means that the API of `Bound` will be severely limited since it will no longer have the ability to introspect itself more than one level deep. This makes for an awkward API that should not be public. This type moves a bunch of text from the main module doccomment and makes it a non-doccomment. It is a move-only of this text; it doesn't change anything. The existing text is somewhat out-of-date but I don't want to change it until we're done with everything else. (It's not too bad; the main thing is that it's now missing the `Context` object.) I believe this is the only "controversial" commit in this PR, because the objects in the Error type actually are, conceptually speaking, individual Bounds rather than Types. But we are stuck between "users should not see or care about bounds" and "the error enum should contain all relevant context" and I think this is the best choice. We can file an issue to revisit this maybe, though I'm willing to live with it.
As part of our project to make `Bound` private, we need to drop the `Context::bind` method, which takes an arbitrary bound and applies it to a type. This method doesn't really need to be public in so much generality, because (for example) binding a type to a free bound is a no-op that should never be done. In fact, it turns out that in Simplicity's typing rules we only ever bind to product bounds. (In some future iteration of Simplicity with e.g. a copair combinator, we would bind to sums; but it's hard to imagine a combinator that would require binding to units or other complete types, since this would represent a combinator whose inputs needed to have exact types, which is not really in the spirit of Simplicity.) So we can get away with just exposing a bind_product method, which takes `Type`s and only constructs a Bound internally.
Previously we had two types, `Type` and `Bound`, which were mutually recursive. `Type` was also exposed in the public API as a type representing an incomplete Simplicity type. `Bound` was exposed in the public API for a couple of reasons which were eliminated over the last few commits. However, because `Type` is both public and unusable without a live type inference context, this means that it needs to contain an `Arc<Context>`. But this means that if we have a self-referential type, this leaks to a somewhat-convoluted reference cycle in which a `Type` holds an `Arc<Context>` which owns a set of `Bound`s which contain the original `Type`. If you are skeptical of this, try running the test harness in valgrind before and after this commit -- you will see that previously we were leaking memory in the `memory_leak` unit test but now we are not. This commit introduces a new private type `TypeInner` which is mutually recursive with (the now-private) `Bound`. Then `Type` contains both a `TypeInner` and an `Arc<Context>` and is not recursive, eliminating the possibility of cyclic references. As a side-effect, it greatly reduces the amount of Arc-cloning that is happening, which should improve performance.
apoelstra
force-pushed
the
2024-06--types-3
branch
from
July 12, 2024 16:33
15d69b2
to
d7cfc34
Compare
Addressed the two actionable comments. Should be good to go. |
uncomputable
approved these changes
Jul 12, 2024
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ACK dada0f2
uncomputable
added a commit
that referenced
this pull request
Jul 15, 2024
8d3eda8 update encoding/decoding API to split off witness data (Andrew Poelstra) d9a5e8d simplicity-sys: update libsimplicity to 1b85dc31d80d36dc012755e4369aeeac815476a6 (Andrew Poelstra) 3251bcd simplicity-sys: update simplicity to 952e126256dd31d7ed8f4b33b99ae8cd1edabe89 (Andrew Poelstra) cbc22ff fixups to vendor-simplicity.sh (Andrew Poelstra) 825c7dc clippy: new lint about ignoring return value of format (Andrew Poelstra) ae96e2f bit decoding: check that bit iterators are fully consumed (Andrew Poelstra) Pull request description: Draft til #233 goes in, and maybe will split into multiple PRs. ACKs for top commit: uncomputable: ACK 8d3eda8 Tree-SHA512: 62485da10137329f8d8f8e5fabc5685c216a7898df522ba2abab6b2317557ac187d0749e3532fce8ae7b602c303afd53aeb3de3465ba74b877997c3f8f17dda8
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Previously we had two types,
Type
andBound
, which were mutually recursive.Type
was also exposed in the public API as a type representing an incomplete Simplicity type.Bound
was exposed in the public API for a couple of reasons which this PR eliminates.However, because
Type
is both public and unusable without a live type inference context, this means that it needs to contain anArc<Context>
. But this means that if we have a self-referential type, this leaks to a somewhat-convoluted reference cycle in which aType
holds anArc<Context>
which owns a set ofBound
s which contain the originalType
. If you are skeptical of this, try running the test harness in valgrind before and after the last commit of this PR -- you will see that previously we were leaking memory in thememory_leak
unit test but now we are not.This completes the "type inference overhaul" needed to eliminate the memory leak in infinitely-sized types.