April 02, 2017
On Saturday, 1 April 2017 at 19:52:14 UTC, Eugene Wissner wrote:
> If I understand correctly exceptions are anyway special class objects.

No, exceptions are just ordinary objects, they just happen to inherit from Throwable which is the interface the compiler requires for the `throw` statement.

> The same as Errors are special class objects, they can be thrown regardless nothrow and @nogc, because these aren't recoverable errors.

@nogc doesn't prevent throwing anything, you can throw an Exception in it too.

But indeed, Error is exempt from nothrow but other than that, it is also just a normal class.
April 01, 2017
On 4/1/2017 7:54 AM, deadalnix wrote:
> The problem you want to address is not GC allocations, it is GC collection
> cycles. If everything is freed, then there is no GC problem. not only this, but
> this is the only way GC and nogc code will interact with each others.

This does not address the stated need (by many programmers) to not even have to link in the GC code. A solution that falls short of this will be rejected. The rejections may not be technically well founded, but we're not in a good position to try to educate the masses on this. A solution that does not require linking to the GC sidesteps that problem.


> As long as a memory allocation has an owner the compiler can track, it can be
> freed explicitly, and, when it cannot, the compiler transfer ownership to the
> GC, which is illegal in @nogc code.
>
> Transfering the ownership to the unwind handler when doing:
>
> throw new FooException();
>
> Is not rocket science and doesn't need any new language addition.

There's also:

   auto e = someFunctionThatReturnsAnException();
   throw e;

where who owns it or how it was allocated is not clear at all.

Other issues that need attention are:

1. chaining exceptions
2. rethrowing


> Now onto to scope. Scope essentially means that you are going to use some object
> without taking ownership of it. Indeed, in case of catch(Exception e) the
> language has to transfers the ownership of the Exception to the GC, which is the
> thing that should be illegal (not throwing). catch(scope Exception e) would work
> both with GC owned and runtime owned exception, and, because the runtime know
> what's up, it can explicitly free the exception when it exit the catch block
> (there is already a runtime call for that), in the case it owns it.

'scope' is indeed a critical factor in making this work.


> It doesn't need any kind of throw new scope Exception, and was proposed,
> literally, years ago during discussion around DIP25 and alike.
>
> I urge you to reconsider the proposal that were made at the time. They solve all
> the problems you are discovering now, and more. And, while more complex that
> DIP25 alone, considering DIP25+DIP1000+this thing+the RC object thing, you are
> already in the zone where the "simple" approach is not so simple already.

I did some searching for this previous proposal discussion, but could not find it. Instead, I'll go by your description of it here.

I've written a more fleshed out proposal and started a new thread with it. Feel free to rip it to shreds!
April 02, 2017
On 4/1/17 2:18 PM, Dmitry Olshansky wrote:
> I don't understand what's so difficult to just recognize that "throw new
> Exception" creates a unique object that is passed to the exception
> handler.

That would be a good possibility: default to creating exceptions as scope objects, speculating that the catch site may also be scope. If the catch site does not use scope, then clone into a heap object. This is speculative, but the cost of cloning is much smaller than the cost of the allocation so it's not a large loss.

> So just mark the exception as unique in the exception handler
> code so that catch site is aware of it. Are we just bend on penalizing
> programmers for not typing out "scope"?

A catch site that does not use "scope" has more freedom, e.g.:

void fun()
{
    static Exception last;
    try { ... }
    catch (Exception e) { last = e; }
    ...
}

Such is not possible with a scoped catch. Of course, that's a concern only if we want to preserve backwards compatibility.

> In turn I don't see what adding "scope" to the catch site accomplishes -
> you still need to ensure the reference doesn't escape.

You don't. Old code behaves as it always did.

> And if it doesn't
> escape you may just as well deallocate the exception object.

Ah, so here we're looking at a deduction scheme. Most interesting! First try to see if "scope" would work (even if not written), and if so just consider it there.

>> Such a scheme preserves backward compatibility and leverages the work
>> done on "scope".
>
> Pardon but I don't see how.

Think again - checks and e.g. deduction (if we add it as you suggested above) would work pretty much out of the box.


Andrei

April 02, 2017
On 4/1/17 2:56 PM, Guillaume Piolat wrote:
> The other @nogc blocker is .destroy

How do you mean that? -- Andrei
April 02, 2017
Am Sun, 02 Apr 2017 00:09:09 +0000
schrieb Adam D. Ruppe <destructionator@gmail.com>:

> On Saturday, 1 April 2017 at 14:54:21 UTC, deadalnix wrote:
> > The problem you want to address is not GC allocations, it is GC collection cycles. If everything is freed, then there is no GC problem. not only this, but this is the only way GC and nogc code will interact with each others.
> 
> Amen. Moreover, for little things like exceptions, you can probably also just hack it to not do a collection cycle when allocating them.

I do not want GC _allocation_ for embedded systems (don't even
want to link in the GC or GC stub code) ;-)


-- Johannes

April 02, 2017
On Sunday, 2 April 2017 at 18:16:43 UTC, Johannes Pfau wrote:
> I do not want GC _allocation_ for embedded systems (don't even
> want to link in the GC or GC stub code) ;-)

Then don't use operator `new`... you're probably using some kind of custom druntime anyway.
April 02, 2017
On Sunday, 2 April 2017 at 17:22:11 UTC, Andrei Alexandrescu wrote:
> On 4/1/17 2:56 PM, Guillaume Piolat wrote:
>> The other @nogc blocker is .destroy
>
> How do you mean that? -- Andrei

https://github.com/dlang/druntime/blob/master/src/object.d#L2732

destroy() infers it's "@nogc"-ness from rt_finalize which is not nothrow and not @nogc:
https://github.com/dlang/druntime/blob/5a94816c8f1d5c225e560151cebe0a09949896a5/src/object.d#L16

I guess the rationale is that rt_finalize call Object.~this() and that may GC allocate, and throw.

In turn this cause every wrapper using emplace+destroy to not be @nogc.
April 02, 2017
On Sunday, 2 April 2017 at 18:41:45 UTC, Adam D. Ruppe wrote:
> On Sunday, 2 April 2017 at 18:16:43 UTC, Johannes Pfau wrote:
>> I do not want GC _allocation_ for embedded systems (don't even
>> want to link in the GC or GC stub code) ;-)
>
> Then don't use operator `new`... you're probably using some kind of custom druntime anyway.

Yes I think it is fair to assume one will have to jump through some hoops if one doesn't use want to use the runtime. That's fine.

April 02, 2017
On 4/2/2017 10:21 AM, Andrei Alexandrescu wrote:
> Such is not possible with a scoped catch. Of course, that's a concern only if we
> want to preserve backwards compatibility.

That can be done if the user makes a clone of 'e' (I don't propose the compiler do this automatically).


>> In turn I don't see what adding "scope" to the catch site accomplishes -
>> you still need to ensure the reference doesn't escape.
>
> You don't. Old code behaves as it always did.
>
>> And if it doesn't
>> escape you may just as well deallocate the exception object.
>
> Ah, so here we're looking at a deduction scheme. Most interesting! First try to
> see if "scope" would work (even if not written), and if so just consider it there.
>
>>> Such a scheme preserves backward compatibility and leverages the work
>>> done on "scope".
>>
>> Pardon but I don't see how.
>
> Think again - checks and e.g. deduction (if we add it as you suggested above)
> would work pretty much out of the box.

The compiler can definitely deduce the 'scope' for the catch object, and if it is, insert code to free it at the close of the catch. But that has problems:

1. If the thrown object was not allocated with the GC (such as if it was 'emplaced'), then doing a GC free on it at the catch site will corrupt memory.

2. There isn't an indication to the user if it is free'd or not at the close of the catch.

3. The GC code still has to be linked in.

4. The throw site still cannot be marked as @nogc.
April 03, 2017
Walter Bright wrote:

> 1. If the thrown object was not allocated with the GC (such as if it was 'emplaced'), then doing a GC free on it at the catch site will corrupt memory.

no, it won't. it is completely safe to free non-GC-owned memory with GC[0].

[0] http://dpldocs.info/experimental-docs/core.memory.GC.free.html