From 58c2310a6c98215c0cfd46b3eea3ff4529d5eb29 Mon Sep 17 00:00:00 2001 From: Vladimir Panteleev Date: Tue, 15 May 2018 05:00:53 +0000 Subject: [PATCH] Fix #10334 - std.allocator: Regions are non-copyable, yet are passed around in examples This doesn't fix that non-copyable regions are still passed around in examples, so we still rely on NRVO to do its thing and elide the copy, but at least this will now catch wrong code that mistakenly copied Regions around. --- .../allocator/building_blocks/free_list.d | 5 +++-- std/experimental/allocator/building_blocks/region.d | 12 +++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/std/experimental/allocator/building_blocks/free_list.d b/std/experimental/allocator/building_blocks/free_list.d index d2b32099226..5859559f0da 100644 --- a/std/experimental/allocator/building_blocks/free_list.d +++ b/std/experimental/allocator/building_blocks/free_list.d @@ -814,8 +814,9 @@ struct ContiguousFreeList(ParentAllocator, import std.experimental.allocator.building_blocks.region : Region; import std.experimental.allocator.gc_allocator : GCAllocator; import std.typecons : Ternary; - alias A = ContiguousFreeList!(Region!GCAllocator, 0, 64); - auto a = A(Region!GCAllocator(1024 * 4), 1024); + alias A = ContiguousFreeList!(Region!GCAllocator*, 0, 64); + auto r = Region!GCAllocator(1024 * 4); + auto a = A(&r, 1024); assert((() nothrow @safe @nogc => a.empty)() == Ternary.yes); diff --git a/std/experimental/allocator/building_blocks/region.d b/std/experimental/allocator/building_blocks/region.d index 736b1858e43..37f40b6dd2a 100644 --- a/std/experimental/allocator/building_blocks/region.d +++ b/std/experimental/allocator/building_blocks/region.d @@ -104,11 +104,6 @@ struct Region(ParentAllocator, this(cast(ubyte[]) (parent.allocate(n.roundUpToAlignment(alignment)))); } - /* - TODO: The postblit of `BasicRegion` should be disabled because such objects - should not be copied around naively. - */ - /** If `ParentAllocator` defines `deallocate`, the region defines a destructor that uses `ParentAllocator.deallocate` to free the memory chunk. @@ -119,6 +114,13 @@ struct Region(ParentAllocator, with (_impl) parent.deallocate(_begin[0 .. _end - _begin]); } + /** + `Region` deallocates on destruction (see above), therefore is not copyable. + */ + static if (!is(ParentAllocator == NullAllocator) + && hasMember!(ParentAllocator, "deallocate")) + @disable this(this); + /** Rounds the given size to a multiple of the `alignment` */