bottom type as parameter or local variable, does that make sense?

Steven Schveighoffer schveiguy at gmail.com
Fri Jan 14 18:49:26 UTC 2022


On 1/14/22 6:52 AM, WebFreak001 wrote:
> For example:
> ```d
> import std.stdio;
> 
> void foo(noreturn a)
> {
>      writeln("we got called!");
> }
> 
> void bar()
> {
>      noreturn b;
>      writeln("calling");
>      foo(b);
> }
> 
> void main()
> {
>      writeln("bar");
>      bar();
>      writeln("done");
> }
> ```
> 
> Guess what it prints and reply to it on this thread. I think the result 
> is pretty nonsensical.
> 
> Reveal: https://run.dlang.io/is/4SXQal
> 
> Should this usage be allowed? I would say not allowing it would make 
> more sense.
> 
> Additionally if we don't allow it we could allow aliasing to it like:
> 
> ```d
> deprecated("OldType is no longer supported, use NewType instead") alias 
> OldType = noreturn;
> ```
> 
> and with that both add hint messages for users to migrate and not allow 
> broken code to compile.
> 
> A sample for this would be libdparse, where the arguments of the visit 
> functions determine which function is called, even if the argument isn't 
> actually used or just ignored. The cases where the argument type is 
> specified, but not used, do happen and migrating types there to force 
> the user to rewrite code is currently not possible without completely 
> removing the type.

I have several thoughts here:

1. I can't find `noreturn` in the spec, so I'm not sure what exactly 
should happen here. In the library it has very very sparse 
documentation. This needs correction. At a minimum, it should go into 
[the Types page](https://dlang.org/spec/type.html).

2. The DIP clearly states that:

    Defining a variable with type noreturn with an initialization 
expression will simply generate that expression as soon as it becomes 
live. Defining a noreturn variable with no initialization expression 
generates an assert(0) only if the variable is accessed, which can be 
useful in generic code where unused noreturn variables may be declared. 
Generating the assert(0) as soon as the variable is live in these cases 
could prematurely end the program.

So if the DIP is implemented as defined, the code in question is not 
assigning an initial value, and if it did, it should generate an assert. 
BUT, it's clearly being used, which means the call to `foo(b)` should be 
the equivalent of `foo(assert(0))`.

3. I wonder if there's some kind of dead-store optimization happening to 
thwart the error?

-Steve


More information about the Digitalmars-d mailing list