www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Is this nogc? dmd and gdc disagree

reply rcorre <ryan rcorre.net> writes:
I recently tried compiling enumap with GDC, and found that it 
disagrees with DMD on whether a function is  nogc. Here's a 
semi-reduced test-case:

---
import std.range;
import std.traits    : EnumMembers;
import std.typecons  : tuple, staticIota;
import std.algorithm : map;

struct Enumap(K, V)
   if(EnumMembers!K == staticIota!(0, EnumMembers!K.length))
{
   enum length = EnumMembers!K.length;
   private V[length] _store;

   ref auto opIndex(K key) inout {
     return _store[key];
   }

    nogc auto byKeyValue() const {
     return only(EnumMembers!K).map!(key => tuple(key, this[key]));
   }
}

 nogc void main() {
     import std.typecons  : tuple;
     import std.algorithm : map;

     enum E { a, b, c, d };
     immutable elements = Enumap!(E, int)([1,2,3,4]);

     auto pairs = elements.byKeyValue.map!(pair => tuple(pair[0], 
pair[1] + 1));
}
---

GDC claims that byKeyValue() allocates a closure, but DMD is just 
fine with me calling it  nogc. I'm inclined to agree with GDC 
here, unless DMD is doing some magic so that actually doesn't 
allocate a closure.
Feb 10 2016
next sibling parent tsbockman <thomas.bockman gmail.com> writes:
On Thursday, 11 February 2016 at 03:09:51 UTC, rcorre wrote:
 GDC claims that byKeyValue() allocates a closure, but DMD is 
 just fine with me calling it  nogc. I'm inclined to agree with 
 GDC here, unless DMD is doing some magic so that actually 
 doesn't allocate a closure.
I cannot reproduce your results. Your example won't compile for me with DMD HEAD: source/app.d(16,14): Error: function app.Enumap!(E, int).Enumap.byKeyValue is nogc yet allocates closures with the GC source/app.d(17,37): app.Enumap!(E, int).Enumap.byKeyValue.__lambda1 closes over variable this at source/app.d(16,14) source/app.d(26,26): Error: template instance app.Enumap!(E, int) error instantiating
Feb 10 2016
prev sibling parent reply tsbockman <thomas.bockman gmail.com> writes:
On Thursday, 11 February 2016 at 03:09:51 UTC, rcorre wrote:
 I recently tried compiling enumap with GDC, and found that it 
 disagrees with DMD on whether a function is  nogc. Here's a 
 semi-reduced test-case:
Here's an nogc version of `byKeyValue()`: nogc auto byKeyValue() const { static immutable keys = [EnumMembers!K]; return zip(keys[], _store[]); } Using zip and slices guarantees that the structure returned will be only 5*size_t.sizeof bytes, regardless of the types of K and V.
Feb 10 2016
parent reply rcorre <ryan rcorre.net> writes:
On Thursday, 11 February 2016 at 04:20:13 UTC, tsbockman wrote:
 On Thursday, 11 February 2016 at 03:09:51 UTC, rcorre wrote:
 I recently tried compiling enumap with GDC, and found that it 
 disagrees with DMD on whether a function is  nogc. Here's a 
 semi-reduced test-case:
Here's an nogc version of `byKeyValue()`: nogc auto byKeyValue() const { static immutable keys = [EnumMembers!K]; return zip(keys[], _store[]); } Using zip and slices guarantees that the structure returned will be only 5*size_t.sizeof bytes, regardless of the types of K and V.
I'm on the DMD 2.070 release, so maybe its fixed in master. Either way, thanks for the suggestion! Somehow I didn't realize what I was doing was an over-complicated zip :)
Feb 11 2016
next sibling parent reply rcorre <ryan rcorre.net> writes:
On Thursday, 11 February 2016 at 12:41:16 UTC, rcorre wrote:
 On Thursday, 11 February 2016 at 04:20:13 UTC, tsbockman wrote:
 Using zip and slices guarantees that the structure returned 
 will be only 5*size_t.sizeof bytes, regardless of the types of 
 K and V.
I'm on the DMD 2.070 release, so maybe its fixed in master. Either way, thanks for the suggestion! Somehow I didn't realize what I was doing was an over-complicated zip :)
Though it appears (in 2.070 at least) that zip's range primitives aren't nogc: --- import std.range; immutable a = [1,2,3]; immutable b = [1,2,3]; nogc void main() { foreach(x, y ; a[].zip(b[])) { } } --- other.d(7): Error: nogc function 'D main' cannot call non- nogc function 'std.range.Zip!(immutable(int)[], immutable(int)[]).Zip.empty' other.d(7): Error: nogc function 'D main' cannot call non- nogc function 'std.range.Zip!(immutable(int)[], immutable(int)[]).Zip.popFront' ---
Feb 11 2016
parent tsbockman <thomas.bockman gmail.com> writes:
On Thursday, 11 February 2016 at 12:55:02 UTC, rcorre wrote:
 Though it appears (in 2.070 at least) that zip's range 
 primitives aren't nogc:
I took a look at the source code for `zip()`, and the cause of this deficiency is that `Zip` takes a `StoppingPolicy` as a runtime parameter, rather than a compile-time parameter as it should. `empty()` and `popFront()` can both throw - but only if `StoppingPolicy.requireSameLength` is selected. The default is `StoppingPolicy.shortest`. This design dates back to 2009, which is probably before `nothrow` was implemented, and certainly before ` nogc`.
Feb 11 2016
prev sibling parent reply Kapps <opantm2+spam gmail.com> writes:
On Thursday, 11 February 2016 at 12:41:16 UTC, rcorre wrote:
 On Thursday, 11 February 2016 at 04:20:13 UTC, tsbockman wrote:
 On Thursday, 11 February 2016 at 03:09:51 UTC, rcorre wrote:
 I recently tried compiling enumap with GDC, and found that it 
 disagrees with DMD on whether a function is  nogc. Here's a 
 semi-reduced test-case:
Here's an nogc version of `byKeyValue()`: nogc auto byKeyValue() const { static immutable keys = [EnumMembers!K]; return zip(keys[], _store[]); } Using zip and slices guarantees that the structure returned will be only 5*size_t.sizeof bytes, regardless of the types of K and V.
I'm on the DMD 2.070 release, so maybe its fixed in master. Either way, thanks for the suggestion! Somehow I didn't realize what I was doing was an over-complicated zip :)
You'll encounter this pretty often in Phobos I think. I really don't think nogc is ready, and tend to avoid it in my code. Exceptions are a big reason for it, and lots of functions in Phobos throw exceptions which prevents them from being used in nogc (barring ugly hacks). I don't want to discourage you before you try it, but I feel like nogc is not yet worth using until something is done about issues such as exceptions, allowing Phobos to properly be able to handle nogc.
Feb 12 2016
parent reply tsbockman <thomas.bockman gmail.com> writes:
On Friday, 12 February 2016 at 23:46:09 UTC, Kapps wrote:
 You'll encounter this pretty often in Phobos I think. I really 
 don't think  nogc is ready, and tend to avoid it in my code. 
 Exceptions are a big reason for it, and lots of functions in 
 Phobos throw exceptions which prevents them from being used in 
  nogc (barring ugly hacks). I don't want to discourage you 
 before you try it, but I feel like  nogc is not yet worth using 
 until something is done about issues such as exceptions, 
 allowing Phobos to properly be able to handle  nogc.
On the other hand... Realistically, the only way that Phobos will reach usability with nogc, is if people keep trying and complaining when something doesn't work that should. I guess the problem is that a lot of this stuff requires RC exceptions to be realistically fixable. (Not this case though.)
Feb 12 2016
parent Kapps <opantm2+spam gmail.com> writes:
On Saturday, 13 February 2016 at 00:41:35 UTC, tsbockman wrote:
 On Friday, 12 February 2016 at 23:46:09 UTC, Kapps wrote:
 You'll encounter this pretty often in Phobos I think. I really 
 don't think  nogc is ready, and tend to avoid it in my code. 
 Exceptions are a big reason for it, and lots of functions in 
 Phobos throw exceptions which prevents them from being used in 
  nogc (barring ugly hacks). I don't want to discourage you 
 before you try it, but I feel like  nogc is not yet worth 
 using until something is done about issues such as exceptions, 
 allowing Phobos to properly be able to handle  nogc.
On the other hand... Realistically, the only way that Phobos will reach usability with nogc, is if people keep trying and complaining when something doesn't work that should. I guess the problem is that a lot of this stuff requires RC exceptions to be realistically fixable. (Not this case though.)
Yeah. I originally intended to go through and make what I needed nogc, but then I realized that it was pointless thanks to exceptions. Hopefully one day...
Feb 13 2016