{"action":"created","comment":{"url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/comments/48578026","id":48578026,"diff_hunk":"@@ -0,0 +1,337 @@\n+/**\n+This module provides OOM-checked and memory safe interfaces to C's $(D malloc)\n+and $(D calloc) functions.\n+\n+Acronyms:\n+$(B OOM:) $(I Out Of Memory), the condition in which an allocator has no more\n+memory space to offer.\n+\n+Copyright: Jakob Øvrum 2015\n+\n+License: $(HTTP boost.org/LICENSE_1_0.txt, Boost License 1.0).\n+\n+Authors: Jakob Øvrum\n+*/\n+module std.internal.mmm;\n+\n+import core.stdc.stdlib : calloc, malloc;\n+import std.traits : hasElaborateDestructor, hasIndirections;\n+import std.range.primitives;\n+\n+private void[] checkedMallocArray(size_t n) nothrow @system @nogc\n+{\n+    import core.exception : onOutOfMemoryError;\n+\n+    if (auto p = malloc(n))\n+        return p[0 .. n];\n+    else\n+    {\n+        onOutOfMemoryError();\n+        assert(false);\n+    }\n+}\n+\n+/**\n+ * Allocate space for one or more objects on the C heap with $(D malloc).\n+ *\n+ * The new objects are uninitialized;\n+ * initialize them with $(XREF conv, emplace) before use.\n+ * $(D @safe) only when T has no indirections.\n+ *\n+ * Params:\n+ *    T = type of object(s)\n+ *    n = number of objects to allocate space for\n+ * Throws:\n+ *   $(D OutOfMemoryError) on OOM\n+ */\n+T* checkedMalloc(T)() @system\n+    if (hasIndirections!T)\n+{\n+    return cast(T*)checkedMallocArray(T.sizeof).ptr;\n+}\n+\n+/// Ditto\n+T* checkedMalloc(T)() @trusted\n+    if (!hasIndirections!T)\n+{\n+    return cast(T*)checkedMallocArray(T.sizeof).ptr;\n+}\n+\n+/// Ditto\n+T[] checkedMallocArray(T)(size_t n) @system\n+    if (hasIndirections!T)\n+{\n+    return cast(T[])checkedMallocArray(T.sizeof * n);\n+}\n+\n+/// Ditto\n+T[] checkedMallocArray(T)(size_t n) @trusted\n+    if (!hasIndirections!T)\n+{\n+    return cast(T[])checkedMallocArray(T.sizeof * n);\n+}\n+\n+/**\n+ * Construct a new T on the C heap with newly allocated space from $(D malloc).\n+ *\n+ * Params:\n+ *    T = type to construct\n+ *    args = construction arguments for T\n+ * Throws:\n+ *    $(D OutOfMemoryError) on OOM\n+ */\n+T* checkedMalloc(T, Args...)(auto ref Args args) // safety inferred\n+{\n+    import core.stdc.stdlib : free;\n+    import std.conv : emplaceRef;\n+\n+    auto p = () @trusted { return checkedMalloc!T(); }();\n+    scope(failure) () @trusted { free(p); }();\n+\n+    emplaceRef(*p, args);\n+    return p;\n+}\n+\n+/**\n+ * Copy the elements of range into a new array allocated with $(D malloc).\n+ *\n+ * Params:\n+ *    T = element type of the new array; defaults to $(D ElementType!Range).\n+ *    range = _range of elements to copy into the new array\n+ * Throws:\n+ *    $(D OutOfMemoryError) on OOM\n+ */\n+T[] checkedMallocArray(T, Range)(Range range) // safety inferred\n+    if (isInputRange!Range && hasLength!Range && is(ElementType!Range : T))\n+{\n+    import core.stdc.stdlib : free;\n+    import std.exception : collectException;\n+    import std.conv : emplaceRef;\n+    import std.traits : hasElaborateDestructor;\n+\n+    immutable length = range.length;\n+    auto arr = () @trusted { return checkedMallocArray!T(length); }();\n+\n+    size_t i = 0; // Number of constructed elements\n+\n+    scope(failure)\n+    {\n+        static if(hasElaborateDestructor!T)\n+        {\n+            for (; i != 0; --i)\n+            {\n+                // collectException(destroy(arr[i])); // Issue 12647\n+                try\n+                    destroy(arr[i]);","path":"std/internal/mmm.d","position":125,"original_position":125,"commit_id":"f7c278fd6a4468567b55ebcf7ebdc09ef9191b5f","original_commit_id":"f7c278fd6a4468567b55ebcf7ebdc09ef9191b5f","user":{"login":"andralex","id":566679,"avatar_url":"https://avatars.githubusercontent.com/u/566679?v=3","gravatar_id":"","url":"https://api.github.com/users/andralex","html_url":"https://github.com/andralex","followers_url":"https://api.github.com/users/andralex/followers","following_url":"https://api.github.com/users/andralex/following{/other_user}","gists_url":"https://api.github.com/users/andralex/gists{/gist_id}","starred_url":"https://api.github.com/users/andralex/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/andralex/subscriptions","organizations_url":"https://api.github.com/users/andralex/orgs","repos_url":"https://api.github.com/users/andralex/repos","events_url":"https://api.github.com/users/andralex/events{/privacy}","received_events_url":"https://api.github.com/users/andralex/received_events","type":"User","site_admin":false},"body":"Something is off here - `arr[0]` will never be destroyed. Looks like a bug. ","created_at":"2015-12-29T23:27:54Z","updated_at":"2015-12-29T23:27:54Z","html_url":"https://github.com/D-Programming-Language/phobos/pull/3031#discussion_r48578026","pull_request_url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3031","_links":{"self":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/comments/48578026"},"html":{"href":"https://github.com/D-Programming-Language/phobos/pull/3031#discussion_r48578026"},"pull_request":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3031"}}},"pull_request":{"url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3031","id":30369005,"html_url":"https://github.com/D-Programming-Language/phobos/pull/3031","diff_url":"https://github.com/D-Programming-Language/phobos/pull/3031.diff","patch_url":"https://github.com/D-Programming-Language/phobos/pull/3031.patch","issue_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3031","number":3031,"state":"open","locked":false,"title":"Add std.internal.mmm and reap benefits in @safe-ty and OOM checking","user":{"login":"JakobOvrum","id":155856,"avatar_url":"https://avatars.githubusercontent.com/u/155856?v=3","gravatar_id":"","url":"https://api.github.com/users/JakobOvrum","html_url":"https://github.com/JakobOvrum","followers_url":"https://api.github.com/users/JakobOvrum/followers","following_url":"https://api.github.com/users/JakobOvrum/following{/other_user}","gists_url":"https://api.github.com/users/JakobOvrum/gists{/gist_id}","starred_url":"https://api.github.com/users/JakobOvrum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JakobOvrum/subscriptions","organizations_url":"https://api.github.com/users/JakobOvrum/orgs","repos_url":"https://api.github.com/users/JakobOvrum/repos","events_url":"https://api.github.com/users/JakobOvrum/events{/privacy}","received_events_url":"https://api.github.com/users/JakobOvrum/received_events","type":"User","site_admin":false},"body":"This patch adds a new internal module std.internal.mmm with the following functions:\r\n```d\r\n// Unsafe as T has pointers\r\nT* checkedMalloc(T)() @system if (hasIndirections!T);\r\n\r\n// Ditto\r\nT[] checkedMallocArray(T)(size_t n) @system if (hasIndirections!T);\r\n\r\n// Known to be safe because T has no pointers\r\nT* checkedMalloc(T)() @trusted if (!hasIndirections!T);\r\n\r\n// Ditto\r\nT[] checkedMallocArray(T)(size_t n) @trusted if (!hasIndirections!T);\r\n\r\n// Attributes depend on emplaceRef\r\nT* checkedMalloc(T, Args...)(auto ref Args args);\r\n\r\n// Attributes depend on the range primitives of `Range` as well as\r\n// the construction and destruction of `ElementType!Range`\r\nT[] checkedMallocArray(T, Range)(Range range)\r\nif (isInputRange!Range && hasLength!Range && is(ElementType!Range : T));\r\n\r\n// Ditto; same as above but with inferred element type\r\nElementType!Range[] checkedMallocArray(Range)(Range range)\r\nif (isInputRange!Range && hasLength!Range);\r\n\r\n// Always safe as calloc zero-initializes memory\r\nT* checkedCalloc(T)() @trusted;\r\n\r\n// Ditto\r\nT[] checkedCallocArray(T)(size_t n) @trusted;\r\n\r\n// Destroy all elements in the given array\r\nvoid[] destroyArray(T)(ref T[] array);\r\n```\r\nAdditionally, inferred purity can be supported if `malloc` and `calloc` are marked `pure` in core.stdc.stdlib in the spirit of memory allocation being practically pure.\r\n\r\nIncluded are a few commits demonstrating how to reap benefits from this module. They can be moved to a different PR if desirable - the point is that they demonstrate the module's usefulness (hopefully).\r\n\r\nIt might be best to review this PR commit-wise.\r\n\r\nedit:\r\n\r\nThese functions also handle OOM correctly; in Phobos, there are more examples of *incorrect* handling of OOM, like trying to *dynamically allocate* an exception, either directly or through `enforce`, rather than use `onOutOfMemoryError`.","created_at":"2015-03-03T12:24:51Z","updated_at":"2015-12-29T23:27:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"e7d4f00609fb8670f6088adef5e19ef3625713e4","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3031/commits","review_comments_url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3031/comments","review_comment_url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/comments{/number}","comments_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3031/comments","statuses_url":"https://api.github.com/repos/D-Programming-Language/phobos/statuses/f7c278fd6a4468567b55ebcf7ebdc09ef9191b5f","head":{"label":"JakobOvrum:malloc_oom","ref":"malloc_oom","sha":"f7c278fd6a4468567b55ebcf7ebdc09ef9191b5f","user":{"login":"JakobOvrum","id":155856,"avatar_url":"https://avatars.githubusercontent.com/u/155856?v=3","gravatar_id":"","url":"https://api.github.com/users/JakobOvrum","html_url":"https://github.com/JakobOvrum","followers_url":"https://api.github.com/users/JakobOvrum/followers","following_url":"https://api.github.com/users/JakobOvrum/following{/other_user}","gists_url":"https://api.github.com/users/JakobOvrum/gists{/gist_id}","starred_url":"https://api.github.com/users/JakobOvrum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JakobOvrum/subscriptions","organizations_url":"https://api.github.com/users/JakobOvrum/orgs","repos_url":"https://api.github.com/users/JakobOvrum/repos","events_url":"https://api.github.com/users/JakobOvrum/events{/privacy}","received_events_url":"https://api.github.com/users/JakobOvrum/received_events","type":"User","site_admin":false},"repo":{"id":6076265,"name":"phobos","full_name":"JakobOvrum/phobos","owner":{"login":"JakobOvrum","id":155856,"avatar_url":"https://avatars.githubusercontent.com/u/155856?v=3","gravatar_id":"","url":"https://api.github.com/users/JakobOvrum","html_url":"https://github.com/JakobOvrum","followers_url":"https://api.github.com/users/JakobOvrum/followers","following_url":"https://api.github.com/users/JakobOvrum/following{/other_user}","gists_url":"https://api.github.com/users/JakobOvrum/gists{/gist_id}","starred_url":"https://api.github.com/users/JakobOvrum/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/JakobOvrum/subscriptions","organizations_url":"https://api.github.com/users/JakobOvrum/orgs","repos_url":"https://api.github.com/users/JakobOvrum/repos","events_url":"https://api.github.com/users/JakobOvrum/events{/privacy}","received_events_url":"https://api.github.com/users/JakobOvrum/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/JakobOvrum/phobos","description":"Runtime library for the D programming language","fork":true,"url":"https://api.github.com/repos/JakobOvrum/phobos","forks_url":"https://api.github.com/repos/JakobOvrum/phobos/forks","keys_url":"https://api.github.com/repos/JakobOvrum/phobos/keys{/key_id}","collaborators_url":"https://api.github.com/repos/JakobOvrum/phobos/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/JakobOvrum/phobos/teams","hooks_url":"https://api.github.com/repos/JakobOvrum/phobos/hooks","issue_events_url":"https://api.github.com/repos/JakobOvrum/phobos/issues/events{/number}","events_url":"https://api.github.com/repos/JakobOvrum/phobos/events","assignees_url":"https://api.github.com/repos/JakobOvrum/phobos/assignees{/user}","branches_url":"https://api.github.com/repos/JakobOvrum/phobos/branches{/branch}","tags_url":"https://api.github.com/repos/JakobOvrum/phobos/tags","blobs_url":"https://api.github.com/repos/JakobOvrum/phobos/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/JakobOvrum/phobos/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/JakobOvrum/phobos/git/refs{/sha}","trees_url":"https://api.github.com/repos/JakobOvrum/phobos/git/trees{/sha}","statuses_url":"https://api.github.com/repos/JakobOvrum/phobos/statuses/{sha}","languages_url":"https://api.github.com/repos/JakobOvrum/phobos/languages","stargazers_url":"https://api.github.com/repos/JakobOvrum/phobos/stargazers","contributors_url":"https://api.github.com/repos/JakobOvrum/phobos/contributors","subscribers_url":"https://api.github.com/repos/JakobOvrum/phobos/subscribers","subscription_url":"https://api.github.com/repos/JakobOvrum/phobos/subscription","commits_url":"https://api.github.com/repos/JakobOvrum/phobos/commits{/sha}","git_commits_url":"https://api.github.com/repos/JakobOvrum/phobos/git/commits{/sha}","comments_url":"https://api.github.com/repos/JakobOvrum/phobos/comments{/number}","issue_comment_url":"https://api.github.com/repos/JakobOvrum/phobos/issues/comments{/number}","contents_url":"https://api.github.com/repos/JakobOvrum/phobos/contents/{+path}","compare_url":"https://api.github.com/repos/JakobOvrum/phobos/compare/{base}...{head}","merges_url":"https://api.github.com/repos/JakobOvrum/phobos/merges","archive_url":"https://api.github.com/repos/JakobOvrum/phobos/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/JakobOvrum/phobos/downloads","issues_url":"https://api.github.com/repos/JakobOvrum/phobos/issues{/number}","pulls_url":"https://api.github.com/repos/JakobOvrum/phobos/pulls{/number}","milestones_url":"https://api.github.com/repos/JakobOvrum/phobos/milestones{/number}","notifications_url":"https://api.github.com/repos/JakobOvrum/phobos/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/JakobOvrum/phobos/labels{/name}","releases_url":"https://api.github.com/repos/JakobOvrum/phobos/releases{/id}","created_at":"2012-10-04T14:09:48Z","updated_at":"2015-01-20T00:38:44Z","pushed_at":"2015-12-22T09:24:49Z","git_url":"git://github.com/JakobOvrum/phobos.git","ssh_url":"git@github.com:JakobOvrum/phobos.git","clone_url":"https://github.com/JakobOvrum/phobos.git","svn_url":"https://github.com/JakobOvrum/phobos","homepage":"d-programming-language.org","size":48436,"stargazers_count":0,"watchers_count":0,"language":"D","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"D-Programming-Language:master","ref":"master","sha":"8d9d606ef8688a48364fe42ef131da1489e35581","user":{"login":"D-Programming-Language","id":565913,"avatar_url":"https://avatars.githubusercontent.com/u/565913?v=3","gravatar_id":"","url":"https://api.github.com/users/D-Programming-Language","html_url":"https://github.com/D-Programming-Language","followers_url":"https://api.github.com/users/D-Programming-Language/followers","following_url":"https://api.github.com/users/D-Programming-Language/following{/other_user}","gists_url":"https://api.github.com/users/D-Programming-Language/gists{/gist_id}","starred_url":"https://api.github.com/users/D-Programming-Language/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/D-Programming-Language/subscriptions","organizations_url":"https://api.github.com/users/D-Programming-Language/orgs","repos_url":"https://api.github.com/users/D-Programming-Language/repos","events_url":"https://api.github.com/users/D-Programming-Language/events{/privacy}","received_events_url":"https://api.github.com/users/D-Programming-Language/received_events","type":"Organization","site_admin":false},"repo":{"id":1257084,"name":"phobos","full_name":"D-Programming-Language/phobos","owner":{"login":"D-Programming-Language","id":565913,"avatar_url":"https://avatars.githubusercontent.com/u/565913?v=3","gravatar_id":"","url":"https://api.github.com/users/D-Programming-Language","html_url":"https://github.com/D-Programming-Language","followers_url":"https://api.github.com/users/D-Programming-Language/followers","following_url":"https://api.github.com/users/D-Programming-Language/following{/other_user}","gists_url":"https://api.github.com/users/D-Programming-Language/gists{/gist_id}","starred_url":"https://api.github.com/users/D-Programming-Language/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/D-Programming-Language/subscriptions","organizations_url":"https://api.github.com/users/D-Programming-Language/orgs","repos_url":"https://api.github.com/users/D-Programming-Language/repos","events_url":"https://api.github.com/users/D-Programming-Language/events{/privacy}","received_events_url":"https://api.github.com/users/D-Programming-Language/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/D-Programming-Language/phobos","description":"The standard library of the D programming language","fork":false,"url":"https://api.github.com/repos/D-Programming-Language/phobos","forks_url":"https://api.github.com/repos/D-Programming-Language/phobos/forks","keys_url":"https://api.github.com/repos/D-Programming-Language/phobos/keys{/key_id}","collaborators_url":"https://api.github.com/repos/D-Programming-Language/phobos/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/D-Programming-Language/phobos/teams","hooks_url":"https://api.github.com/repos/D-Programming-Language/phobos/hooks","issue_events_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/events{/number}","events_url":"https://api.github.com/repos/D-Programming-Language/phobos/events","assignees_url":"https://api.github.com/repos/D-Programming-Language/phobos/assignees{/user}","branches_url":"https://api.github.com/repos/D-Programming-Language/phobos/branches{/branch}","tags_url":"https://api.github.com/repos/D-Programming-Language/phobos/tags","blobs_url":"https://api.github.com/repos/D-Programming-Language/phobos/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/D-Programming-Language/phobos/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/D-Programming-Language/phobos/git/refs{/sha}","trees_url":"https://api.github.com/repos/D-Programming-Language/phobos/git/trees{/sha}","statuses_url":"https://api.github.com/repos/D-Programming-Language/phobos/statuses/{sha}","languages_url":"https://api.github.com/repos/D-Programming-Language/phobos/languages","stargazers_url":"https://api.github.com/repos/D-Programming-Language/phobos/stargazers","contributors_url":"https://api.github.com/repos/D-Programming-Language/phobos/contributors","subscribers_url":"https://api.github.com/repos/D-Programming-Language/phobos/subscribers","subscription_url":"https://api.github.com/repos/D-Programming-Language/phobos/subscription","commits_url":"https://api.github.com/repos/D-Programming-Language/phobos/commits{/sha}","git_commits_url":"https://api.github.com/repos/D-Programming-Language/phobos/git/commits{/sha}","comments_url":"https://api.github.com/repos/D-Programming-Language/phobos/comments{/number}","issue_comment_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues/comments{/number}","contents_url":"https://api.github.com/repos/D-Programming-Language/phobos/contents/{+path}","compare_url":"https://api.github.com/repos/D-Programming-Language/phobos/compare/{base}...{head}","merges_url":"https://api.github.com/repos/D-Programming-Language/phobos/merges","archive_url":"https://api.github.com/repos/D-Programming-Language/phobos/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/D-Programming-Language/phobos/downloads","issues_url":"https://api.github.com/repos/D-Programming-Language/phobos/issues{/number}","pulls_url":"https://api.github.com/repos/D-Programming-Language/phobos/pulls{/number}","milestones_url":"https://api.github.com/repos/D-Programming-Language/phobos/milestones{/number}","notifications_url":"https://api.github.com/repos/D-Programming-Language/phobos/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/D-Programming-Language/phobos/labels{/name}","releases_url":"https://api.github.com/repos/D-Programming-Language/phobos/releases{/id}","created_at":"2011-01-15T07:00:06Z","updated_at":"2015-12-29T01:29:21Z","pushed_at":"2015-12-29T22:28:42Z","git_url":"git://github.com/D-Programming-Language/phobos.git","ssh_url":"git@github.com:D-Programming-Language/phobos.git","clone_url":"https://github.com/D-Programming-Language/phobos.git","svn_url":"https://github.com/D-Programming-Language/phobos","homepage":"dlang.org/phobos","size":68801,"stargazers_count":659,"watchers_count":659,"language":"D","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":436,"mirror_url":null,"open_issues_count":77,"forks":436,"open_issues":77,"watchers":659,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3031"},"html":{"href":"https://github.com/D-Programming-Language/phobos/pull/3031"},"issue":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3031"},"comments":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/issues/3031/comments"},"review_comments":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3031/comments"},"review_comment":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/pulls/3031/commits"},"statuses":{"href":"https://api.github.com/repos/D-Programming-Language/phobos/statuses/f7c278fd6a4468567b55ebcf7ebdc09ef9191b5f"}}}}