From abe87898903853c5c57fc5e436025e19526e9b71 Mon Sep 17 00:00:00 2001 From: Tetralux Date: Sun, 26 Jan 2020 01:03:14 +0000 Subject: [PATCH] Fix `make(map[K]V, 0)` by ensuring `reserve` always sets an allocator Currently, `make(map[K]V, 0)` asserts, because trying `reserve` zero items does not set the allocator; it early-outs. `__dynamic_map_reserve` assumed that `__dynamic_array_reserve` would always set the allocator - even if given a desired capacity of `0`. Rather than making `__slice_resize` just _also_ set the default allocator if there isn't one, this makes `__dynamic_array_reserve` always set the allocator, even if it is about to early out. This is because users are lead to understand that `append` will set the allocator if one is not already set - `reserve` should work the same way. --- core/runtime/core.odin | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/core/runtime/core.odin b/core/runtime/core.odin index ac623a53e..ad8b83fee 100644 --- a/core/runtime/core.odin +++ b/core/runtime/core.odin @@ -1125,12 +1125,14 @@ __dynamic_array_make :: proc(array_: rawptr, elem_size, elem_align: int, len, ca __dynamic_array_reserve :: proc(array_: rawptr, elem_size, elem_align: int, cap: int, loc := #caller_location) -> bool { array := (^Raw_Dynamic_Array)(array_); - if cap <= array.cap do return true; - + // NOTE(tetra, 2020-01-26): We set the allocator before earlying-out below, because user code is usually written + // assuming that appending/reserving will set the allocator, if it is not already set. if array.allocator.procedure == nil { array.allocator = context.allocator; } assert(array.allocator.procedure != nil); + + if cap <= array.cap do return true; old_size := array.cap * elem_size; new_size := cap * elem_size;