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:
>> 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?

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.
May 31
On Friday, 31 May 2024 at 11:21:30 UTC, Dukc wrote:
> Atila Neves kirjoitti 30.5.2024 klo 21.31:
>> [...]
>
> 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 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.

> 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 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:

>

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?

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.

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:
> > 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?
>
> 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.

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 Davis




June 01
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 Davis

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?
June 01

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

June 01

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




June 01

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.

June 01
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.