I've run into my own series of trials and tribulations with a
@nogc main function (i.e. entire project is @nogc). While the
idea and implementation is great, its interaction with
druntime/Phobos is lacking. This isn't a complete list - it's
only what I remember and can reproduce now:
1. destroy(Object) seems to not call the dtor; I'm not sure this
is an issue with 2.066 or nogc, seeing as it happens in 2.065 as
well: http://dpaste.dzfl.pl/d0c754bb78c6 - to get around this, I
wrote my own destroy that automatically calls __dtor.
2. std.typecons.RefCounted doesn't compile in @nogc as the dtor
isn't @nogc. Attempted to annotate it with @nogc, but then this
happened:
Error: @nogc function 'std.typecons.RefCounted!(Test,
cast(RefCountedAutoInitialize)1).RefCounted.~this' cannot call
non-@nogc function 'object.destroy!(Test).destroy'.
Also attempts to call GC.removeRange, which fails for obvious
reasons. Got around this by writing my own ref-counted pointer
that uses the destroy replacement from (1).
3. std.container.Array doesn't compile in @nogc as it uses
std.typecons.RefCounted. Got around this by writing my own Array
type.
4. @nogc code takes on some of the characteristics of nothrow as
Phobos/druntime liberally use `throw new Exception` and
`enforce`. This leads to a _vast_ majority of the standard
library being locked out. This is really one of the killer
issues, and it can only be resolved with allowing GC allocations
in failure situations (as Walter says) or by pre-allocating
exceptions in the stdlib (which is unlikely). Out of curiosity,
as I haven't looked at this problem, what does D do differently
to C++ that requires heap allocation of exceptions?
5. As a result of (4), even some of the most trivial things don't
work. std.stdio.writeln() (i.e. no arguments) fails because of
this:
enforce(fputc('\n', .stdout._p.handle) == '\n');
There is _no need_ to enforce that \n was actually output! This
is absolutely ridiculous! I got around this by writing my own
wrapper around printf that doesn't allocate or throw.
6. std.allocator doesn't work with @nogc. Understandable, since
it hasn't been updated for @nogc yet. Got around this by starting
work on my own allocators.
7. This is more a tangential issue, but still a mild irritant:
placing @nogc at a top of a file doesn't cover the entire module
- structs and classes also have to be manually tagged @nogc:
module test;
@nogc:
struct Test
{
@nogc:
this() { /* ... */ }
}
I ran into these issues with GIT HEAD from 2-3 weeks ago. When I
resume work on my @nogc project, I'll update to the 2.066
beta/release and report on any more issues. I'm aware that it's
early days yet for @nogc, so I'm not fussed about these issues,
but they are rather concerning. I considered sending in PRs to
resolve some of these problems, but fixing the Exception
situation (which many of the above stem from) requires
significant work.