-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
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
std interface reform (#1829) #2533
Closed
tgschultz
wants to merge
25
commits into
ziglang:master
from
tgschultz:git_stdlib-interface_reform_3
Closed
std interface reform (#1829) #2533
tgschultz
wants to merge
25
commits into
ziglang:master
from
tgschultz:git_stdlib-interface_reform_3
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
…loc/ShrinkFn, 0-bit types don't work after all when passed as parameters.
…schultz/zig into git_stdlib-interface_reform_3
Please see #130 (comment). I'm closing this pull request because it's not really mergable, but I do consider it to be an invaluable tool in evaluating how to proceed with that issue, once the time comes to do that. 👍 Thank you @tgschultz! (I'm going to copy this comment to the other 2 pull requests, for the benefit of anyone stumbling upon them.) |
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.
Attempt 3 of this went pretty well. It is my determination that this is close to the best we can do in userland today. Here's the summary:
Interfaces are in the form of
pub fn InterfaceName(comptime T: type, comptime SomeFn: type...) type
. For instance, the Allocator interface signature ispub fn Allocator(comptime A: type, comptime ReallocFn: type, comptime ShrinkFn: type) type
. The interface function is used to produce an interface implementation from a struct by passing the*Self
and type(s) of the implementation functions. The implementation will have animpl
field, which is a pointer to the implementation instance, and one or moresomeFn
fields that point to the implementation functions. The interface provides functions that utilize these implementation fn fields by calling them withimpl
as the first parameter. Since these generated interfaces are unique to a each type they wrap, they must be taken asvar
parameters, but will retain errorset information.Any struct providing an interface implementation should provide a function named after the interface that returns the implementation. For example,
Pcg
has arandom()
function which returns its Random interface implementation. Further, the struct should expose apub const
defining its implementation type in the form ofInterfaceImpl
(Pcg.RandomImpl
in the above case) and any errorsets in the form ofImplFnError
. For instance, all Allocator implementing structs exposeReallocError
(this should be unnecessary when bugs regarding error inference are cleared up, #1810, #1386, etc.).If one needs to store an interface implementation in a non-generic struct, or otherwise pass around a runtime-determined interface implementation, the interface provides an 'abstracted' form with the name of
AnyInterfaceName
(AnyAllocator
,AnyRandom
etc.), These can be obtained from the non-abstracted interface implementation usingtoAny()
, i.e.var allocator = direct_allocator.allocator().toAny();
.Interfaces support implementations with 0-bit types. When creating its interface implementation the struct must set
.impl
tonull
, and instead of taking*Self
must takeUnused
. This prevents a problem where the abstracted interface passes a pointer as the first (assumed asself
) parameter when no value is expected (because it is 0-bit). Note that the implementation returning function (allocator()
,random()
, etc.) should take self asvar
to allow it to work with method call syntax.Async is supported via a hack, where
AnyAllocator
supplies two additional fields that point a differentrealloc
andshrink
implementations to account for the expected behavior of the status-quo Allocator interface. So, when providing an allocator to async, it must be of type *AnyAllocator. As async is due to be redesigned to not require an allocator at all (#2377), this is temporary.Please see interface.zig for a test case that demonstrates the pattern.
Pros compared to status-quo interfaces:
Cons compared status-quo interfaces:
var
paramters, making function signatures less self-explanatory (could be fixed with Proposal: User definable type constraints on polymorphic parameters #1669)Alternatives:
@fieldParentPtr