digitalmars.D - Union redux
- deadalnix (49/49) Jun 01 2015 After discussion at DConf, it ends up that union have some lack
- Andrei Alexandrescu (28/66) Jun 01 2015 Do not define constructors. They ostensibly imply commitment to
- Walter Bright (18/82) Jun 01 2015 "Fine" as in "yes" :-)
- CraigDillabaugh (6/25) Jun 01 2015 Maybe this explains why my wife was upset with me when she
- Walter Bright (3/9) Jun 01 2015 Hah, I should have said that "fine" has the meaning reversed when it is ...
- wobbles (2/12) Jun 02 2015 English is a wonderful language :)
- Walter Bright (6/18) Jun 02 2015 Reminds me of a friend who said he enjoyed programming the Z80. I said t...
- Steven Schveighoffer (9/33) Jun 01 2015 Yes and no :) It all depends on the context and emotion. There is so
- Andrei Alexandrescu (5/8) Jun 01 2015 Unions should accept all types, including those with @disabled or
- Steven Schveighoffer (5/13) Jun 01 2015 So what happens on destruction? What about postblit? This was the piece
- Brad Roberts via Digitalmars-d (7/21) Jun 01 2015 I think the basic thinking is that these two should be semantically iden...
- Andrei Alexandrescu (4/6) Jun 01 2015 Nothing happens.
- Timon Gehr (2/8) Jun 02 2015 Is there an official way to invoke them manually?
- Andrei Alexandrescu (3/17) Jun 02 2015 destroy calls the dtor. Just copying out the appropriate member invokes
- Timon Gehr (2/20) Jun 02 2015 OK. What about copying in instead of out?
- Andrei Alexandrescu (3/4) Jun 02 2015 If the appropriate type has already been constructed, assignment
- Steven Schveighoffer (6/10) Jun 02 2015 My concern is if you copy the enclosing type. This means you have
- Andrei Alexandrescu (2/12) Jun 02 2015 Copying unions as a whole won't do any miracles. Just memcpy. -- Andrei
- Timon Gehr (4/17) Jun 02 2015 Copy is memcpy & postblit.
- Andrei Alexandrescu (6/25) Jun 02 2015 Oh, I only now understood the question. Yes, it's possible to only call
- Timon Gehr (3/30) Jun 02 2015 Indeed, but I think this facility is undocumented. Maybe it should be
- Steven Schveighoffer (5/13) Jun 02 2015 I don't see the need. It's simply the name of the compiled member. I
- Andrei Alexandrescu (2/4) Jun 02 2015 A good idea, please bugzilla so we don't forget. -- Andrei
- Timon Gehr (2/6) Jun 03 2015 https://issues.dlang.org/show_bug.cgi?id=14646
- Andrei Alexandrescu (2/5) Jun 01 2015 Thanks for the lesson. Indeed I did mean it as "yes". -- Andrei
- Andrei Alexandrescu (2/5) Jun 01 2015 What should we do here then? -- Andrei
- Jonathan M Davis (11/19) Jun 01 2015 The fact that we essentially decided that everything was @safe
- Walter Bright (3/9) Jun 01 2015 There's nothing unsafe about:
- Andrei Alexandrescu (2/13) Jun 01 2015 Sounds good, no indirection => safety is in good shape. -- Andrei
- deadalnix (12/47) Jun 01 2015 This is implied in C++ because of manual memory management. I
- Andrei Alexandrescu (7/41) Jun 01 2015 I intentionally gave enough information to allow easy further research.
- deadalnix (8/53) Jun 01 2015 It is common in D to have a struct with a constructor and no
- Andrei Alexandrescu (12/55) Jun 01 2015 Probably there's a misunderstanding then. I'm saying the right way to go...
- deadalnix (25/99) Jun 01 2015 No, I asked you what is the rationale used to get types with
- Andrei Alexandrescu (32/50) Jun 01 2015 From http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2248.html...
- deadalnix (9/53) Jun 02 2015 It is unfortunate that the explanation do not go over the
- Manu via Digitalmars-d (7/13) Jun 02 2015 Isn't it the case that some of the members of a union need to be
- Andrei Alexandrescu (2/16) Jun 02 2015 That could be done, but strikes me as too clever for its own good. -- An...
- Steven Schveighoffer (5/25) Jun 02 2015 It's actually unnecessarily redundant. In all cases, you can simply move...
- Manu via Digitalmars-d (6/28) Jun 02 2015 Right. See, I thought that's just how it already was ;)
After discussion at DConf, it ends up that union have some lack of specification, and some nonsensical behavior right now. Here are some points discussed and possible solutions : 1/ .init for unions is not defined. I propose to define it as the .init of the first field + padding with 0s if the union is larger than its first member. It seems to be what is generated right now. 2/ Default constructor takes one argument per union's field and assign them all one over the other. This does not make any sense and need to be changed. Proposed solutions : a. Define one constructor for the first field. b. Define N constructors, one per field. c. Do not define constructors. My preference goes for b, then a, then c, in that order. 3/ union and safe is currently undefined. I proposed to make everything involving unions system, and we will figure it out from there. At the very least, all union with indirections and fields having a posblit/destructor ust be system. 4/ tupleof for unions generate a tuple will all field of the union. It does not make much sense, and it is unclear if tupleof can make sense at all on a union. Let's not have tupleof on union at all. 5/ union currently disallow members with postblit and/or destructor . It seems that this was needed in C++ as per Andrei's comments. It seems to me that, because of manual memory management, C++ would have a lot more struct with copy constructor and/or destructor than in D, so I'm not sure if this require change in spec. Andrei, can you give more details on the C++ situation here ? 6/ struct with anonymous union in them define one parameter per union field in the default constructor. This should probably lead to the same solution as 2/ 7/ struct with anonymous union in them have one entry per union field in their tupleof. All the union field should be present as one entry in the tupleof, with a compiler generated union type. 8/ unions and structs are mangled the same way (or so it seems). Bug or feature ? 9/ union alignement is not specified. union align should be least common multiple of union's fields. 10/ union that capture a closure are undefined. I think that right now, they just add the context pointer at the same address as other fields, which is nonsensical. Proposal : a. Add the context at an address that do not overlap with other fields. b. Do not allow union to capture a context. Union can have member method and they could use captured info to know how to process the union in an opaque (voldemort) way. I see no reason to forbid it, and adding an exception for union create extra special casing (from a user standpoint) which is undesirable. My preference goes to a.
Jun 01 2015
On 6/1/15 12:00 PM, deadalnix wrote:1/ .init for unions is not defined. I propose to define it as the .init of the first field + padding with 0s if the union is larger than its first member. It seems to be what is generated right now.Fine.2/ Default constructor takes one argument per union's field and assign them all one over the other. This does not make any sense and need to be changed. Proposed solutions : a. Define one constructor for the first field. b. Define N constructors, one per field. c. Do not define constructors. My preference goes for b, then a, then c, in that order.Do not define constructors. They ostensibly imply commitment to remembering to call the appropriate destructor. A union can only be default constructed (with its init value as described) and has no destructor.3/ union and safe is currently undefined. I proposed to make everything involving unions system, and we will figure it out from there. At the very least, all union with indirections and fields having a posblit/destructor ust be system.A good first step. Let's.4/ tupleof for unions generate a tuple will all field of the union. It does not make much sense, and it is unclear if tupleof can make sense at all on a union. Let's not have tupleof on union at all.tupleof must generate a tuple recognizable by introspection engines. I therefore thing tupleof with all members is the only approach that doesn't lose information. Introspection engines can check is(X == union) prior to interpreting tupleof.5/ union currently disallow members with postblit and/or destructor . It seems that this was needed in C++ as per Andrei's comments. It seems to me that, because of manual memory management, C++ would have a lot more struct with copy constructor and/or destructor than in D, so I'm not sure if this require change in spec. Andrei, can you give more details on the C++ situation here ?That rule has hurt C++ everywhere, and the community credits Lois Goldthwaite for pushing the current rule, which allows types with cdtors in unions. Let's go the same way, unions are all but useless otherwise.6/ struct with anonymous union in them define one parameter per union field in the default constructor. This should probably lead to the same solution as 2/Structs can have auto-defined ctors only up to the union member.7/ struct with anonymous union in them have one entry per union field in their tupleof. All the union field should be present as one entry in the tupleof, with a compiler generated union type.Again the litmus test here is enabling introspection. Structs with anonymous union members should have one member called e.g. __anonymous__ in their tupleof, and in turn introspecting that member should list its tuple.8/ unions and structs are mangled the same way (or so it seems). Bug or feature ?Not sure. Walter?9/ union alignement is not specified. union align should be least common multiple of union's fields.Yes. Since they're all powers of 2, taking the max is the same thing. BTW, to my surprise on OSX real.alignof is 16, but the alignof a union containing a real is 8. I think that's a bug. Please verify and file.10/ union that capture a closure are undefined. I think that right now, they just add the context pointer at the same address as other fields, which is nonsensical. Proposal : a. Add the context at an address that do not overlap with other fields. b. Do not allow union to capture a context.No context please. We may add it later. I'd say check the existing semantics, file bug reports, and make PRs for a section on unions in the language reference that links to the issues wherever the actual behavior is not in sync with the spec. Andrei
Jun 01 2015
On 6/1/2015 12:43 PM, Andrei Alexandrescu wrote:On 6/1/15 12:00 PM, deadalnix wrote:"Fine" as in "yes" :-) For non-native speakers, the use of "fine" is often confusing. "Fine" in American english means "you're wrong, but I won't argue the point." It does not signify endorsement.1/ .init for unions is not defined. I propose to define it as the .init of the first field + padding with 0s if the union is larger than its first member. It seems to be what is generated right now.Fine.Yes. Option (c). (We can always relax this later, but undoing (a) or (b) may be impossible.)2/ Default constructor takes one argument per union's field and assign them all one over the other. This does not make any sense and need to be changed. Proposed solutions : a. Define one constructor for the first field. b. Define N constructors, one per field. c. Do not define constructors. My preference goes for b, then a, then c, in that order.Do not define constructors. They ostensibly imply commitment to remembering to call the appropriate destructor. A union can only be default constructed (with its init value as described) and has no destructor.No.3/ union and safe is currently undefined. I proposed to make everything involving unions system, and we will figure it out from there.Yes.At the very least, all union with indirections and fields having a posblit/destructor ust be system.Yes.4/ tupleof for unions generate a tuple will all field of the union. It does not make much sense, and it is unclear if tupleof can make sense at all on a union. Let's not have tupleof on union at all.tupleof must generate a tuple recognizable by introspection engines. I therefore thing tupleof with all members is the only approach that doesn't lose information. Introspection engines can check is(X == union) prior to interpreting tupleof.I defer to Andrei's expertise here.5/ union currently disallow members with postblit and/or destructor . It seems that this was needed in C++ as per Andrei's comments. It seems to me that, because of manual memory management, C++ would have a lot more struct with copy constructor and/or destructor than in D, so I'm not sure if this require change in spec. Andrei, can you give more details on the C++ situation here ?That rule has hurt C++ everywhere, and the community credits Lois Goldthwaite for pushing the current rule, which allows types with cdtors in unions. Let's go the same way, unions are all but useless otherwise.Yes.6/ struct with anonymous union in them define one parameter per union field in the default constructor. This should probably lead to the same solution as 2/Structs can have auto-defined ctors only up to the union member.Sounds good.7/ struct with anonymous union in them have one entry per union field in their tupleof. All the union field should be present as one entry in the tupleof, with a compiler generated union type.Again the litmus test here is enabling introspection. Structs with anonymous union members should have one member called e.g. __anonymous__ in their tupleof, and in turn introspecting that member should list its tuple.I think it's fine.8/ unions and structs are mangled the same way (or so it seems). Bug or feature ?Not sure. Walter?Union alignment must be the largest alignment of any of its fields. The same as for structs.9/ union alignement is not specified. union align should be least common multiple of union's fields.Yes. Since they're all powers of 2, taking the max is the same thing. BTW, to my surprise on OSX real.alignof is 16, but the alignof a union containing a real is 8. I think that's a bug. Please verify and file.Yes. Option (b) - issue an error if it is attempted.10/ union that capture a closure are undefined. I think that right now, they just add the context pointer at the same address as other fields, which is nonsensical. Proposal : a. Add the context at an address that do not overlap with other fields. b. Do not allow union to capture a context.No context please. We may add it later.I'd say check the existing semantics, file bug reports, and make PRs for a section on unions in the language reference that links to the issues wherever the actual behavior is not in sync with the spec.Yes.
Jun 01 2015
On Monday, 1 June 2015 at 21:02:30 UTC, Walter Bright wrote:On 6/1/2015 12:43 PM, Andrei Alexandrescu wrote:Maybe this explains why my wife was upset with me when she asked how she looked and I said "Fine".On 6/1/15 12:00 PM, deadalnix wrote:"Fine" as in "yes" :-) For non-native speakers, the use of "fine" is often confusing. "Fine" in American english means "you're wrong, but I won't argue the point." It does not signify endorsement.1/ .init for unions is not defined. I propose to define it as the .init of the first field + padding with 0s if the union is larger than its first member. It seems to be what is generated right now.Fine.So are you saying you think don't think they are mangled the same way, but that you don't want to bother arguing. CraigI think it's fine.8/ unions and structs are mangled the same way (or so it seems). Bug or feature ?Not sure. Walter?
Jun 01 2015
On 6/1/2015 2:17 PM, CraigDillabaugh wrote:Hah, I should have said that "fine" has the meaning reversed when it is used as a single word sentence. "Seems fine", or "That's fine" indicate approval.So are you saying you think don't think they are mangled the same way, but that you don't want to bother arguing.Not sure. Walter?I think it's fine.
Jun 01 2015
On Monday, 1 June 2015 at 22:45:55 UTC, Walter Bright wrote:On 6/1/2015 2:17 PM, CraigDillabaugh wrote:English is a wonderful language :)Hah, I should have said that "fine" has the meaning reversed when it is used as a single word sentence. "Seems fine", or "That's fine" indicate approval.So are you saying you think don't think they are mangled the same way, but that you don't want to bother arguing.Not sure. Walter?I think it's fine.
Jun 02 2015
On 6/2/2015 1:34 AM, wobbles wrote:On Monday, 1 June 2015 at 22:45:55 UTC, Walter Bright wrote:Reminds me of a friend who said he enjoyed programming the Z80. I said the Z80 was exceptionally complicated. He replied that's what he liked about it - he could make that processor sing like nobody else. Anybody could program a simple CPU. (He wrote software for arcade games back in the 70's.)On 6/1/2015 2:17 PM, CraigDillabaugh wrote:English is a wonderful language :)Hah, I should have said that "fine" has the meaning reversed when it is used as a single word sentence. "Seems fine", or "That's fine" indicate approval.So are you saying you think don't think they are mangled the same way, but that you don't want to bother arguing.Not sure. Walter?I think it's fine.
Jun 02 2015
On 6/1/15 5:02 PM, Walter Bright wrote:On 6/1/2015 12:43 PM, Andrei Alexandrescu wrote:Yes and no :) It all depends on the context and emotion. There is so little emotion in posts, and having one-word sentences doesn't help. Reading "Fine." in context of all of Andrei's other answers, I took it to mean "yeah, that's fine" -- i.e. "I agree"On 6/1/15 12:00 PM, deadalnix wrote:"Fine" as in "yes" :-) For non-native speakers, the use of "fine" is often confusing. "Fine" in American english means "you're wrong, but I won't argue the point." It does not signify endorsement.1/ .init for unions is not defined. I propose to define it as the .init of the first field + padding with 0s if the union is larger than its first member. It seems to be what is generated right now.Fine.I would make it clear here what you mean. I can't tell what "the rule" is (there may be 2 rules, or 1, but I can't tell), and whether Andrei agrees we should do it or not. -SteveI defer to Andrei's expertise here.5/ union currently disallow members with postblit and/or destructor . It seems that this was needed in C++ as per Andrei's comments. It seems to me that, because of manual memory management, C++ would have a lot more struct with copy constructor and/or destructor than in D, so I'm not sure if this require change in spec. Andrei, can you give more details on the C++ situation here ?That rule has hurt C++ everywhere, and the community credits Lois Goldthwaite for pushing the current rule, which allows types with cdtors in unions. Let's go the same way, unions are all but useless otherwise.
Jun 01 2015
On 6/1/15 2:22 PM, Steven Schveighoffer wrote:I would make it clear here what you mean. I can't tell what "the rule" is (there may be 2 rules, or 1, but I can't tell), and whether Andrei agrees we should do it or not.Unions should accept all types, including those with disabled or elaborated constructors/postblits/dtors. Essentially a union is appropriate storage for any type mentioned in its members, whilst leaving it to its user to write and read the needed values. -- Andrei
Jun 01 2015
On 6/1/15 5:36 PM, Andrei Alexandrescu wrote:On 6/1/15 2:22 PM, Steven Schveighoffer wrote:So what happens on destruction? What about postblit? This was the piece I'm not understanding. For D, requiring that a struct can be constructed statically is a win here. -SteveI would make it clear here what you mean. I can't tell what "the rule" is (there may be 2 rules, or 1, but I can't tell), and whether Andrei agrees we should do it or not.Unions should accept all types, including those with disabled or elaborated constructors/postblits/dtors. Essentially a union is appropriate storage for any type mentioned in its members, whilst leaving it to its user to write and read the needed values. -- Andrei
Jun 01 2015
On 6/1/15 2:40 PM, Steven Schveighoffer via Digitalmars-d wrote:On 6/1/15 5:36 PM, Andrei Alexandrescu wrote:I think the basic thinking is that these two should be semantically identical: struct(T) { T t; } and struct(T) { union { T } U; U t; } Having extra members inside the union certainly make the topic a little more complex, certainly, but the above should be a good base to start from.On 6/1/15 2:22 PM, Steven Schveighoffer wrote:So what happens on destruction? What about postblit? This was the piece I'm not understanding. For D, requiring that a struct can be constructed statically is a win here. -SteveI would make it clear here what you mean. I can't tell what "the rule" is (there may be 2 rules, or 1, but I can't tell), and whether Andrei agrees we should do it or not.Unions should accept all types, including those with disabled or elaborated constructors/postblits/dtors. Essentially a union is appropriate storage for any type mentioned in its members, whilst leaving it to its user to write and read the needed values. -- Andrei
Jun 01 2015
On 6/1/15 2:40 PM, Steven Schveighoffer wrote:So what happens on destruction?Nothing happens.What about postblit?Nothing happens. Andrei
Jun 01 2015
On 06/02/2015 01:55 AM, Andrei Alexandrescu wrote:On 6/1/15 2:40 PM, Steven Schveighoffer wrote:Is there an official way to invoke them manually?So what happens on destruction?Nothing happens.What about postblit?Nothing happens. Andrei
Jun 02 2015
On 6/2/15 3:43 AM, Timon Gehr wrote:On 06/02/2015 01:55 AM, Andrei Alexandrescu wrote:destroy calls the dtor. Just copying out the appropriate member invokes postblit on the target. Also emplace is good for construction. -- AndreiOn 6/1/15 2:40 PM, Steven Schveighoffer wrote:Is there an official way to invoke them manually?So what happens on destruction?Nothing happens.What about postblit?Nothing happens. Andrei
Jun 02 2015
On 06/02/2015 09:48 PM, Andrei Alexandrescu wrote:On 6/2/15 3:43 AM, Timon Gehr wrote:OK. What about copying in instead of out?On 06/02/2015 01:55 AM, Andrei Alexandrescu wrote:destroy calls the dtor. Just copying out the appropriate member invokes postblit on the target. Also emplace is good for construction. -- AndreiOn 6/1/15 2:40 PM, Steven Schveighoffer wrote:Is there an official way to invoke them manually?So what happens on destruction?Nothing happens.What about postblit?Nothing happens. Andrei
Jun 02 2015
On 6/2/15 2:57 PM, Timon Gehr wrote:OK. What about copying in instead of out?If the appropriate type has already been constructed, assignment suffices. Otherwise, emplace(&target, source) is needed. -- Andrei
Jun 02 2015
On 6/2/15 6:14 PM, Andrei Alexandrescu wrote:On 6/2/15 2:57 PM, Timon Gehr wrote:My concern is if you copy the enclosing type. This means you have already copied the bits, and the postblit of the enclosing type is responsible for calling the postblit of the valid union member (as defined by the semantics of the type). How does it do that? -SteveOK. What about copying in instead of out?If the appropriate type has already been constructed, assignment suffices. Otherwise, emplace(&target, source) is needed. -- Andrei
Jun 02 2015
On 6/2/15 3:42 PM, Steven Schveighoffer wrote:On 6/2/15 6:14 PM, Andrei Alexandrescu wrote:Copying unions as a whole won't do any miracles. Just memcpy. -- AndreiOn 6/2/15 2:57 PM, Timon Gehr wrote:My concern is if you copy the enclosing type. This means you have already copied the bits, and the postblit of the enclosing type is responsible for calling the postblit of the valid union member (as defined by the semantics of the type). How does it do that?OK. What about copying in instead of out?If the appropriate type has already been constructed, assignment suffices. Otherwise, emplace(&target, source) is needed. -- Andrei
Jun 02 2015
On 06/03/2015 01:07 AM, Andrei Alexandrescu wrote:On 6/2/15 3:42 PM, Steven Schveighoffer wrote:Copy is memcpy & postblit. If the bit-copy has already been done (e.g. execution is inside a postblit) emplace(&f,f) seems wasteful.On 6/2/15 6:14 PM, Andrei Alexandrescu wrote:Copying unions as a whole won't do any miracles. Just memcpy. -- AndreiOn 6/2/15 2:57 PM, Timon Gehr wrote:My concern is if you copy the enclosing type. This means you have already copied the bits, and the postblit of the enclosing type is responsible for calling the postblit of the valid union member (as defined by the semantics of the type). How does it do that?OK. What about copying in instead of out?If the appropriate type has already been constructed, assignment suffices. Otherwise, emplace(&target, source) is needed. -- Andrei
Jun 02 2015
On 6/2/15 4:14 PM, Timon Gehr wrote:On 06/03/2015 01:07 AM, Andrei Alexandrescu wrote:Oh, I only now understood the question. Yes, it's possible to only call postblit if defined: static if (hasElaborateCopyConstructor!T) tvar.__postblit(); AndreiOn 6/2/15 3:42 PM, Steven Schveighoffer wrote:Copy is memcpy & postblit. If the bit-copy has already been done (e.g. execution is inside a postblit) emplace(&f,f) seems wasteful.On 6/2/15 6:14 PM, Andrei Alexandrescu wrote:Copying unions as a whole won't do any miracles. Just memcpy. -- AndreiOn 6/2/15 2:57 PM, Timon Gehr wrote:My concern is if you copy the enclosing type. This means you have already copied the bits, and the postblit of the enclosing type is responsible for calling the postblit of the valid union member (as defined by the semantics of the type). How does it do that?OK. What about copying in instead of out?If the appropriate type has already been constructed, assignment suffices. Otherwise, emplace(&target, source) is needed. -- Andrei
Jun 02 2015
On 06/03/2015 02:51 AM, Andrei Alexandrescu wrote:On 6/2/15 4:14 PM, Timon Gehr wrote:Indeed, but I think this facility is undocumented. Maybe it should be exposed via the standard library?On 06/03/2015 01:07 AM, Andrei Alexandrescu wrote:Oh, I only now understood the question. Yes, it's possible to only call postblit if defined: static if (hasElaborateCopyConstructor!T) tvar.__postblit(); AndreiOn 6/2/15 3:42 PM, Steven Schveighoffer wrote:Copy is memcpy & postblit. If the bit-copy has already been done (e.g. execution is inside a postblit) emplace(&f,f) seems wasteful.On 6/2/15 6:14 PM, Andrei Alexandrescu wrote:Copying unions as a whole won't do any miracles. Just memcpy. -- AndreiOn 6/2/15 2:57 PM, Timon Gehr wrote:My concern is if you copy the enclosing type. This means you have already copied the bits, and the postblit of the enclosing type is responsible for calling the postblit of the valid union member (as defined by the semantics of the type). How does it do that?OK. What about copying in instead of out?If the appropriate type has already been constructed, assignment suffices. Otherwise, emplace(&target, source) is needed. -- Andrei
Jun 02 2015
On 6/2/15 8:53 PM, Timon Gehr wrote:On 06/03/2015 02:51 AM, Andrei Alexandrescu wrote:The sad part is, I knew this :(Oh, I only now understood the question. Yes, it's possible to only call postblit if defined: static if (hasElaborateCopyConstructor!T) tvar.__postblit();Indeed, but I think this facility is undocumented. Maybe it should be exposed via the standard library?I don't see the need. It's simply the name of the compiled member. I think it should be documented, however. -Steve
Jun 02 2015
On 6/2/15 5:53 PM, Timon Gehr wrote:Indeed, but I think this facility is undocumented. Maybe it should be exposed via the standard library?A good idea, please bugzilla so we don't forget. -- Andrei
Jun 02 2015
On 06/03/2015 03:47 AM, Andrei Alexandrescu wrote:On 6/2/15 5:53 PM, Timon Gehr wrote:https://issues.dlang.org/show_bug.cgi?id=14646Indeed, but I think this facility is undocumented. Maybe it should be exposed via the standard library?A good idea, please bugzilla so we don't forget. -- Andrei
Jun 03 2015
On 6/1/15 2:02 PM, Walter Bright wrote:For non-native speakers, the use of "fine" is often confusing. "Fine" in American english means "you're wrong, but I won't argue the point." It does not signify endorsement.Thanks for the lesson. Indeed I did mean it as "yes". -- Andrei
Jun 01 2015
On 6/1/15 2:02 PM, Walter Bright wrote:What should we do here then? -- AndreiNo.3/ union and safe is currently undefined. I proposed to make everything involving unions system, and we will figure it out from there.
Jun 01 2015
On Monday, 1 June 2015 at 21:32:32 UTC, Andrei Alexandrescu wrote:On 6/1/15 2:02 PM, Walter Bright wrote:The fact that we essentially decided that everything was safe until proven otherwise - i.e. used a blacklist for safety rather than a whitelist - has already proven to be a problem in that we keep missing stuff, and changing the rules later (like we will need to fix safety issues) will break existing code. It minimum, if we're not sure that something is safe, we need to make it system. As it stands, we've definitely dropped the ball on this. https://issues.dlang.org/show_bug.cgi?id=8838 is one example of that. - Jonathan M DavisWhat should we do here then? -- AndreiNo.3/ union and safe is currently undefined. I proposed to make everything involving unions system, and we will figure it out from there.
Jun 01 2015
On 6/1/2015 2:32 PM, Andrei Alexandrescu wrote:On 6/1/15 2:02 PM, Walter Bright wrote:There's nothing unsafe about: union { char c; int i; }What should we do here then? -- AndreiNo.3/ union and safe is currently undefined. I proposed to make everything involving unions system, and we will figure it out from there.
Jun 01 2015
On 6/1/15 3:44 PM, Walter Bright wrote:On 6/1/2015 2:32 PM, Andrei Alexandrescu wrote:Sounds good, no indirection => safety is in good shape. -- AndreiOn 6/1/15 2:02 PM, Walter Bright wrote:There's nothing unsafe about: union { char c; int i; }What should we do here then? -- AndreiNo.3/ union and safe is currently undefined. I proposed to make everything involving unions system, and we will figure it out from there.
Jun 01 2015
On Monday, 1 June 2015 at 19:43:33 UTC, Andrei Alexandrescu wrote:Do not define constructors. They ostensibly imply commitment to remembering to call the appropriate destructor. A union can only be default constructed (with its init value as described) and has no destructor.This is implied in C++ because of manual memory management. I don't think it is in D.Without knowing the rationale in C++, it is difficult to assert that this is also valid in D. You seems to be knowledgeable of the subject, so surely you can enlight us on that one.5/ union currently disallow members with postblit and/or destructor . It seems that this was needed in C++ as per Andrei's comments. It seems to me that, because of manual memory management, C++ would have a lot more struct with copy constructor and/or destructor than in D, so I'm not sure if this require change in spec. Andrei, can you give more details on the C++ situation here ?That rule has hurt C++ everywhere, and the community credits Lois Goldthwaite for pushing the current rule, which allows types with cdtors in unions. Let's go the same way, unions are all but useless otherwise.Compiler generated tuples are auto flattening in D. That would not work unless the entry in the struct tuple is an (compiler generated) union.7/ struct with anonymous union in them have one entry per union field in their tupleof. All the union field should be present as one entry in the tupleof, with a compiler generated union type.Again the litmus test here is enabling introspection. Structs with anonymous union members should have one member called e.g. __anonymous__ in their tupleof, and in turn introspecting that member should list its tuple.Indeed, max is the same thing, but because of plateform specific characteristics. I don't think we should rely on them unless we need to (implementation can still use max).9/ union alignement is not specified. union align should be least common multiple of union's fields.Yes. Since they're all powers of 2, taking the max is the same thing. BTW, to my surprise on OSX real.alignof is 16, but the alignof a union containing a real is 8. I think that's a bug. Please verify and file.
Jun 01 2015
On 6/1/15 3:43 PM, deadalnix wrote:On Monday, 1 June 2015 at 19:43:33 UTC, Andrei Alexandrescu wrote:It is because destructors exist in both languages.Do not define constructors. They ostensibly imply commitment to remembering to call the appropriate destructor. A union can only be default constructed (with its init value as described) and has no destructor.This is implied in C++ because of manual memory management. I don't think it is in D.I intentionally gave enough information to allow easy further research. http://goo.gl/19Nol5 lists N2412 and N2248 as top hits, their motivation sections are relevant.Without knowing the rationale in C++, it is difficult to assert that this is also valid in D. You seems to be knowledgeable of the subject, so surely you can enlight us on that one.5/ union currently disallow members with postblit and/or destructor . It seems that this was needed in C++ as per Andrei's comments. It seems to me that, because of manual memory management, C++ would have a lot more struct with copy constructor and/or destructor than in D, so I'm not sure if this require change in spec. Andrei, can you give more details on the C++ situation here ?That rule has hurt C++ everywhere, and the community credits Lois Goldthwaite for pushing the current rule, which allows types with cdtors in unions. Let's go the same way, unions are all but useless otherwise.So it seems like generating an __anonymous__ name is the way to go. AndreiCompiler generated tuples are auto flattening in D. That would not work unless the entry in the struct tuple is an (compiler generated) union.7/ struct with anonymous union in them have one entry per union field in their tupleof. All the union field should be present as one entry in the tupleof, with a compiler generated union type.Again the litmus test here is enabling introspection. Structs with anonymous union members should have one member called e.g. __anonymous__ in their tupleof, and in turn introspecting that member should list its tuple.
Jun 01 2015
On Tuesday, 2 June 2015 at 00:11:09 UTC, Andrei Alexandrescu wrote:On 6/1/15 3:43 PM, deadalnix wrote:It is common in D to have a struct with a constructor and no destructor.On Monday, 1 June 2015 at 19:43:33 UTC, Andrei Alexandrescu wrote:It is because destructors exist in both languages.Do not define constructors. They ostensibly imply commitment to remembering to call the appropriate destructor. A union can only be default constructed (with its init value as described) and has no destructor.This is implied in C++ because of manual memory management. I don't think it is in D.The abstract of the 2 above mentioned link only discuss the *constructor* case. It was never question of struct with constructor not being able to be in union. You attitude is only weakening your point.I intentionally gave enough information to allow easy further research. http://goo.gl/19Nol5 lists N2412 and N2248 as top hits, their motivation sections are relevant.Without knowing the rationale in C++, it is difficult to assert that this is also valid in D. You seems to be knowledgeable of the subject, so surely you can enlight us on that one.5/ union currently disallow members with postblit and/or destructor . It seems that this was needed in C++ as per Andrei's comments. It seems to me that, because of manual memory management, C++ would have a lot more struct with copy constructor and/or destructor than in D, so I'm not sure if this require change in spec. Andrei, can you give more details on the C++ situation here ?That rule has hurt C++ everywhere, and the community credits Lois Goldthwaite for pushing the current rule, which allows types with cdtors in unions. Let's go the same way, unions are all but useless otherwise.
Jun 01 2015
On 6/1/15 7:18 PM, deadalnix wrote:On Tuesday, 2 June 2015 at 00:11:09 UTC, Andrei Alexandrescu wrote:Probably there's a misunderstanding then. I'm saying the right way to go is unions have no destructors at all.On 6/1/15 3:43 PM, deadalnix wrote:It is common in D to have a struct with a constructor and no destructor.On Monday, 1 June 2015 at 19:43:33 UTC, Andrei Alexandrescu wrote:It is because destructors exist in both languages.Do not define constructors. They ostensibly imply commitment to remembering to call the appropriate destructor. A union can only be default constructed (with its init value as described) and has no destructor.This is implied in C++ because of manual memory management. I don't think it is in D.Then again sorry I am misunderstanding something. I'm saying the right way to go is unions accept all types.The abstract of the 2 above mentioned link only discuss the *constructor* case. It was never question of struct with constructor not being able to be in union.I intentionally gave enough information to allow easy further research. http://goo.gl/19Nol5 lists N2412 and N2248 as top hits, their motivation sections are relevant.Without knowing the rationale in C++, it is difficult to assert that this is also valid in D. You seems to be knowledgeable of the subject, so surely you can enlight us on that one.5/ union currently disallow members with postblit and/or destructor . It seems that this was needed in C++ as per Andrei's comments. It seems to me that, because of manual memory management, C++ would have a lot more struct with copy constructor and/or destructor than in D, so I'm not sure if this require change in spec. Andrei, can you give more details on the C++ situation here ?That rule has hurt C++ everywhere, and the community credits Lois Goldthwaite for pushing the current rule, which allows types with cdtors in unions. Let's go the same way, unions are all but useless otherwise.You attitude is only weakening your point.I'm not making a point. There is no debate. You said you want to work on unions, that would be great. But this is a cut and dried area. There's no room for creativity here. If you want to be creative and design new programming language facilities, do something else. For unions do what needs be done. Thanks, Andrei
Jun 01 2015
On Tuesday, 2 June 2015 at 02:32:55 UTC, Andrei Alexandrescu wrote:On 6/1/15 7:18 PM, deadalnix wrote:No, I asked you what is the rationale used to get types with postblit/destructor in unions (right now, the spec says no). I asked about the rationale for introduction of element with destructor/copy constructor in C++, but it turns out that the link provided also include constructor, and, in fact, only explore the constructor case in the rationale. It is important to consider why C++ did something to know if it makes sense to import it in D. I remind you that this is a change that you propose to the current state of affairs, meaning the burden of proof in on you.On Tuesday, 2 June 2015 at 00:11:09 UTC, Andrei Alexandrescu wrote:Probably there's a misunderstanding then. I'm saying the right way to go is unions have no destructors at all.On 6/1/15 3:43 PM, deadalnix wrote:It is common in D to have a struct with a constructor and no destructor.On Monday, 1 June 2015 at 19:43:33 UTC, Andrei Alexandrescu wrote:It is because destructors exist in both languages.Do not define constructors. They ostensibly imply commitment to remembering to call the appropriate destructor. A union can only be default constructed (with its init value as described) and has no destructor.This is implied in C++ because of manual memory management. I don't think it is in D.You are saying this. Many on that thread said otherwise. I personally have no strong opinion one way or another. That is why I'm asking about what makes you think element with postblit/destructor needs to be accepted in unions, in order to have all elements I needs to have an informed opinion. Right now I'm not getting any of it, and instead I'm getting confrontation. That is not productive.Then again sorry I am misunderstanding something. I'm saying the right way to go is unions accept all types.The abstract of the 2 above mentioned link only discuss the *constructor* case. It was never question of struct with constructor not being able to be in union.I intentionally gave enough information to allow easy further research. http://goo.gl/19Nol5 lists N2412 and N2248 as top hits, their motivation sections are relevant.Without knowing the rationale in C++, it is difficult to assert that this is also valid in D. You seems to be knowledgeable of the subject, so surely you can enlight us on that one.5/ union currently disallow members with postblit and/or destructor . It seems that this was needed in C++ as per Andrei's comments. It seems to me that, because of manual memory management, C++ would have a lot more struct with copy constructor and/or destructor than in D, so I'm not sure if this require change in spec. Andrei, can you give more details on the C++ situation here ?That rule has hurt C++ everywhere, and the community credits Lois Goldthwaite for pushing the current rule, which allows types with cdtors in unions. Let's go the same way, unions are all but useless otherwise.That is dishonest. First because there is almost no spec - so there is much to debate, second because what you propose is different from what is describe in the little spec there is (literally, no postblit/destructor in the union or its elements is the only that is specified). Please stop projecting. You are the one being creative here.You attitude is only weakening your point.I'm not making a point. There is no debate. You said you want to work on unions, that would be great. But this is a cut and dried area. There's no room for creativity here. If you want to be creative and design new programming language facilities, do something else. For unions do what needs be done.
Jun 01 2015
On 6/1/15 9:46 PM, deadalnix wrote:No, I asked you what is the rationale used to get types with postblit/destructor in unions (right now, the spec says no). I asked about the rationale for introduction of element with destructor/copy constructor in C++, but it turns out that the link provided also include constructor, and, in fact, only explore the constructor case in the rationale.From http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2248.html: ======== Unfortunately this brute-force approach cannot be extended to every user-defined type that a programmer might want to pass around transparently. As class types, unions are definitely second class: although a union may define a constructor and destructor for instances of its type, the standard does not allow it to contain any member whose default constructor, copy constructor, copy assignment operator, or destructor are non-trivial. The reason for these tight restrictions is obvious -- the compiler can hardly be expected to generate sensible default special member functions for an object whose type will only become known at run time, and therefore a "lowest-common-denominator" policy applies. With the rules in place, default initialization is effectively a no-op, likewise destruction, and copying is performed using a low-level memcpy. This rules out the inclusion of "interesting" types, or else requires the programmer to ignore good design practice in order to make them conform to the straightjacket of trivial types (see discussion in N2172). And yet the need for a "variant" data structure that can hold one object of a set of unrelated types is a problem that arises over and over [...] ======== There are others to be found in related docs. The simple explanation is that non-discriminated unions are most useful as unstructured bags that allow their users to plant their own types in whilst keeping their discriminant elsewhere. Planting either gratuitous restrictions on the storable data, or smarts regarding construction and destruction, simply reduces the range of things that unions are good at. I don't know how to explain this better.It is important to consider why C++ did something to know if it makes sense to import it in D. I remind you that this is a change that you propose to the current state of affairs, meaning the burden of proof in on you.Fair enough.The same explanation as above stands. AndreiThen again sorry I am misunderstanding something. I'm saying the right way to go is unions accept all types.You are saying this. Many on that thread said otherwise. I personally have no strong opinion one way or another. That is why I'm asking about what makes you think element with postblit/destructor needs to be accepted in unions, in order to have all elements I needs to have an informed opinion.
Jun 01 2015
On Tuesday, 2 June 2015 at 05:07:43 UTC, Andrei Alexandrescu wrote:On 6/1/15 9:46 PM, deadalnix wrote:It is unfortunate that the explanation do not go over the constructor but no desturctor case (way more common in D than in C++). I think the case is not as strong for D, as a we already allow struct with constructor, contrary to C++ when this document was done. Still probably the right way forward, granted this is system. When you are in union land, you are pretty much on your own anyway.No, I asked you what is the rationale used to get types with postblit/destructor in unions (right now, the spec says no). I asked about the rationale for introduction of element with destructor/copy constructor in C++, but it turns out that the link provided also include constructor, and, in fact, only explore the constructor case in the rationale.From http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2248.html: ======== Unfortunately this brute-force approach cannot be extended to every user-defined type that a programmer might want to pass around transparently. As class types, unions are definitely second class: although a union may define a constructor and destructor for instances of its type, the standard does not allow it to contain any member whose default constructor, copy constructor, copy assignment operator, or destructor are non-trivial. The reason for these tight restrictions is obvious -- the compiler can hardly be expected to generate sensible default special member functions for an object whose type will only become known at run time, and therefore a "lowest-common-denominator" policy applies. With the rules in place, default initialization is effectively a no-op, likewise destruction, and copying is performed using a low-level memcpy. This rules out the inclusion of "interesting" types, or else requires the programmer to ignore good design practice in order to make them conform to the straightjacket of trivial types (see discussion in N2172). And yet the need for a "variant" data structure that can hold one object of a set of unrelated types is a problem that arises over and over [...] ======== There are others to be found in related docs. The simple explanation is that non-discriminated unions are most useful as unstructured bags that allow their users to plant their own types in whilst keeping their discriminant elsewhere. Planting either gratuitous restrictions on the storable data, or smarts regarding construction and destruction, simply reduces the range of things that unions are good at. I don't know how to explain this better.
Jun 02 2015
On 2 June 2015 at 05:00, deadalnix via Digitalmars-d <digitalmars-d puremagic.com> wrote:After discussion at DConf, it ends up that union have some lack of specification, and some nonsensical behavior right now. Here are some points discussed and possible solutions : 1/ .init for unions is not defined. I propose to define it as the .init of the first field + padding with 0s if the union is larger than its first member. It seems to be what is generated right now.Isn't it the case that some of the members of a union need to be declared with init =void, such that only one version of the union provides the init values? At that point, isn't the state of init clearly defined by the members that aren't =void?
Jun 02 2015
On 6/2/15 1:48 AM, Manu via Digitalmars-d wrote:On 2 June 2015 at 05:00, deadalnix via Digitalmars-d <digitalmars-d puremagic.com> wrote:That could be done, but strikes me as too clever for its own good. -- AndreiAfter discussion at DConf, it ends up that union have some lack of specification, and some nonsensical behavior right now. Here are some points discussed and possible solutions : 1/ .init for unions is not defined. I propose to define it as the .init of the first field + padding with 0s if the union is larger than its first member. It seems to be what is generated right now.Isn't it the case that some of the members of a union need to be declared with init =void, such that only one version of the union provides the init values? At that point, isn't the state of init clearly defined by the members that aren't =void?
Jun 02 2015
On 6/2/15 6:50 PM, Andrei Alexandrescu wrote:On 6/2/15 1:48 AM, Manu via Digitalmars-d wrote:It's actually unnecessarily redundant. In all cases, you can simply move the "valid" one to the first member. Initing the first member is the right call. -SteveOn 2 June 2015 at 05:00, deadalnix via Digitalmars-d <digitalmars-d puremagic.com> wrote:That could be done, but strikes me as too clever for its own good. -- AndreiAfter discussion at DConf, it ends up that union have some lack of specification, and some nonsensical behavior right now. Here are some points discussed and possible solutions : 1/ .init for unions is not defined. I propose to define it as the .init of the first field + padding with 0s if the union is larger than its first member. It seems to be what is generated right now.Isn't it the case that some of the members of a union need to be declared with init =void, such that only one version of the union provides the init values? At that point, isn't the state of init clearly defined by the members that aren't =void?
Jun 02 2015
On 3 June 2015 at 08:50, Andrei Alexandrescu via Digitalmars-d <digitalmars-d puremagic.com> wrote:On 6/2/15 1:48 AM, Manu via Digitalmars-d wrote:Right. See, I thought that's just how it already was ;) I recall writing some union code and having compile errors, and being required to resolve it by setting =void to all the members in conflict, effectively making the initialisation of the union explicit.On 2 June 2015 at 05:00, deadalnix via Digitalmars-d <digitalmars-d puremagic.com> wrote:That could be done, but strikes me as too clever for its own good. -- AndreiAfter discussion at DConf, it ends up that union have some lack of specification, and some nonsensical behavior right now. Here are some points discussed and possible solutions : 1/ .init for unions is not defined. I propose to define it as the .init of the first field + padding with 0s if the union is larger than its first member. It seems to be what is generated right now.Isn't it the case that some of the members of a union need to be declared with init =void, such that only one version of the union provides the init values? At that point, isn't the state of init clearly defined by the members that aren't =void?
Jun 02 2015