www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Getting action on your favorite D issues

reply Walter Bright <newshound2 digitalmars.com> writes:
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
next sibling parent reply ag0aep6g <anonymous example.com> writes:
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
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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
parent reply mw <mingwu gmail.com> writes:
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
next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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:
 
 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?
[...] 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 Wirchenko
Jun 05 2020
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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
next sibling parent aberba <karabutaworld gmail.com> writes:
On Saturday, 6 June 2020 at 02:41:51 UTC, Walter Bright wrote:
 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.
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.
Jun 06 2020
prev sibling parent reply ag0aep6g <anonymous example.com> writes:
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
parent reply Seb <seb wilzba.ch> writes:
On Saturday, 6 June 2020 at 13:08:06 UTC, ag0aep6g wrote:
 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.
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/411
Jun 06 2020
parent aberba <karabutaworld gmail.com> writes:
On Saturday, 6 June 2020 at 13:30:53 UTC, Seb wrote:
 On Saturday, 6 June 2020 at 13:08:06 UTC, ag0aep6g wrote:
 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.
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/411
So should issues continue to be filed in bugzilla? Why not move new issues to GitHub directly?
Jun 06 2020
prev sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
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
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
next sibling parent TheGag96 <thegag96 gmail.com> writes:
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
prev sibling parent reply Patrick Schluter <Patrick.Schluter bbox.fr> writes:
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: [...]
 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
TEST AL,AL gives "not zero"
 dead
XOR 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
next sibling parent Stanislav Blinov <stanislav.blinov gmail.com> writes:
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
prev sibling parent reply Avrina <avrina12309412342 gmail.com> writes:
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:
 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.
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 byte
Jun 06 2020
next sibling parent reply ag0aep6g <anonymous example.com> writes:
On 06.06.20 16:34, Avrina wrote:
 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.
With statements like this I always feel like people don't understand what "undefined behavior" means.
I'm not so sure if you really understand what "undefined behavior" means. By saying this:
 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
next sibling parent Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Saturday, 6 June 2020 at 15:16:06 UTC, ag0aep6g wrote:
 On 06.06.20 16:34, Avrina wrote:
 [...]
[...]
 [...]
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.
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.
 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
prev sibling next sibling parent reply Avrina <avrina12309412342 gmail.com> writes:
On Saturday, 6 June 2020 at 15:16:06 UTC, ag0aep6g wrote:
 On 06.06.20 16:34, Avrina wrote:
 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.
With statements like this I always feel like people don't understand what "undefined behavior" means.
I'm not so sure if you really understand what "undefined behavior" means. By saying this:
 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.
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.
 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/2260
Yea 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
parent reply ag0aep6g <anonymous example.com> writes:
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.
 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.
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 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
Yea 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.
Sure. But as long as the PR is in limbo, Patrick Schluter has a point when he says that "undefined behaviour is undefined behaviour".
Jun 06 2020
parent reply Avrina <avrina12309412342 gmail.com> writes:
On Saturday, 6 June 2020 at 20:20:54 UTC, ag0aep6g wrote:
 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.
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.
 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.
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.
 [...]
 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
Yea 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.
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. 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.
Jun 07 2020
parent reply ag0aep6g <anonymous example.com> writes:
On Sunday, 7 June 2020 at 13:10:22 UTC, Avrina wrote:
 On Saturday, 6 June 2020 at 20:20:54 UTC, ag0aep6g wrote:
[...]
 ----
 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.
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.
 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. [...]
 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.
That's just not true. It doesn't happen as fast as everyone would like, but bugs are getting fixed. [...]
 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.
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.
Jun 07 2020
parent reply Avrina <avrina12309412342 gmail.com> writes:
On Sunday, 7 June 2020 at 14:55:07 UTC, ag0aep6g wrote:
 On Sunday, 7 June 2020 at 13:10:22 UTC, Avrina wrote:
 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.
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.
Jun 07 2020
parent Timon Gehr <timon.gehr gmx.ch> writes:
On 07.06.20 21:01, Avrina wrote:
 On Sunday, 7 June 2020 at 14:55:07 UTC, ag0aep6g wrote:
 On Sunday, 7 June 2020 at 13:10:22 UTC, Avrina wrote:
 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.
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 is not so simple, as the case with bool demonstrates.
 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
prev sibling parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
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/2260
Reading 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? 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
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 06.06.20 21:30, Joseph Rushton Wakeling wrote:
 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/2260
Reading 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
...
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.
 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
parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
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
prev sibling parent reply Patrick Schluter <Patrick.Schluter bbox.fr> writes:
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:
 On Friday, 5 June 2020 at 23:53:28 UTC, H. S. Teoh wrote:
 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.
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.
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.
 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 byte
This 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
parent Avrina <avrina12309412342 gmail.com> writes:
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:
 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:
 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.
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.
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.
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.
 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.
 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 byte
This 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).
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).
Jun 06 2020
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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:
 [...]
 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:
[...] 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.
Jun 05 2020
next sibling parent reply David Gileadi <gileadisNOSPM gmail.com> writes:
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:
 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:
[...] 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
These two posts made me very amused. Thank you.
Jun 05 2020
parent mw <mingwu gmail.com> writes:
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
prev sibling next sibling parent reply Meta <jared771 gmail.com> writes:
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:
 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:
[...] 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
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.
Jun 05 2020
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
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
parent reply Meta <jared771 gmail.com> writes:
On Saturday, 6 June 2020 at 03:56:43 UTC, Timon Gehr wrote:
 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.
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.
Jun 06 2020
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
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:
 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.
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.
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:
 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
parent reply ag0aep6g <anonymous example.com> writes:
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:
 
 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
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>).
Jun 06 2020
parent reply Paul Backus <snarwin gmail.com> writes:
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
parent ag0aep6g <anonymous example.com> writes:
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
prev sibling next sibling parent Avrina <avrina12309412342 gmail.com> writes:
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:
 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.
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.
Ironically, he argued it's for performance.
Jun 06 2020
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/6/20 9:31 AM, Meta wrote:
 On Saturday, 6 June 2020 at 03:56:43 UTC, Timon Gehr wrote:
 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.
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.
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. -Steve
Jun 06 2020
parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
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
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/6/20 12:54 PM, Joseph Rushton Wakeling wrote:
 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 ... ?
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.
 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
parent reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
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
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 6/6/20 5:38 PM, Joseph Rushton Wakeling wrote:
 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)?
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. -Steve
Jun 06 2020
next sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
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
prev sibling parent reply Paul Backus <snarwin gmail.com> writes:
On Saturday, 6 June 2020 at 22:01:51 UTC, Steven Schveighoffer 
wrote:
 On 6/6/20 5:38 PM, Joseph Rushton Wakeling wrote:
 
 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)?
Here's the definition of "trap representation" from the C99 standard:
 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
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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
parent ag0aep6g <anonymous example.com> writes:
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
prev sibling parent Alex <sascha.orlov gmail.com> writes:
On Saturday, 6 June 2020, at 00:25:15 UTC, H. S. Teoh wrote:
 [... snip ...]
 OK, I'll stop now. :-P


 T
Sorry, 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
prev sibling parent Patrick Schluter <Patrick.Schluter bbox.fr> writes:
On Friday, 5 June 2020 at 21:57:39 UTC, ag0aep6g wrote:
 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.
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.
 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
prev sibling next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
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
parent Stefan Koch <uplink.coder googlemail.com> writes:
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:
 [...]
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.
bugzilla: https://issues.dlang.org/show_bug.cgi?id=20839 and: https://issues.dlang.org/show_bug.cgi?id=15631
Jun 06 2020
prev sibling next sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
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
prev sibling parent reply Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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
parent Andrej Mitrovic <andrej.mitrovich gmail.com> writes:
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