digitalmars.dip.ideas - D Editions
- Atila Neves (2/2) May 30 https://github.com/atilaneves/DIPs/blob/editions/editions.md
- Richard (Rikki) Andrew Cattermole (13/15) May 30 Instead of changing Object I have proposed that we introduce custom
- Atila Neves (5/21) May 30 That would be the `-edition=2024` switch. I don't think the
- bachmeier (5/8) May 30 This is critically important for editions to work, but how would
- Atila Neves (16/24) May 30 In that case `@system` would be the default for the imported
- Steven Schveighoffer (5/6) May 31 You mean `module new_ 2024`?
- Nicholas Wilson (3/5) May 30 minor nit, in the grammar changes it look like `module foo
- Atila Neves (5/11) May 31 I've been through so many versions now that I don't remember what
- Gregor =?UTF-8?B?TcO8Y2ts?= (15/17) May 30 How are editions going to retain compatibility across modules
- Atila Neves (11/29) May 31 Interesting question! Given the interface ABI now
- Jonathan M Davis (13/46) May 31 One crucial element here is that the expectation is that all of the code
- Gregor =?UTF-8?B?TcO8Y2ts?= (6/21) May 31 Defining things that way simplifies matters a lot.
- Jonathan M Davis (29/33) May 31 Mostly, yes, druntime will be kind of stuck. In some cases, we should be
- Adam Wilson (34/39) May 31 As we dig into Phobos 3 this is something that I’ve started to
- Dukc (23/29) Jun 02 Yes, I agree this is something we need to decide. I also agree that
- Adam Wilson (40/65) Jun 02 I'm writing a longer post on this subject. But the TL;DR is that
- Steven Schveighoffer (40/64) Jun 02 This is not correct. DRT is the library side of the compiler
- Richard (Rikki) Andrew Cattermole (14/14) Jun 02 I've gone through this with Adam already.
- Adam Wilson (7/8) Jun 05 On Monday, 3 June 2024 at 02:36:08 UTC, Steven Schveighoffer
- Meta (2/6) May 31 Including mixin templates?
- Atila Neves (5/13) May 31 Yes, they were written with that edition in mind, and the
- Dukc (47/50) May 31 I suggest a different syntax. I think it should be something that would
- Atila Neves (5/16) May 31 I don't think this is a good idea, it splits the language into
- Steven Schveighoffer (12/14) May 31 Unsaid in this, but something that went into the design decisions
- Atila Neves (5/17) Jun 03 Yes.
- Timon Gehr (13/16) Jun 01 - How do you compile different modules with different editions on the
- Steven Schveighoffer (29/46) Jun 01 I'm not the author of the proposal, but I have thoughts on how to
- Timon Gehr (15/76) Jun 06 The whole point is not having to edit modules that were written by
- Atila Neves (8/25) Jun 03 If they all have module declarations, it's handled there,
- Dukc (6/13) Jun 04 This doesn't work, except for mixins. A version block will be turned on
- Timon Gehr (14/46) Jun 06 A lot of code will be written against the default edition and then
- Steven Schveighoffer (7/13) Jun 01 It should be specified how this would work. Is it something like
- Quirin Schroll (10/11) Jun 03 It looks like Editions are intended to be (Gregorian) years. If
- Atila Neves (5/16) Jun 03 I left it open in case we decided to not go with the year of
- Federico (38/40) Jun 05 I hope you will tolerate this unsolicited intrusion of mine, but
- Timon Gehr (16/39) Jun 06 Use the same compiler and it will work. With editions, even using a
- Atila Neves (12/40) Jun 06 There's a "Destroy!" right there, so I can't see how the
- Federico (88/131) Jun 07 Unsolicited because, having abandoned the study of this language,
- Mike Parker (10/11) Jun 07 While your perspective is welcome, this forum is specifically for
- Vladimir Panteleev (17/19) Jun 09 I would just like to comment on one aspect of the DIP for now:
- Atila Neves (5/24) Jun 11 Good questions. Enforce would have to take a delegate, but
- Quirin Schroll (39/68) Jun 12 I don’t see why `assert` would be considered “magic.” On the one
- Quirin Schroll (76/77) Jun 12 One hurdle I can see coming is the following: Writing and
- Quirin Schroll (5/6) Jun 14 The DIP doesn’t mention the addition of new keywords without
- Atila Neves (2/8) Jun 17 I don't think that scales given how many attributes we have.
- Quirin Schroll (9/18) Jun 19 Of the ones I mean, we have four: `@safe`, `nothrow`, `@nogc`,
- Richard (Rikki) Andrew Cattermole (9/9) Jun 20 We're briefly discussing editions on Discord and complexity of
- harakim (5/8) Aug 03 This is a great solution to my problem I proposed above. I should
- harakim (56/65) Aug 03 Editions, as outlined and discussed, will easily solve the most
https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!
May 30
No exceptionsDoesn't need to be an edition, its not an either/or situation.Change class ABI (monitor) and/or hierarchyInstead of changing Object I have proposed that we introduce custom roots. Then people use whatever fits their needs. --- I'm happy to see the change to an integer for editions. I do want to see D2 (version 2) to be defined as missing DIP1000 enforcement. There is missing all of the release scheduling as well as a guarantee of when an edition is made. It shouldn't be done yearly (see languages like It would also be nice to see a work in progress edition which includes all the currently approved preview flags, so that people can get a feel of what the next edition is going to be like (find bugs ext.).
May 30
On Thursday, 30 May 2024 at 18:43:43 UTC, Richard (Rikki) Andrew Cattermole wrote:That would be the `-edition=2024` switch. I don't think the edition needs to be finalised before we introduce the compiler switch.No exceptionsDoesn't need to be an edition, its not an either/or situation.Change class ABI (monitor) and/or hierarchyInstead of changing Object I have proposed that we introduce custom roots. Then people use whatever fits their needs. --- I'm happy to see the change to an integer for editions. I do want to see D2 (version 2) to be defined as missing DIP1000 enforcement. There is missing all of the release scheduling as well as a guarantee of when an edition is made. It shouldn't be done It would also be nice to see a work in progress edition which includes all the currently approved preview flags, so that people can get a feel of what the next edition is going to be like (find bugs ext.).
May 30
On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:The feature is meant to be backwards and forwards compatible: D modules of different editions should be able to import each other.This is critically important for editions to work, but how would it be implemented? Suppose safe becomes the default in the future. How would a module from a recent edition interact with a module from an old edition?
May 30
On Thursday, 30 May 2024 at 19:36:30 UTC, bachmeier wrote:On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:In that case ` system` would be the default for the imported module. There are probably some cases that will be tricky, but I don't think this is one of them. ``` module old; void foo() { } // no annotation so system ``` ``` module(2024) new_; import old; void bar() { // no annotation so safe foo; // ERROR, cannot call ` system` function `foo` in ` safe` function `bar`. } ```The feature is meant to be backwards and forwards compatible: D modules of different editions should be able to import each other.This is critically important for editions to work, but how would it be implemented? Suppose safe becomes the default in the future. How would a module from a recent edition interact with a module from an old edition?
May 30
On Thursday, 30 May 2024 at 21:45:59 UTC, Atila Neves wrote:module(2024) new_;You mean `module new_ 2024`? At least that's what the grammar currently says. I kind of like the above though... -Steve
May 31
On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!minor nit, in the grammar changes it look like `module foo 2024;`, without parentheses, is allowed. Is that intended?
May 30
On Thursday, 30 May 2024 at 23:34:27 UTC, Nicholas Wilson wrote:On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:I've been through so many versions now that I don't remember what I intended :P I generally think that parens are usually visual noise, so maybe this is better?https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!minor nit, in the grammar changes it look like `module foo 2024;`, without parentheses, is allowed. Is that intended?
May 31
On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!How are editions going to retain compatibility across modules with different ABIs? I believe that combinations of inheritance and interface implementations may make this quite challenging. A probably needlessly convoluted example would be this: - a module A, edition 2024, containing a class Foo - a module B, edition 2024+x, containing a class Bar, and - a module C, edition 2024+y, defining an interface IFooBar and two classes FooBar_Foo and FooBar_Bar that derive from Foo and Bar respectively, but implement the IFooBar interface on top of them. Any function that takes a IFooBar should be able to take both implementation interchangeably. But how would this work if there was an ABI change to the class memory layout affecting Foo and Bar?
May 30
On Friday, 31 May 2024 at 00:56:36 UTC, Gregor Mückl wrote:On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:Interesting question! Given the interface ABI now (https://dlang.org/spec/abi.html#interfaces), if we don't change that all of this *should* work. But suppose a future edition changes the ABI for interfaces (unlikely). It would probably be complicated to implement in the compiler, but I can't see any fundamental problems there: we know what module the interface is defined in, so we know what layout to expect for any function taking one. If I'm wrong I'd love if someone educated me. It's much more likely we change the ABI for classes in a future edition though, or the root class.https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!How are editions going to retain compatibility across modules with different ABIs? I believe that combinations of inheritance and interface implementations may make this quite challenging. A probably needlessly convoluted example would be this: - a module A, edition 2024, containing a class Foo - a module B, edition 2024+x, containing a class Bar, and - a module C, edition 2024+y, defining an interface IFooBar and two classes FooBar_Foo and FooBar_Bar that derive from Foo and Bar respectively, but implement the IFooBar interface on top of them. Any function that takes a IFooBar should be able to take both implementation interchangeably. But how would this work if there was an ABI change to the class memory layout affecting Foo and Bar?
May 31
On Friday, May 31, 2024 10:29:54 AM MDT Atila Neves via dip.ideas wrote:On Friday, 31 May 2024 at 00:56:36 UTC, Gregor Mückl wrote:One crucial element here is that the expectation is that all of the code will be built with the same version of the same compiler. We're going for source compatibility, not binary compatibility. So, as long as the compiler is able to compile the code in a fashion that it all works correctly, we're fine regardless of how previous versions of the compiler would have compiled that code. And there is no guarantee of ABI compatibility across compiler versions. So, unless there's something fundamental that changes with an edition where we can't maintain compatibility, we're fine, and the previous discussions on this came to the conclusion that if making a change in an edition was going to make it so that you couldn't have multiple editions interacting together, then we couldn't make that change. - Jonathan M DavisOn Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:Interesting question! Given the interface ABI now (https://dlang.org/spec/abi.html#interfaces), if we don't change that all of this *should* work. But suppose a future edition changes the ABI for interfaces (unlikely). It would probably be complicated to implement in the compiler, but I can't see any fundamental problems there: we know what module the interface is defined in, so we know what layout to expect for any function taking one. If I'm wrong I'd love if someone educated me. It's much more likely we change the ABI for classes in a future edition though, or the root class.https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!How are editions going to retain compatibility across modules with different ABIs? I believe that combinations of inheritance and interface implementations may make this quite challenging. A probably needlessly convoluted example would be this: - a module A, edition 2024, containing a class Foo - a module B, edition 2024+x, containing a class Bar, and - a module C, edition 2024+y, defining an interface IFooBar and two classes FooBar_Foo and FooBar_Bar that derive from Foo and Bar respectively, but implement the IFooBar interface on top of them. Any function that takes a IFooBar should be able to take both implementation interchangeably. But how would this work if there was an ABI change to the class memory layout affecting Foo and Bar?
May 31
On Friday, 31 May 2024 at 16:39:11 UTC, Jonathan M Davis wrote:One crucial element here is that the expectation is that all of the code will be built with the same version of the same compiler. We're going for source compatibility, not binary compatibility. So, as long as the compiler is able to compile the code in a fashion that it all works correctly, we're fine regardless of how previous versions of the compiler would have compiled that code. And there is no guarantee of ABI compatibility across compiler versions. So, unless there's something fundamental that changes with an edition where we can't maintain compatibility, we're fine, and the previous discussions on this came to the conclusion that if making a change in an edition was going to make it so that you couldn't have multiple editions interacting together, then we couldn't make that change. - Jonathan M DavisDefining things that way simplifies matters a lot. This brings me to a follow-up question: how can e.g. druntime evolve in this framework? Its public interface (e.g. the object class) needs to always stay compatible with *all* editions the compiler supports at that time, right?
May 31
On Friday, May 31, 2024 6:30:36 PM MDT Gregor Mückl via dip.ideas wrote:This brings me to a follow-up question: how can e.g. druntime evolve in this framework? Its public interface (e.g. the object class) needs to always stay compatible with *all* editions the compiler supports at that time, right?Mostly, yes, druntime will be kind of stuck. In some cases, we should be able to make compatible changes - e.g. we've discussed putting a new base class under Object so that we can move away from a base class that has functions like opEquals on it and potentially get rid of the monitor; so new code would be able to use the new base class instead, but old code would continue to use Object. However, some changes may not be possible, because we won't be able to do them in a way that doesn't break old Editions (e.g. Object itself will likely maintain its current set of functions). We may also find more creative ways to over time to maintain compatability via compiler tricks (e.g. we could theoretically play games and make it so that Object still had opEquals and friends for older Editions, but they wouldn't be accessible for newer Editions even though they'd technically still be there underneath the hood; I don't think that we're going to do that, but there may be things like that that we do at some point so that the same code will work for multiple Editions while still allowing us to make breaking changes). There's also some possibility that we will eventually start deprecating Editions once they're old enough, which might enable us to make larger changes, but that's not the current plan. And in some cases, we should be able to change functionality by versioning it based on the Edition, but since druntime as a whole will need to be provided as a single library, there will definitely be limitations with that (particularly for code that isn't templated). Fortunately, _most_ stuff shouldn't be limited by that, but even when it is, Editions will still allow us to change a lot more than we can reasonably change right now. So, the situation is not without its downsides, but it should be an improvement overall. - Jonathan M Davis
May 31
On Saturday, 1 June 2024 at 00:30:36 UTC, Gregor Mückl wrote:Defining things that way simplifies matters a lot. This brings me to a follow-up question: how can e.g. druntime evolve in this framework? Its public interface (e.g. the object class) needs to always stay compatible with *all* editions the compiler supports at that time, right?As we dig into Phobos 3 this is something that I’ve started to think about more. Realistically, I think the concept of entirely freezing DRT is simply not practical in the long term. Phobos is going to expand, and DRT will need to expand with it. I can only see pain and ruination if we box ourselves into freezing DRT. Furthermore, before we can address the technical issues, I think we need to agree on whether DRT is part of the Compiler Editions or part of the Phobos Releases. I bring this up because the runtime sits in both camps, the Compiler hooks the runtime and the Library leverages the runtime to access system resources. I have a longer post that I am working on with my thoughts on what we’ll need to address specifically for Phobos 3+. My inclination is to tie DRT to Phobos, and the reason is that *most* of what DRT does is provide access to system resources in a uniform manner for consumption by Phobos. Yes, DRT exposes compiler hook points, but that is a minor portion of what it provides. The bulk of the work that DRT does is in support of the Standard Library, so it should be tied to it. Here are my thoughts on the rules for DRT. From an ABI standpoint, there are only three actions that can be taken: Add, Rename, Remove. 1. Remove: Banned. We cannot remove symbols from the DRT API. But we can rename them provided we follow the rename rules. 2. Rename: Renames include changing the parameters in any way. We can support this by offering either a shim that redirects to the new method or leaving the original method alone and building a new one next to it. 3. Add: The is probably the easiest. New symbols can be added at any time. If we follow these rules then we can safely use the *latest* DRT version with all prior editions. Using the latest version of DRT means that we are free to ship critical fixes and ensure they get into the ecosystem as fast and as broadly as possible.
May 31
Adam Wilson kirjoitti 1.6.2024 klo 7.31:As we dig into Phobos 3 this is something that I’ve started to think about more. Realistically, I think the concept of entirely freezing DRT is simply not practical in the long term. Phobos is going to expand, and DRT will need to expand with it. I can only see pain and ruination if we box ourselves into freezing DRT. [snip]Yes, I agree this is something we need to decide. I also agree that locking DRuntime API isn't a good idea. But, I think it should be updated with the compiler, not with Phobos. DRuntime is essentially language API that is called without special langauge syntax. I think what edition DRuntime uses internally is it's own implementation detail. We should design it so it works with all editions on the client side - just like any widely used library will want to do. There will probably be times when we want to change behaviour based on what edition client code uses. I suggest adding a special token for that, `__EDITION__`. A DRuntime function, (or any D function, really), can use that as a default parameter to figure out what edition the client is using, just like `__FILE__` and `__LINE__` can be used as default parameters for debugging functions. We can use that trick to deprecate old functions. Given any particular edition X, a DRuntime function should be supported indefinitely, but when changing editions in the client module, DRuntime calls may also need revision. This also lets code to call DRuntime functions from other editions if they really want to, which I see as a good thing. This also means Phobos will have easy time using it, since it can pick it's own edition for it's modules and DRuntime will support that to matter the compiler version.
Jun 02
On Sunday, 2 June 2024 at 09:38:54 UTC, Dukc wrote:Yes, I agree this is something we need to decide. I also agree that locking DRuntime API isn't a good idea. But, I think it should be updated with the compiler, not with Phobos. DRuntime is essentially language API that is called without special langauge syntax.I'm writing a longer post on this subject. But the TL;DR is that this view is factually incorrect and is based on an misunderstanding of what DRT is to the ecosystem. Only a tiny fraction of DRT today deals with the compiler (as an API for language). The vast majority of DRT is providing system resources to Phobos. Given that the library-system interface is only going to continue to grow, logic would dictate that tying DRT to the library is the only practical choice. Tying DRT to the compiler forces Phobos to wait for the latest edition to use the latest DRT, which makes no sense given that the vast majority of the work is on the system-interface components and not the compiler-interface. Fun historical note, DRT began as a system-interface library for Tango and only later was it used as a convenient place to put compiler hooks. The commonly held view that DRT primarily exists to serve the compiler is a fascinating confirmation that we've moved past the Tango/Phobos split though.I think what edition DRuntime uses internally is it's own implementation detail. We should design it so it works with all editions on the client side - just like any widely used library will want to do.Technically yes, but in practice, because we can mix-match editions, DRT will always need to support the latest edition. From a practical standpoint you always need to be using the most recent edition that the user code is compiled to, and since Editions are being built as "latest edition by default" that means that by default the latest Runtime and Libraries are going to be used. So might as well just support the latest.There will probably be times when we want to change behaviour based on what edition client code uses. I suggest adding a special token for that, `__EDITION__`. A DRuntime function, (or any D function, really), can use that as a default parameter to figure out what edition the client is using, just like `__FILE__` and `__LINE__` can be used as default parameters for debugging functions. We can use that trick to deprecate old functions.IMO, special tokens are always a horrible solution. In this case because it does not fully solve any of the three ABI scenarios I listed. You still have to follow the Rename rules the moment you need to change the parameter list in any way. All the special token does is allow you to branch on different editions when the code has internal changes, so it solves arguably the least important subset of Edition related problems. Furthermore, once you are forced to change the parameter list you've now create a small number of methods that each contain an opaque number of Edition implementations, which means the consumer now has to mentally juggle which API contains which edition they need.Given any particular edition X, a DRuntime function should be supported indefinitely, but when changing editions in the client module, DRuntime calls may also need revision. This also lets code to call DRuntime functions from other editions if they really want to, which I see as a good thing. This also means Phobos will have easy time using it, since it can pick it's own edition for it's modules and DRuntime will support that to matter the compiler version.Agreed. When designing for the long-term there are very few practical ways to do it, which is why I laid out the process that I did. It's a well established way of handling this problem. We know it works.
Jun 02
On Monday, 3 June 2024 at 00:57:45 UTC, Adam Wilson wrote:On Sunday, 2 June 2024 at 09:38:54 UTC, Dukc wrote:This is not correct. DRT is the library side of the compiler implementation. It does not exist mostly to support phobos. It supplies the implementation of: * AAs * Garbage Collector * Threads and threading primitives (needed for garbage collector support) * static constructors/destructors * TypeInfo and Object * string switch * interpolation expression sequences * varargs * exceptions and stack unwinding These are *very much* tied to the compiler, and do not belong in phobos. Incidentally, it has some pieces that are not compiler hooks or language specific pieces, but are useful to implement the druntime parts, and so they go into druntime because of the dependency direction. It also contains system library bindings, which aren't part of the language, but are useful in both druntime and phobos.Yes, I agree this is something we need to decide. I also agree that locking DRuntime API isn't a good idea. But, I think it should be updated with the compiler, not with Phobos. DRuntime is essentially language API that is called without special langauge syntax.I'm writing a longer post on this subject. But the TL;DR is that this view is factually incorrect and is based on an misunderstanding of what DRT is to the ecosystem. Only a tiny fraction of DRT today deals with the compiler (as an API for language). The vast majority of DRT is providing system resources to Phobos. Given that the library-system interface is only going to continue to grow, logic would dictate that tying DRT to the library is the only practical choice. Tying DRT to the compiler forces Phobos to wait for the latest edition to use the latest DRT, which makes no sense given that the vast majority of the work is on the system-interface components and not the compiler-interface.Fun historical note, DRT began as a system-interface library for Tango and only later was it used as a convenient place to put compiler hooks. The commonly held view that DRT primarily exists to serve the compiler is a fascinating confirmation that we've moved past the Tango/Phobos split though.Tango's language runtime began as "Ares", an alternate to phobos, and was incorporated into Tango. At the time Druntime was split out from Tango, both Tango and Phobos had the language runtime completely contained within their codebases, but the runtimes were incompatible. Druntime was an effort to separate and release a common runtime so both Tango and Phobos libraries could work together. Unfortunately, that possibility never came to fruition as druntime was D2 only, and Tango did not make the move to D2 until much much later (and by then, not many were using it). So in fact, DRuntime is *exactly* an effort to serve just the compiler-needed library hooks as narrowly as possible. Druntime needs to continue to exist as the library implementation of the language. I think it serves a very well-defined separation point, and we should not abandon that. When porting to a new platform, one only needs to port druntime (not a small task), not phobos. -Steve
Jun 02
I've gone through this with Adam already. What he is seeing is related to interdependencies of different aspects to the ecosystem and he is very much correct about this. I saw this myself many years ago. However the terminology and language he uses is different than what we are using so it may appear he is talking wild when in fact it is a matter of recognizing dependencies and putting things in a better place. Ultimately we have a ton of technical debt, the entire TypeInfo hierarchy doesn't have a purpose for example. The GC certainly doesn't need it, it could work 100% with just a by-value struct. Which leads to the interesting discussion of how to handle its removal wrt. editions. My general conclusion there is to use shims that are do-nothing long term but keep code compiling and then deprecate in like 10 years.
Jun 02
On Monday, 3 June 2024 at 02:36:08 UTC, Steven Schveighoffer wrote: ...[snip]-SteveIt was not my intent to hijack this thread, so I've started a new one in general here: https://forum.dlang.org/post/zljtammlddzxjmpfzqsv forum.dlang.org I hope it addresses some of what you mention.
Jun 05
On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!Templates would obey the rules of the edition of the module they are defined in, not the module where they are instantiated.Including mixin templates?
May 31
On Friday, 31 May 2024 at 07:45:50 UTC, Meta wrote:On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:Yes, they were written with that edition in mind, and the compiler knows the module the mixin template is from. String mixins are another matter, though, I don't know if we can do anything about that.https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!Templates would obey the rules of the edition of the module they are defined in, not the module where they are instantiated.Including mixin templates?
May 31
Atila Neves kirjoitti 30.5.2024 klo 21.31:https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!I suggest a different syntax. I think it should be something that would lend itself to enabling/disabling individual features (compiler switches) module-wise. I'm not necessarily arguing we should make our current compiler switches capable of being turned on or off module by module, just that if we decided to to that, we could use the same syntax to do it. Therefore, a decimal without any keywords is probably bad. Version specifications are IMO a good tool for this. Just like the proposed edition declarations, a specification is local to the module. ```D module core.atomic; version = D_2024; /+ If we decided to allow it, this syntax would work for compiler switches (although we'd probably need a version specification for the reverse setting too) +/ version = D_NoBoundsChecks; ``` Another possibility is pragmas. This is what Haskell, or more precisely it's Glasgow compiler does to accomplish the same. I also think it's per-module extension would be well worth putting to "prior work" section (and investigating if you haven't already). Another issue, that doesn't strictly affect the design of this DIP but should be given cosideration as soon as it's used for enabling features selectively. Suppose ` safe` is the default for edition 2026 but the present rules apply for edition 2024. What should happen in this case? ```D #line 1 "modulea.d" module modulea 2024; template T(int i) { // No explicit attributes. // Note, no auto inference, because only eponymous // functions inside a template get auto-inference. int incr(int j) => i + j; } #line 1 "moduleb.d" module moduleb 2026; import modulea; //Defined within edition 2024, but instantiated within edition 2026. // safe or system? //I quess system but I want to read your opinion. alias incr = T!(3).incr; ``` As a whole, I'm highly receptive to this DIP.
May 31
On Friday, 31 May 2024 at 11:21:30 UTC, Dukc wrote:Atila Neves kirjoitti 30.5.2024 klo 21.31:I don't think this is a good idea, it splits the language into 2^N dialects where N is the number of preview switches. The linear progression is a feature of the DIP.[...]I suggest a different syntax. I think it should be something that would lend itself to enabling/disabling individual features (compiler switches) module-wise.Another issue, that doesn't strictly affect the design of this DIP but should be given cosideration as soon as it's used for enabling features selectively. Suppose ` safe` is the default for edition 2026 but the present rules apply for edition 2024. What should happen in this case? [...]system.
May 31
On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!Unsaid in this, but something that went into the design decisions for which versions are the default -- the compiler switches will allow dub to specify a compiler version for an entire package. I think it's pretty good. I think it should specify in the proposal what Jonathan said -- editions are meant to be source compatible. That is, all code is expected to be built with the same compiler, even if not with the same edition. It should also be mentioned that only *one* version of druntime will be included with each compiler, and it will support all editions that compiler supports. -Steve
May 31
On Saturday, 1 June 2024 at 01:57:14 UTC, Steven Schveighoffer wrote:On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:Yes.https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!You mean module new_ 2024?I think it's pretty good. I think it should specify in the proposal what Jonathan said -- editions are meant to be source compatible. That is, all code is expected to be built with the same compiler, even if not with the same edition.Added.It should also be mentioned that only *one* version of druntime will be included with each compiler, and it will support all editions that compiler supports.Also added.
Jun 03
On 5/30/24 20:31, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy- How do you compile different modules with different editions on the same command line? - How would a library expose different interfaces to importers that use different editions? (This may be required because different editions allow different interface designs and guarantees, or have a different user-accessible druntime interface and e.g. druntime types are in the library API.) - How does a newer edition with less ` safe` bugs treat ` safe` code from an older edition that has more memory safety holes? - How do function interfaces work when some type annotations exist in only either the language edition of the caller or the language edition of the callee? E.g. think DIP1000 is in one edition but not in another.
Jun 01
I'm not the author of the proposal, but I have thoughts on how to answer these questions. On Saturday, 1 June 2024 at 21:14:38 UTC, Timon Gehr wrote:On 5/30/24 20:31, Atila Neves wrote:You can attribute a module with the edition you are using to build. I don't know that it makes a whole lot of sense to cater to a case where you are building multiple modules with different editions by specifying command line parameters. Other than that, there is separate compilation (which is supported via the `-E` switch).https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy- How do you compile different modules with different editions on the same command line?- How would a library expose different interfaces to importers that use different editions? (This may be required because different editions allow different interface designs and guarantees, or have a different user-accessible druntime interface and e.g. druntime types are in the library API.)This could be via separate modules. I would anticipate the need for this to be so rare that catering to this case is also not worth the effort.- How does a newer edition with less ` safe` bugs treat ` safe` code from an older edition that has more memory safety holes?A good question. I would approach it from the sense that calling a function must be safe for both sides. So if you called a function with different safety rules, and those rules reduce or compromise the safety of either the caller or the callee, it would have to be a trusted call. Note that in terms of ` safe` *bugs* and not ` safe` *design*, one would assume the safety bugs will be fixed in the newer compiler.- How do function interfaces work when some type annotations exist in only either the language edition of the caller or the language edition of the callee? E.g. think DIP1000 is in one edition but not in another.The type annotations are defined by the language edition for the imported module. So those would be in effect. In other words, this is not like today where you compile one module with dip1000 and another module without, and the compiler blindly assumes all are compiled the same way. This does introduce an interesting wrinkle -- if there are differences, newer editions *must define* the interactions like this between editions as part of the release. -Steve
Jun 01
On 6/2/24 02:39, Steven Schveighoffer wrote:I'm not the author of the proposal, but I have thoughts on how to answer these questions. On Saturday, 1 June 2024 at 21:14:38 UTC, Timon Gehr wrote:The whole point is not having to edit modules that were written by someone else just to be able to import them.On 5/30/24 20:31, Atila Neves wrote:You can attribute a module with the edition you are using to build.https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy- How do you compile different modules with different editions on the same command line?I don't know that it makes a whole lot of sense to cater to a case where you are building multiple modules with different editions by specifying command line parameters. ...Editions are a module-level concept, and the default edition changes over time. To me it does not even seem like a serious idea to not enable a module-specific setting to be specified per module. We would have a -mv switch to virtually change the compiler-visible file paths of individual modules, but not a way to set their edition?Other than that, there is separate compilation (which is supported via the `-E` switch). ...Exactly, a really weird UX inconsistency. We can directly import and build C code along D code, but somehow other D code is not afforded that privilege?I wouldn't.- How would a library expose different interfaces to importers that use different editions? (This may be required because different editions allow different interface designs and guarantees, or have a different user-accessible druntime interface and e.g. druntime types are in the library API.)This could be via separate modules. I would anticipate the need for this to be so rare that catering to this case is also not worth the effort. ...So old editions will keep breaking? There are currently safety bugs that are not being fixed specifically to avoid breakage.- How does a newer edition with less ` safe` bugs treat ` safe` code from an older edition that has more memory safety holes?A good question. I would approach it from the sense that calling a function must be safe for both sides. So if you called a function with different safety rules, and those rules reduce or compromise the safety of either the caller or the callee, it would have to be a trusted call. Note that in terms of ` safe` *bugs* and not ` safe` *design*, one would assume the safety bugs will be fixed in the newer compiler. ...Should be in the DIP.- How do function interfaces work when some type annotations exist in only either the language edition of the caller or the language edition of the callee? E.g. think DIP1000 is in one edition but not in another.The type annotations are defined by the language edition for the imported module. So those would be in effect. In other words, this is not like today where you compile one module with dip1000 and another module without, and the compiler blindly assumes all are compiled the same way. This does introduce an interesting wrinkle -- if there are differences, newer editions *must define* the interactions like this between editions as part of the release. -Steve
Jun 06
On Saturday, 1 June 2024 at 21:14:38 UTC, Timon Gehr wrote:On 5/30/24 20:31, Atila Neves wrote:If they all have module declarations, it's handled there, otherwise I hadn't thought of that. Do you think that will be common? I'm not sure it will be.https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy- How do you compile different modules with different editions on the same command line?- How would a library expose different interfaces to importers that use different editions? (This may be required because different editions allow different interface designs and guarantees, or have a different user-accessible druntime interface and e.g. druntime types are in the library API.)Good question. I guess we'll need some kind of `version(Edition2024)`.- How does a newer edition with less ` safe` bugs treat ` safe` code from an older edition that has more memory safety holes?I think I'd need a concrete example.- How do function interfaces work when some type annotations exist in only either the language edition of the caller or the language edition of the callee? E.g. think DIP1000 is in one edition but not in another.The semantics of the edition of the callee apply.
Jun 03
Atila Neves kirjoitti 3.6.2024 klo 19.05:This doesn't work, except for mixins. A version block will be turned on or off based on edition of the library, not of the client - or at least that's what I'd expect. See my idea about `__EDITION__` special token earlier in this thread for an alternative.- How would a library expose different interfaces to importers that use different editions? (This may be required because different editions allow different interface designs and guarantees, or have a different user-accessible druntime interface and e.g. druntime types are in the library API.)Good question. I guess we'll need some kind of `version(Edition2024)`.
Jun 04
On 6/3/24 18:05, Atila Neves wrote:On Saturday, 1 June 2024 at 21:14:38 UTC, Timon Gehr wrote:A lot of code will be written against the default edition and then abandoned at some point.On 5/30/24 20:31, Atila Neves wrote:If they all have module declarations, it's handled there, otherwise I hadn't thought of that. Do you think that will be common? I'm not sure it will be. ...https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy- How do you compile different modules with different editions on the same command line?Something like that, but `version` only includes one of the symbols, while here we would need to compile all of them.- How would a library expose different interfaces to importers that use different editions? (This may be required because different editions allow different interface designs and guarantees, or have a different user-accessible druntime interface and e.g. druntime types are in the library API.)Good question. I guess we'll need some kind of `version(Edition2024)`. ...E.g., there are bugs that allow you to mutate through `const` pointers. Some of them may not be fixed in edition 2024 because the fix would break code. However, in edition 2025 the bugs are fixed. Now edition 2025 calls into a function from edition 2024 that violates memory safety by modifying a const pointer. All involved code is ` safe`, yet memory safety is violated and this hole can never be fixed if edition 2025 can just call into edition 2024.- How does a newer edition with less ` safe` bugs treat ` safe` code from an older edition that has more memory safety holes?I think I'd need a concrete example. ...This might not work because annotations in a parameter list may require caller-side guarantees in order to be checked.- How do function interfaces work when some type annotations exist in only either the language edition of the caller or the language edition of the callee? E.g. think DIP1000 is in one edition but not in another.The semantics of the edition of the callee apply.
Jun 06
On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!From the text:Another compiler switch to aid transitioning that this DIP recommends is a -E switch which would function like -I for imports but would allow the user to specify what the edition should be for those imports.It should be specified how this would work. Is it something like `-E2024/usr/import/mycooldlib` ? I'm pretty sure you meant something like this, but spelling it out would make it clearer what that is for. -Steve
Jun 01
On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/editions/editions.mdIt looks like Editions are intended to be (Gregorian) years. If that is the case, the DIP should explicitly say that. I like the idea, but it limits us to making a new edition at most once per year. That might sound like a reasonable assumption, but it may fail occasionally, e.g. if regressions are found and fixed. It could be worth having a monthly or even a weekly resolution in Editions, i.e. make edition IDs of the form `YYYY-MM` or `YYYY-WW` where `WW` is the number of the week of the year (ranging between 1 and 53).
Jun 03
On Monday, 3 June 2024 at 10:49:10 UTC, Quirin Schroll wrote:On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:I left it open in case we decided to not go with the year of release, but I'd rather that be the case. I don't think releasing editions more frequently than that is a good idea, and that bug fixes are something else entirely.https://github.com/atilaneves/DIPs/blob/editions/editions.mdIt looks like Editions are intended to be (Gregorian) years. If that is the case, the DIP should explicitly say that. I like the idea, but it limits us to making a new edition at most once per year. That might sound like a reasonable assumption, but it may fail occasionally, e.g. if regressions are found and fixed. It could be worth having a monthly or even a weekly resolution in Editions, i.e. make edition IDs of the form `YYYY-MM` or `YYYY-WW` where `WW` is the number of the week of the year (ranging between 1 and 53).
Jun 03
On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!I hope you will tolerate this unsolicited intrusion of mine, but as an outsider to your world, I feel the need to say something. Not long ago, I approached this language because, after examining its fundamentals, I judged it to be the perfect evolution of "my" C language. A few days later, I changed my mind, not because I was wrong in judging the D language, but because D is unusable. And it is unusable because you do everything to make it so. Let me explain: the primary requirement for a programming language is not its flexibility, power, ease of learning, etc. No, the primary requirement is its stability and the certainty that code written for a release will be compiled by all compilers and libraries that support it. And this is what makes D unusable (and indeed practically unused). As soon as it is born, a fork of its system library... as soon as it starts to receive support from major IDEs, a fork of the language. Now I see your willingness to make it "dynamically scalable"... my friends, this way, you're going nowhere. Let's talk about the initiative related to this thread: it doesn't work. It's not acceptable that using the same language, I would write code that wouldn't be compiled by the machine of the programmer at the desk next to mine. This would be possible if I were programming in C and he in D, but if we both work in Dv2, the language standard must be the same for everyone. Of course, there can be a Dv3, Dv4... Dv2001, but someone has to standardize each version and, once done, there must be a freeze that prevents changes (except for debugging). Maybe I am too conservative for a lively language like this, it happens to us sixty-year-olds. But being sixty has an advantage: we know the business world well. From experience, I would find it very difficult to convince a company to use code written in D. Companies are more conservative than sixty-year-olds and do not like investments that change from one day to the next. Asking a programmer what version of D they work with is inconvenient, it is much more practical not to accept D. Now I retreat, apologizing for the inconvenience caused. Regards, U.
Jun 05
On 6/6/24 06:21, Federico wrote:Let's talk about the initiative related to this thread: it doesn't work. It's not acceptable that using the same language, I would write code that wouldn't be compiled by the machine of the programmer at the desk next to mine.Use the same compiler and it will work. With editions, even using a newer compiler, you will still be able to compile older code. That is part of the value proposition here.This would be possible if I were programming in C and he in D, but if we both work in Dv2, the language standard must be the same for everyone. ...There is no single language standard. And even in C and C++, the language standards are often not formal enough about all details, so in the end it's still about consensus of compiler implementations. Those compilers also have switches to enable different language behaviors.Of course, there can be a Dv3, Dv4... Dv2001, but someone has to standardize each version and, once done, there must be a freeze that prevents changes (except for debugging). ...That is exactly what this DIP is proposing. I do not understand your objection. Even more: It proposes that different standard "immutable" versions remain compatible.Maybe I am too conservative for a lively language like this, it happens to us sixty-year-olds. But being sixty has an advantage: we know the business world well. From experience, I would find it very difficult to convince a company to use code written in D. Companies are more conservative than sixty-year-olds and do not like investments that change from one day to the next. Asking a programmer what version of D they work with is inconvenient,You no longer have to ask with this proposal. That is the point.it is much more practical not to accept D. ...Well, D users have always been a self-selected group and it has had advantages, also for the businesses that did choose to engage with D.Now I retreat, apologizing for the inconvenience caused.Well it seems you misunderstood what this proposal is about. It's actually more conservative than the status quo.
Jun 06
On Thursday, 6 June 2024 at 04:21:23 UTC, Federico wrote:On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:There's a "Destroy!" right there, so I can't see how the "intrusion" would have been unsolicited. ;)https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!I hope you will tolerate this unsolicited intrusion of mine,Let me explain: the primary requirement for a programming language is not its flexibility, power, ease of learning, etc. No, the primary requirement is its stability and the certainty that code written for a release will be compiled by all compilers and libraries that support it.I agree that should be a goal.And this is what makes D unusable (and indeed practically unused).What makes you think that? Especially since in a world where those things are true I wouldn't have my current job(s). As soon as it is born, a fork of its system library...as soon as it starts to receive support from major IDEs, a fork of the language. Now I see your willingness to make it "dynamically scalable"... my friends, this way, you're going nowhere. Let's talk about the initiative related to this thread: it doesn't work. It's not acceptable that using the same language, I would write code that wouldn't be compiled by the machine of the programmer at the desk next to mine. This would be possible if I were programming in C and he in D, but if we both work in Dv2, the language standard must be the same for everyone.I agree. What in the proposal makes you think that it wouldn't work?Of course, there can be a Dv3, Dv4... Dv2001, but someone has to standardize each version and, once done, there must be a freeze that prevents changes (except for debugging).Those would be editions.From experience, I would find it very difficult to convince a company to use code written in D.I would also find it difficult to convince most companies to use Haskell or Clojure, but I'm not sure how that's relevant.
Jun 06
On Friday, 7 June 2024 at 00:53:51 UTC, Atila Neves wrote:On Thursday, 6 June 2024 at 04:21:23 UTC, Federico wrote:Unsolicited because, having abandoned the study of this language, I am not part of the community. Abandoned with great regret, I must add. I am a very concrete person, Atila, so I judge things by results and not by potential, or at least I do so when enough time has passed to say that a final assessment can be made. Now, should D have achieved significant penetration, at least in terms of potential? Absolutely yes, as I have already said, this language represents the natural evolution of C and is suitable for any field. Of course, there are some incomprehensible choices, but no one is forced to use those features. The "core" of the language is what any C programmer would want to have in their hands... Bright did an extraordinary job! And yet it did not happen. The penetration of D is modest to say the least, despite being the ideal candidate for the migration of C programmers seeking a more modern environment without significantly sacrificing efficiency already two decades ago, this affirmation did not happen. It is correct to say that D has underperformed its potential. And we must not think that we C programmers did not desire an evolution of the tool. Many switched to C++ (not me because I find it inelegant and very inefficient) and more recently to Rust, in this case deservedly. And here begins D's problem: D is superior to C++, it is more elegant, more efficient, and its implementation of the object-oriented paradigm is more "natural" than what we can find in C++. And yet there was almost no migration from C/C++ to D! Why? The first serious blow came with the Phobos-Tango affair. Incomprehensible! No one likes everything about the official libraries of C, just as I imagine is the case with any other language, but for this reason, no one wakes up tomorrow morning and creates a fork. What happens is the addition of other libraries while leaving the official ones unchanged. There is no "stdlib_v2" that implements functions with syntax and semantics different from the standard stdlib.h. Let's come to the present day. D finally acquires support from the professional development environment for Microsoft, which is not Visual Studio Code but Visual Studio Pro/Enterprise, the plugin for the other professional programming environment on Linux, the Jetbrains IDEs, starts to work... and what does your community do? A nice fork of the language! Instead of writing E, which would be rational, they start developing modifications to the main language. And that's not all, because the maintainer of the Jetbrains plugin declares on GitHub that he wants to follow OpenD. So we will have a D language for Windows and a D language for Linux. Fantastic, ideal for protecting software investments! At that point, I, a novice language student, come here to the official forum to try to understand what is happening, and I find this magnificent thread discussing the dynamic scalability of the language. The only possible reaction: put D aside, albeit with much regret. Why this would not work I have explained: if you want to safeguard investments, there cannot be "dynamic evolution." The correct (and accepted by companies) way to evolve a language is to convene a conference at intervals of 3 to 6 years, more precisely when there are new developments in the computer paradigm that render the previous version obsolete, find a synthesis of the various proposals, and produce ONE document that describes the next step to which ALL compilers claiming compliance with that version must adhere. It is true, there are successful languages that do not follow the already mentioned Rust. But there is a notable difference: the governance and/or the strength given by the already acquired adopter base. Google, and so on. In these cases, it is the weight of the company behind the language that ensures both the critical mass of users and the security of the path taken. Rust's story is a bit different. Rust was widely adopted because it seriously addressed security needs just when software security was experiencing the worst crisis in its history. In this case, it is the mass of its users that guarantees both the future and the support in development tools (with the absence of Visual Studio because Microsoft certainly does not view it sympathetically). Now Atila, despite its not short lifespan an its undeniable qualities, D does not find itself in any of those fortunate conditions. On the contrary, it seems to me, it still has to offer developers a reason for its adoption, which certainly cannot pass through uncertainty about the path followed. I apologize for having made it unbearably long.On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:There's a "Destroy!" right there, so I can't see how the "intrusion" would have been unsolicited. ;)https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!I hope you will tolerate this unsolicited intrusion of mine,Let me explain: the primary requirement for a programming language is not its flexibility, power, ease of learning, etc. No, the primary requirement is its stability and the certainty that code written for a release will be compiled by all compilers and libraries that support it.I agree that should be a goal.And this is what makes D unusable (and indeed practically unused).What makes you think that? Especially since in a world where those things are true I wouldn't have my current job(s). As soon as it is born, a fork of its system library...as soon as it starts to receive support from major IDEs, a fork of the language. Now I see your willingness to make it "dynamically scalable"... my friends, this way, you're going nowhere. Let's talk about the initiative related to this thread: it doesn't work. It's not acceptable that using the same language, I would write code that wouldn't be compiled by the machine of the programmer at the desk next to mine. This would be possible if I were programming in C and he in D, but if we both work in Dv2, the language standard must be the same for everyone.I agree. What in the proposal makes you think that it wouldn't work?Of course, there can be a Dv3, Dv4... Dv2001, but someone has to standardize each version and, once done, there must be a freeze that prevents changes (except for debugging).Those would be editions.From experience, I would find it very difficult to convince a company to use code written in D.I would also find it difficult to convince most companies to use Haskell or Clojure, but I'm not sure how that's relevant.
Jun 07
On Friday, 7 June 2024 at 15:01:03 UTC, Federico wrote:I am a very concrete person, Atila, so I judge things byWhile your perspective is welcome, this forum is specifically for discussing DIP ideas. A discussion of D's prospects is off topic in this thread. Please see the forum rules linked at the top of the page if you're viewing from the web interface. Normally, I'd delete the post outright. In this case, though, I'll just ask that anyone wanting to continue this discussion please start a new thread in the General forum. I will delete any further off-topic posts, though. Thanks!
Jun 07
On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!I would just like to comment on one aspect of the DIP for now: the "Examples" section is a bit of a sore sight currently. It's difficult to get excited about the idea when the proposed actions it unlocks is "we're changing two defaults and removing three features without providing an immediate replacement". Regarding the removal of `lazy`, I'm particularly curious about the consequent fate of `assert` and `enforce`, two prominent current users of `lazy. It seems like either way would involve a compromise: - Will `assert` fully become "compiler magic", unimplementable in user code, and `enforce` replaced with an explicit delegate variant? - Will both `assert` and `enforce` require an explicit delegate, thus making unit tests quite a bit more syntactically noisy? - Will both `assert` and `enforce` become "compiler magic" (and therefore unimplementable in user code)?
Jun 09
On Sunday, 9 June 2024 at 18:43:51 UTC, Vladimir Panteleev wrote:On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:Good questions. Enforce would have to take a delegate, but `assert` could be magic. I'm not sure that's a good idea though. In any case, that's an idea of what we could do, I'm not sure we will.[...]I would just like to comment on one aspect of the DIP for now: the "Examples" section is a bit of a sore sight currently. It's difficult to get excited about the idea when the proposed actions it unlocks is "we're changing two defaults and removing three features without providing an immediate replacement". Regarding the removal of `lazy`, I'm particularly curious about the consequent fate of `assert` and `enforce`, two prominent current users of `lazy. It seems like either way would involve a compromise: - Will `assert` fully become "compiler magic", unimplementable in user code, and `enforce` replaced with an explicit delegate variant? - Will both `assert` and `enforce` require an explicit delegate, thus making unit tests quite a bit more syntactically noisy? - Will both `assert` and `enforce` become "compiler magic" (and therefore unimplementable in user code)?
Jun 11
On Tuesday, 11 June 2024 at 16:08:54 UTC, Atila Neves wrote:On Sunday, 9 June 2024 at 18:43:51 UTC, Vladimir Panteleev wrote:I don’t see why `assert` would be considered “magic.” On the one hand, it’s a language primitive, so it’s not magic, it’s just defined in some way, and short circuiting operations do exist in `&&` and `||` and those are around basically forever. On the other hand, why not just evaluate the message regardless if the condition fails? In many cases, the message is a string literal, and almost all cases where it’s not just a literal, it has no side-effects, so the compiler can actually refrain from evaluating the message unless the condition fails – as an optimization. Assert messages with side-effects are such an anti-pattern, maybe it shouldn’t even be allowed. For `lazy`, yes, lazy function parameters are weird and I’d rather have explicit delegates. One thing `lazy` could bring as a storage class applied to a delegate type or array or slice of delegate type parameter: The caller guarantees that each such delegate is evaluated at most once. TL;DR (next): Don’t give up `lazy` as a keyword, it might be handy. For data members of structs or classes, `lazy` could be implemented so that they’re lazily evaluated. Of course, for mutable objects, one can implement lazy evaluation by hand, but in D, `immutable` values can’t make use of lazy evaluation except by having state that’s conceptually part of an object actually placed in a global/thread local outside of them, which is incompatible with `pure`. With `lazy`, one could have an object be `immutable` with all its guarantees (maybe with select exceptions such as placing it in the read only section of the binary), but allowing for lazy evaluation. If the language handles the lazy evaluation, it can make guarantees that the programmer simply can’t. It’s a design hole. The essence of `immutable` is that no-one can observe mutations of this object. If the programmer cannot ask: “Has this `lazy` data member been evaluated and cached yet?” No mutations can be observed. It does not have to be a data member storage class either, it might be much more practical to implement as a function attribute so that the annotated function runs at most once, and if it did, the result is cached into a (hidden) data member, so that when it runs again, only the value of the data member is returned.On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:Good questions. Enforce would have to take a delegate, but `assert` could be magic. I'm not sure that's a good idea though. In any case, that's an idea of what we could do, I'm not sure we will.[...]I would just like to comment on one aspect of the DIP for now: the "Examples" section is a bit of a sore sight currently. It's difficult to get excited about the idea when the proposed actions it unlocks is "we're changing two defaults and removing three features without providing an immediate replacement". Regarding the removal of `lazy`, I'm particularly curious about the consequent fate of `assert` and `enforce`, two prominent current users of `lazy. It seems like either way would involve a compromise: - Will `assert` fully become "compiler magic", unimplementable in user code, and `enforce` replaced with an explicit delegate variant? - Will both `assert` and `enforce` require an explicit delegate, thus making unit tests quite a bit more syntactically noisy? - Will both `assert` and `enforce` become "compiler magic" (and therefore unimplementable in user code)?
Jun 12
On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/editions/editions.mdOne hurdle I can see coming is the following: Writing and maintaining a compiler that just supports multiple editions is error-prone to begin with. A much, much bigger hurdle is writing and maintaining a compiler that supports all interactions between the semantics of different editions. If done as proposed, any compiler supporting 3 or more editions is doomed: If *n* is the number of editions to support, the number of semantic interactions is *n*!/(*n*−2). For *n* = 2, that’s just 2 (one interaction forth, and another back). For *n* = 3, it’s already 6 and for *n* = 4, it’s 12. The way of handling deprecations is a lot like *n* = 2, as the compiler must somehow support changes in semantics, at least recognize an erroneous old way and diagnose it properly. One might assume that the number of interactions would be *n* choose 2, which would render *n* = 3 (close to) feasible, but that disregards the difference between back and forth interactions. If functions in modules `A` and `B` of different editions call each other, it makes a difference if `A.f` calls `B.g` or the other way around: The lexically same signature of `A.f` might mean something entirely different were it the signature of `B.g`. (That is the whole point of having editions.) For three editions *X, Y,* and *Z,* semantics could be that *X* → *Z* is defined through *X* → *Y* and *Y* → *Z* (and the other way around for *Z* → *X*), but without proof, my suspicion is that this cannot be done in general. The question how older edition code calls newer edition code: Even in the ideal case, there are inheritance, delegates/function pointers and templates. My best guess is that inheritance and delegates/function pointers with some effort are largely doable. There’s the issue what storage classes and attributes mean exactly, that must be clearly defined. The biggest issue here is that it might not be possible without surprising the programmer. My fear is that templates will become worse than C++ templates. It’s already not that easy to reason about them. (Example: In D, one can’t instantiate any template due to `auto ref` parameters – and that despite the fact that D officially has no function templates, it just has templates, and IFTI is defined for a template that happens to contain just a function declaration.) Don’t get me started on mixin templates, those are already next to impossible to write in a way that makes them impossible to use incorrectly. In the not-so-ideal case, there’s a code base and some modules are older and for edition *X.* Then edition *Y* came out and newer modules were written for *Y* – which works as *Y* and *X* interactions are well-defined. The some *X* modules needed fixing and end up calling *Y* module functions because it’s just practical. Rinse and repeat with edition *Z.* If we have to allow interactions between editions, do so by a narrowly defined subset of the language. Essentially, if a module `A` is for edition *X,* and module `B` for edition *Y,* for `B`, declarations in `A` that aren’t in that subset are effectively private, and vice versa. Interactions between editions is something that even C++ does not do (editions are called language versions, but it’s conceptually the same). Using conditional compilation, you can write files that are compile with C++98 and C++23, but you can’t compile a.cpp with `-std=c++98` and b.cpp with `-std=cpp23` and expect that you can link a.obj and b.obj. The headers a.hpp and b.hpp, which both .cpp files include, are likely different depending on language version, but even assuming they’re not, even mangling can be different, what stdlib classes/functions do is different, etc., etc. What you could do, however, is use `extern "C"` declarations. Back to the common subset for D. From a conservative standpoint, let’s just allow `extern(C)` non-template stuff. Effectively, `extern(C)` would be the `public`-across-editions visibility. The reason is simple: Whatever newer editions do, what `extern(C)` declarations mean won’t change much. It’s not a panacea either, as `extern(C)` declarations can carry attributes and their meaning can change. However, there’s no question what the parameter storage class `in` means on an `extern(C)` function, it’s just not allowed. Classes are out, too. Non-POD structs are out as well. Start from a very narrow subset, then expand as needed. For compatibility of editions to work with ≥ 3 editions, the subset must be very, very stable.
Jun 12
On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/editions/editions.mdThe DIP doesn’t mention the addition of new keywords without breaking identifiers identical to them. I’m thinking of `impure` here, as it would be the most orthogonal way to introduce an inverse for `pure`.
Jun 14
On Friday, 14 June 2024 at 17:24:59 UTC, Quirin Schroll wrote:On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:I don't think that scales given how many attributes we have.https://github.com/atilaneves/DIPs/blob/editions/editions.mdThe DIP doesn’t mention the addition of new keywords without breaking identifiers identical to them. I’m thinking of `impure` here, as it would be the most orthogonal way to introduce an inverse for `pure`.
Jun 17
On Monday, 17 June 2024 at 22:47:03 UTC, Atila Neves wrote:On Friday, 14 June 2024 at 17:24:59 UTC, Quirin Schroll wrote:Of the ones I mean, we have four: ` safe`, `nothrow`, ` nogc`, and `pure`. Of those, ` safe` had ` system` from the get-go and `throw` was added by DIP 1029 (seems unimplemented). I’m writing a DIP to add ` gc`. Then, only `pure` remains without inverse. There’s also ` live`, but it’s not transitive and it me, it seems it makes no outward guarantees (e.g. one can override a ` live` function by a non-` live` one, or assign a non-` live` function’s address to a function pointer variable with ` live`).On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:I don't think that scales given how many attributes we have.https://github.com/atilaneves/DIPs/blob/editions/editions.mdThe DIP doesn’t mention the addition of new keywords without breaking identifiers identical to them. I’m thinking of `impure` here, as it would be the most orthogonal way to introduce an inverse for `pure`.
Jun 19
We're briefly discussing editions on Discord and complexity of implementation where I'm making the note that some of the infrastructure and one change is already applied. However a point I want to make is in the implementation there is a legacy version along with 2024. https://github.com/dlang/dmd/blob/15f66f89c9d80bbd71274f272e58c273684905ee/compiler/src/dmd/astenums.d#L22 This is a point I've previously made that the base version (aka legacy) should be given the version number 2 and should not have DIP1000 enabled for it.
Jun 20
On Thursday, 20 June 2024 at 15:30:43 UTC, Richard (Rikki) Andrew Cattermole wrote:However a point I want to make is in the implementation there is a legacy version along with 2024. https://github.com/dlang/dmd/blob/15f66f89c9d80bbd71274f272e58c273684905ee/compiler/src/dmd/astenums.d#L22This is a great solution to my problem I proposed above. I should have gone back and read all the new messages before I posted. Sorry I suck at the forums.
Aug 03
On Thursday, 30 May 2024 at 18:31:48 UTC, Atila Neves wrote:https://github.com/atilaneves/DIPs/blob/editions/editions.md Destroy!Editions, as outlined and discussed, will easily solve the most problematic issues. There are no compilation failures I have run into in the past few years that would have been hard to solve with editions as described. That means my experience (and anyone like me) would have been ideal during that time period, at only the cost that I have to specify the edition. That is a huge win. There are lots of comments, such as: "Mostly, yes, druntime will be kind of stuck." "How does a newer edition with less safe bugs treat safe code from an older edition that has more memory safety holes?" This is a completely reasonable fear. Suppose there is a feature that is not possible or practical to add in an edition. I don't think it's unreasonable to (rarely!) make a breaking change and start a new stream of editions. The situation will be much better than it is today where my code fails to compile after almost every compiler release. It would be important to put these changes off and make them all at once. So you have, for example, three years of stability and then three breaking changes at once, instead of one breaking change each year. You have to break some eggs if you want to make a omelette. If there are a few of these over the next few years, editions will be better than the current state during the meantime. And then the lessons learned will create a future where it doesn't need to happen as often. I can think of solutions to make this less painful than it is today. This proposal is good as is and if it isn't perfect, it's still a step in the right direction, with the potential to be nearly perfect in the future. Now to comment specifically on the proposal, you said: "Modules without a module declaration would be considered to be using the latest edition unless the default edition is specified explicitly with a command line argument." That is the obvious sensible plan. The only issue I see with this is that is this scenario. Timon Gehr said:In ten years, I don't want to have to remember the name of the first edition, not to mention the edition naming may get more complicated as things tend to do. Most code that is not annotated with an edition will be from the first edition so it almost seems like it should be the default. Except that it would obviously be annoying for the end user and a language feature a new programmer would need to know. So that is a no go. This needs a solution and I don't have a great one. Perhaps there is a flag like -edition=first or an easy way to look it up. It does not need to be a part of this proposal, but I think it will need to be a part of editions come two or three years. As for version naming, let's say this is version 2 of the language. Then the first edition could be "2.1". And the next version could be 2.2. Once you need a truly breaking change, then the edition becomes 3.1 (or start with 2.0/3.0 because we are programmers.) This would be intuitive for someone to understand it's a different language version and needs a different tool. Although, regardless of edition naming, if you try to compile 2024 code with a 2029 (incompatible) compiler, the compiler would easily be able to say "This needs such-and-such compiler" or other, simpler solutions I can think of for new users.The whole point is not having to edit modules that were written by someone else just to be able to import them.How do you compile different modules with different editions on the same command line?You can attribute a module with the edition you are using to build.
Aug 03