-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
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
Add some documentation for standard library things. #3540
Conversation
Added a bunch of descriptions for array_list. Added some usage notes for failing_allocator. Documented some of mem.Allocator.
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.
Thank you for getting the documentation effort started!
lib/std/array_list.zig
Outdated
@@ -5,6 +5,10 @@ const testing = std.testing; | |||
const mem = std.mem; | |||
const Allocator = mem.Allocator; | |||
|
|||
/// Safe, resizable array type. |
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.
I think calling this "safe" is misleading, since there are a handful of ways to use ArrayList unsafely.
- obtaining a reference to an element and then appending an element or otherwise changing the size.
- accessing items directly instead of using
toSlice
ortoSliceConst
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.
That's fair. I wanted to characterize it somewhat like std::vector, since that's what it seems to be. It's safer than just passing an unsized array around. Maybe just leave the "List of elements" part? I feel like this should be where an example for canonical use goes.
lib/std/array_list.zig
Outdated
/// Extend the list by 1 element, but assuming `self.capacity` | ||
/// is sufficient to hold an additional item. Use with care; | ||
/// will produce undefined behavior in ReleaseFast and | ||
/// ReleaseSmall modes. |
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.
See #2402, and consider that "assert" means "invokes detectable illegal behavior if the asserted value is false". I would phrase like this:
/// Extend the list by 1 element, asserting `self.capacity` /// is sufficient to hold an additional item.
The concept of illegal behavior and assertions is pervasive in all zig code. Documentation readers absolutely must understand what "assert" means in documentation.
You can see that the definition of std.debug.assert
matches this:
Lines 195 to 207 in f756d87
/// This function invokes undefined behavior when `ok` is `false`. | |
/// In Debug and ReleaseSafe modes, calls to this function are always | |
/// generated, and the `unreachable` statement triggers a panic. | |
/// In ReleaseFast and ReleaseSmall modes, calls to this function are | |
/// optimized away, and in fact the optimizer is able to use the assertion | |
/// in its heuristics. | |
/// Inside a test block, it is best to use the `std.testing` module rather | |
/// than this function, because this function may not detect a test failure | |
/// in ReleaseFast and ReleaseSmall mode. Outside of a test block, this assert | |
/// function is the correct function to use. | |
pub fn assert(ok: bool) void { | |
if (!ok) unreachable; // assertion failure | |
} |
lib/std/array_list.zig
Outdated
pub fn appendAssumeCapacity(self: *Self, item: T) void { | ||
const new_item_ptr = self.addOneAssumeCapacity(); | ||
new_item_ptr.* = item; | ||
} | ||
|
||
/// Remove the element at index `i` from the list and return | ||
/// its value. |
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.
As an example from the previous comment, this function also asserts something.
Asserts the array has at least one element.
Better to use the word "assert" here, I think, than repeat the "Use with care..." sentence.
lib/std/array_list.zig
Outdated
/// Append the slice of items to the list. Copies the contents | ||
/// of `items`. |
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.
"Copies the contents of items
" is a bit misleading here. What is this sentence disambiguating? If the answer is nothing, let's omit it.
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.
I was trying to make it clear that it's not a move, and that if items
contains any pointers they're aliased now. Of course, that's true for all the insertion functions, so it probably either belongs in all of them or none of them. Maybe when the top-level doc has examples, it can be made clear there.
lib/std/array_list.zig
Outdated
@@ -191,11 +221,13 @@ pub fn AlignedArrayList(comptime T: type, comptime alignment: ?u29) type { | |||
return result; | |||
} | |||
|
|||
/// Remove and return the last element from the list. |
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.
/// Asserts the array has at least one element.
lib/std/debug/failing_allocator.zig
Outdated
/// | ||
/// To use this, first initialize it and get an allocator with | ||
/// | ||
/// `var failing_allocator = &FailingAllocator.init(<allocator>, |
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.
/// `var failing_allocator = &FailingAllocator.init(<allocator>, | |
/// `const failing_allocator = &FailingAllocator.init(<allocator>, |
lib/std/debug/failing_allocator.zig
Outdated
/// fail_index is the number of successful allocations you can | ||
/// expect from this allocator. Allocation <fail_index> + 1 will | ||
/// fail. |
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.
fail_index
is the index that will fail. What makes you think it's fail_index + 1
?
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.
This is a zero-based index vs. 1-based index confusion thing. I'll change it to fail_index
and add an example to clarify.
lib/std/mem.zig
Outdated
/// Returns an uninitialized array of T. Call `free` to free the | ||
/// memory. |
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.
Not uninitialized - set to undefined
. This is meaningful in Zig. Also, free
is not always required, for example the purpose of std.heap.ArenaAllocator
is to make freeing not required.
Allocates an array of
n
items of typeT
and sets all the items toundefined
. Depending on theAllocator
implementation, it may be required to callfree
once the memory is no longer needed, to avoid a resource leak. If theAllocator
implementation is unknown, then correct code will callfree
when done.For allocating a single item, see
create
.
Note that accepted proposal #2292 would make it possible to determine whether calling free() is necessary.
lib/std/mem.zig
Outdated
@@ -218,6 +220,7 @@ pub const Allocator = struct { | |||
return @bytesToSlice(T, @alignCast(new_alignment, byte_slice)); | |||
} | |||
|
|||
/// Free an array allocated with `alloc`. |
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.
Additional docs:
To free a single item, see
destroy
.
Added a bunch of descriptions for array_list.
Added some usage notes for failing_allocator.
Documented some of mem.Allocator.