digitalmars.D - Discussion Thread: DIP 1034--Add a Bottom Type (reboot)--Community
- Mike Parker (21/21) May 06 2020 This is the discussion thread for the first round of Community
- Mike Parker (3/8) May 06 2020 The feedback thread is located here:
- Panke (3/6) May 06 2020 I think this is one the best written DIPs I've seen in while
- jmh530 (2/5) May 06 2020 I had the same thought as well.
- Patrick Schluter (5/8) May 06 2020 Love it!
- Paul Backus (14/20) May 06 2020 In one of the examples, it is asserted that there is no way to
- Meta (7/7) May 06 2020 noreturn x0; // compile error, must have bottom value
- Dennis (6/13) May 06 2020 The bottom one gives a compile error today.
- Meta (46/59) May 06 2020 The problem is that these require special cases in generic code.
- Dennis (15/21) May 06 2020 It doesn't compile today, as it would be instantiated with a
- Johannes Loher (47/49) May 06 2020 Thats exactly how it should be done. From my point of view, there is no
- Johannes Loher (11/12) May 06 2020 After writing this, I just realized another thing: At the moment, it is
- Dennis (2/4) May 07 2020 I think so.
- Walter Bright (7/11) May 06 2020 Thank you, Dennis, for a well-written DIP, and fixing #DIP1017. Maybe yo...
- Dennis (16/22) May 07 2020 Glad to hear that. I have some other things (such as dmd bugs and
- wolframw (45/46) May 07 2020 Even though it's not a systems programming language, Scala could
- Walter Bright (2/13) May 07 2020 Actually, I think that link would be enough.
- Jonathan Marler (2/4) May 13 2020 Thanks for this Dennis! You're doing the Lord's work :)
- Petar Kirov [ZombineDev] (6/10) Jun 05 2020 I think it's good to consider how UFCS would interact with the
This is the discussion thread for the first round of Community Review of DIP 1034, "Add a Bottom Type (reboot)": https://github.com/dlang/DIPs/blob/15081980cd393e21218da6836321ed37ebc48dd3/DIPs/DIP1034.md The review period will end at 11:59 PM ET on May 20, or when I make a post declaring it complete. Discussion in this thread may continue beyond that point. Here in the discussion thread, you are free to discuss anything and everything related to the DIP. Express your support or opposition, debate alternatives, argue the merits, etc. However, if you have any specific feedback on how to improve the proposal itself, then please post it in the feedback thread. The feedback thread will be the source for the review summary I write at the end of this review round. I will post a link to that thread immediately following this post. Just be sure to read and understand the Reviewer Guidelines before posting there: https://github.com/dlang/DIPs/blob/master/docs/guidelines-reviewers.md And my blog post on the difference between the Discussion and Feedback threads: https://dlang.org/blog/2020/01/26/dip-reviews-discussion-vs-feedback/ Please stay on topic here. I will delete posts that are completely off-topic.
May 06 2020
On Wednesday, 6 May 2020 at 11:04:06 UTC, Mike Parker wrote:However, if you have any specific feedback on how to improve the proposal itself, then please post it in the feedback thread. The feedback thread will be the source for the review summary I write at the end of this review round. I will post a link to that thread immediately following this post.The feedback thread is located here: https://forum.dlang.org/post/arcpszmdarekxtnsnwfl forum.dlang.org
May 06 2020
On Wednesday, 6 May 2020 at 11:04:06 UTC, Mike Parker wrote:This is the discussion thread for the first round of Community Review of DIP 1034, "Add a Bottom Type (reboot)": [...]I think this is one the best written DIPs I've seen in while independent from the changes it discusses.
May 06 2020
On Wednesday, 6 May 2020 at 14:21:43 UTC, Panke wrote:[snip] I think this is one the best written DIPs I've seen in while independent from the changes it discusses.I had the same thought as well.
May 06 2020
On Wednesday, 6 May 2020 at 11:04:06 UTC, Mike Parker wrote:This is the discussion thread for the first round of Community Review of DIP 1034, "Add a Bottom Type (reboot)": [...]Love it! There was no point in DIP-1017 but this one makes an excellent case for the bottom type and explains it well enough that even dummies like me understand it.
May 06 2020
On Wednesday, 6 May 2020 at 11:04:06 UTC, Mike Parker wrote:This is the discussion thread for the first round of Community Review of DIP 1034, "Add a Bottom Type (reboot)": https://github.com/dlang/DIPs/blob/15081980cd393e21218da6836321ed37ebc48dd3/DIPs/DIP1034.mdIn one of the examples, it is asserted that there is no way to use `assert(0)` in a switch-like higher-order function that uses lambdas for its cases (such as sumtype's `match`).In a switch statement, it is possible to add a case default: assert(0);. This is not possible when using lambda-handlers to simulate a switch, like the sumtype package does:This is not strictly true. It can be done by specifying the return type of the `assert(0)` lambda explicitly, rather than relying on type inference: int round(Var v) { return v.match!( (int x) => return x, (double x) => return cast(int) x, function int (other) { assert(0); } // compiles ); }
May 06 2020
noreturn x0; // compile error, must have bottom value noreturn[1] x4; // compile error, init value is [assert(0)] struct S {int x; noreturn y;} // definition is fine S x5; // compile error, must have bottom value enum E : noreturn {x = assert(0), y = assert(0)} E e; // compile error, must have bottom value Why are these defined to cause a compile error?
May 06 2020
On Wednesday, 6 May 2020 at 16:22:48 UTC, Meta wrote:Why are these defined to cause a compile error?My reasoning is that the following are all equivalent:noreturn x; noreturn x = noreturn.init; noreturn x = assert(0); auto x = assert(0); auto x = () {assert(0);} ();The bottom one gives a compile error today.Error: `assert(0)` failedI don't intend to change that. (This comparison with errors during CTFE is also mentioned in "Interaction with other language features" by the way).
May 06 2020
On Wednesday, 6 May 2020 at 16:39:30 UTC, Dennis wrote:On Wednesday, 6 May 2020 at 16:22:48 UTC, Meta wrote:The problem is that these require special cases in generic code. If these common cases cause compile errors, then every template will either have to have a `if (!is(T == noreturn))`, or allow itself to fail (possibly deep inside a stack of instantiated templates). std.algorithm.group, for example, returns a Group struct, defined as follows: struct Group(alias pred, R) if (isInputRange!R) { import std.typecons : Rebindable, tuple, Tuple; private alias E = ElementType!R; static if ((is(E == class) || is(E == interface)) && (is(E == const) || is(E == immutable))) { private alias MutableE = Rebindable!E; } else static if (is(E : Unqual!E)) { private alias MutableE = Unqual!E; } else { private alias MutableE = E; } private R _input; private Tuple!(MutableE, uint) _current; ... } But if R is noreturn[], then this becomes: struct Group(alias pred, R) if (isInputRange!R) { private noreturn[] _input; private Tuple!(noreturn, uint) _current; } And because Tuple is itself a struct, and Tuple!(noreturn, uint) has a field of type noreturn, the following code will fail to compile: [].group() With a confusing error message inside Tuple. Maybe this is not a realistic scenario, but I think it should at least be considered that this will cause code that previously seemed fairly innocuous to now fail to compile, for a reason that may not be obvious.Why are these defined to cause a compile error?My reasoning is that the following are all equivalent:noreturn x; noreturn x = noreturn.init; noreturn x = assert(0); auto x = assert(0); auto x = () {assert(0);} ();The bottom one gives a compile error today.Error: `assert(0)` failedI don't intend to change that. (This comparison with errors during CTFE is also mentioned in "Interaction with other language features" by the way).
May 06 2020
On Wednesday, 6 May 2020 at 17:03:56 UTC, Meta wrote:Maybe this is not a realistic scenario, but I think it should at least be considered that this will cause code that previously seemed fairly innocuous to now fail to compile, for a reason that may not be obvious.It doesn't compile today, as it would be instantiated with a void[]: ``` import std; void main() {writeln([].group());} ```instance std.algorithm.iteration.Group!("a == b", void[]) does not match template declaration ...You do raise a very good point though, I don't want to introduce a lot of `static if (is(T == noreturn[]))` to make range algorithms work with []. I'm considering changing it so that local noreturn variables give an error on usage instead of initialization. I need think about the implications of that though. I'll try to make a prototype implementation before final review and see if I can make [] work with range functions in Phobos.
May 06 2020
Am 06.05.20 um 21:07 schrieb Dennis:I'm considering changing it so that local noreturn variables give an error on usage instead of initialization.Thats exactly how it should be done. From my point of view, there is no reason why declaring a variable of type noreturn should assert(0). Only accessing it should do that, at least for local variables. For example consider the following code: auto fun(alias f)() { alias Type = ReturnType!f; Type ret; ret = f(); /* do something with ret */ } noreturn throwingFunction() { throw new Exception("foobar"); } noreturn nonReturningFunction() { for(;;){} } void main() { try { fun!(nonReturningFunction)(); // should throw Exception("foobar") } catch(Exception e) { // silently ignore it } fun!(nonReturningFunction)(); // should loop forever } I am not 100% sure about the implications for global variables, but if global variables of type noreturn are initialized explicitly, it will be a compile error because it will either be an infinite loop at compile time or throw an exception at compile time (I guess there are also some other situations, like failed asserts in betterC, but they also are compile errors). If the variable is not initialized explicitly, I don't see any issue with it compiling. However, as soon as the variable is accessed at runtime, it must assert(0). H.S. Theo and me had a long discussion about this stuff in one of the review threads for DIP1017 and if I remember correctly we basically agreed that this should be the behavior. The main reasoning was that this way we can avoid special cases in generic code and there is no reason not to do it that way, it's just natural. It would be a weird special case to disallow declaring variables of any type (you apply the same reasoning to void in the DIP for making void a proper unit type and I wholeheartedly agree!). However I don't remember if we considered global variables. Aside from that: I really love this DIP, I was looking forward to it since I noticed you were working on it! It (and also the void DIP) would make D's type system feel much more natural. Thanks for your work!
May 06 2020
Am 06.05.20 um 23:07 schrieb Johannes Loher:...After writing this, I just realized another thing: At the moment, it is required that the main function is declared using one of the following forms: void main() { ... } void main(string[] args) { ... } int main() { ... } int main(string[] args) { ... } (https://dlang.org/spec/function.html#main) With this DIP, might it make sense to also allow noreturn as a return type for main, just for consistency?
May 06 2020
On Wednesday, 6 May 2020 at 21:44:17 UTC, Johannes Loher wrote:With this DIP, might it make sense to also allow noreturn as a return type for main, just for consistency?I think so.
May 07 2020
On 5/6/2020 4:04 AM, Mike Parker wrote:This is the discussion thread for the first round of Community Review of DIP 1034, "Add a Bottom Type (reboot)": https://github.com/dlang/DIPs/blob/15081980cd393e21218da6836321ed37ebc4 dd3/DIPs/DIP1034.mdThank you, Dennis, for a well-written DIP, and fixing #DIP1017. Maybe you can take a stab at improving the D spec prose, too? * Mangling: prefer to stick with alpha_numeric characters for mangling. It doesn't need to be short, as I expect it to be rare * Mention the conversion level, should be "convert". * For comparisons, I'd use a more popular language than zig.
May 06 2020
On Wednesday, 6 May 2020 at 22:26:13 UTC, Walter Bright wrote:Thank you, Dennis, for a well-written DIP, and fixing #DIP1017. Maybe you can take a stab at improving the D spec prose, too?Glad to hear that. I have some other things (such as dmd bugs and prototype DIP implementations) I like to work on before looking at the D specification, but maybe I can find some time for it.* Mangling: prefer to stick with alpha_numeric characters for mangling. It doesn't need to be short, as I expect it to be rareAgreed.* Mention the conversion level, should be "convert".Will do.* For comparisons, I'd use a more popular language than zig.While Zig is young, from what I've seen it's gaining traction. More importantly, it has overlapping goals with D (systems programming language, fix C's mistakes). That makes their design decisions more interesting to me than e.g. TypeScript or Python even though those are more popular. The only other systems programming language that I know of that has a bottom type is Rust, which I already included in the DIP. Do you have a particular language you'd like to see compared? For reference: https://en.wikipedia.org/wiki/Bottom_type#In_programming_languages
May 07 2020
On Thursday, 7 May 2020 at 13:45:41 UTC, Dennis wrote:Do you have a particular language you'd like to see compared?Even though it's not a systems programming language, Scala could be a good example. Scala has a notoriously strict and sophisticated type system that is very much inspired by type theory: There is a top type called "Any" (which is a supertype of every other type), a bottom type called "Nothing" (which is a subtype of every other type), and void type is referred to as "Unit". (see [1] for a diagram of Scala's type system) In Scala, "Nothing" is a non-instantiable type that is used for anything that doesn't return. Conceptually it appears to be very similar to what is envisioned in the DIP. Here are a few "Nothing" examples: val foo = throw new Exception(); // compiles; `foo` will have type `Nothing` // `foo` will never be assigned to def bar(n: Int): String = { n match { case 1 => "one" case 2 => "two" // note that even though the return type is `String`, the following is // valid because `Nothing` is a subtype of `String` (and every other type) case _ => throw new Exception() // `case _` is equivalent to `default` in D // alternatively, `assert(false)` would give a similar result // `case _ => Nothing` would NOT work because `Nothing` is non-instantiable } } val baz = () => throw new Exception() // type of baz is Function0[Nothing] // meaning: a nullary function that returns `Nothing` (i.e. doesn't return at all) As one would expect, the Scala standard library uses "Nothing" as the return type of its exit and error functions: see [2] (notice the hack in exit: Since Java's System.exit returns void -- or "Unit" in Scala lingo -- the exit function throws, just so its return type can be "Nothing") [1] https://docs.scala-lang.org/resources/images/tour/unified-types-diagram.svg [2] https://github.com/scala/scala/blob/2.13.x/src/library/scala/sys/package.scala#L22
May 07 2020
On 5/7/2020 6:45 AM, Dennis wrote:Actually, I think that link would be enough.* For comparisons, I'd use a more popular language than zig.While Zig is young, from what I've seen it's gaining traction. More importantly, it has overlapping goals with D (systems programming language, fix C's mistakes). That makes their design decisions more interesting to me than e.g. TypeScript or Python even though those are more popular. The only other systems programming language that I know of that has a bottom type is Rust, which I already included in the DIP. Do you have a particular language you'd like to see compared? For reference: https://en.wikipedia.org/wiki/Bottom_type#In_programming_languages
May 07 2020
On Wednesday, 6 May 2020 at 11:04:06 UTC, Mike Parker wrote:This is the discussion thread for the first round of Community Review of DIP 1034, "Add a Bottom Type (reboot)":Thanks for this Dennis! You're doing the Lord's work :)
May 13 2020
On Wednesday, 6 May 2020 at 11:04:06 UTC, Mike Parker wrote:[..]I think it's good to consider how UFCS would interact with the bottom type. I just saw that Dart decided that it should not be possible to have extensions (which are similar to UFCS in D) on Never (more precisely that extensions would not apply to Never): https://github.com/dart-lang/language/pull/1003/files#diff-dcbb29985b096645570ae14645f65d53R713For the purposes of extension method resolution, the type `Never` is considered to implement all members, and hence no extension may apply to an expression of type `Never`.
Jun 05 2020