proposed @noreturn attribute

2017-07-08 Thread Walter Bright via Digitalmars-d
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.


Has anyone a better idea? Does anyone want to write a DIP for this?

Example:

DMC uses a pragma to do it:

void ThisFunctionExits();
#pragma noreturn(ThisFunctionExits);

GCC uses an attribute:

void ThisFunctionExits() __attribute__ ((__noreturn__));

VC uses:

__declspec(noreturn) void ThisFunctionExits();



Re: proposed @noreturn attribute

2017-07-08 Thread Nicholas Wilson via Digitalmars-d

On Saturday, 8 July 2017 at 10:15:39 UTC, 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.


On the contrary I think attributes are wonderful, and I have a 
DIP in the pipeline to address some the the problems 
(https://github.com/dlang/DIPs/pull/75)




Has anyone a better idea? Does anyone want to write a DIP for 
this?


Example:

DMC uses a pragma to do it:

void ThisFunctionExits();
#pragma noreturn(ThisFunctionExits);

GCC uses an attribute:

void ThisFunctionExits() __attribute__ ((__noreturn__));

VC uses:

__declspec(noreturn) void ThisFunctionExits();


consider that GDC and LDC already both have that attribute 
courtesy of their backends (@attribute("noreturn") and 
@llvmAttr("noreturn") respectively).


While it may seem a good idea to unify them, if people want 
performance then they will use either GDC or LDC, which already 
have that attribute. So I would question the usefulness of such 
an attribute but won't go so far as to discourage anyone from 
trying. However it should be a compiler dependant alias in 
core.attribute if it is to become a thing.


Re: proposed @noreturn attribute

2017-07-08 Thread bachmeier via Digitalmars-d

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? It looks to 
me that the goal is to pass information to the compiler, and 
according to the spec:


"Pragmas are a way to pass special information to the compiler 
and to add vendor specific extensions to D. Pragmas can be used 
by themselves terminated with a ‘;’, they can influence a 
statement, a block of statements, a declaration, or a block of 
declarations."


Re: proposed @noreturn attribute

2017-07-08 Thread Andrei Alexandrescu via Digitalmars-d

On 7/8/17 6:15 AM, Walter Bright wrote:

Has anyone a better idea? Does anyone want to write a DIP for this?


An attribute is fine. A more PL-minded possibility is to return a 
specific type:


struct None
{
@disable this();
@disable this(this);
@disable @property None init();
}

None ThisFunctionExits();

The compiler detects (without having anything hardwired about the 
particular type "None") that the type None is impossible to create and 
copy/move from a function, and therefore decrees the function will never 
return.



Andrei


Re: proposed @noreturn attribute

2017-07-08 Thread Andrei Alexandrescu via Digitalmars-d

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



Re: proposed @noreturn attribute

2017-07-08 Thread Stefan Koch via Digitalmars-d
On Saturday, 8 July 2017 at 12:17:57 UTC, Andrei Alexandrescu 
wrote:

On 7/8/17 6:15 AM, Walter Bright wrote:
Has anyone a better idea? Does anyone want to write a DIP for 
this?


An attribute is fine. A more PL-minded possibility is to return 
a specific type:


struct None
{
@disable this();
@disable this(this);
@disable @property None init();
}

None ThisFunctionExits();

The compiler detects (without having anything hardwired about 
the particular type "None") that the type None is impossible to 
create and copy/move from a function, and therefore decrees the 
function will never return.



Andrei


... since it's going to be special cased by the compiler we might 
as well hardwire a type called none.
Although it seems to be that the scope of no-return is extremely 
narrow.

Because we do have precisely builtin assert(0).



Re: proposed @noreturn attribute

2017-07-08 Thread bachmeier via Digitalmars-d
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


But it's additional clutter being added for the benefit of the 
compiler. Additions like this make it hard for those of us 
showing the language to others.


Re: proposed @noreturn attribute

2017-07-08 Thread Jonathan Marler via Digitalmars-d

On Saturday, 8 July 2017 at 10:15:39 UTC, 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.


Has anyone a better idea? Does anyone want to write a DIP for 
this?


Example:

DMC uses a pragma to do it:

void ThisFunctionExits();
#pragma noreturn(ThisFunctionExits);

GCC uses an attribute:

void ThisFunctionExits() __attribute__ ((__noreturn__));

VC uses:

__declspec(noreturn) void ThisFunctionExits();


Some questions...

What kinds of control flow does this apply to?  My guess is that 
you consider a function to be "no-return" so long as it never 
returns control directly back to the caller.  The examples I can 
think of would be functions that prevent returning to the caller 
by calling exit, asserting, throwing or even just executing an 
infinite loop (expecting the program to exit via signal or some 
other means).  Is this right?


Another question I had was would the compiler provide control 
flow checking to make sure that the function does not return?


Also, I can imagine some optimizations that can be done with this 
information, would you mind sharing the optimization(s) you had 
in mind?


Re: proposed @noreturn attribute

2017-07-08 Thread Andrei Alexandrescu via Digitalmars-d

On 07/08/2017 08:20 AM, Stefan Koch wrote:
... since it's going to be special cased by the compiler we might as 
well hardwire a type called none.


Walter and I have repeated experience with moving compiler smarts into 
library artifacts. Sometimes it's arguably not the best way to go, but 
in the majority of cases it's been beneficial for both the language and 
the compiler implementation.



Although it seems to be that the scope of no-return is extremely narrow.
Because we do have precisely builtin assert(0).


What is the signature of a function that logs something to a file and 
ends in assert(0)?



Andrei


Re: proposed @noreturn attribute

2017-07-08 Thread Jack Stouffer via Digitalmars-d

On Saturday, 8 July 2017 at 11:07:32 UTC, bachmeier wrote:

Why should this be an attribute rather than a pragma?


I agree. There's no reason I can think of as to why the no-return 
should be part of the ABI.


Re: proposed @noreturn attribute

2017-07-08 Thread Andrei Alexandrescu via Digitalmars-d

On 07/08/2017 01:14 PM, Jack Stouffer wrote:

On Saturday, 8 July 2017 at 11:07:32 UTC, bachmeier wrote:

Why should this be an attribute rather than a pragma?


I agree. There's no reason I can think of as to why the no-return should 
be part of the ABI.


If present in the signature of the function you can figure that the 
function won't return by introspection. -- Andrei


Re: proposed @noreturn attribute

2017-07-08 Thread Stefan Koch via Digitalmars-d
On Saturday, 8 July 2017 at 17:14:32 UTC, Andrei Alexandrescu 
wrote:


What is the signature of a function that logs something to a 
file and ends in assert(0)?




I do get your point.
However I still doubt that this is worth a the additional 
language complexity.


Usually the clue would be in the name.
sth. like
void logAndDie(string lastWords) { ... }


Re: proposed @noreturn attribute

2017-07-08 Thread John Colvin via Digitalmars-d
On Saturday, 8 July 2017 at 12:17:57 UTC, Andrei Alexandrescu 
wrote:

On 7/8/17 6:15 AM, Walter Bright wrote:
Has anyone a better idea? Does anyone want to write a DIP for 
this?


An attribute is fine. A more PL-minded possibility is to return 
a specific type:


struct None
{
@disable this();
@disable this(this);
@disable @property None init();
}

None ThisFunctionExits();

The compiler detects (without having anything hardwired about 
the particular type "None") that the type None is impossible to 
create and copy/move from a function, and therefore decrees the 
function will never return.



Andrei


I wonder if some lessons from Haskell's "bottom" type would be 
relevant here.


Re: proposed @noreturn attribute

2017-07-08 Thread Andrei Alexandrescu via Digitalmars-d

On 7/8/17 2:26 PM, John Colvin wrote:
I wonder if some lessons from Haskell's "bottom" type would be relevant 
here.


Affirmative. The nice touch of bottom (heh) is that it's convertible to 
anything, so you can use it in complex expressions as a wildcard. -- Andrei


Re: proposed @noreturn attribute

2017-07-08 Thread Andrei Alexandrescu via Digitalmars-d

On 7/8/17 1:30 PM, Stefan Koch wrote:

On Saturday, 8 July 2017 at 17:14:32 UTC, Andrei Alexandrescu wrote:


What is the signature of a function that logs something to a file and 
ends in assert(0)?




I do get your point.
However I still doubt that this is worth a the additional language 
complexity.


Yah, there's marginal utility only - improves code generation and makes 
a few awkward workarounds unnecessary. Yet many other languages and 
implementations have it, so apparently the utility is justifiable.



Usually the clue would be in the name.
sth. like
void logAndDie(string lastWords) { ... }


Problem here being this code is opaque to compile-time analysis and to 
introspection. Unless, that is, the compiler understands the name 
(smell) or the introspection does heuristics on name - e.g. everything 
that ends in "andDie" does not return (smell). -- Andrei


Re: proposed @noreturn attribute

2017-07-08 Thread Walter Bright via Digitalmars-d

On 7/8/2017 3:52 AM, Nicholas Wilson wrote:
consider that GDC and LDC already both have that attribute courtesy of their 
backends (@attribute("noreturn") and @llvmAttr("noreturn") respectively).


One could argue that since "noreturn" changes the interface of a function, it 
should also change its signature (i.e. name mangling). I don't believe this is 
currently the case with any C++ compiler, or with LDC/GDC.


And frankly I'm sure it's annoying to users to use that attribute portably 
between GDC/LDC. The concept of noreturn should be part of the language, not a 
compiler implementation.


Re: proposed @noreturn attribute

2017-07-08 Thread Walter Bright via Digitalmars-d

On 7/8/2017 5:17 AM, Andrei Alexandrescu wrote:

None ThisFunctionExits();

The compiler detects (without having anything hardwired about the particular 
type "None") that the type None is impossible to create and copy/move from a 
function, and therefore decrees the function will never return.


That is a scathingly brilliant idea. It has another nice effect - the compiler 
doesn't have to diagnose:


   @noreturn int foo();

as an error!

Me like.


Re: proposed @noreturn attribute

2017-07-08 Thread Walter Bright via Digitalmars-d

On 7/8/2017 10:14 AM, Jack Stouffer wrote:

On Saturday, 8 July 2017 at 11:07:32 UTC, bachmeier wrote:

Why should this be an attribute rather than a pragma?


I agree. There's no reason I can think of as to why the no-return should be part 
of the ABI.


Separate compilation. I.e. if one changes the implementation of a function such 
that it now returns, it will break any compiled code that relied on it being 
noreturn.


This is why, for example, nothrow is part of the signature.


Re: proposed @noreturn attribute

2017-07-08 Thread H. S. Teoh via Digitalmars-d
On Sat, Jul 08, 2017 at 01:09:35PM -0700, Walter Bright via Digitalmars-d wrote:
> On 7/8/2017 5:17 AM, Andrei Alexandrescu wrote:
> > None ThisFunctionExits();
> > 
> > The compiler detects (without having anything hardwired about the
> > particular type "None") that the type None is impossible to create
> > and copy/move from a function, and therefore decrees the function
> > will never return.
> 
> That is a scathingly brilliant idea. It has another nice effect - the
> compiler doesn't have to diagnose:
> 
>@noreturn int foo();
> 
> as an error!
[...]

Hmmm. Just to clarify, what exactly does @noreturn include? If I have a
function that calls exit(), that's @noreturn? What about a function that
always throws? Or a function that calls exec()? A function that always
ends in assert(0)? A function that context-switches to a different
thread / fibre and terminates this one?

Personally, I'm for this. It is useful for functions that constructs
then throws an exception, for example. It would be nice to be able to
call such a function from another function that returns non-void without
having to insert assert(0) into the latter to avoid the compiler
complaining that you failed to return a value.

As for Andrei's idea, it's pretty clever but we would need to
standardize the None type, otherwise we risk hard-to-read code when
everyone rolls their own None type with different names. An attribute
has the advantage that it will be universally understood.


T

-- 
It only takes one twig to burn down a forest.


Re: proposed @noreturn attribute

2017-07-08 Thread H. S. Teoh via Digitalmars-d
On Sat, Jul 08, 2017 at 01:20:03PM -0700, H. S. Teoh via Digitalmars-d wrote:
[...]
> Personally, I'm for this. It is useful for functions that constructs
> then throws an exception, for example. It would be nice to be able to
> call such a function from another function that returns non-void
> without having to insert assert(0) into the latter to avoid the
> compiler complaining that you failed to return a value.
> 
> As for Andrei's idea, it's pretty clever but we would need to
> standardize the None type, otherwise we risk hard-to-read code when
> everyone rolls their own None type with different names. An attribute
> has the advantage that it will be universally understood.
[...]

Also, a @noreturn attribute would allow overriding a non-void class
method with a @noreturn one (e.g. the derived class is a sentinel object
that forces an exception / termination upon calling that method),
whereas you can't do that with a None return type because the signature
would not match the base class's.


T

-- 
"Hi." "'Lo."


Re: proposed @noreturn attribute

2017-07-08 Thread Vladimir Panteleev via Digitalmars-d
On Saturday, 8 July 2017 at 12:17:57 UTC, Andrei Alexandrescu 
wrote:

@disable @property None init();


You meant static here I guess.

The compiler detects (without having anything hardwired about 
the particular type "None") that the type None is impossible to 
create and copy/move from a function, and therefore decrees the 
function will never return.


Cheat: https://is.gd/pf25nP

Works because of NRVO I guess. This particular one is countered 
by also adding a disabled destructor.




Re: proposed @noreturn attribute

2017-07-08 Thread Vladimir Panteleev via Digitalmars-d
On Saturday, 8 July 2017 at 21:03:57 UTC, Vladimir Panteleev 
wrote:
This particular one is countered by also adding a disabled 
destructor.


Oops, never mind that - this makes the function uncallable.



Re: proposed @noreturn attribute

2017-07-08 Thread Walter Bright via Digitalmars-d

On 7/8/2017 1:20 PM, H. S. Teoh via Digitalmars-d wrote:

Hmmm. Just to clarify, what exactly does @noreturn include? If I have a
function that calls exit(), that's @noreturn? What about a function that
always throws? Or a function that calls exec()? A function that always
ends in assert(0)? A function that context-switches to a different
thread / fibre and terminates this one?


There's no subtlety to it. It's a function that never returns. I.e. it doesn't 
execute a 'RET' instruction.




As for Andrei's idea, it's pretty clever but we would need to
standardize the None type, otherwise we risk hard-to-read code when
everyone rolls their own None type with different names. An attribute
has the advantage that it will be universally understood.


It would be like `size_t`.


Re: proposed @noreturn attribute

2017-07-08 Thread Martin Nowak via Digitalmars-d
On Saturday, 8 July 2017 at 12:17:57 UTC, Andrei Alexandrescu 
wrote:

struct None
{
@disable this();
@disable this(this);
@disable @property None init();
}

None ThisFunctionExits();

The compiler detects (without having anything hardwired about 
the particular type "None") that the type None is impossible to 
create and copy/move from a function, and therefore decrees the 
function will never return.


That's a lot more complex (for the compiler and to explain) than 
using a simple magic @noreturn attribute.
Agreed that this is rarely needed but sometimes nice to have. Far 
from being important though ;).




Re: proposed @noreturn attribute

2017-07-08 Thread Walter Bright via Digitalmars-d

On 7/8/2017 4:36 PM, Martin Nowak wrote:
That's a lot more complex (for the compiler and to explain) than using a simple 
magic @noreturn attribute.
Agreed that this is rarely needed but sometimes nice to have. Far from being 
important though ;).


We have types that cannot be named (Voldemort types), types that have no type 
(void), I suppose that types that cannot exist will fill out the edge cases of 
the menagerie.


I assume there is a standard jargon for this - does anyone know Type Theory?

Are there any other interesting uses for a type that cannot exist?


Re: proposed @noreturn attribute

2017-07-08 Thread crimaniak via Digitalmars-d

On Sunday, 9 July 2017 at 00:16:50 UTC, Walter Bright wrote:
I assume there is a standard jargon for this - does anyone know 
Type Theory?
I'm afraid it's perpendicular to type theory - every type 
including Nothing can be returned. Most simple solution - just to 
remove '@' and call this type 'noreturn'.


noreturn functionFoo(bla-bla-bla);




Re: proposed @noreturn attribute

2017-07-08 Thread sarn via Digitalmars-d

On Sunday, 9 July 2017 at 00:16:50 UTC, Walter Bright wrote:
We have types that cannot be named (Voldemort types), types 
that have no type (void), I suppose that types that cannot 
exist will fill out the edge cases of the menagerie.


I assume there is a standard jargon for this - does anyone know 
Type Theory?


Are there any other interesting uses for a type that cannot 
exist?


In pure functional languages, that's what "bottom" or Haskell's 
Void is.


In Curry–Howard "programs are proofs" theory, a type is a 
proposition and an instance is a proof.  A type with no instance 
is a proposition that can't be proved.


https://codewords.recurse.com/issues/one/type-systems-and-logic

I'm not sure how much impact this has on everyday D programming, 
but hey, it's a thing.


Re: proposed @noreturn attribute

2017-07-08 Thread Walter Bright via Digitalmars-d

On 7/8/2017 7:01 PM, sarn wrote:

On Sunday, 9 July 2017 at 00:16:50 UTC, Walter Bright wrote:
We have types that cannot be named (Voldemort types), types that have no type 
(void), I suppose that types that cannot exist will fill out the edge cases of 
the menagerie.


I assume there is a standard jargon for this - does anyone know Type Theory?

Are there any other interesting uses for a type that cannot exist?


In pure functional languages, that's what "bottom" or Haskell's Void is.

In Curry–Howard "programs are proofs" theory, a type is a proposition and an 
instance is a proof.  A type with no instance is a proposition that can't be 
proved.


https://codewords.recurse.com/issues/one/type-systems-and-logic

I'm not sure how much impact this has on everyday D programming, but hey, it's a 
thing.


Thanks, it looks like we won't get any help from type theory. We're on our own 
:-)

(D already has a `void` type, so can't use Haskell's word.)


Re: proposed @noreturn attribute

2017-07-08 Thread H. S. Teoh via Digitalmars-d
On Sun, Jul 09, 2017 at 02:01:26AM +, sarn via Digitalmars-d wrote:
> On Sunday, 9 July 2017 at 00:16:50 UTC, Walter Bright wrote:
> > We have types that cannot be named (Voldemort types), types that
> > have no type (void), I suppose that types that cannot exist will
> > fill out the edge cases of the menagerie.
> > 
> > I assume there is a standard jargon for this - does anyone know Type
> > Theory?
> > 
> > Are there any other interesting uses for a type that cannot exist?

Technically, the *type* itself exist, it's just that you cannot create
any instances of it. :-P  From the POV of types as sets of possible
values, it's a type that corresponds with an empty set.  However, then
we cannot distinguish between void (which is also by definition a type
that has no instances) and noreturn.  I'm not sure how to interpret
noreturn in this framework... perhaps a set that doesn't exist? :-P  We
could call it a RussellsParadox set. :-D


> In pure functional languages, that's what "bottom" or Haskell's Void
> is.
[...]

Are you sure?  IIRC, it's legal to return bottom; it just signifies that
the value is invalid, and that any operation on it will also result in
bottom.  Sortof like NaN.  That's not the same thing as "this function
never returns".


T

-- 
The computer is only a tool. Unfortunately, so is the user. -- Armaphine, K5


Re: proposed @noreturn attribute

2017-07-08 Thread Meta via Digitalmars-d

On Sunday, 9 July 2017 at 02:25:50 UTC, Walter Bright wrote:

(D already has a `void` type, so can't use Haskell's word.)


Just so we are all on the same page, from a type-theory 
perspective void is a unit type (it has 1 value), not an 
uninhabited type (it has no values, i.e. Haskell's _|_ (bottom) 
type).


A function with a return type of unit means "this function 
returns no useful information", because the type only has one 
possible value anyway. A function with a return type of bottom 
means "this function can never return", because there is no value 
of type bottom that could be returned. All that can be done is 
for the function to diverge (throwing an exception, ending the 
program, looping forever, etc.).


We sort of have this already with `assert(0)`. The compiler knows 
that no execution can take place after an `assert(0)` is 
encountered (in other words, it knows that the function 
diverges). We just don't have a corresponding type to represent 
this (Rust uses ! but if I remember correctly it's not quite a 
first class type).


If we wanted to be cute we could use `typeof()` to represent this 
type as there is no value you can give to typeof such that it 
returns the bottom type. It also avoids having to come up with 
some special symbol or name for it.





Re: proposed @noreturn attribute

2017-07-08 Thread Meta via Digitalmars-d

On Sunday, 9 July 2017 at 04:23:15 UTC, Meta wrote:

On Sunday, 9 July 2017 at 02:25:50 UTC, Walter Bright wrote:

(D already has a `void` type, so can't use Haskell's word.)


Just so we are all on the same page, from a type-theory 
perspective void is a unit type (it has 1 value), not an 
uninhabited type (it has no values, i.e. Haskell's _|_ (bottom) 
type).


A function with a return type of unit means "this function 
returns no useful information", because the type only has one 
possible value anyway. A function with a return type of bottom 
means "this function can never return", because there is no 
value of type bottom that could be returned. All that can be 
done is for the function to diverge (throwing an exception, 
ending the program, looping forever, etc.).


We sort of have this already with `assert(0)`. The compiler 
knows that no execution can take place after an `assert(0)` is 
encountered (in other words, it knows that the function 
diverges). We just don't have a corresponding type to represent 
this (Rust uses ! but if I remember correctly it's not quite a 
first class type).


If we wanted to be cute we could use `typeof()` to represent 
this type as there is no value you can give to typeof such that 
it returns the bottom type. It also avoids having to come up 
with some special symbol or name for it.


In C++/D terms, the unit type could be expressed as `enum Unit { 
unit }` while the bottom type would be `enum Bottom {}` (although 
only conceptually because in C++/D you can still do `Bottom b;`).


Re: proposed @noreturn attribute

2017-07-08 Thread Andrei Alexandrescu via Digitalmars-d

On 07/08/2017 10:25 PM, Walter Bright wrote:

On 7/8/2017 7:01 PM, sarn wrote:

On Sunday, 9 July 2017 at 00:16:50 UTC, Walter Bright wrote:
We have types that cannot be named (Voldemort types), types that have 
no type (void), I suppose that types that cannot exist will fill out 
the edge cases of the menagerie.


I assume there is a standard jargon for this - does anyone know Type 
Theory?


Are there any other interesting uses for a type that cannot exist?


In pure functional languages, that's what "bottom" or Haskell's Void is.

In Curry–Howard "programs are proofs" theory, a type is a proposition 
and an instance is a proof.  A type with no instance is a proposition 
that can't be proved.


https://codewords.recurse.com/issues/one/type-systems-and-logic

I'm not sure how much impact this has on everyday D programming, but 
hey, it's a thing.


Thanks, it looks like we won't get any help from type theory. We're on 
our own :-)


How does the information provided lead to such a conclusion? There's 
established theory and practice on that.


https://en.wikipedia.org/wiki/Bottom_type

The "Bottom" type (bottom of the type hierarchy lattice) is what's 
needed. If "Object" is the total set i.e. the top of the lattice i.e. 
the type that is so general all types are a subset of it, then "Bottom" 
is the type that is a subtype of all types and is so particular it can't 
be even instantiated. It implicitly converts to everything because it's 
a subtype of everything. Obviously conversion doesn't need to be honored 
because the function never returns.



Andrei


Re: proposed @noreturn attribute

2017-07-08 Thread Andrei Alexandrescu via Digitalmars-d

On 07/08/2017 05:03 PM, Vladimir Panteleev wrote:

On Saturday, 8 July 2017 at 12:17:57 UTC, Andrei Alexandrescu wrote:

@disable @property None init();


You meant static here I guess.

The compiler detects (without having anything hardwired about the 
particular type "None") that the type None is impossible to create and 
copy/move from a function, and therefore decrees the function will 
never return.


Cheat: https://is.gd/pf25nP

Works because of NRVO I guess. This particular one is countered by also 
adding a disabled destructor.


Eh, interesting. Indeed this doesn't compile anymore:

struct None
{
@disable this();
@disable this(this);
@disable ~this();
@disable static @property None init();
}

None fun()
{
None none = void;
return none;
}

void main()
{
fun();
}

The type None would then go in object.d.

The compiler detects the pattern and make None implicitly convertible to 
anything so people can write things like:


int x = y ? 100 / y : fun();

Without the conversion, None is a less useful artifact.


Andrei


Re: proposed @noreturn attribute

2017-07-08 Thread Walter Bright via Digitalmars-d

On 7/8/2017 9:23 PM, Meta wrote:

On Sunday, 9 July 2017 at 02:25:50 UTC, Walter Bright wrote:

(D already has a `void` type, so can't use Haskell's word.)


Just so we are all on the same page, from a type-theory perspective void is a 
unit type (it has 1 value), not an uninhabited type (it has no values, i.e. 
Haskell's _|_ (bottom) type).


A function with a return type of unit means "this function returns no useful 
information", because the type only has one possible value anyway. A function 
with a return type of bottom means "this function can never return", because 
there is no value of type bottom that could be returned. All that can be done is 
for the function to diverge (throwing an exception, ending the program, looping 
forever, etc.).


Thanks for the explanation.


We sort of have this already with `assert(0)`. The compiler knows that no 
execution can take place after an `assert(0)` is encountered (in other words, it 
knows that the function diverges). We just don't have a corresponding type to 
represent this (Rust uses ! but if I remember correctly it's not quite a first 
class type).


If we wanted to be cute we could use `typeof()` to represent this type as there 
is no value you can give to typeof such that it returns the bottom type. It also 
avoids having to come up with some special symbol or name for it.


That is indeed an interesting idea. Thanks!

(This thread is turning out to be more productive than I anticipated.)



Re: proposed @noreturn attribute

2017-07-08 Thread Walter Bright via Digitalmars-d

On 7/8/2017 9:32 PM, Meta wrote:

On Sunday, 9 July 2017 at 04:23:15 UTC, Meta wrote:

On Sunday, 9 July 2017 at 02:25:50 UTC, Walter Bright wrote:

(D already has a `void` type, so can't use Haskell's word.)


Just so we are all on the same page, from a type-theory perspective void is a 
unit type (it has 1 value), not an uninhabited type (it has no values, i.e. 
Haskell's _|_ (bottom) type).


I read that a Void function in Haskell does not return. Is that incorrect? I'm 
not sure how Void relates to _|_


  https://en.wikipedia.org/wiki/Bottom_type#In_programming_languages

says Haskell does not support empty (i.e. bottom) types.

A function with a return type of unit means "this function returns no useful 
information", because the type only has one possible value anyway. A function 
with a return type of bottom means "this function can never return", because 
there is no value of type bottom that could be returned. All that can be done 
is for the function to diverge (throwing an exception, ending the program, 
looping forever, etc.).


We sort of have this already with `assert(0)`. The compiler knows that no 
execution can take place after an `assert(0)` is encountered (in other words, 
it knows that the function diverges). We just don't have a corresponding type 
to represent this (Rust uses ! but if I remember correctly it's not quite a 
first class type).


If we wanted to be cute we could use `typeof()` to represent this type as 
there is no value you can give to typeof such that it returns the bottom type. 
It also avoids having to come up with some special symbol or name for it.


In C++/D terms, the unit type could be expressed as `enum Unit { unit }` while 
the bottom type would be `enum Bottom {}` (although only conceptually because in 
C++/D you can still do `Bottom b;`).


In D, void is used to signify a function doesn't return a value, but it still 
returns. It also means untyped data, and no initializer.


Re: proposed @noreturn attribute

2017-07-09 Thread Mr.D via Digitalmars-d

On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright wrote:


Has anyone a better idea?


What about

scope(exit) assert(0);

?


Re: proposed @noreturn attribute

2017-07-09 Thread Timon Gehr via Digitalmars-d

On 09.07.2017 07:44, Walter Bright wrote:

On 7/8/2017 9:32 PM, Meta wrote:

On Sunday, 9 July 2017 at 04:23:15 UTC, Meta wrote:

On Sunday, 9 July 2017 at 02:25:50 UTC, Walter Bright wrote:

(D already has a `void` type, so can't use Haskell's word.)


Just so we are all on the same page, from a type-theory perspective 
void is a unit type (it has 1 value), not an uninhabited type (it has 
no values, i.e. Haskell's _|_ (bottom) type).


I read that a Void function in Haskell does not return. Is that 
incorrect?


It is indeed incorrect, but this has little relevance for D. In Haskell, 
non-termination and exceptions are values that you can store in a 
variable (due to lazy evaluation). A function can return non-termination 
or exceptions non-evaluated. When those values are finally lazily 
evaluated, you get actual non-termination or a thrown exception. This is 
why Haskell has no empty type. If evaluation in Haskell was strict (as 
D's is), a function with return type Void would not be able to return. 
(BTW: it makes more sense to return a polymorphic value, i.e. x :: t 
instead of using the Void type, because Haskell does not have subtyping. 
This still implies that x does not contain a 'real' value, because we 
can instantiate t with Void.)



I'm not sure how Void relates to _|_

   https://en.wikipedia.org/wiki/Bottom_type#In_programming_languages

says Haskell does not support empty (i.e. bottom) types.
...


Re: proposed @noreturn attribute

2017-07-09 Thread Daniel N via Digitalmars-d

On Sunday, 9 July 2017 at 10:31:47 UTC, Mr.D wrote:

On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright wrote:


Has anyone a better idea?


What about

scope(exit) assert(0);

?


void func()
out { assert(0); }
body
{
}


Re: proposed @noreturn attribute

2017-07-09 Thread Steven Schveighoffer via Digitalmars-d

On Sunday, 9 July 2017 at 10:51:50 UTC, Daniel N wrote:

On Sunday, 9 July 2017 at 10:31:47 UTC, Mr.D wrote:

On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright wrote:


Has anyone a better idea?


What about

scope(exit) assert(0);

?


void func()
out { assert(0); }
body
{
}


Yes, this!

-Steve


Re: proposed @noreturn attribute

2017-07-09 Thread Nicholas Wilson via Digitalmars-d
On Sunday, 9 July 2017 at 10:59:43 UTC, Steven Schveighoffer 
wrote:

On Sunday, 9 July 2017 at 10:51:50 UTC, Daniel N wrote:

On Sunday, 9 July 2017 at 10:31:47 UTC, Mr.D wrote:

On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright wrote:


Has anyone a better idea?


What about

scope(exit) assert(0);

?


void func()
out { assert(0); }
body
{
}


Yes, this!

-Steve


That certainly signals intention, but I still think that an 
attribute is a whole lot simpler than compiler voodoo like this 
or the "None" discussed earlier.


Re: proposed @noreturn attribute

2017-07-09 Thread Walter Bright via Digitalmars-d

On 7/9/2017 3:48 AM, Timon Gehr wrote:

It is indeed incorrect, [...]


Thanks!


Re: proposed @noreturn attribute

2017-07-09 Thread Walter Bright via Digitalmars-d

On 7/9/2017 3:31 AM, Mr.D wrote:

scope(exit) assert(0);


It needs to be part of the function signature, not the function implementation.


Re: proposed @noreturn attribute

2017-07-09 Thread Steven Schveighoffer via Digitalmars-d

On 7/9/17 7:07 AM, Nicholas Wilson wrote:

On Sunday, 9 July 2017 at 10:59:43 UTC, Steven Schveighoffer wrote:

On Sunday, 9 July 2017 at 10:51:50 UTC, Daniel N wrote:

On Sunday, 9 July 2017 at 10:31:47 UTC, Mr.D wrote:

On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright wrote:


Has anyone a better idea?


What about

scope(exit) assert(0);

?


void func()
out { assert(0); }
body
{
}


Yes, this!

That certainly signals intention, but I still think that an attribute is 
a whole lot simpler than compiler voodoo like this or the "None" 
discussed earlier.


This whole proposal is compiler voodoo :)

Unlike a currently undefined attribute, assert(0) in the out contract 
currently is effective to mean no return. It also guarantees that if 
there is a return statement somewhere, it still doesn't return.


Also, since the out contract is part of the signature, it will still be 
present in the case of separate compilation.


The one disadvantage, is that -release removes contracts. So in this 
particular case, the out contract should remain.


Not sure if it has been mentioned yet, but @disable(return) could work 
as something that doesn't add any new attributes.


-Steve


Re: proposed @noreturn attribute

2017-07-09 Thread Nicholas Wilson via Digitalmars-d
On Sunday, 9 July 2017 at 11:26:27 UTC, Steven Schveighoffer 
wrote:

On 7/9/17 7:07 AM, Nicholas Wilson wrote:
On Sunday, 9 July 2017 at 10:59:43 UTC, Steven Schveighoffer 
wrote:

On Sunday, 9 July 2017 at 10:51:50 UTC, Daniel N wrote:

On Sunday, 9 July 2017 at 10:31:47 UTC, Mr.D wrote:
On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright 
wrote:



Has anyone a better idea?


What about

scope(exit) assert(0);

?


void func()
out { assert(0); }
body
{
}


Yes, this!

That certainly signals intention, but I still think that an 
attribute is a whole lot simpler than compiler voodoo like 
this or the "None" discussed earlier.


This whole proposal is compiler voodoo :)

Unlike a currently undefined attribute, assert(0) in the out 
contract currently is effective to mean no return. It also 
guarantees that if there is a return statement somewhere, it 
still doesn't return.


Also, since the out contract is part of the signature, it will 
still be present in the case of separate compilation.


The one disadvantage, is that -release removes contracts. So in 
this particular case, the out contract should remain.


Not sure if it has been mentioned yet, but @disable(return) 
could work as something that doesn't add any new attributes.


-Steve


If the compiler is like a magician, adding an attribute is like 
conjuring a rabbit, adding the "None" would be like summoning 
Chthulu.


I like the @disable(return) but I still think a plain attribute 
is the simplest way to achieve the goals of:

* documentation, is doesn't get much simpler than @noreturn
* optimisation, its already in LDC and GDC, just under a 
different name
* compatibility between compilers, its as simple as an alias in a 
version statement per compiler.




Re: proposed @noreturn attribute

2017-07-09 Thread Andrei Alexandrescu via Digitalmars-d

On 7/9/17 1:36 AM, Walter Bright wrote:


If we wanted to be cute we could use `typeof()` to represent this type 
as there is no value you can give to typeof such that it returns the 
bottom type. It also avoids having to come up with some special symbol 
or name for it.


That is indeed an interesting idea. Thanks!


We should use typeof(assert(0)) for Bottom. There is precedent - there 
is no name for typeof(null). -- Andrei


Re: proposed @noreturn attribute

2017-07-09 Thread Andrei Alexandrescu via Digitalmars-d

On 7/9/17 7:26 AM, Steven Schveighoffer wrote:

On 7/9/17 7:07 AM, Nicholas Wilson wrote:

On Sunday, 9 July 2017 at 10:59:43 UTC, Steven Schveighoffer wrote:

On Sunday, 9 July 2017 at 10:51:50 UTC, Daniel N wrote:

On Sunday, 9 July 2017 at 10:31:47 UTC, Mr.D wrote:

On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright wrote:


Has anyone a better idea?


What about

scope(exit) assert(0);

?


void func()
out { assert(0); }
body
{
}


Yes, this!

That certainly signals intention, but I still think that an attribute 
is a whole lot simpler than compiler voodoo like this or the "None" 
discussed earlier.


This whole proposal is compiler voodoo :)

Unlike a currently undefined attribute, assert(0) in the out contract 
currently is effective to mean no return. It also guarantees that if 
there is a return statement somewhere, it still doesn't return.


Also, since the out contract is part of the signature, it will still be 
present in the case of separate compilation.


The one disadvantage, is that -release removes contracts. So in this 
particular case, the out contract should remain.


Not sure if it has been mentioned yet, but @disable(return) could work 
as something that doesn't add any new attributes.


I wonder why there's so much attraction to exotic approaches when 
encoding "no return" with types has so much established theory and 
practice with it. -- Andrei




Re: proposed @noreturn attribute

2017-07-09 Thread Stefan Koch via Digitalmars-d

On Sunday, 9 July 2017 at 13:13:28 UTC, Andrei Alexandrescu wrote:

On 7/9/17 1:36 AM, Walter Bright wrote:


If we wanted to be cute we could use `typeof()` to represent 
this type as there is no value you can give to typeof such 
that it returns the bottom type. It also avoids having to 
come up with some special symbol or name for it.


That is indeed an interesting idea. Thanks!


We should use typeof(assert(0)) for Bottom. There is precedent 
- there is no name for typeof(null). -- Andrei


I agree with is approach.
It does not add a magic Type :)



Re: proposed @noreturn attribute

2017-07-09 Thread Steven Schveighoffer via Digitalmars-d

On 7/9/17 9:16 AM, Andrei Alexandrescu wrote:

I wonder why there's so much attraction to exotic approaches when 
encoding "no return" with types has so much established theory and 
practice with it. -- Andrei




Your definition of exotic differs from mine.

I haven't seen another solution other than out { assert(0); } which 
semantically means "this function cannot return" in the current 
compiler, and pretty much all historical D compilers, is obvious to the 
reader that it does so, available in the prototype, and is there and 
ready for the compiler to optimize with. Literally we have to change 
nothing in the language or library, only how the optimizer handles it.


Adding specialized attributes, esoteric types, etc, does not have this 
same level of compatibility. That is why I find this more attractive 
than any other suggestions so far.


-Steve


Re: proposed @noreturn attribute

2017-07-09 Thread Andrei Alexandrescu via Digitalmars-d

On 07/09/2017 10:10 AM, Steven Schveighoffer wrote:

On 7/9/17 9:16 AM, Andrei Alexandrescu wrote:

I wonder why there's so much attraction to exotic approaches when 
encoding "no return" with types has so much established theory and 
practice with it. -- Andrei




Your definition of exotic differs from mine.


Mine is closest to: "strikingly, excitingly, or mysteriously different 
or unusual" :o) in https://www.merriam-webster.com/dictionary/exotic -- 
Andrei




Re: proposed @noreturn attribute

2017-07-09 Thread Andrei Alexandrescu via Digitalmars-d

On 07/09/2017 10:10 AM, Steven Schveighoffer wrote:

I haven't seen another solution other than out { assert(0); }


Your own comment takes it to the recycle bin:


The one disadvantage, is that -release removes contracts. So in this
particular case, the out contract should remain.


That's already a hack on top of a hack.


Andrei


Re: proposed @noreturn attribute

2017-07-09 Thread Steven Schveighoffer via Digitalmars-d

On Sunday, 9 July 2017 at 14:43:20 UTC, Andrei Alexandrescu wrote:

On 07/09/2017 10:10 AM, Steven Schveighoffer wrote:

I haven't seen another solution other than out { assert(0); }


Your own comment takes it to the recycle bin:

The one disadvantage, is that -release removes contracts. So 
in this

particular case, the out contract should remain.


That's already a hack on top of a hack.


An out contract should apply even when contracts are removed. The 
compiler can treat it as not returning even if contracts are 
removed. But the compiler could in this case leave the contract 
in as a stop gap in case the function does return.


I fact it's fine if it doesn't. It will just be UB.

It's no more of a hack than leaving assert(0) in release code.

-Steve




Re: proposed @noreturn attribute

2017-07-09 Thread Andrei Alexandrescu via Digitalmars-d

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


Re: proposed @noreturn attribute

2017-07-09 Thread Stefan Koch via Digitalmars-d

On Sunday, 9 July 2017 at 18:01:08 UTC, Andrei Alexandrescu 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


Adding a new builtin-type would also be okay.
But a compiler-recognized custom structs is quite costly and 
brings with it a much higher complexity and more importantly a 
higher compile-time cost.


It would also require yet another symbol in object.d which is too 
big as it is.




Re: proposed @noreturn attribute

2017-07-09 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

On 07/08/2017 02:37 PM, Andrei Alexandrescu wrote:

nice touch of bottom (heh)


Where's D's PC-police now?


Re: proposed @noreturn attribute

2017-07-09 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

On 07/08/2017 08:17 AM, Andrei Alexandrescu wrote:

On 7/8/17 6:15 AM, Walter Bright wrote:

Has anyone a better idea? Does anyone want to write a DIP for this?


An attribute is fine. A more PL-minded possibility is to return a 
specific type:


struct None
{
 @disable this();
 @disable this(this);
 @disable @property None init();
}

None ThisFunctionExits();

The compiler detects (without having anything hardwired about the 
particular type "None") that the type None is impossible to create and 
copy/move from a function, and therefore decrees the function will never 
return.


Pro:
- Having the indication "this doesn't return" syntactically be the 
return type makes a lot of sense. I like that a lot. (Though I'd have no 
objection to Walter's original suggestion either).


- It's one less built-in @attribute to scare people away with objections 
of "too many attributes"! (And admittedly, idiomatic D can end up with 
lots of attribtes all over the place.)


Con:
- Inferring that a type is meant to indicate "functions 'returning' this 
do not return", strikes me as very round-about, hackish, unintuitive and 
just unclean.


I really think this is one case where a dedicated compiler-understood 
symbol is not only fully justified but also much cleaner.


That would be my #1 top preference: Your suggestion here, but just make 
"NoReturn" (or whatever it'll be called) a special compiler-understood 
"type", not something inferred from the detailed of a library-provided type.


In any case, I'm definitely onboard with the idea of having SOME 
standard way to tell the compiler "this does not return". That would be 
nice to have.


Re: proposed @noreturn attribute

2017-07-09 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

On 07/09/2017 06:51 AM, Daniel N wrote:

On Sunday, 9 July 2017 at 10:31:47 UTC, Mr.D wrote:

On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright wrote:


Has anyone a better idea?


What about

scope(exit) assert(0);

?


void func()
out { assert(0); }
body
{
}


Too indirect and verbose. An attribute or special "return type" would 
just cut straight to the case.


Re: proposed @noreturn attribute

2017-07-09 Thread Walter Bright via Digitalmars-d

On 7/9/2017 6:13 AM, Andrei Alexandrescu wrote:
We should use typeof(assert(0)) for Bottom. There is precedent - there is no 
name for typeof(null).
I had forgotten about the typeof(null) thing. You're right. But there are some 
issues. What do we do with:


typeof(assert(0))* p;

? What does that mean?


Re: proposed @noreturn attribute

2017-07-09 Thread Walter Bright via Digitalmars-d

On 7/9/2017 6:13 AM, Andrei Alexandrescu wrote:

We should use typeof(assert(0)) for Bottom.


That also leaves the door open for:

alias noreturn = typeof(assert(0));


Re: proposed @noreturn attribute

2017-07-09 Thread Meta via Digitalmars-d

On Sunday, 9 July 2017 at 18:01:08 UTC, Andrei Alexandrescu 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 thought some more about the ramifications of having a Bottom 
type in D. Having a special type like this interacts badly with 
most aspects of D's generic programming capabilities, even on the 
simplest level. At the least we would probably have to create 
special cases everywhere in the compiler and/or libraries that 
check if the type we're working with is the bottom type. A few 
simple cases I can think of off the top of my head:


alias Bottom = typeof(assert(0)); //for convenience

Bottom*  pb; //Must be statically disallowed as this makes no 
sense

Bottom[] ab; //ditto
cast(Bottom)1; //ditto

struct TupleLike(T...)
{
T fields;
}

//What now? Do we allow this type to be instantiated but never 
created,
//as it contains Bottom? Or do we allow it to be instantiated and 
created,
//but the program crashes at runtime when it actually attempts to 
create a

//value of type Bottom?
TupleLike!(string, int, Bottom) t;

//Likewise. Either user code will have to add `if (!is(T == 
Bottom))`

//every time they define a wrapper struct like this, or an error
//would be generated from inside the aggregate the declares a `T 
t`

//member. The former is tedious, the latter defeats the purpose
//of template guards in the first place
alias Bad = Nullable!Bottom;

And I'm sure there are many more.

We could make passing Bottom as a template argument an error, 
which seems reasonable to me (this is the route Rust goes, I 
think). Here's a few good links:


https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#the-never-type--that-never-returns
https://www.reddit.com/r/rust/comments/3j22vx/what_is_the_meaning_of_as_a_return_type/
https://github.com/rust-lang/rfcs/pull/1216

There's a discussion in that Reddit thread about some of the 
advantages/disadvantages of making Bottom a first-class type.


Also a point of interest is that by adding a Bottom type to D and 
with a bit of fiddling we can *almost* implement `assert(0)` in 
library code as opposed to in the compiler:


void assert(T)(lazy T cond, lazy string msg = "")
if (is(typeof(cast(bool)cond))
{
if (is(T == int) && cond == 0))
{
//Compiles recognizes that a value of type Bottom
//is being created and inserts a HLT instruction
//(Or whatever it is that assert(0) does nowadays)
Bottom impossible;
}

if (cond)
return;

if (msg.length)
{
import std.stdio;
stderr.writeln(msg);
}
assert(0);
}

I say almost because there's no way in user code to detect the 
specific form `assert(0)` without making changes to how we call 
it. A user could unintentionally halt the program by doing 
something like `assert(m - n, "m and n should not be the same")`. 
It could be done with templates but it'd break user code:


//`assert(0)` must now be called like `assert!0`
Bottom assert(int n: 0)(lazy string msg = "")
{
if (msg.length)
{
import std.stdio;
stderr.writeln(msg);
}
Bottom impossible;
}


Re: proposed @noreturn attribute

2017-07-09 Thread Stefan Koch via Digitalmars-d

On Sunday, 9 July 2017 at 19:12:45 UTC, Walter Bright wrote:

On 7/9/2017 6:13 AM, Andrei Alexandrescu wrote:
We should use typeof(assert(0)) for Bottom. There is precedent 
- there is no name for typeof(null).
I had forgotten about the typeof(null) thing. You're right. But 
there are some issues. What do we do with:


typeof(assert(0))* p;

? What does that mean?


Not valid.
Cannot take a pointer of typeof(assert(0)).



Re: proposed @noreturn attribute

2017-07-09 Thread Meta via Digitalmars-d

On Sunday, 9 July 2017 at 19:30:25 UTC, Meta wrote:
I thought some more about the ramifications of having a Bottom 
type in D. Having a special type like this interacts badly with 
most aspects of D's generic programming capabilities, even on 
the simplest level. At the least we would probably have to 
create special cases everywhere in the compiler and/or 
libraries that check if the type we're working with is the 
bottom type. A few simple cases I can think of off the top of 
my head:


alias Bottom = typeof(assert(0)); //for convenience

Bottom*  pb; //Must be statically disallowed as this makes no 
sense

Bottom[] ab; //ditto
cast(Bottom)1; //ditto


Another case that we should probably just statically disallow:

alias ImmutableBottom = immutable Bottom; //Ditto for shared, 
const, etc.


This obviously doesn't make any sense anyway.



Re: proposed @noreturn attribute

2017-07-09 Thread Steven Schveighoffer via Digitalmars-d

On Sunday, 9 July 2017 at 18:01:08 UTC, Andrei Alexandrescu 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.


I would argue a type hack in the compiler doesn't compare to the 
principaled use of existing syntax and semantics  ;)


-Steve




Re: proposed @noreturn attribute

2017-07-09 Thread Walter Bright via Digitalmars-d

On 7/9/2017 12:30 PM, Meta wrote:

[...]


Some great info and links. It's a compelling argument to add a bottom type.


Re: proposed @noreturn attribute

2017-07-09 Thread H. S. Teoh via Digitalmars-d
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".


T

-- 
Freedom: (n.) Man's self-given right to be enslaved by his own depravity.


Re: proposed @noreturn attribute

2017-07-09 Thread Walter Bright via Digitalmars-d

On 7/9/2017 1:24 PM, Meta wrote:

Another case that we should probably just statically disallow:

alias ImmutableBottom = immutable Bottom; //Ditto for shared, const, etc.

This obviously doesn't make any sense anyway.




Wouldn't `immutable(Bottom)` simply resolve to `Bottom`?


Re: proposed @noreturn attribute

2017-07-09 Thread Meta via Digitalmars-d

On Sunday, 9 July 2017 at 21:32:31 UTC, Walter Bright wrote:

On 7/9/2017 1:24 PM, Meta wrote:

Another case that we should probably just statically disallow:

alias ImmutableBottom = immutable Bottom; //Ditto for shared, 
const, etc.


This obviously doesn't make any sense anyway.




Wouldn't `immutable(Bottom)` simply resolve to `Bottom`?


I was thinking about that (and in fact, making Bottom a "viral" 
type in the same way that NaN is a viral value), but it's not 
really worth it and we might as well make it an error. It can't 
occur in any template code if we disallow passing Bottom as a 
template argument, e.g., the following would fail:


alias Pointificate(T) = T*;
alias Immutable(T) = immutable T;

//Error: cannot pass Bottom as a template type argument
alias PointerToBottom = Pointificate!Bottom;
alias ImmutableBottom = Immutable!Bottom;

So the only place left where we could make a modified Bottom type 
would be doing `alias Immutable Bottom = immutable Bottom` and 
the like. It doesn't really matter either way, I don't think, but 
we might as well keeps things streamlined and just disallow 
everything to do with Bottom that we don't like. Unless there's a 
compelling reason to be able to apply immutable, shared, etc. to 
Bottom (and I don't see how there can be as you can never have a 
value of type Bottom that could be immutable, shared, etc. 
anyway) we should just disallow it.


Some functional languages do allow you to create things like 
`Either!(T, Bottom)` (from the Reddit thread: "Sometimes you have 
a generic procedure over a sum type and you want to pass it a 
single thing: `Either a Bottom` is isomorphic to a.") but I don't 
see a reason for us to ever need to do that.


Re: proposed @noreturn attribute

2017-07-09 Thread bachmeier via Digitalmars-d
On Sunday, 9 July 2017 at 11:26:27 UTC, Steven Schveighoffer 
wrote:


The one disadvantage, is that -release removes contracts. So in 
this particular case, the out contract should remain.


Doesn't the compiler know about an out contract even with 
-release? I don't understand why -release would prevent the 
relevant information from being passed to the compiler.


Re: proposed @noreturn attribute

2017-07-09 Thread Andrei Alexandrescu via Digitalmars-d

On 07/09/2017 03:12 PM, Walter Bright wrote:

On 7/9/2017 6:13 AM, Andrei Alexandrescu wrote:
We should use typeof(assert(0)) for Bottom. There is precedent - there 
is no name for typeof(null).
I had forgotten about the typeof(null) thing. You're right. But there 
are some issues. What do we do with:


 typeof(assert(0))* p;

? What does that mean?


That would be a pointer that may only be null - a consequence of the 
typeof(assert(0)) being uninstantiable.


Generally I'm not too worried about constructs like typeof(assert(0))[], 
typeof(assert(0))*, use in templates etc - we don't need to "design" 
these cases, their behavior flows from the properties of 
typeof(assert(0)) itself.


Similarly, I don't recall ever there being a problem with typeof(null)*, 
typeof(null)[], people complaining they passed typeof(null) to a 
template where it did bad things, etc.



Andrei


Re: proposed @noreturn attribute

2017-07-09 Thread Andrei Alexandrescu via Digitalmars-d

On 07/09/2017 03:30 PM, Meta wrote:

alias Bottom = typeof(assert(0)); //for convenience


Speaking of which, I think we shouldn't give it a name, same as 
typeof(null). Just keep it typeof(assert(0)). Then wherever it occurs it 
is immediately clear it has a special status requiring a second look 
(which it does). -- Andrei


Re: proposed @noreturn attribute

2017-07-09 Thread Andrei Alexandrescu via Digitalmars-d

On 07/09/2017 06:32 PM, Andrei Alexandrescu wrote:

On 07/09/2017 03:30 PM, Meta wrote:

alias Bottom = typeof(assert(0)); //for convenience


Speaking of which, I think we shouldn't give it a name, same as 
typeof(null). Just keep it typeof(assert(0)). Then wherever it occurs it 
is immediately clear it has a special status requiring a second look 
(which it does). -- Andrei


And btw this is technically a breaking change because somebody somewhere 
is liable to write code like:


void fun()
{
   ...
   return assert(0);
}

I'm not too worried about it though, and in fact we may even still 
accept it because hey typeof(assert(0)) converts to anything so how 
about it even converts to void.



Andrei


Re: proposed @noreturn attribute

2017-07-09 Thread Meta via Digitalmars-d

On Sunday, 9 July 2017 at 22:28:50 UTC, Andrei Alexandrescu wrote:

On 07/09/2017 03:12 PM, Walter Bright wrote:

On 7/9/2017 6:13 AM, Andrei Alexandrescu wrote:
We should use typeof(assert(0)) for Bottom. There is 
precedent - there is no name for typeof(null).
I had forgotten about the typeof(null) thing. You're right. 
But there are some issues. What do we do with:


 typeof(assert(0))* p;

? What does that mean?


That would be a pointer that may only be null - a consequence 
of the typeof(assert(0)) being uninstantiable.


Generally I'm not too worried about constructs like 
typeof(assert(0))[], typeof(assert(0))*, use in templates etc - 
we don't need to "design" these cases, their behavior flows 
from the properties of typeof(assert(0)) itself.


Similarly, I don't recall ever there being a problem with 
typeof(null)*, typeof(null)[], people complaining they passed 
typeof(null) to a template where it did bad things, etc.



Andrei


`typeof(null)` actually has one valid value and doesn't crash the 
program when when you try to create an instance of it. We should 
not treat this the same as `typeof(null)`.


Re: proposed @noreturn attribute

2017-07-09 Thread Andrei Alexandrescu via Digitalmars-d

On 07/09/2017 07:34 PM, Meta wrote:

On Sunday, 9 July 2017 at 22:28:50 UTC, Andrei Alexandrescu wrote:

On 07/09/2017 03:12 PM, Walter Bright wrote:

On 7/9/2017 6:13 AM, Andrei Alexandrescu wrote:
We should use typeof(assert(0)) for Bottom. There is precedent - 
there is no name for typeof(null).
I had forgotten about the typeof(null) thing. You're right. But there 
are some issues. What do we do with:


 typeof(assert(0))* p;

? What does that mean?


That would be a pointer that may only be null - a consequence of the 
typeof(assert(0)) being uninstantiable.


Generally I'm not too worried about constructs like 
typeof(assert(0))[], typeof(assert(0))*, use in templates etc - we 
don't need to "design" these cases, their behavior flows from the 
properties of typeof(assert(0)) itself.


Similarly, I don't recall ever there being a problem with 
typeof(null)*, typeof(null)[], people complaining they passed 
typeof(null) to a template where it did bad things, etc.



Andrei


`typeof(null)` actually has one valid value and doesn't crash the 
program when when you try to create an instance of it. We should not 
treat this the same as `typeof(null)`.


Agreed (with the mention it's not in contradiction with the above). -- 
Andrei


Re: proposed @noreturn attribute

2017-07-09 Thread Walter Bright via Digitalmars-d

Let's call the bottom type 'B' for the moment, for convenience.

If we think of it like a floating point NaN, then any type construction of B 
yields a B:


const(B) -> B
B* -> B
B[] -> B
X[B] -> B
B[X] -> 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);

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

B b; -> assert(0);

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.

struct S {
   T t;
}

should then yield an error, while:

struct S {
   T[1..1] t; // t is of type X
}

would not.


Re: proposed @noreturn attribute

2017-07-09 Thread Nick Sabalausky (Abscissa) via Digitalmars-d

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.


Re: proposed @noreturn attribute

2017-07-09 Thread Nicholas Wilson via Digitalmars-d
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.


Re: proposed @noreturn attribute

2017-07-10 Thread Olivier FAURE via Digitalmars-d

On Sunday, 9 July 2017 at 19:14:37 UTC, Walter Bright wrote:

On 7/9/2017 6:13 AM, Andrei Alexandrescu wrote:

We should use typeof(assert(0)) for Bottom.


That also leaves the door open for:

alias noreturn = typeof(assert(0));


I would really prefer noreturn (or noreturn_t) to be the default 
appellation for such a type. typeof(assert(0)) is way uglier, 
while noreturn is a lot more intuitive and explicit.


Re: proposed @noreturn attribute

2017-07-10 Thread Steven Schveighoffer via Digitalmars-d

On 7/10/17 12:02 AM, Nicholas Wilson wrote:

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.


I'm pretty much giving up on arguing in this thread, as it seems people 
are really keen to add more bloat to the language in spite of the 
obvious bloat-free solution.


But I have to ask, what is the benefit of statically determining that a 
function is noreturn? I thought it was just a hint to the compiler that 
some optimizations can be done for that call?


-Steve


Re: proposed @noreturn attribute

2017-07-10 Thread Jacob Carlborg via Digitalmars-d

On 2017-07-09 23:14, H. S. Teoh via Digitalmars-d wrote:


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. 


I highly doubt that the compiler does not need to be changed at all to 
get the wanted behavior.


It that case it's just as easy to add a compiler recognized UDA. It 
doesn't add any more baggage than "out{ assert(0); }".


With that said, I don't care that much at all and I'm questioning how 
useful this feature is to have at all.


--
/Jacob Carlborg


Re: proposed @noreturn attribute

2017-07-10 Thread Meta via Digitalmars-d
On Monday, 10 July 2017 at 00:34:54 UTC, Andrei Alexandrescu 
wrote:
`typeof(null)` actually has one valid value and doesn't crash 
the program when when you try to create an instance of it. We 
should not treat this the same as `typeof(null)`.


Agreed (with the mention it's not in contradiction with the 
above). -- Andrei


That was in response to:

Similarly, I don't recall ever there being a problem with 
typeof(null)*, typeof(null)[], people complaining they passed 
typeof(null) to a template where it did bad things, etc.


My point was that I don't agree with the analogy as there really 
isn't any similarity between typeof(assert(0)) and typeof(null). 
There are no problems with stuff like typeof(null)* etc. because 
for the most part it's just a regular type, unlike Bottom. 
Although now that you mention it, there might be some interesting 
uses for a pointer/array that we statically know can only be null 
(none that I can think of OTOH though).


I still think we should err on the side of disabling stuff like 
`immutable Bottom`, `Bottom*`, `Nullable!Bottom`, etc. until we 
fully understand the ramifications. We also cannot allow 
struct/class members of the type Bottom for obvious reasons. 
Interestingly enough, unions would conceptually be okay, and you 
would statically know that a union such as `union IntOrBottom { 
int n; Bottom b; }` can only ever contain an int. Therefore, 
IntOrBottom could safely be aliased away to just int (syntactic 
differences between working with a union vs. working with an int 
aside).


We also need to disallow `enum Sneaky: Bottom { val }` and `enum: 
Bottom { val }`. I don't know how enums are implemented in the 
compiler so it may be a non-issue. `enum Okay: Bottom {}` is fine 
and Okay could just alias itself away (but we should still 
disable it to prevent confusion). `enum: Bottom {}` makes no 
sense so we should prevent that as well.


Re: proposed @noreturn attribute

2017-07-10 Thread H. S. Teoh via Digitalmars-d
On Mon, Jul 10, 2017 at 03:47:35PM +0200, Jacob Carlborg via Digitalmars-d 
wrote:
> On 2017-07-09 23:14, H. S. Teoh via Digitalmars-d wrote:
> 
> > 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.
> 
> I highly doubt that the compiler does not need to be changed at all to
> get the wanted behavior.

I did not say the compiler does not need to be changed. I said the
*language* does not need to be changed.


> It that case it's just as easy to add a compiler recognized UDA. It
> doesn't add any more baggage than "out{ assert(0); }".
> 
> With that said, I don't care that much at all and I'm questioning how
> useful this feature is to have at all.
[...]

As is usual around here, things of marginal consequence receive the most
attention and energy spent in debating every last nitpick. Sigh.


T

-- 
Unix was not designed to stop people from doing stupid things, because that 
would also stop them from doing clever things. -- Doug Gwyn


Re: proposed @noreturn attribute

2017-07-10 Thread H. S. Teoh via Digitalmars-d
On Sun, Jul 09, 2017 at 02:49:35PM -0400, Nick Sabalausky (Abscissa) via 
Digitalmars-d wrote:
> On 07/09/2017 06:51 AM, Daniel N wrote:
> > On Sunday, 9 July 2017 at 10:31:47 UTC, Mr.D wrote:
> > > On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright wrote:
> > > 
> > > > Has anyone a better idea?
> > > 
> > > What about
> > > 
> > > scope(exit) assert(0);
> > > 
> > > ?
> > 
> > void func()
> > out { assert(0); }
> > body
> > {
> > }
> 
> Too indirect and verbose. An attribute or special "return type" would
> just cut straight to the case.

If DIP 1009 is accepted, this would not be verbose at all:

void func()
out(false) // it even tells you it won't return
{
...
}

Plus, this has the advantage that you can specify a valid return type
for when you need to override a base class method, e.g.:

class JitCompiler {
Code compile(string code);
}
class InvalidCompiler : JitCompiler {
override Code compile(string code) out(false) {...}
}

A Bottom type that implicitly converts to anything would also fit the
bill, granted, but does require changing the language.

The main thing I have against adding a Bottom type is that it adds yet
another built-in type to the language, which means (1) a combinatorial
explosion of existing language constructs combined with the new type,
with currently-unknown consequences (and possibly corner cases we
haven't thought of that will come back to bite us), (2) yet another
special type newcomers have to learn with special semantics (I can
already anticipate complaints to D.learn about what's the difference
between null and bottom); (3) having to implement lots of compiler
changes to handle how this new type interacts with operators and other
types in all possible cases; (4) all of this just for something that (a)
is only rarely used, and (b) could have been easily implemented by
adding @noreturn or using existing contract syntax without adding a
whole new basic type to the language.

Honestly, I'd vote for @noreturn as the simplest, most straightforward
solution, and the only reason I'm arguing for out{assert(0);} (or
out(false) if DIP 1009 is accepted) is because people are all up in arms
about adding Gosh Yet Another Special UDA In Addition To The Numerous
Special UDAs We Already Have Like @safe and @nogc.


T

-- 
The diminished 7th chord is the most flexible and fear-instilling chord. Use it 
often, use it unsparingly, to subdue your listeners into submission!


Re: proposed @noreturn attribute

2017-07-10 Thread Walter Bright via Digitalmars-d

On 7/10/2017 4:00 AM, Steven Schveighoffer wrote:
But I have to ask, what is the benefit of statically determining that a function 
is noreturn?


It is useful anywhere dataflow analysis is useful.

   FunctionThatDoesnotReturn();
   a = b; // error: unreachable code


Re: proposed @noreturn attribute

2017-07-10 Thread Steven Schveighoffer via Digitalmars-d

On 7/10/17 2:38 PM, Walter Bright wrote:

On 7/10/2017 4:00 AM, Steven Schveighoffer wrote:
But I have to ask, what is the benefit of statically determining that 
a function is noreturn?


It is useful anywhere dataflow analysis is useful.

FunctionThatDoesnotReturn();
a = b; // error: unreachable code


That doesn't require static introspection. The compiler can see that, 
the user doesn't have to worry about it.


Note, one thing that hasn't been mentioned is how we are now going to be 
able to make regular functions noreturn. This means templates that 
accept aliases will now have to deal with the possibility that those 
aliases are noreturn.


So if the compiler, for instance, marks the above as an error, what 
happens here?


foo(alias f)()
{
   f();
   auto a = b;
}

if f is a noreturn function, is this instantiation an error? That's 
going to get messy. It's not a problem today, because you can't alias 
`assert`, and the compiler doesn't care about other functions that don't 
return (even if they are completely available).


I learned the hard way with inout not to proactively make obvious errors 
errors. For instance, you can't return inout if you don't have any inout 
parameters. It makes complete logical sense when you think about it, 
just use const. This leads to the (inout int = 0) crap we see everywhere 
in phobos.


-Steve


Re: proposed @noreturn attribute

2017-07-10 Thread Jacob Carlborg via Digitalmars-d

On 2017-07-08 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.


I'm going to ask the stupid question: I understand that this is for the 
compiler to generate better code. But, since the attribute (or whatever 
it is) indicates that a function won't return, it can only be used in 
very few cases. Are those few cases worth optimizing for?


--
/Jacob Carlborg


Re: proposed @noreturn attribute

2017-07-10 Thread Meta via Digitalmars-d
On Monday, 10 July 2017 at 18:50:54 UTC, Steven Schveighoffer 
wrote:

On 7/10/17 2:38 PM, Walter Bright wrote:

On 7/10/2017 4:00 AM, Steven Schveighoffer wrote:
But I have to ask, what is the benefit of statically 
determining that a function is noreturn?


It is useful anywhere dataflow analysis is useful.

FunctionThatDoesnotReturn();
a = b; // error: unreachable code


That doesn't require static introspection. The compiler can see 
that, the user doesn't have to worry about it.


Note, one thing that hasn't been mentioned is how we are now 
going to be able to make regular functions noreturn. This means 
templates that accept aliases will now have to deal with the 
possibility that those aliases are noreturn.


So if the compiler, for instance, marks the above as an error, 
what happens here?


foo(alias f)()
{
   f();
   auto a = b;
}

if f is a noreturn function, is this instantiation an error?


Currently not. This is either a bug or the compiler's flow 
analysis is not robust enough to detect this case.


int b;

auto foo(alias f)()
{
f();
auto a = b; //no unreachable code error
}

void main()
{
foo!(() => assert(0))();
}




Re: proposed @noreturn attribute

2017-07-10 Thread Patrick Schluter via Digitalmars-d

On Monday, 10 July 2017 at 18:09:54 UTC, H. S. Teoh wrote:
On Sun, Jul 09, 2017 at 02:49:35PM -0400, Nick Sabalausky 
(Abscissa) via Digitalmars-d wrote:

On 07/09/2017 06:51 AM, Daniel N wrote:
> On Sunday, 9 July 2017 at 10:31:47 UTC, Mr.D wrote:
> > On Saturday, 8 July 2017 at 10:15:39 UTC, Walter Bright 
> > wrote:
> > 
> > > Has anyone a better idea?
> > 
> > What about
> > 
> > scope(exit) assert(0);
> > 
> > ?
> 
> void func()

> out { assert(0); }
> body
> {
> }

Too indirect and verbose. An attribute or special "return 
type" would just cut straight to the case.


If DIP 1009 is accepted, this would not be verbose at all:

void func()
out(false) // it even tells you it won't return
{
...
}

Plus, this has the advantage that you can specify a valid 
return type for when you need to override a base class method, 
e.g.:


class JitCompiler {
Code compile(string code);
}
class InvalidCompiler : JitCompiler {
override Code compile(string code) out(false) {...}
}

A Bottom type that implicitly converts to anything would also 
fit the bill, granted, but does require changing the language.


The main thing I have against adding a Bottom type is that it 
adds yet another built-in type to the language, which means (1) 
a combinatorial explosion of existing language constructs 
combined with the new type, with currently-unknown consequences 
(and possibly corner cases we haven't thought of that will come 
back to bite us), (2) yet another special type newcomers have 
to learn with special semantics (I can already anticipate 
complaints to D.learn about what's the difference between null 
and bottom); (3) having to implement lots of compiler changes 
to handle how this new type interacts with operators and other 
types in all possible cases; (4) all of this just for something 
that (a) is only rarely used, and (b) could have been easily 
implemented by adding @noreturn or using existing contract 
syntax without adding a whole new basic type to the language.


Honestly, I'd vote for @noreturn as the simplest, most 
straightforward solution, and the only reason I'm arguing for 
out{assert(0);} (or out(false) if DIP 1009 is accepted) is 
because people are all up in arms about adding Gosh Yet Another 
Special UDA In Addition To The Numerous Special UDAs We Already 
Have Like @safe and @nogc.



+1



Re: proposed @noreturn attribute

2017-07-10 Thread ketmar via Digitalmars-d

Jacob Carlborg wrote:

I'm going to ask the stupid question: I understand that this is for the 
compiler to generate better code. But, since the attribute (or whatever 
it is) indicates that a function won't return, it can only be used in 
very few cases. Are those few cases worth optimizing for?


the case that makes @noreturn worth having is even not optimizing, but 
don't adding visual noise at the call site.


case Smth: error("boo");
case Other: ...

oops. i know that `error()` will never return, but compiler doesn't, and 
insisting on adding `break;` there.


sure, i can either put break, or always put `assert(0);` after noreturn 
functions, but hey, aren't we invented computers exactly to lay off such 
borning things onto them!? ;-)


Re: proposed @noreturn attribute

2017-07-10 Thread Walter Bright via Digitalmars-d

On 7/10/2017 12:05 PM, Meta wrote:
Currently not. This is either a bug or the compiler's flow analysis is not 
robust enough to detect this case.


Flow analysis relies on the function's signature, not its implementation, and 
currently the signature contains no information about noreturn.


Addressing this is the whole point of this thread.


Re: proposed @noreturn attribute

2017-07-10 Thread Steven Schveighoffer via Digitalmars-d

On 7/10/17 3:05 PM, Meta wrote:

On Monday, 10 July 2017 at 18:50:54 UTC, Steven Schveighoffer wrote:

On 7/10/17 2:38 PM, Walter Bright wrote:

On 7/10/2017 4:00 AM, Steven Schveighoffer wrote:
But I have to ask, what is the benefit of statically determining 
that a function is noreturn?


It is useful anywhere dataflow analysis is useful.

FunctionThatDoesnotReturn();
a = b; // error: unreachable code


That doesn't require static introspection. The compiler can see that, 
the user doesn't have to worry about it.


Note, one thing that hasn't been mentioned is how we are now going to 
be able to make regular functions noreturn. This means templates that 
accept aliases will now have to deal with the possibility that those 
aliases are noreturn.


So if the compiler, for instance, marks the above as an error, what 
happens here?


foo(alias f)()
{
   f();
   auto a = b;
}

if f is a noreturn function, is this instantiation an error?


Currently not. This is either a bug or the compiler's flow analysis is 
not robust enough to detect this case.


I think the implication from Walter is that f would be treated just like 
a direct call to assert(0) (i.e. it doesn't return).


So where code like this produces an "unreachable statement" error:

void foo()
{
   assert(0);
   auto a = b;
}

with dmd -w, code like the above will potentially produce an unreachable 
code error if f is a noreturn (the compiler can now do dataflow analysis 
and determine it's unreachable).


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


Re: proposed @noreturn attribute

2017-07-10 Thread Walter Bright via Digitalmars-d

On 7/10/2017 12:02 PM, Jacob Carlborg wrote:

Are those few cases worth optimizing for?


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



Re: proposed @noreturn attribute

2017-07-10 Thread Marco Leise via Digitalmars-d
Am Sat, 8 Jul 2017 03:15:39 -0700
schrieb Walter Bright :

> […]
>
> 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



Re: proposed @noreturn attribute

2017-07-10 Thread Jacob Carlborg via Digitalmars-d

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


Re: proposed @noreturn attribute

2017-07-11 Thread Iain Buclaw via Digitalmars-d
On 11 July 2017 at 08:46, Jacob Carlborg via Digitalmars-d
 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.


Re: proposed @noreturn attribute

2017-07-11 Thread Rainer Schuetze via Digitalmars-d



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?


Re: proposed @noreturn attribute

2017-07-11 Thread Jacob Carlborg via Digitalmars-d

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


Re: proposed @noreturn attribute

2017-07-11 Thread Timon Gehr via Digitalmars-d

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.


Re: proposed @noreturn attribute

2017-07-11 Thread Timon Gehr via Digitalmars-d

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].


Re: proposed @noreturn attribute

2017-07-11 Thread Meta via Digitalmars-d

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.


Re: proposed @noreturn attribute

2017-07-11 Thread Meta via Digitalmars-d
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?


Re: proposed @noreturn attribute

2017-07-11 Thread Random D user via Digitalmars-d
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 :|


  1   2   >