September 12

On Thursday, 12 September 2024 at 09:56:44 UTC, Paul Backus wrote:

> >

Also I propose that the tag type is enumerated type that is implicitly convertible to int. The base type is an unsigned integer type big enough to hold all the field types. Default value and the enumerated values (other than having one for each type) can remain unspecified though.

By "tag type" I assume you mean the type of the __tag property. Is there any practical difference between what you describe and just using size_t?

Well, size_t takes more space. Then again, if the tag property would be a getter as opposed to a direct field accessor the tag type wouldn't necessarily have to match with the real type of the tag field, in which case there's no difference.

September 12

On Thursday, 12 September 2024 at 10:24:01 UTC, Dukc wrote:

>

On Thursday, 12 September 2024 at 09:56:44 UTC, Paul Backus wrote:

>

You can use them in foreign languages by defining an extern(C) API and treating the content as opaque.

Yes, if the foreign language will only handle it via a pointer. But if the ABI is nailed down, the foreign language can have the sum type on an array or at the stack, and pass them to D functions by value.

Even for that, all the foreign language has to know is the size and the alignment. It doesn't have to know how the data is arranged internally.

>

Pattern matching is complex enough that I agree it's best as it's own DIP. But I think this DIP still needs the simple getter function since a language-level sum type really doesn't carry it's weight if it is too low-level. We already have union for the low-level work.

Yes, I agree! Pattern matching is the actual important feature here. Language-level sum types, while nice to have, are an incremental improvement at best.

Alas, I am not the one who sets priorities for D--Walter is. And Walter has decided to start with a sum type DIP, not a pattern-matching DIP.

>

I was initially thinking about assignment operator too, but there's a problem. You might have two or more fields with the same type, in which case assigning a value of that type to the sum type is ambiguous. If you instead/also mean an assignment to field of the sum type, then that avoids the problem.

Yes, I mean assignment to both the fields and to the object as a whole (like how std.sumtype does it).

>

...and if they are, we don't need the annoying special case that the setter wouldn't take a value argument for void fields. I think it's worth mentioning in the DIP though as a future development, once/if you submit it for real.

Honestly I am not very interested in submitting this DIP "for real"--I'm satisfied with std.sumtype for my own work. I just want to put forward an alternative design to the one in Walter's DIP, and this seemed like the most effective way to do that.

September 12

On Thursday, 12 September 2024 at 10:32:39 UTC, Dukc wrote:

>

On Thursday, 12 September 2024 at 09:56:44 UTC, Paul Backus wrote:

> >

Also I propose that the tag type is enumerated type that is implicitly convertible to int. The base type is an unsigned integer type big enough to hold all the field types. Default value and the enumerated values (other than having one for each type) can remain unspecified though.

By "tag type" I assume you mean the type of the __tag property. Is there any practical difference between what you describe and just using size_t?

Well, size_t takes more space. Then again, if the tag property would be a getter as opposed to a direct field accessor the tag type wouldn't necessarily have to match with the real type of the tag field, in which case there's no difference.

__tag is an rvalue property, and the intent is that the size_t it returns can be computed at runtime from the data stored in the tag field. It's analogous to SumType's typeIndex method.

September 12

On Thursday, 12 September 2024 at 10:32:39 UTC, Dukc wrote:

>

Well, size_t takes more space. Then again, if the tag property would be a getter as opposed to a direct field accessor the tag type wouldn't necessarily have to match with the real type of the tag field, in which case there's no difference.

Oops, let me take that a bit back. I also proposed what I did because the default base type of an enumerated type is int, not size_t.

September 12

On Thursday, 12 September 2024 at 10:33:35 UTC, Paul Backus wrote:

>

On Thursday, 12 September 2024 at 10:24:01 UTC, Dukc wrote:

>

Yes, if the foreign language will only handle it via a pointer. But if the ABI is nailed down, the foreign language can have the sum type on an array or at the stack, and pass them to D functions by value.

Even for that, all the foreign language has to know is the size and the alignment. It doesn't have to know how the data is arranged internally.

But to know the size of the sum type, the existence, size and alignment of the tag field has to be known. That's why I'd prefer it to be specified.

September 12

On Thursday, 12 September 2024 at 11:19:07 UTC, Dukc wrote:

>

On Thursday, 12 September 2024 at 10:33:35 UTC, Paul Backus wrote:

>

On Thursday, 12 September 2024 at 10:24:01 UTC, Dukc wrote:

>

Yes, if the foreign language will only handle it via a pointer. But if the ABI is nailed down, the foreign language can have the sum type on an array or at the stack, and pass them to D functions by value.

Even for that, all the foreign language has to know is the size and the alignment. It doesn't have to know how the data is arranged internally.

But to know the size of the sum type, the existence, size and alignment of the tag field has to be known. That's why I'd prefer it to be specified.

The sum type will have a .sizeof property that gives its total size, with the tag field included.

When the DIP says "the size of the tag field is unspecified," what that means is that it's unspecified is how much of the "extra" space is actually used for the tag field, and how much of it is padding.

September 12

On Thursday, 12 September 2024 at 11:19:07 UTC, Dukc wrote:

>

But to know the size of the sum type, the existence, size and alignment of the tag field has to be known. That's why I'd prefer it to be specified.

Also, the tag field itself will be visible to reflection (via __traits(allMembers), which includes hidden fields), and will have its own .sizeof, .alignof, and .offsetof properties. So you can get this information if you really want it.

"Unspecified" just means that the compiler is free to choose whatever layout it wants for the tag field, and is not required to document its choice, so the programmer should not make any assumptions about it.

September 12

On Thursday, 12 September 2024 at 02:42:17 UTC, Paul Backus wrote:

>

https://gist.github.com/pbackus/28e7f5668219ce83467c83c347ec7202

This DIP proposes a conservative design for sum types that aims to be consistent with existing D syntax and semantics. It does not discuss pattern matching.

Thank you for writing this up.

September 12

On Thursday, 12 September 2024 at 12:01:38 UTC, Paul Backus wrote:

>

The sum type will have a .sizeof property that gives its total size, with the tag field included.

When the DIP says "the size of the tag field is unspecified," what that means is that it's unspecified is how much of the "extra" space is actually used for the tag field, and how much of it is padding.

That still means the foreign code will have to account for each different D compiler it's going to support, even when the D compilers are built the same C ABI.

Then again, this is a pretty theoretical argument since all the widely used D compilers are currently based on the same frontend and would therefore probably have the same ABI for the same C ABI in practice. So maybe it's worth to nail it down only if/when different D frontends start to see widespread use.

September 12

On Thursday, 12 September 2024 at 09:44:01 UTC, Paul Backus wrote:

>

On Thursday, 12 September 2024 at 03:22:07 UTC, Steven Schveighoffer wrote:

> >

Access to the tag field of an enum union, if it exists, is always @system.

Does this mean obj.__tag is @system? Surely, having this knowledge is not a safety violation.

__tag is an rvalue property that returns an index. Accessing it is @safe.

The tag field is a hidden field whose content is unspecified. Accessing it is @system.

They are two different things.

Given the confusion, I think it should be explicitly said that accessing __tag is @safe.

> >

I think your example with the @trusted attribute is not safe, because the type in question may not be @safe to return (i.e. copy constructor not @safe).

It returns by reference, so no copy constructor is called.

Ah, OK. I missed that.

BTW, there is an opportunity here. You can use final switch on a __tag, and the compiler can know when you are missing a case (i.e. you add another member to the enum union), and also have a default case assert automatically generated.

I'm also just realizing, there isn't anything to say you can't have more than one union member with the same type. While this is somewhat fine, it should be explicitly stated that this is fine or that it is not allowed.

For instance, std.sumtype doesn't allow this.

-Steve

1 2
Next ›   Last »