Error: @nogc function 'test.func2' cannot call non- at nogc delegate 'msg'

A Guy With a Question aguywithanquestion at gmail.com
Sun Dec 10 13:57:27 UTC 2017


On Sunday, 10 December 2017 at 11:44:20 UTC, Jonathan M Davis 
wrote:
> On Sunday, December 10, 2017 12:54:00 Shachar Shemesh via 
> Digitalmars-d wrote:
>> void func1(scope lazy string msg) @nogc {
>> }
>>
>> void func2(scope lazy string msg) @nogc {
>>      func1(msg);
>> }
>>
>> What? Why is msg GC allocating, especially since I scoped the 
>> lazy? Why is msg even evaluated?
>>
>> Something seems off here.
>
> Well, I'm not exactly sure how lazy is implemented underneath 
> the hood (other than the fact that it generates a delegate and 
> potentially a closure), but based on the error message, it 
> sounds like the delegate that's being generated isn't @nogc, so 
> it can't be called within the function, which would be a 
> completely different issue from allocating a closure.

> Curiously, pure doesn't seem to have the same problem, and I 
> would have guessed that it would given that @nogc does.
>
> But if it matters that the delegate be pure or @nogc because 
> the function is marked that way, then that's a bit of a 
> problem, because presumably, there can only be one delegate 
> (since the function isn't templated), and the same function 
> could be called with an expression that allocated and with an 
> expression that didn't allocate. So, if the delegate is 
> restricted like that, then that would restrict the caller, 
> which doesn't follow how non-lazy arguments work, and an 
> argument could be made that whether calling the delegate 
> allocates memory or not or is pure or not doesn't matter even 
> if the function being called is @nogc or pure on the basis that 
> it's conceptually just a delayed evaluation of the argument in 
> the caller's scope. But for that to work, the generated 
> delegate can't be checked for @nogc or pure or nothrow or any 
> of that inside the function with the lazy parameter. Given that 
> pure works but @nogc doesn't, it makes it seem like the 
> compiler was made smart enough to ignore purity for lazy 
> parameters but not smart enough to ignore the lack of @nogc.
>
> As for scope, I don't know if it really applies to lazy 
> parameters or not at this point. Without -dip1000, all it 
> applies to is delegates, but lazy parameters are turned into 
> delegates, so you would _think_ that scope would apply, but I 
> don't know. scope has always been underimplemented, though 
> Walter's work on -dip1000 is fixing that. Regardless, the error 
> message makes it sound like scope and closures have nothing to 
> do with the problem (though it could potentially be a problem 
> once the @nogc problem with the delegate is fixed).
>
> In any case, I think that it's pretty clear that this merits 
> being reported in bugzilla. The fact that pure works while 
> @nogc doesn't strongly indicates that something is off with 
> @nogc - especially if scope is involved. Worst case, a fix will 
> have to be lumped in with -dip1000, depending on what scope is 
> supposed to be doing now and exactly how lazy is working 
> underneath the hood, but I definitely think that your code 
> should work.
>
> - Jonathan M Davis

What does D throw so many errors on code people don't write? I 
realize that "lowering" has some uses and I'm not advocating 
*not* doing it, but why not after a semantic pass? Why is it so 
consistently throwing semantic errors on code it's users did not 
write...

It would cut down on the cryptic errors...


More information about the Digitalmars-d mailing list