digitalmars.D - Getting action on your favorite D issues
- Walter Bright (9/9) Jun 05 2020 If you've got problems using D that should be fixed:
- ag0aep6g (29/31) Jun 05 2020 How frequent is "now and then"? Like, once a month? Once a year?
- Walter Bright (3/7) Jun 05 2020 Everybody's idea of what is important and what is not is different.
- mw (5/7) Jun 05 2020 Actually I'm wondering if we can have a web poll widget
- H. S. Teoh (10/16) Jun 05 2020 [...]
- Walter Bright (4/8) Jun 05 2020 You can already vote on Bugzilla issues.
- aberba (15/24) Jun 06 2020 So being here for a while, I've only had to figure out for myself
- ag0aep6g (2/3) Jun 06 2020 No you can't. The feature was disabled or removed at some point.
- Joseph Rushton Wakeling (4/7) Jun 06 2020 I'm not sure if voting is necessarily the best way to prioritize,
- H. S. Teoh (37/41) Jun 05 2020 [...]
- TheGag96 (30/32) Jun 05 2020 I actually encountered something goofy like this a few weeks ago
- Patrick Schluter (15/53) Jun 06 2020 XOR AL,1 gives "not zero"
- Stanislav Blinov (3/5) Jun 06 2020 Indeed, the code generator is not at fault. But, in the bug
- Avrina (14/26) Jun 06 2020 With statements like this I always feel like people don't
- ag0aep6g (15/22) Jun 06 2020 I'm not so sure if you really understand what "undefined behavior" means...
- Patrick Schluter (5/25) Jun 06 2020 The interesting thing is that the compiler detects that case when
- Avrina (15/41) Jun 06 2020 So your saying void initializers don't have a defined function
- ag0aep6g (19/40) Jun 06 2020 It's not void initializers themselves that have undefined
- Avrina (36/79) Jun 07 2020 g is defined behavior, or it wouldn't work. The result may not be
- ag0aep6g (40/79) Jun 07 2020 Per the current spec, g has undefined behavior. Yes, a compiler
- Avrina (13/27) Jun 07 2020 I think we agree on about everything else.
- Timon Gehr (6/37) Jun 07 2020 Reading a trap representation is UB in C++, so reading an uninitialized
- Joseph Rushton Wakeling (8/15) Jun 06 2020 Which makes me ask: what _does_ "undefined behaviour" mean
- Timon Gehr (18/35) Jun 06 2020 You have to read it in context. The PR attempts to change accessing
- Joseph Rushton Wakeling (12/15) Jun 06 2020 The C99 standard has better terminology, though: it describes it
- Patrick Schluter (14/41) Jun 06 2020 Then it is also a bug in llvm and gcc as they generate the code
- Avrina (9/57) Jun 06 2020 No, that's why LDC doesn't have the same issue. D is suppose to
- H. S. Teoh (28/38) Jun 05 2020 [...]
- David Gileadi (2/48) Jun 05 2020 These two posts made me very amused. Thank you.
- mw (5/6) Jun 05 2020 I just said few days ago: D is fun to work with everyday!
- Meta (6/44) Jun 05 2020 The linked defect, and the issue you posted, don't really make
- Timon Gehr (2/7) Jun 05 2020 Right. It's in @safe code.
- Meta (4/12) Jun 06 2020 Ah, yes, I missed that. Why the hell is = void allowed in @safe
- Paul Backus (7/21) Jun 06 2020 Iirc it's only forbidden for pointers, because for other types
- ag0aep6g (9/19) Jun 06 2020 I had thought about special-casing bool there, precisely because of the
- Paul Backus (9/18) Jun 06 2020 It seems to me like (a) whether void initialization results in
- ag0aep6g (4/9) Jun 06 2020 That would be fine, yes. I just don't expect that Walter will
- Avrina (2/15) Jun 06 2020 Ironically, he argued it's for performance.
- Steven Schveighoffer (9/21) Jun 06 2020 int x = void;
- Joseph Rushton Wakeling (10/13) Jun 06 2020 Yes, which is presumably why the other example above -- using the
- Steven Schveighoffer (19/33) Jun 06 2020 There are two things here:
- Joseph Rushton Wakeling (5/7) Jun 06 2020 Doesn't that also apply to void-initialized values in the case
- Steven Schveighoffer (15/22) Jun 06 2020 Yes, it's the same thing. This is why I specifically said that the case ...
- Joseph Rushton Wakeling (9/23) Jun 06 2020 Ahh, gotcha. I didn't quite follow the nuances there before.
- Paul Backus (19/39) Jun 06 2020 Here's the definition of "trap representation" from the C99
- Steven Schveighoffer (14/15) Jun 07 2020 Consider an integer which represents the length of an array. Instead of
- ag0aep6g (6/20) Jun 07 2020 For reference, there's a DIP being written to address this issue:
- Alex (23/26) Jun 06 2020 Sorry, but I have another one. The point in Schrödinger's matter
- Patrick Schluter (8/42) Jun 06 2020 Undefined behaviour. This said, there is a real code generation
- Stefan Koch (5/17) Jun 06 2020 I have one that I really can't fix myself.
- Stefan Koch (3/10) Jun 06 2020 bugzilla: https://issues.dlang.org/show_bug.cgi?id=20839
- Joseph Rushton Wakeling (31/41) Jun 06 2020 All good and right to do of course. But one thing that could
- Andrej Mitrovic (14/26) Jun 06 2020 I'd also say just make it a habit of filing bugs! It's really
- Andrej Mitrovic (4/5) Jun 06 2020 And one tiny correction here, I meant issues, not bugs. Most were
If you've got problems using D that should be fixed: 1. File bugzilla issue for them. Issues not in bugzilla don't get fixed. 2. When talking about the issue, provide a link to the bugzilla issue so we know what you're talking about and know what the current status is. 3. If you have a laundry list of issues that are important to you, keep a list of bugzilla issue links to them. Then, when you are asked about what problems you're having, cut&paste that list. Bring them up now and then. It's that simple!
Jun 05 2020
On 05.06.20 22:35, Walter Bright wrote:1. File bugzilla issue for them. Issues not in bugzilla don't get fixed.[...]Bring them up now and then.How frequent is "now and then"? Like, once a month? Once a year? Ideally, you would be prioritizing issues based on severity and impact. If you only fix the issues that people nag you about, you risk leaving serious bugs unattended. Anyway, here are some personal favorites: 1) The DIP 1000 implementation has a glaring accepts-invalid bug with `pure` functions. https://issues.dlang.org/show_bug.cgi?id=20150 In my opinion, this one is a blocker for DIP 1000. And unfortunately, it probably made DIP 1000 look better than it is. 2) "bool can be both true and false" https://issues.dlang.org/show_bug.cgi?id=20148 This one is just silly. 3) DMD's codegen for the BT (bit test) instruction is all kinds of wrong. https://issues.dlang.org/show_bug.cgi?id=18750 A testimony for the questionable quality of DMD's backend. 4) "import doesn't verify module declaration" https://issues.dlang.org/show_bug.cgi?id=15086 This accepts-invalid (and arguably wrong-code) issue had some lively discussion years ago. There was a PR, the issue was closed as invalid, it was reopened. And finally it was forgotten. 5) std.stdio tries converting between different UTF variants, but fails horribly. https://issues.dlang.org/show_bug.cgi?id=18789 and https://issues.dlang.org/show_bug.cgi?id=18801 I tried fixing this one but got stuck when I couldn't reproduce the failures on Windows that the auto-tester shows.
Jun 05 2020
On 6/5/2020 2:57 PM, ag0aep6g wrote:How frequent is "now and then"? Like, once a month? Once a year?If you start annoying people, then it's too often.Ideally, you would be prioritizing issues based on severity and impact. If you only fix the issues that people nag you about, you risk leaving serious bugs unattended.Everybody's idea of what is important and what is not is different.
Jun 05 2020
On Friday, 5 June 2020 at 22:50:35 UTC, Walter Bright wrote:Everybody's idea of what is important and what is not is different.Actually I'm wondering if we can have a web poll widget somewhere, so people can vote on the priority of bugs / features / DIPs? Better be on the front page of https://forum.dlang.org ?
Jun 05 2020
On Sat, Jun 06, 2020 at 12:01:46AM +0000, mw via Digitalmars-d wrote:On Friday, 5 June 2020 at 22:50:35 UTC, Walter Bright wrote:[...] Polls are a dime a dozen, but rarely lead to any actual change. What actually makes a difference is someone who's willing to put in the time and effort to actually work on these bugs, or at least dig further into them to obtain more useful, actionable information. Just sayin', from past experience. T -- Computerese Irregular Verb Conjugation: I have preferences. You have biases. He/She has prejudices. -- Gene WirchenkoEverybody's idea of what is important and what is not is different.Actually I'm wondering if we can have a web poll widget somewhere, so people can vote on the priority of bugs / features / DIPs?
Jun 05 2020
On 6/5/2020 5:01 PM, mw wrote:Actually I'm wondering if we can have a web poll widget somewhere, so people can vote on the priority of bugs / features / DIPs? Better be on the front page of https://forum.dlang.org ?You can already vote on Bugzilla issues. But what matters is finding someone with the time, interest, and expertise to address each problem.
Jun 05 2020
On Saturday, 6 June 2020 at 02:41:51 UTC, Walter Bright wrote:On 6/5/2020 5:01 PM, mw wrote:So being here for a while, I've only had to figure out for myself this, that the D contributors are not enough to handle the incoming bug reports so only the most critical bug are first considered making the others fall behind. So I'll say there's a need for more pull requests. But are pull requests getting through considering you have absolute control over most decisions and... honestly not familiar with most other user programming domains... like network, utilities, helpers, and other issues you may not encounter yourself writing compiler code...also stuff Andre had been join more of previously~ ? Whatever be the case, we're always short of hands. Unfortunately some of us have zero usefulness beyound regular application code... rarely encountering 99% of issues here.Actually I'm wondering if we can have a web poll widget somewhere, so people can vote on the priority of bugs / features / DIPs? Better be on the front page of https://forum.dlang.org ?You can already vote on Bugzilla issues. But what matters is finding someone with the time, interest, and expertise to address each problem.
Jun 06 2020
On 06.06.20 04:41, Walter Bright wrote:You can already vote on Bugzilla issues.No you can't. The feature was disabled or removed at some point.
Jun 06 2020
On Saturday, 6 June 2020 at 13:08:06 UTC, ag0aep6g wrote:On 06.06.20 04:41, Walter Bright wrote:Yeah, though hopefully with the in-progress migration to GitHub issues voting will soon be possible again, see e.g. https://github.com/dlang/tools/issues/411You can already vote on Bugzilla issues.No you can't. The feature was disabled or removed at some point.
Jun 06 2020
On Saturday, 6 June 2020 at 13:30:53 UTC, Seb wrote:On Saturday, 6 June 2020 at 13:08:06 UTC, ag0aep6g wrote:So should issues continue to be filed in bugzilla? Why not move new issues to GitHub directly?On 06.06.20 04:41, Walter Bright wrote:Yeah, though hopefully with the in-progress migration to GitHub issues voting will soon be possible again, see e.g. https://github.com/dlang/tools/issues/411You can already vote on Bugzilla issues.No you can't. The feature was disabled or removed at some point.
Jun 06 2020
On Saturday, 6 June 2020 at 00:01:46 UTC, mw wrote:Actually I'm wondering if we can have a web poll widget somewhere, so people can vote on the priority of bugs / features / DIPs?I'm not sure if voting is necessarily the best way to prioritize, although it probably is important to have some way to track how many people are affected by a given issue.
Jun 06 2020
On Fri, Jun 05, 2020 at 11:57:39PM +0200, ag0aep6g via Digitalmars-d wrote: [...]2) "bool can be both true and false" https://issues.dlang.org/show_bug.cgi?id=20148 This one is just silly.[...] Nah, it's not silly, it's just that DMD's backend produces code that exhibits quantum uncertainty: ----------------- bool schrodingersCat() safe { union Box { bool b; int spin; } Box u; u.spin = 2; return u.b; } void main() safe { import std.stdio; bool b = schrodingersCat(); if (b) writeln("alive"); if (!b) writeln("dead"); } ----------------- Output: ----------------- alive dead ----------------- :-D Unfortunately, LDC's backend seems a lot more classical, as the above code produces this output with absolute certainty: Output: ----------------- dead ----------------- Truly, DMD's backend is in the bright future of strange and wonderful quantum effects, whereas LDC is clearly still stuck in the antiquated classical past. ;-) T -- Recently, our IT department hired a bug-fix engineer. He used to work for Volkswagen.
Jun 05 2020
On Friday, 5 June 2020 at 23:53:28 UTC, H. S. Teoh wrote:Nah, it's not silly, it's just that DMD's backend produces code that exhibits quantum uncertainty:I actually encountered something goofy like this a few weeks ago when working on my 3DS homebrew, compiling with LDC. I started failing an assert in a game entity's frame logic function that checks two numbers for equality that I knew totally should have been going through. Right before the assert, I added code that looked like this, just to check my sanity: if (a != b) { printf("%d %d %d\n", a, b, a == b); foreach (i; 0..10) { printf("%d %d %d\n", a, b, a == b); } } The result was, I kid you not, something like this: 1234 1234 0 1234 1234 1 1234 1234 1 1234 1234 1 1234 1234 1 1234 1234 1 1234 1234 1 1234 1234 1 1234 1234 1 1234 1234 1 1234 1234 1 I was probably hitting UB somewhere... I slap all my entity instances together in an array where the element size is the size of the biggest entity type, using a union to accomplish that. After shifting some code around, it went away, and I haven't seen it since. Spooky...!
Jun 05 2020
On Friday, 5 June 2020 at 23:53:28 UTC, H. S. Teoh wrote:On Fri, Jun 05, 2020 at 11:57:39PM +0200, ag0aep6g via Digitalmars-d wrote: [...]TEST AL,AL gives "not zero"2) "bool can be both true and false" https://issues.dlang.org/show_bug.cgi?id=20148 This one is just silly.[...] Nah, it's not silly, it's just that DMD's backend produces code that exhibits quantum uncertainty: ----------------- bool schrodingersCat() safe { union Box { bool b; int spin; } Box u; u.spin = 2; return u.b; } void main() safe { import std.stdio; bool b = schrodingersCat(); if (b) writeln("alive"); if (!b) writeln("dead"); } ----------------- Output: ----------------- alivedeadXOR AL,1 gives "not zero" xor al,1 is faster than NOT AL => stupid Intel prefered to not change flags TEST AL,AL----------------- :-D Unfortunately, LDC's backend seems a lot more classical, as the above code produces this output with absolute certainty:optimizing LDC is so smart that it compiled main down to writeln("dead"); non optimizing it inserts a (b&1) before testing which explains while the optimizer completely remove the test. GDC does a cmp,0 for the first test and then a xor 1+test unoptimized but when optimizing it only does first condition with a TEST AL,AL but then prints always the second string.Output: ----------------- dead ----------------- Truly, DMD's backend is in the bright future of strange and wonderful quantum effects, whereas LDC is clearly still stuck in the antiquated classical past. ;-)Sorry, but undefined behaviour is undefined behaviour. The dmd code generator is not at fault here.
Jun 06 2020
On Saturday, 6 June 2020 at 10:09:07 UTC, Patrick Schluter wrote:Sorry, but undefined behaviour is undefined behaviour. The dmd code generator is not at fault here.Indeed, the code generator is not at fault. But, in the bug report, the code is annotated safe. Yet it compiles :)
Jun 06 2020
On Saturday, 6 June 2020 at 10:09:07 UTC, Patrick Schluter wrote:On Friday, 5 June 2020 at 23:53:28 UTC, H. S. Teoh wrote:With statements like this I always feel like people don't understand what "undefined behavior" means. All the void initializer does is not initialize the memory of the bool. DMD is testing more than a single bit for a type that is only a single bit, it flip flops between testing a byte and testing a bit. That is most definitely a bug in the DMD backend. Just to bring up an old debate, this has been argued to not be a bug and is defined behavior and *will not* be changed. void foo(bool); void foo(byte); foo(0); // calls bool foo(1); // calls bool foo(2); // calls byteOutput: ----------------- dead ----------------- Truly, DMD's backend is in the bright future of strange and wonderful quantum effects, whereas LDC is clearly still stuck in the antiquated classical past. ;-)Sorry, but undefined behaviour is undefined behaviour. The dmd code generator is not at fault here.
Jun 06 2020
On 06.06.20 16:34, Avrina wrote:On Saturday, 6 June 2020 at 10:09:07 UTC, Patrick Schluter wrote:[...]I'm not so sure if you really understand what "undefined behavior" means. By saying this:Sorry, but undefined behaviour is undefined behaviour. The dmd code generator is not at fault here.With statements like this I always feel like people don't understand what "undefined behavior" means.All the void initializer does is not initialize the memory of the bool.you're defining the behavior of using void initialized values. Once you do that, it's not undefined behavior anymore. But the spec doesn't do that. Instead it says: "If a void initialized variable's value is used before it is set, the behavior is undefined." That is, the spec explicitly says that doing so is not allowed, and that compilers may assume that it doesn't happen. Because that's what "undefined behavior" means. But Walter agrees with you: Using a void value shouldn't actually have undefined behavior; it should just be an arbitrary value. Which is why he has an open pull request to change the spec: https://github.com/dlang/dlang.org/pull/2260
Jun 06 2020
On Saturday, 6 June 2020 at 15:16:06 UTC, ag0aep6g wrote:On 06.06.20 16:34, Avrina wrote:The interesting thing is that the compiler detects that case when doing lifetime check, which is only enabled when optimizing. So the issue with the not initialized bool only happens on unoptimized code.[...][...][...]I'm not so sure if you really understand what "undefined behavior" means. By saying this:[...]you're defining the behavior of using void initialized values. Once you do that, it's not undefined behavior anymore. But the spec doesn't do that. Instead it says: "If a void initialized variable's value is used before it is set, the behavior is undefined." That is, the spec explicitly says that doing so is not allowed, and that compilers may assume that it doesn't happen. Because that's what "undefined behavior" means.But Walter agrees with you: Using a void value shouldn't actually have undefined behavior; it should just be an arbitrary value. Which is why he has an open pull request to change the spec: https://github.com/dlang/dlang.org/pull/2260
Jun 06 2020
On Saturday, 6 June 2020 at 15:16:06 UTC, ag0aep6g wrote:On 06.06.20 16:34, Avrina wrote:So your saying void initializers don't have a defined function then? So if LDC wants it could initialise the memory.of all void initialized variables to zero and that would be considered within defined behaviour? If void initializers are undefined behaviour then the feature is useless.On Saturday, 6 June 2020 at 10:09:07 UTC, Patrick Schluter wrote:[...]I'm not so sure if you really understand what "undefined behavior" means. By saying this:Sorry, but undefined behaviour is undefined behaviour. The dmd code generator is not at fault here.With statements like this I always feel like people don't understand what "undefined behavior" means.All the void initializer does is not initialize the memory of the bool.you're defining the behavior of using void initialized values. Once you do that, it's not undefined behavior anymore.But the spec doesn't do that. Instead it says: "If a void initialized variable's value is used before it is set, the behavior is undefined." That is, the spec explicitly says that doing so is not allowed, and that compilers may assume that it doesn't happen. Because that's what "undefined behavior" means.The spec is poorly written. The language doesn't do what's written in it for a lot of cases on top of that. It just means the compiler can choose to implement it in any way it wants. DMD chooses to treat a boolean as both a 1-bit integer and an 8-bit integer. That isn't consistent with its own implementation. There's no reason for it to to be consistent.But Walter agrees with you: Using a void value shouldn't actually have undefined behavior; it should just be an arbitrary value. Which is why he has an open pull request to change the spec: https://github.com/dlang/dlang.org/pull/2260Yea and that pull request is years old. If that change does go into effect then the spec will reflect the actual reality of what is happening.
Jun 06 2020
On Saturday, 6 June 2020 at 18:30:15 UTC, Avrina wrote:On Saturday, 6 June 2020 at 15:16:06 UTC, ag0aep6g wrote:[...]So your saying void initializers don't have a defined function then? So if LDC wants it could initialise the memory.of all void initialized variables to zero and that would be considered within defined behaviour? If void initializers are undefined behaviour then the feature is useless.It's not void initializers themselves that have undefined behavior. Using an uninitialized value has undefined behavior. In code: ---- int f() { int x = void; x = 42; return x + 1; } /* This is fine. */ int g() { int x = void; return x + 1; } /* This is not. */ ---- If LDC defines behavior for `g`, it creates a dialect of D which has less undefined behavior than (current) standard D.True. Which is why a lot of fixing needs to be done. Sometimes the spec needs to be changed, sometimes the implementation, sometimes both. [...]But the spec doesn't do that. Instead it says: "If a void initialized variable's value is used before it is set, the behavior is undefined." That is, the spec explicitly says that doing so is not allowed, and that compilers may assume that it doesn't happen. Because that's what "undefined behavior" means.The spec is poorly written. The language doesn't do what's written in it for a lot of cases on top of that.Sure. But as long as the PR is in limbo, Patrick Schluter has a point when he says that "undefined behaviour is undefined behaviour".But Walter agrees with you: Using a void value shouldn't actually have undefined behavior; it should just be an arbitrary value. Which is why he has an open pull request to change the spec: https://github.com/dlang/dlang.org/pull/2260Yea and that pull request is years old. If that change does go into effect then the spec will reflect the actual reality of what is happening.
Jun 06 2020
On Saturday, 6 June 2020 at 20:20:54 UTC, ag0aep6g wrote:On Saturday, 6 June 2020 at 18:30:15 UTC, Avrina wrote:g is defined behavior, or it wouldn't work. The result may not be known, but it is defined. Otherwise, what, a compiler could just insert anything they want there. An assert(0) that terminates the application. The issue isn't with void initializers. It is whether a bool should be treated as a byte or single bit. Void initialization just leads to the problem, there's many ways it can be expressed. Someone else has shown it with unions. You can also just use casts as well and you'll get the same problem. bool e() { int x = 2; return *cast(bool*)&x; } The issue with void initializers is that they aren't actually safe, just as I can't use cast's in safe code, I shouldn't be allowed to use void initializers in safe. Aside from that, it is still a problem because DMD's backend isn't consistent. Is bool a byte or a 1-bit integer. The decision has to be made and the backend fixed. The only thing in the spec I can find is that bool is a byte.On Saturday, 6 June 2020 at 15:16:06 UTC, ag0aep6g wrote:[...]So your saying void initializers don't have a defined function then? So if LDC wants it could initialise the memory.of all void initialized variables to zero and that would be considered within defined behaviour? If void initializers are undefined behaviour then the feature is useless.It's not void initializers themselves that have undefined behavior. Using an uninitialized value has undefined behavior. In code: ---- int f() { int x = void; x = 42; return x + 1; } /* This is fine. */ int g() { int x = void; return x + 1; } /* This is not. */ ---- If LDC defines behavior for `g`, it creates a dialect of D which has less undefined behavior than (current) standard D.No one is going to waste their time with that.True. Which is why a lot of fixing needs to be done. Sometimes the spec needs to be changed, sometimes the implementation, sometimes both.But the spec doesn't do that. Instead it says: "If a void initialized variable's value is used before it is set, the behavior is undefined." That is, the spec explicitly says that doing so is not allowed, and that compilers may assume that it doesn't happen. Because that's what "undefined behavior" means.The spec is poorly written. The language doesn't do what's written in it for a lot of cases on top of that.[...]It's not though. There is expected behavior for void initializers. Otherwise what you are saying is that C++ has undefined behavior for using variables that aren't initialized (which are all of them unless they are initialized first). But it doesn't. The behavior is expected. The root of the problem isn't with void initialization because the behavior is defined. The problem is with the boolean type and the loose definition the spec provides it. Boolean is undefined behavior in D, as long as the implementation in DMD and LDC differ, and there's nothing in the spec to define it. Like I said, the Spec doesn't follow what is actually implemented. If you are to say that, then I would say, it is defined behavior unless the DMD or LDC implementation changes in such as way that makes it undefined behavior. It is the spec that differs, it doesn't match the implementation. Hell even that pull request wouldn't accurately make it match what the implementation does.Sure. But as long as the PR is in limbo, Patrick Schluter has a point when he says that "undefined behaviour is undefined behaviour".But Walter agrees with you: Using a void value shouldn't actually have undefined behavior; it should just be an arbitrary value. Which is why he has an open pull request to change the spec: https://github.com/dlang/dlang.org/pull/2260Yea and that pull request is years old. If that change does go into effect then the spec will reflect the actual reality of what is happening.
Jun 07 2020
On Sunday, 7 June 2020 at 13:10:22 UTC, Avrina wrote:On Saturday, 6 June 2020 at 20:20:54 UTC, ag0aep6g wrote:[...]Per the current spec, g has undefined behavior. Yes, a compiler can just insert anything it wants there. Yes, it can replace the body of g with `assert(0);`. That's how undefined behavior works. Please consider the possibility that you might not fully understand what "undefined behavior" means.---- int f() { int x = void; x = 42; return x + 1; } /* This is fine. */ int g() { int x = void; return x + 1; } /* This is not. */ ---- If LDC defines behavior for `g`, it creates a dialect of D which has less undefined behavior than (current) standard D.g is defined behavior, or it wouldn't work. The result may not be known, but it is defined. Otherwise, what, a compiler could just insert anything they want there. An assert(0) that terminates the application.The issue isn't with void initializers. It is whether a bool should be treated as a byte or single bit. Void initialization just leads to the problem, there's many ways it can be expressed. Someone else has shown it with unions. You can also just use casts as well and you'll get the same problem. bool e() { int x = 2; return *cast(bool*)&x; }It's true that you can get exotic bools in other ways that also pass as safe. That's a valid counter to Patrick Schluter's remark about undefined behavior. If we look at an example that has undefined behavior (per the spec), then Patrick is right that we can't expect any particular result. With undefined behavior, a bool can be true and false at the same time. But if we look at an example that doesn't have undefined behavior, then a bool should really be either true or false and not both. If it's both, the compiler has a bug. This is what you're saying, and I agree. On top of that, an example that passes as safe cannot have undefined behavior (per the spec). If the compiler accepts code with undefined behavior as safe, there is another bug (in the compiler or in the spec). This is what Walter's pull request is about.The issue with void initializers is that they aren't actually safe, just as I can't use cast's in safe code, I shouldn't be allowed to use void initializers in safe.I think that's a reasonable stance. And it's what the spec says at the moment. But it's not the only way to resolve the issue. And judging from his pull request, it's not how Walter wants to proceed. On a side note: You can use casts in safe code. Not all of them, of course, but your reinterpret cast above actually compiles as safe when you compile with -preview=dip1000. [...]That's just not true. It doesn't happen as fast as everyone would like, but bugs are getting fixed. [...]True. Which is why a lot of fixing needs to be done. Sometimes the spec needs to be changed, sometimes the implementation, sometimes both.No one is going to waste their time with that.The spec clearly says that using an uninitialized value has undefined behavior. That doesn't go away just because you don't like it, or because C++ doesn't have that rule. But yes, the issue with exotic bools goes beyond undefined behavior, as the examples with unions and casts show. As far as I can tell, the spec doesn't rule those out as undefined behavior.Sure. But as long as the PR is in limbo, Patrick Schluter has a point when he says that "undefined behaviour is undefined behaviour".It's not though. There is expected behavior for void initializers. Otherwise what you are saying is that C++ has undefined behavior for using variables that aren't initialized (which are all of them unless they are initialized first). But it doesn't. The behavior is expected. The root of the problem isn't with void initialization because the behavior is defined. The problem is with the boolean type and the loose definition the spec provides it. Boolean is undefined behavior in D, as long as the implementation in DMD and LDC differ, and there's nothing in the spec to define it.
Jun 07 2020
On Sunday, 7 June 2020 at 14:55:07 UTC, ag0aep6g wrote:On Sunday, 7 June 2020 at 13:10:22 UTC, Avrina wrote:I think we agree on about everything else. The spec is wrong/incorrect/incomplete in a lot of places, as you agree. This is just another one. There's nothing an implementation can do that would reasonably make sense for it undefined behavior, unlike with something like little/big endian and unions or bit fields in C++. Reading a void initialized variable is no different than reading a randomized variable. Right C++ is more linate with undefined behavior, and it doesn't even have the rule that D does. Reading uninitialized memory doesn't change or have any reason to change under any circumstances. It has no reason to be undefined behavior and is a mistake in the specs part.It's not though. There is expected behavior for void initializers. Otherwise what you are saying is that C++ has undefined behavior for using variables that aren't initialized (which are all of them unless they are initialized first). But it doesn't. The behavior is expected. The root of the problem isn't with void initialization because the behavior is defined. The problem is with the boolean type and the loose definition the spec provides it. Boolean is undefined behavior in D, as long as the implementation in DMD and LDC differ, and there's nothing in the spec to define it.The spec clearly says that using an uninitialized value has undefined behavior. That doesn't go away just because you don't like it, or because C++ doesn't have that rule.
Jun 07 2020
On 07.06.20 21:01, Avrina wrote:On Sunday, 7 June 2020 at 14:55:07 UTC, ag0aep6g wrote:It is not so simple, as the case with bool demonstrates.On Sunday, 7 June 2020 at 13:10:22 UTC, Avrina wrote:I think we agree on about everything else. The spec is wrong/incorrect/incomplete in a lot of places, as you agree. This is just another one. There's nothing an implementation can do that would reasonably make sense for it undefined behavior, unlike with something like little/big endian and unions or bit fields in C++. Reading a void initialized variable is no different than reading a randomized variable. ...It's not though. There is expected behavior for void initializers. Otherwise what you are saying is that C++ has undefined behavior for using variables that aren't initialized (which are all of them unless they are initialized first). But it doesn't. The behavior is expected. The root of the problem isn't with void initialization because the behavior is defined. The problem is with the boolean type and the loose definition the spec provides it. Boolean is undefined behavior in D, as long as the implementation in DMD and LDC differ, and there's nothing in the spec to define it.The spec clearly says that using an uninitialized value has undefined behavior. That doesn't go away just because you don't like it, or because C++ doesn't have that rule.Right C++ is more linate with undefined behavior, and it doesn't even have the rule that D does.Reading a trap representation is UB in C++, so reading an uninitialized bool in C++ will cause UB.Reading uninitialized memory doesn't change or have any reason to change under any circumstances. It has no reason to be undefined behavior and is a mistake in the specs part.It's not a mistake, there is also no reason why it can't be UB. The mistake is that it is UB and allowed in safe code at the same time.
Jun 07 2020
On Saturday, 6 June 2020 at 15:16:06 UTC, ag0aep6g wrote:But Walter agrees with you: Using a void value shouldn't actually have undefined behavior; it should just be an arbitrary value. Which is why he has an open pull request to change the spec: https://github.com/dlang/dlang.org/pull/2260Reading that PR, one comment stood out:The fact that the compilers don't define the behavior doesn't make it undefined according to the language specWhich makes me ask: what _does_ "undefined behaviour" mean according to the D language spec? I'm not sure that the spec actually gives a definition: it certainly (in the Introduction) starts talking about things that _result_ in undefined behaviour, without ever first saying what undefined behaviour is.
Jun 06 2020
On 06.06.20 21:30, Joseph Rushton Wakeling wrote:On Saturday, 6 June 2020 at 15:16:06 UTC, ag0aep6g wrote:You have to read it in context. The PR attempts to change accessing void-initialized memory from undefined behavior to implementation-defined behavior. (I don't see how that helps in any way, but that's what it does.) I.e., compiler implementations would have to specify the behavior. Walter is saying that if they fail to do that, that would then be an error in the documentation of those compilers.But Walter agrees with you: Using a void value shouldn't actually have undefined behavior; it should just be an arbitrary value. Which is why he has an open pull request to change the spec: https://github.com/dlang/dlang.org/pull/2260Reading that PR, one comment stood out:The fact that the compilers don't define the behavior doesn't make it undefined according to the language spec...Which makes me ask: what _does_ "undefined behaviour" mean according to the D language spec? ...Unfortunately it does not mean the behavior is not defined. It means the behavior is explicitly defined to be arbitrary. It's not very well-designed terminology, but D inherits it from C.I'm not sure that the spec actually gives a definition: it certainly (in the Introduction) starts talking about things that _result_ in undefined behaviour, without ever first saying what undefined behaviour is.In practice, it means what the backend developers take it to mean. In practice, this means that they will develop code generation procedures that are correct under the assumption that the source program never triggers UB. If that assumption is violated, demons may fly out of your nose, or more likely, bad actors will be able to take control of your process by carefully crafting inputs that exploit memory corruption. https://en.wikipedia.org/wiki/Undefined_behavior
Jun 06 2020
On Saturday, 6 June 2020 at 19:52:11 UTC, Timon Gehr wrote:Unfortunately it does not mean the behavior is not defined. It means the behavior is explicitly defined to be arbitrary. It's not very well-designed terminology, but D inherits it from C.The C99 standard has better terminology, though: it describes it as _indeterminate_, which can be either unspecified, or a trap value (the latter of which IIUC means any arbitrary bit pattern that fits in the block of memory the variable is stored in?). If I've understood the spec correctly, "unspecified" allows for the possibility that an individual implementation _could_ specify the behaviour, it just doesn't require it -- right? -- whereas as you say, "implementation defined" in C explicitly means that the implementation _must_ specify the behaviour. It looks like the D spec might benefit from adapting that kind of more precisely defined terminology.
Jun 06 2020
On Saturday, 6 June 2020 at 14:34:11 UTC, Avrina wrote:On Saturday, 6 June 2020 at 10:09:07 UTC, Patrick Schluter wrote:Then it is also a bug in llvm and gcc as they generate the code under exactly the same assumption that a bool is 1 or 0 (and that in C, C++ and D). Only in contexts where there is int promotion is all the word checked. This has nothing to do with the D frontend, #pure or whatnot. It's a pure backend code generation assumption. If the frontend violates that assumption, it is an issue of the frontend.On Friday, 5 June 2020 at 23:53:28 UTC, H. S. Teoh wrote:With statements like this I always feel like people don't understand what "undefined behavior" means. All the void initializer does is not initialize the memory of the bool. DMD is testing more than a single bit for a type that is only a single bit, it flip flops between testing a byte and testing a bit. That is most definitely a bug in the DMD backend.Output: ----------------- dead ----------------- Truly, DMD's backend is in the bright future of strange and wonderful quantum effects, whereas LDC is clearly still stuck in the antiquated classical past. ;-)Sorry, but undefined behaviour is undefined behaviour. The dmd code generator is not at fault here.Just to bring up an old debate, this has been argued to not be a bug and is defined behavior and *will not* be changed. void foo(bool); void foo(byte); foo(0); // calls bool foo(1); // calls bool foo(2); // calls byteThis has nothing to do with the issue at hand. This it's a technical choice. It might be surprising, it is very likely a wrong choice, but it is not violation of the assumption of the backend (even if it a violation of the programmer).
Jun 06 2020
On Saturday, 6 June 2020 at 15:36:07 UTC, Patrick Schluter wrote:On Saturday, 6 June 2020 at 14:34:11 UTC, Avrina wrote:No, that's why LDC doesn't have the same issue. D is suppose to be better than C and C++, so saying its broken in C and C++ so D should be broken too isn't a very convincing argument. The issue is that DMD isn't consistent. Like I said before, it flip flops between checking a single bit and 8 bits.On Saturday, 6 June 2020 at 10:09:07 UTC, Patrick Schluter wrote:Then it is also a bug in llvm and gcc as they generate the code under exactly the same assumption that a bool is 1 or 0 (and that in C, C++ and D). Only in contexts where there is int promotion is all the word checked.On Friday, 5 June 2020 at 23:53:28 UTC, H. S. Teoh wrote:With statements like this I always feel like people don't understand what "undefined behavior" means. All the void initializer does is not initialize the memory of the bool. DMD is testing more than a single bit for a type that is only a single bit, it flip flops between testing a byte and testing a bit. That is most definitely a bug in the DMD backend.Output: ----------------- dead ----------------- Truly, DMD's backend is in the bright future of strange and wonderful quantum effects, whereas LDC is clearly still stuck in the antiquated classical past. ;-)Sorry, but undefined behaviour is undefined behaviour. The dmd code generator is not at fault here.This has nothing to do with the D frontend, #pure or whatnot. It's a pure backend code generation assumption. If the frontend violates that assumption, it is an issue of the frontend.Which is why I said its an issue with the backend.I know it doesn't. The point was that book is treated as a 1-bit integer, and DMDs backend treats it like a byte (sometimes).Just to bring up an old debate, this has been argued to not be a bug and is defined behavior and *will not* be changed. void foo(bool); void foo(byte); foo(0); // calls bool foo(1); // calls bool foo(2); // calls byteThis has nothing to do with the issue at hand. This it's a technical choice. It might be surprising, it is very likely a wrong choice, but it is not violation of the assumption of the backend (even if it a violation of the programmer).
Jun 06 2020
On Fri, Jun 05, 2020 at 04:53:28PM -0700, H. S. Teoh via Digitalmars-d wrote:On Fri, Jun 05, 2020 at 11:57:39PM +0200, ag0aep6g via Digitalmars-d wrote: [...][...] For even more quantum fun: ---------- bool schrodingersCat() safe { import std.random; union Box { bool b; int state; } Box u; u.state = uniform(2, int.max); return u.b; } void main() safe { import std.stdio; bool b = schrodingersCat(); if (b) writeln("alive"); if (!b) writeln("dead"); } ---------- With LDC, this code will output either "alive" or "dead" with a roughly 50% probability of each. So it's a classical observer. With DMD, however, this code will perceive the quantum superimposition directly and output both "alive" and "dead" every time. :-D // OK, I'll stop now. :-P T -- Bare foot: (n.) A device for locating thumb tacks on the floor.2) "bool can be both true and false" https://issues.dlang.org/show_bug.cgi?id=20148 This one is just silly.[...] Nah, it's not silly, it's just that DMD's backend produces code that exhibits quantum uncertainty:
Jun 05 2020
On 6/5/20 5:25 PM, H. S. Teoh wrote:On Fri, Jun 05, 2020 at 04:53:28PM -0700, H. S. Teoh via Digitalmars-d wrote:These two posts made me very amused. Thank you.On Fri, Jun 05, 2020 at 11:57:39PM +0200, ag0aep6g via Digitalmars-d wrote: [...][...] For even more quantum fun: ---------- bool schrodingersCat() safe { import std.random; union Box { bool b; int state; } Box u; u.state = uniform(2, int.max); return u.b; } void main() safe { import std.stdio; bool b = schrodingersCat(); if (b) writeln("alive"); if (!b) writeln("dead"); } ---------- With LDC, this code will output either "alive" or "dead" with a roughly 50% probability of each. So it's a classical observer. With DMD, however, this code will perceive the quantum superimposition directly and output both "alive" and "dead" every time. :-D // OK, I'll stop now. :-P T2) "bool can be both true and false" https://issues.dlang.org/show_bug.cgi?id=20148 This one is just silly.[...] Nah, it's not silly, it's just that DMD's backend produces code that exhibits quantum uncertainty:
Jun 05 2020
On Saturday, 6 June 2020 at 00:33:03 UTC, David Gileadi wrote:These two posts made me very amused. Thank you.I just said few days ago: D is fun to work with everyday! https://forum.dlang.org/post/iqohjalciprrnbxticpi forum.dlang.org I think if we have a poll widget, this fun bug will surely be top voted :-)
Jun 05 2020
On Saturday, 6 June 2020 at 00:25:15 UTC, H. S. Teoh wrote:On Fri, Jun 05, 2020 at 04:53:28PM -0700, H. S. Teoh via Digitalmars-d wrote:The linked defect, and the issue you posted, don't really make sense to me. They both have UB; reading from an uninitialized variable (= void), or writing to one member of a union and reading from the other. Invoke Undefined Behaviour and you get... Undefined Behaviour.On Fri, Jun 05, 2020 at 11:57:39PM +0200, ag0aep6g via Digitalmars-d wrote: [...][...] For even more quantum fun: ---------- bool schrodingersCat() safe { import std.random; union Box { bool b; int state; } Box u; u.state = uniform(2, int.max); return u.b; } void main() safe { import std.stdio; bool b = schrodingersCat(); if (b) writeln("alive"); if (!b) writeln("dead"); } ---------- With LDC, this code will output either "alive" or "dead" with a roughly 50% probability of each. So it's a classical observer. With DMD, however, this code will perceive the quantum superimposition directly and output both "alive" and "dead" every time. :-D // OK, I'll stop now. :-P T2) "bool can be both true and false" https://issues.dlang.org/show_bug.cgi?id=20148 This one is just silly.[...] Nah, it's not silly, it's just that DMD's backend produces code that exhibits quantum uncertainty:
Jun 05 2020
On 06.06.20 05:40, Meta wrote:The linked defect, and the issue you posted, don't really make sense to me. They both have UB; reading from an uninitialized variable (= void), or writing to one member of a union and reading from the other. Invoke Undefined Behaviour and you get... Undefined Behaviour.Right. It's in safe code.
Jun 05 2020
On Saturday, 6 June 2020 at 03:56:43 UTC, Timon Gehr wrote:On 06.06.20 05:40, Meta wrote:Ah, yes, I missed that. Why the hell is = void allowed in safe again? I vaguely remember Walter arguing that it should be for some reason.The linked defect, and the issue you posted, don't really make sense to me. They both have UB; reading from an uninitialized variable (= void), or writing to one member of a union and reading from the other. Invoke Undefined Behaviour and you get... Undefined Behaviour.Right. It's in safe code.
Jun 06 2020
On Saturday, 6 June 2020 at 13:31:31 UTC, Meta wrote:On Saturday, 6 June 2020 at 03:56:43 UTC, Timon Gehr wrote:Iirc it's only forbidden for pointers, because for other types garbage value != memory corruption. This is reflected in the recently updated spec section on "safe values" [1], which states:On 06.06.20 05:40, Meta wrote:Ah, yes, I missed that. Why the hell is = void allowed in safe again? I vaguely remember Walter arguing that it should be for some reason.The linked defect, and the issue you posted, don't really make sense to me. They both have UB; reading from an uninitialized variable (= void), or writing to one member of a union and reading from the other. Invoke Undefined Behaviour and you get... Undefined Behaviour.Right. It's in safe code.For basic data types, all possible bit patterns are safe.It seems evident from this discussion that the above statement is not actually true, at least when it comes to bool. [1] https://dlang.org/spec/function.html#safe-values
Jun 06 2020
On 06.06.20 15:42, Paul Backus wrote:Iirc it's only forbidden for pointers, because for other types garbage value != memory corruption. This is reflected in the recently updated spec section on "safe values" [1], which states:I had thought about special-casing bool there, precisely because of the issue at hand. I almost wrote that only 0 and 1 are safe values for bool. I decided against it, because it seems unlikely that creating values beyond 1 will be banned in safe code. It seems more likely that the implementation gets changed to treat all non-zero values as true. At least that's what I extrapolate from Walter's position on void initialization in general (see <https://github.com/dlang/dlang.org/pull/2260/files>).For basic data types, all possible bit patterns are safe.It seems evident from this discussion that the above statement is not actually true, at least when it comes to bool. [1] https://dlang.org/spec/function.html#safe-values
Jun 06 2020
On Saturday, 6 June 2020 at 14:02:54 UTC, ag0aep6g wrote:I had thought about special-casing bool there, precisely because of the issue at hand. I almost wrote that only 0 and 1 are safe values for bool. I decided against it, because it seems unlikely that creating values beyond 1 will be banned in safe code. It seems more likely that the implementation gets changed to treat all non-zero values as true. At least that's what I extrapolate from Walter's position on void initialization in general (see <https://github.com/dlang/dlang.org/pull/2260/files>).It seems to me like (a) whether void initialization results in undefined behavior or merely unspecified values, and (b) whether bool values other than 0 and 1 are considered valid are independent questions. That is, it would be perfectly consistent to say that void initialization of int in safe code is fine, because every 4-byte bit pattern represents a valid int, but void-initialization of bool in safe code is no good, because many 1-byte bit patterns do not represent valid bools.
Jun 06 2020
On Saturday, 6 June 2020 at 18:43:43 UTC, Paul Backus wrote:That is, it would be perfectly consistent to say that void initialization of int in safe code is fine, because every 4-byte bit pattern represents a valid int, but void-initialization of bool in safe code is no good, because many 1-byte bit patterns do not represent valid bools.That would be fine, yes. I just don't expect that Walter will resolve the issue that way. If he does, updating the spec will be no big deal compared to updating the compiler.
Jun 06 2020
On Saturday, 6 June 2020 at 13:31:31 UTC, Meta wrote:On Saturday, 6 June 2020 at 03:56:43 UTC, Timon Gehr wrote:Ironically, he argued it's for performance.On 06.06.20 05:40, Meta wrote:Ah, yes, I missed that. Why the hell is = void allowed in safe again? I vaguely remember Walter arguing that it should be for some reason.The linked defect, and the issue you posted, don't really make sense to me. They both have UB; reading from an uninitialized variable (= void), or writing to one member of a union and reading from the other. Invoke Undefined Behaviour and you get... Undefined Behaviour.Right. It's in safe code.
Jun 06 2020
On 6/6/20 9:31 AM, Meta wrote:On Saturday, 6 June 2020 at 03:56:43 UTC, Timon Gehr wrote:int x = void; Does not and cannot corrupt memory (assuming everything that uses it is safe). The larger issue here is that bool is really an integer type from 0 to 1, but is implemented as an 8-bit value. In that case, the assumptions made by the compiler are not always correct. There was a DIP to make bool actually not an integer, and it was rejected. -SteveOn 06.06.20 05:40, Meta wrote:Ah, yes, I missed that. Why the hell is = void allowed in safe again? I vaguely remember Walter arguing that it should be for some reason.The linked defect, and the issue you posted, don't really make sense to me. They both have UB; reading from an uninitialized variable (= void), or writing to one member of a union and reading from the other. Invoke Undefined Behaviour and you get... Undefined Behaviour.Right. It's in safe code.
Jun 06 2020
On Saturday, 6 June 2020 at 16:48:56 UTC, Steven Schveighoffer wrote:int x = void; Does not and cannot corrupt memory (assuming everything that uses it is safe).Yes, which is presumably why the other example above -- using the wrong accessor of a union -- is also allowed in safe code ... ? That said, the definition of a safe interface is, according to spec, that it exhibits no undefined behaviour: https://dlang.org/spec/function.html#safe-interfaces Don't using void-initialized variables or the wrong accessors of a union both count as undefined behaviour, even if they are memory-safe?
Jun 06 2020
On 6/6/20 12:54 PM, Joseph Rushton Wakeling wrote:On Saturday, 6 June 2020 at 16:48:56 UTC, Steven Schveighoffer wrote:There are two things here: 1. using the value of a union that was not set in safe code can lead to corruption *easily*. Consider a union with perfectly overlapping fields, that are not pointers. The individual fields could have (possibly UFCS) trusted semantics that are invalid when you arbitrarily set the data. 2. The compiler cannot be made to detect when this happens (halting problem). So we have two options I can see: 1. declare that unions are not accessible in safe, period. This would be a huge breaking change, but would be a correct distinction. You would have to mark all such code trusted. 2. Somehow mark that unions with further semantic safe guarantees are not allowed in safe code. This could be a possible compromise that allows using unions still in safe code. The talk proposal I was going to submit this year was going to be very much about this problem.int x = void; Does not and cannot corrupt memory (assuming everything that uses it is safe).Yes, which is presumably why the other example above -- using the wrong accessor of a union -- is also allowed in safe code ... ?That said, the definition of a safe interface is, according to spec, that it exhibits no undefined behaviour: https://dlang.org/spec/function.html#safe-interfaces Don't using void-initialized variables or the wrong accessors of a union both count as undefined behaviour, even if they are memory-safe?Yes, either the spec or the behavior definition needs to be adjusted. -Steve
Jun 06 2020
On Saturday, 6 June 2020 at 21:01:05 UTC, Steven Schveighoffer wrote:The individual fields could have (possibly UFCS) trusted semantics that are invalid when you arbitrarily set the data.Doesn't that also apply to void-initialized values in the case that the implementation allows arbitrary bit-patterns (what IIUC the C99 standard calls trap values)?
Jun 06 2020
On 6/6/20 5:38 PM, Joseph Rushton Wakeling wrote:On Saturday, 6 June 2020 at 21:01:05 UTC, Steven Schveighoffer wrote:Yes, it's the same thing. This is why I specifically said that the case of: int x = void; won't corrupt memory *as long as everything that uses it is safe*. This is due to the fact that all indexing operations in safe code are bounds-checked. As soon as you start using trusted, then the semantic meaning of what x actually represents comes into play. The thing we *should* do is just disallow all these corner cases in safe code. It's much easier to relax it in certain cases later than it is to add on band-aids for all the bad cases. I don't think the code breakage would be tolerable for many people. Then again, maybe void initialization isn't common enough to cause a lot of breakage, I don't know. But I'm sure union usage is higher. -SteveThe individual fields could have (possibly UFCS) trusted semantics that are invalid when you arbitrarily set the data.Doesn't that also apply to void-initialized values in the case that the implementation allows arbitrary bit-patterns (what IIUC the C99 standard calls trap values)?
Jun 06 2020
On Saturday, 6 June 2020 at 22:01:51 UTC, Steven Schveighoffer wrote:Yes, it's the same thing. This is why I specifically said that the case of: int x = void; won't corrupt memory *as long as everything that uses it is safe*. This is due to the fact that all indexing operations in safe code are bounds-checked.Ahh, gotcha. I didn't quite follow the nuances there before. Thanks for clarifying, and for all the previous explanation.The thing we *should* do is just disallow all these corner cases in safe code. It's much easier to relax it in certain cases later than it is to add on band-aids for all the bad cases. I don't think the code breakage would be tolerable for many people. Then again, maybe void initialization isn't common enough to cause a lot of breakage, I don't know. But I'm sure union usage is higher.Could be interesting to put together compiler options to ban one or the other, and test them on a few major codebases (starting with druntime and phobos) to see how much breaks. If nothing else it'd be useful information to consider for that D3 proposal ... :-)
Jun 06 2020
On Saturday, 6 June 2020 at 22:01:51 UTC, Steven Schveighoffer wrote:On 6/6/20 5:38 PM, Joseph Rushton Wakeling wrote:Here's the definition of "trap representation" from the C99 standard:Doesn't that also apply to void-initialized values in the case that the implementation allows arbitrary bit-patterns (what IIUC the C99 standard calls trap values)?Certain object representations need not represent a value of the object type. [...] Such a representation is called a trap representation.So, for example, 0x42 is a trap representation for the type `bool`, because there's no value of type `bool` that corresponds to that pattern of bits.Yes, it's the same thing. This is why I specifically said that the case of: int x = void; won't corrupt memory *as long as everything that uses it is safe*. This is due to the fact that all indexing operations in safe code are bounds-checked.It's also due to the fact that the type `int` has no trap representations. Every bit pattern corresponds to a valid integer.As soon as you start using trusted, then the semantic meaning of what x actually represents comes into play.As long as the trusted code is written correctly, it's safe regardless. The trusted code has to be prepared to receive every possible safe value [1] of type `int`. Since every value of `int` is safe, it must be prepared for all possible values of type `int`. And since `int` has no trap representations, this is the same as being prepared for all possible bit patterns that could be stored in an `int`.The thing we *should* do is just disallow all these corner cases in safe code. It's much easier to relax it in certain cases later than it is to add on band-aids for all the bad cases.It is sufficient to forbid void-initialization of any type with unsafe values [1]--including trap representations. [1] https://dlang.org/spec/function.html#safe-values
Jun 06 2020
On 6/6/20 8:33 PM, Paul Backus wrote:As long as the trusted code is written correctly, it's safe regardless.Consider an integer which represents the length of an array. Instead of the full bit pattern of the integer being valid, only the bit pattern that is less than or equal to the memory size is valid. And this is not something that can be checked even at runtime -- trusted code must depend on the value being correct. This is enforced for D's builtin arrays, but not for a custom array type. And currently there's no way to convey that danger to the compiler. Especially where unions and void initializations are involved, there are ways to use safe code to subvert trusted code, even for private variables. Even with careful encapsulation, D has ways to get at the data. This is especially a problem with types which have a semantic invariant between calls to its members. -Steve
Jun 07 2020
On Sunday, 7 June 2020 at 14:14:51 UTC, Steven Schveighoffer wrote:Consider an integer which represents the length of an array. Instead of the full bit pattern of the integer being valid, only the bit pattern that is less than or equal to the memory size is valid. And this is not something that can be checked even at runtime -- trusted code must depend on the value being correct. This is enforced for D's builtin arrays, but not for a custom array type. And currently there's no way to convey that danger to the compiler. Especially where unions and void initializations are involved, there are ways to use safe code to subvert trusted code, even for private variables. Even with careful encapsulation, D has ways to get at the data. This is especially a problem with types which have a semantic invariant between calls to its members.For reference, there's a DIP being written to address this issue: https://github.com/dlang/DIPs/pull/179 I know that you're already aware of it, Steven. But others might not be.
Jun 07 2020
On Saturday, 6 June 2020, at 00:25:15 UTC, H. S. Teoh wrote:[... snip ...] OK, I'll stop now. :-P TSorry, but I have another one. The point in Schrödinger's matter is not to formulate a state, which does not exist. On observation, the cat is either dead or alive. With the current D behavior, the state of the cat is more like in The Walking Dead. ´´´ auto schrodingersCat() safe { union Box { bool b; int spin; } Box u; u.spin = 2; return u.b; } void main() safe { import std.stdio : writeln; const b = schrodingersCat(); if(b & !b){ writeln("doomed"); } else { if (b) writeln("alive"); if (!b) writeln("dead"); } } ´´´
Jun 06 2020
On Friday, 5 June 2020 at 21:57:39 UTC, ag0aep6g wrote:On 05.06.20 22:35, Walter Bright wrote:Undefined behaviour. This said, there is a real code generation error in dmd (not in gdc and ldc) as H.S.Teoh noticed which manifests only in non optimized code. It's in the parameter passing of bool values to a function. It should use the zero extending mov instruction instead. The bug happens only with 8 bit sized types (bool, byte, ubyte and char). With short it uses correctly the movzx instruction.1. File bugzilla issue for them. Issues not in bugzilla don't get fixed.[...]Bring them up now and then.How frequent is "now and then"? Like, once a month? Once a year? Ideally, you would be prioritizing issues based on severity and impact. If you only fix the issues that people nag you about, you risk leaving serious bugs unattended. Anyway, here are some personal favorites: 1) The DIP 1000 implementation has a glaring accepts-invalid bug with `pure` functions. https://issues.dlang.org/show_bug.cgi?id=20150 In my opinion, this one is a blocker for DIP 1000. And unfortunately, it probably made DIP 1000 look better than it is. 2) "bool can be both true and false" https://issues.dlang.org/show_bug.cgi?id=20148 This one is just silly.3) DMD's codegen for the BT (bit test) instruction is all kinds of wrong. https://issues.dlang.org/show_bug.cgi?id=18750 A testimony for the questionable quality of DMD's backend. 4) "import doesn't verify module declaration" https://issues.dlang.org/show_bug.cgi?id=15086 This accepts-invalid (and arguably wrong-code) issue had some lively discussion years ago. There was a PR, the issue was closed as invalid, it was reopened. And finally it was forgotten. 5) std.stdio tries converting between different UTF variants, but fails horribly. https://issues.dlang.org/show_bug.cgi?id=18789 and https://issues.dlang.org/show_bug.cgi?id=18801 I tried fixing this one but got stuck when I couldn't reproduce the failures on Windows that the auto-tester shows.
Jun 06 2020
On Friday, 5 June 2020 at 20:35:57 UTC, Walter Bright wrote:If you've got problems using D that should be fixed: 1. File bugzilla issue for them. Issues not in bugzilla don't get fixed. 2. When talking about the issue, provide a link to the bugzilla issue so we know what you're talking about and know what the current status is. 3. If you have a laundry list of issues that are important to you, keep a list of bugzilla issue links to them. Then, when you are asked about what problems you're having, cut&paste that list. Bring them up now and then. It's that simple!I have one that I really can't fix myself. The dwarf tag DW_TAG_inheritance which corresponds to the codeview's LF_BCLASS is missing. This inhibits debugging to executable build by dmd. On linux.
Jun 06 2020
On Saturday, 6 June 2020 at 08:33:51 UTC, Stefan Koch wrote:On Friday, 5 June 2020 at 20:35:57 UTC, Walter Bright wrote:bugzilla: https://issues.dlang.org/show_bug.cgi?id=20839 and: https://issues.dlang.org/show_bug.cgi?id=15631[...]I have one that I really can't fix myself. The dwarf tag DW_TAG_inheritance which corresponds to the codeview's LF_BCLASS is missing. This inhibits debugging [for] executable[s] build by dmd. On linux.
Jun 06 2020
On Friday, 5 June 2020 at 20:35:57 UTC, Walter Bright wrote:If you've got problems using D that should be fixed: 1. File bugzilla issue for them. Issues not in bugzilla don't get fixed. 2. When talking about the issue, provide a link to the bugzilla issue so we know what you're talking about and know what the current status is. 3. If you have a laundry list of issues that are important to you, keep a list of bugzilla issue links to them. Then, when you are asked about what problems you're having, cut&paste that list.All good and right to do of course. But one thing that could really help is if there was also some kind of higher-level (and well-maintained) priority roadmap for issues. In other words, it needs to be easy at any given time to: * find the high priority issues that are being actively worked on (and who is working on them) * find the high priority issues that need a contributor * see which issues are being targeted for which release The idea here is that this should make it easy at any time for community members to: * get a good overview of what is being actively worked on * quickly identify which issues might be most helpful to work on * see the priority given to issues they care about (and request inclusion if it looks like something is not on the roadmap when it should be) Right now I don't feel that I can get a good at-a-glance overview of what the priorities and roadmaps are for the D community. And indeed quite often I've found that stuff is happening that was agreed by a relatively small number of people in discussions that are not obviously visible to me (e.g. it wasn't agreed in an issue, or if there _is_ an issue it just states what's to be done without making clear _why_). Sometimes it seems like some of this is just deriving from Slack discussion between a relatively small group of people. Obviously it's fine that core developers will have internal discussion that results in decisions and action items, but it would be helpful if the results of that discussion were shared in a more structured fashion that makes it easier to keep track of both what is happening and why it's happening.
Jun 06 2020
On Friday, 5 June 2020 at 20:35:57 UTC, Walter Bright wrote:If you've got problems using D that should be fixed: 1. File bugzilla issue for them. Issues not in bugzilla don't get fixed. 2. When talking about the issue, provide a link to the bugzilla issue so we know what you're talking about and know what the current status is. 3. If you have a laundry list of issues that are important to you, keep a list of bugzilla issue links to them. Then, when you are asked about what problems you're having, cut&paste that list. Bring them up now and then. It's that simple!I'd also say just make it a habit of filing bugs! It's really important to file bugs even if one thinks they're the only one that could be affected by the bug. Even if a bug doesn't get a response in a long time it does not mean it's ignored! I've filed 697 bugs on Bugzilla so far. And while on first glance it might seem like "wow, D sure has a lot of bugs!", I don't feel about it that way. If you use this language for over a decade you are sure to find some implementation bugs here and there. And there is no goalpost where one could say "*this* is a reasonable amount of open bugs a project should have". If D's user base suddenly grew 10x over night we would have a lot more bugs filed. But that's a good thing because it means those bugs were always there, they were just undiscovered or not filed.
Jun 06 2020
On Saturday, 6 June 2020 at 15:46:10 UTC, Andrej Mitrovic wrote:I've filed 697 bugs on Bugzilla so far.And one tiny correction here, I meant issues, not bugs. Most were bugs, but some were enhancements and others were invalid bugs too. Anyway tl;dr: file bugs!
Jun 06 2020