On Monday, 10 July 2017 at 03:25:26 UTC, Nick Sabalausky (Abscissa) wrote:
On 07/09/2017 05:14 PM, H. S. Teoh via Digitalmars-d wrote:
On Sun, Jul 09, 2017 at 02:01:08PM -0400, Andrei Alexandrescu via Digitalmars-d wrote:
On 07/09/2017 12:19 PM, Steven Schveighoffer wrote:
It's no more of a hack than leaving assert(0) in release code.

I wouldn't argue that. I do argue it's a hack compared to the
principled solution of a bottom type. -- Andrei

I like out{ assert(0); } for pretty much the same reasons as Steven lists. The biggest pro is that **the language already supports it*. Contract syntax already is meant to signal intent, and assert(0) signals "never gets here". You can't find a better solution than this. All the other alternatives require adding even more baggage to an already heavy language, or compiler voodoo to recognize a particular pattern of defining a type. I'd say out{assert(0);} is the principled solution -- expressing something the current language can already express, and it's
the other alternatives that are "exotic".


Prioritizing "path of least resistense" over "this is cleaner and more principled" is the hallmark of C++-style langauge design. Please, please, please, let's stay away from that path.

While I agree with your sentiment in principle (heh), we need to keep in mind it purpose.
So far I count four requirements of a solution:
    documentation
    optimisation
    ability to statically reflect upon
    ability to implement

Of the approached listed only out{assert(0);} fails the static reflection check.
Which leaves
1)@noreturn
2)@disable(return)
3)none

1 & 2 are almost functionally identical in their implementation with 2 requiring some semantic hacks to the compiler and precludes the AliasSeq approach below, so I consider 1 to be superior to 2.

this leaves 1 & 3.

w.r.t documentation for 1 this is a solved problem, it becomes part of the type signature and will be picked up in the documentation building tools. 3 it becomes part of the return type and can also be solved by documenting the type.

w.r.t optimisation assuming both 1 & 3 impact DMD equally then there is no difference except that:

Implementation: 3 would require GDC and LDC to make changes _when they already have a solution_. It would also be _considerably more work_ than 1, and would be _backwards incompatible_ with older compilers. In fact 1 could be implemented _Immediately_ for GDC and LDC by having

enum __noreturn;
version (DigitalMars) alias noreturn = __noreturn;
else version(GNU) {
    import gcc.attributes : attribute;
    alias noreturn = AliasSeq!(__noreturn,attribute("noreturn"));
}
else version (LDC)
{
    import ldc.attributes : llvmAttr;
    alias noreturn = AliasSeq!(__noreturn,llvmAttr("noreturn"));
}

and reflect upon the presence of __noreturn;

I am strongly against the need to complicate the compiler when an equal (IMHO better) solution _already exists_, for extremely marginal gain: anyone seriously concerned about the small optimisation benefit will already be using GDC or LDC, the applicability of noreturn is minuscule, AFAICT C's _exit and an unconditional throw (Exception or Error) are the only functions for which it applies.

Reply via email to