Bug 12666 – @nogc std.array.front, popFront, and more

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-04-27T19:16:00Z
Last change time
2017-07-19T17:43:09Z
Keywords
pull, rejects-valid
Assigned to
nobody
Creator
bearophile_hugs

Comments

Comment #0 by bearophile_hugs — 2014-04-27T19:16:25Z
import std.algorithm: map; immutable data = [1]; void main() @nogc { foreach (w; data.map!((x) @nogc pure nothrow => x)) {} } test.d(4,5): Error: @nogc function 'D main' cannot call non-@nogc function 'test.main.MapResult!(__lambda1, immutable(int)[]).MapResult.popFront' test.d(4,5): Error: @nogc function 'D main' cannot call non-@nogc function 'test.main.MapResult!(__lambda1, immutable(int)[]).MapResult.front' Taking a better look the problem seems to be in std.array.front (and popFront): @property ref T front(T)(T[] a) @safe pure nothrow if (!isNarrowString!(T[]) && !is(T[] == void[])) { assert(a.length, "Attempting to fetch the front of an empty array of " ~ T.stringof); return a[0]; } void main() @nogc { auto data = [1]; data.front; } A possible solution: import std.traits: isNarrowString; @property ref T front(T)(T[] a) @safe pure nothrow if (!isNarrowString!(T[]) && !is(T[] == void[])) { enum msg = "Attempting to fetch the front of an empty array of " ~ T.stringof; assert(a.length, msg); return a[0]; } void main() @nogc { auto data = [1]; data.front; } A small disadvantage of this solution is that the error message is now computed statically, increasing binary size. But those array functions are too much important, otherwise lot of other ranges can't work in @nogc code.
Comment #1 by bearophile_hugs — 2014-04-27T19:32:55Z
(In reply to bearophile_hugs from comment #0) > enum msg = "Attempting to fetch the front of an empty array of " ~ > T.stringof; > assert(a.length, msg); A little shorter code, that requires less changes: assert(a.length, ctEval!("Attempting to fetch the front of an empty array of " ~ T.stringof)); Where ctEval is a very small construct that should be added to Phobos that forces the evaluation of an expression at compile-time.
Comment #2 by yebblies — 2014-05-12T16:07:27Z
I suspect the error message is already being computed statically thanks to constfolding, it just happens after @nogc inference has been run.
Comment #3 by ag0aep6g — 2015-04-23T20:43:40Z
Apparently, the underlying dmd issue has been fixed/implemented. A pull request to add @nogc to the various functions: https://github.com/D-Programming-Language/phobos/pull/3219
Comment #4 by github-bugzilla — 2015-04-24T04:55:04Z
Commit pushed to master at https://github.com/D-Programming-Language/phobos https://github.com/D-Programming-Language/phobos/commit/0842fc7841b9c3db558681717c2d8b4da1479ce6 @nogc for std.range.primitives.{empty,save,popFront,popBack,front,back} Excluding the UTF-decoding variants, because those throw GC allocated exceptions. Makes sure that issue 12666 - "@nogc std.array.front, popFront, and more" stays fixed.
Comment #5 by github-bugzilla — 2017-07-19T17:43:09Z
Commit pushed to dmd-cxx at https://github.com/dlang/phobos https://github.com/dlang/phobos/commit/0842fc7841b9c3db558681717c2d8b4da1479ce6 @nogc for std.range.primitives.{empty,save,popFront,popBack,front,back}