proposed @noreturn attribute
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
On 7/9/2017 3:48 AM, Timon Gehr wrote: It is indeed incorrect, [...] Thanks!
Re: proposed @noreturn attribute
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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 :|