July 11, 2017
Am Sat, 8 Jul 2017 03:15:39 -0700
schrieb Walter Bright <newshound2@digitalmars.com>:

> […]
>
> Having an @noreturn attribute will take care of that:
> 
>     @noreturn void ThisFunctionExits();
> 
> Yes, it's another builtin attribute and attributes are arguably a failure in language design.

The 'none' return type sounds interesting, because a @noreturn function is also a void function, it is practical to implement this as a void sub-type or compiler recognized druntime defined "type intrinsic". On the other hand, the attribute solution has worked well for the existing compilers in practice and such a rarely used tag doesn't add significantly to the meticulous D programmers list: "pure @safe nothrow @nogc".

-- 
Marco

July 11, 2017
On 2017-07-10 22:00, Walter Bright wrote:

> Yes. Not having it makes enforce(), for example, generate poor code.

Not sure I understand. "enforce" will return if the condition is true.

-- 
/Jacob Carlborg
July 11, 2017
On 11 July 2017 at 08:46, Jacob Carlborg via Digitalmars-d <digitalmars-d@puremagic.com> wrote:
> On 2017-07-10 22:00, Walter Bright wrote:
>
>> Yes. Not having it makes enforce(), for example, generate poor code.
>
>
> Not sure I understand. "enforce" will return if the condition is true.
>

Right, you can't put noreturn on enforce itself, but you can on the internal bailOut function called by enforce.
July 11, 2017

On 08.07.2017 12:15, Walter Bright wrote:
> C compilers (and by extension C++ compilers) usually have an extension which allows a function to be marked as one that never returns. The point of this is it enables improved data flow analysis and better code being generated.
> 
> Noreturn functions crop up in things like assert's and enforce's. DMD internally hardcodes a few functions it knows about that are noreturn, and the DMD optimizer and codegen take advantage of it.
> 
> But when people write their own assert's and enforce's, this falls apart. While the programs will still work, they won't be as efficient as they could be.
> 
> Having an @noreturn attribute will take care of that:
> 
>     @noreturn void ThisFunctionExits();
> 
> Yes, it's another builtin attribute and attributes are arguably a failure in language design.

I don't like the inflation of attributes, too, but encoding it into the return type seems too clever, especially when having to explain it again and again to people without functional language background (like me).

A few questions inspired from discussion in https://github.com/dlang/druntime/pull/1839:

- Does @noreturn need to be inferred for templates?

    void msgAssert(bool cond)(string msg)
    {
        debug writeln(msg);
        assert(cond);
    }

- The template function above is (strongly) pure, how does @noreturn interact with that? Will @noreturn ensure it is not elided?

- If it does, how does this propagate to a function calling it, e.g.

   void c_assert(bool cond, string msg) pure
   {
       if (!cond)
           msgAssert!false(msg);
   }

A call to c_assert can be elided according to the pure rules. Any chance that this can be avoided with the help of @noreturn?
July 11, 2017
On 2017-07-11 09:37, Iain Buclaw via Digitalmars-d wrote:

> Right, you can't put noreturn on enforce itself, but you can on the
> internal bailOut function called by enforce.

Ah, but I though it would just contain a "throw" for the case the the condition is false. I see now that it doesn't.

-- 
/Jacob Carlborg
July 11, 2017
On 10.07.2017 18:23, Meta wrote:
> ...
> problems with stuff like typeof(null)* etc. because for the most part it's just a regular type, unlike Bottom.

Bottom is just a regular type.
July 11, 2017
On 10.07.2017 04:44, Walter Bright wrote:
> Let's call the bottom type 'B' for the moment, for convenience.
> 
> If we think of it like a floating point NaN,

It's not. It's an empty type.

> then any type construction of B yields a B:
> 
>      const(B) -> B

I don't see why to add this special case.

>      B* -> B
>      B[] -> B
>      X[B] -> B
>      B[X] -> B
> ...

This would be wrong. All of the types on the left have valid values, they are not isomorphic to B.

> Since B cannot have a value, any expression that forms a B can be replaced with an assert(0).
> 
>      B foo(); // declaration
>      foo() -> foo(); assert(0);
> 

Yes.


>      cast(B)exp -> exp; assert(0);
> 
>      B b; -> assert(0);
> 

Those wouldn't compile. (Nothing can be cast to bottom, there is no default initializer that the variable declaration can use.)

> Given a tuple of types:
> 
>      alias T = tuple(B,X);
> 
> is T equivalent to which of:
> 
>      B           (1)
>      tuple(X)    (2)
>      tuple(Y,X)  (3)
>      tuple(B,X)  (4)
> 
> ? I'm leaning toward (4) as making the most sense.
> ...

It's the only one that makes any sense.

>      struct S {
>         T t;
>      }
> 
> should then yield an error, while:
> 
>      struct S {
>         T[1..1] t; // t is of type X
>      }
> 
> would not.

I guess you meant T[1..2].
July 11, 2017
On Tuesday, 11 July 2017 at 08:29:12 UTC, Timon Gehr wrote:
> On 10.07.2017 18:23, Meta wrote:
>> ...
>> problems with stuff like typeof(null)* etc. because for the most part it's just a regular type, unlike Bottom.
>
> Bottom is just a regular type.

It's a regular type with unusual behaviour due to it being uninhabited.
July 11, 2017
On Monday, 10 July 2017 at 20:00:10 UTC, Steven Schveighoffer wrote:
> This means that you get errors for some instantiations. Which ironically means you'd need to do something like this:
>
> void foo(alias f)()
> {
>    f();
>    static if(!isNoreturn!f)
>    {
>        auto a = 5;
>        ...// etc.
>    }
> }
>
> Today, it's not a big issue. We can't alias `assert` function directly, so it's obvious where it's an assert or not (because you have to spell it out!).
>
> We have similar problems today with generic code causing unreachability errors. See for instance https://issues.dlang.org/show_bug.cgi?id=14835
>
> -Steve

I think that for our own sanity the dead-code check would have to be disabled in this case. I agree that it'd be awful putting `static if (!isNoReturn!f)` everywhere.

Actually, why not just disable it entirely in templated functions?
July 11, 2017
On Saturday, 8 July 2017 at 12:18:38 UTC, Andrei Alexandrescu wrote:
> On 7/8/17 7:07 AM, bachmeier wrote:
>> On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright wrote:
>> 
>>> Having an @noreturn attribute will take care of that:
>>>
>>>    @noreturn void ThisFunctionExits();
>> 
>> Why should this be an attribute rather than a pragma?
>
> So it's part of the summary of the function. -- Andrei

If it feels like a pragma, should be part of the function and reflectable, then how about:

void assertFalse(bool cond) @pragma(noreturn)

or

void assertFalse(bool cond) @pragma("noreturn")

The compiler could probably give an error if the "" (inside @pragma) wasn't a known string.
Also @pragma would be useful as standard way of saying "special compiler attribute". No need to consume global attribute namespace.

I'm expecting to see @myproject_safe and @myproject_noreturn type of attributes someday in some project :|