difference between x = Nullable.init and x.nullify
Stanislav Blinov via Digitalmars-d-learn
digitalmars-d-learn at puremagic.com
Sun Jun 4 02:29:49 PDT 2017
On Sunday, 4 June 2017 at 09:04:14 UTC, Jonathan M Davis wrote:
>> if throwing in a destructor is considered a runtime error,
>> perhaps another valid enhancement would be to statically
>> disallow throwing Exceptions in destructors, i.e. *require*
>> them be nothrow?..
>
> My initial reaction would be that destructors should always be
> nothrow, though I vaguely recall there being some reason why it
> was supposed to be nice that destructors in D could cleanly
> deal with exceptions. And remember that when we're talking
> about rt_finalize, we're talking about finalizers, not
> destructors in general. When a destructor is in a GC
> heap-allocated object, it's treated as a finalizer and may or
> may not be run (since the object may or may not be collected),
It doesn't matter. The only thing that matters is that it may be
run, and therefore rt_finalize has to count on that. And it sort
of does, at the moment, by assuming the worst possible
combination of attributes. Problem is, with current language
rules, it cannot be any other way, as the runtime doesn't carry
any information about attributes of finalized object, or the
context in which finalization takes place (i.e. is it within a
@safe function?), which, sadly, makes unsafe code silently
executable in a safe context, in direct contradiction to language
guarantees.
> whereas when a destructor is on an object that's on the stack,
> it's really a destructor. So, while they use the same syntax,
It's worse than that. There are two "destructors": __xdtor that
calls destructors of RAII members, and, on classes, __dtor that
actually calls ~this() for the class. But only that class, not
it's ancestors or descendants. Such segregation is, as it turns
out, as useful as it is unwieldy.
> and in the case of a struct, the same function could be either
> a destructor or a finalizer depending on where the struct is
> declared, they're not quite the same thing. And destroy muddies
> the water a bit, because it then explicitly calls the finalizer
> on a class, whereas it would normally be the GC that does it
> (and while calling GC-related functions in a finalizer is
> forbidden when called by the GC, it's fine when called via
> destroy, since the GC is then not in the middle of a
> collection).
>
> So, I don't know whether it would be reasonable to require that
> destructors be nothrow. Certainly, it's _more_ likely for it to
> be reasonable for destructors on classes to be nothrow, since
> classes always live on the heap (and are thus finalizers)
> unless you're playing games with something like
> std.typecons.scoped, but I'd have to study the matter quite a
> bit more to give a properly informed answer as to whether it
> would be reasonable to require that all destructors be nothrow.
Scoped is not necessary. Classes may not necessarily exist in the
GC heap, thanks to custom allocators and emplace(). But because
the language does not enforce propagation of destructor
attributes, destroy() is @system and not nothrow, which spills
out into user code that would otherwise take advantage of static
inference. Unfortunately, right now making it any other would
impose certain restrictions on classes without real language
support, and that is... scary.
More information about the Digitalmars-d-learn
mailing list