Skip to content

ability to annotate functions which allocate resources, with a way to deallocate the returned resources #782

Closed as not planned
@andrewrk

Description

@andrewrk

This pattern is extremely common in zig code:

    const err_pipe = try makePipe();
    errdefer destroyPipe(err_pipe);

    var in_file = try os.File.openRead(allocator, source_path);
    defer in_file.close();

    var atomic_file = try AtomicFile.init(allocator, dest_path, mode);
    defer atomic_file.deinit();

    var direct_allocator = std.heap.DirectAllocator.init();
    defer direct_allocator.deinit();

    var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator);
    defer arena.deinit();

Generally:

    const resource = allocateResource();
    defer deallocateResource(resource); // or errdefer

This proposal is to

  • make it harder to forget to clean up a resource
  • make it easier to clean up resources

Strategy:

  • Functions which allocate resources are annotated with the corresponding cleanup function.
  • New keywords, corresponding to the defer keywords:
    • clean corresponding to defer theCleanupFunction(resource);
    • errclean corresponding to errdefer theCleanupFunction(resource);
  • If you want to handle resources manually, you must use noclean to indicate that you accept
    responsibility for the resource. Otherwise you get error: must specify resource cleanup strategy.

The above code example becomes:

    const err_pipe = errclean try makePipe();
    var in_file = clean try os.File.openRead(allocator, source_path);
    var atomic_file = clean try AtomicFile.init(allocator, dest_path, mode);
    var direct_allocator = clean std.heap.DirectAllocator.init();
    var arena = clean std.heap.ArenaAllocator.init(&direct_allocator.allocator);

How to annotate cleanup functions:

// std.mem.Allocator
fn create(self: &Allocator, comptime T: type) !&T
    cleanup self.destroy(_)
{
    const slice = try self.alloc(T, 1);
    return &slice[0];
}

// function pointer field of struct
allocFn: fn (self: &Allocator, byte_count: usize, alignment: u29) Error![]u8
            cleanup self.freeFn(self, _),

// std.os.File
pub fn openRead(allocator: &mem.Allocator, path: []const u8) OpenError!File
    cleanup _.close()

Having functions which allocate a resource mention their cleanup functions will make generated documentation more consistent and helpful.

Metadata

Metadata

Assignees

No one assigned

    Labels

    proposalThis issue suggests modifications. If it also has the "accepted" label then it is planned.

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions