digitalmars.D - Why does intpromote spew warnings for ~ operator?
- Steven Schveighoffer (38/38) Sep 12 2021 ```d
- Walter Bright (5/7) Sep 12 2021 The question for ~x is to promote x to an int and then complement, or co...
- Alexey (15/24) Sep 12 2021 But is this really ok to change variable size for simple bit
- Walter Bright (2/3) Sep 13 2021 The idea is that C like expressions should behave like C.
- Steven Schveighoffer (4/8) Sep 13 2021 C allows exactly what he wrote, and it already works the same as it does...
- Walter Bright (3/4) Sep 13 2021 Allowing it is one thing, behaving the same is another.
- Steven Schveighoffer (23/31) Sep 13 2021 The behavior is the same in this case. When you flip the bits in a
- Walter Bright (8/20) Sep 15 2021 The thing is, if b is a ubyte:
- Steven Schveighoffer (13/19) Sep 16 2021 It's clear that you aren't going to budge at all on this, but just to
- Steven Schveighoffer (41/52) Sep 13 2021 I'm fine with the C way, I'm fine with what intpromote is trying to
- Dennis (6/9) Sep 13 2021 It could also help with finally turning it into an error and then
- Steven Schveighoffer (9/11) Sep 13 2021 I thought I had tested this, but I must have been wrong. With
- H. S. Teoh (106/113) Sep 13 2021 [...]
- Paul Backus (4/9) Sep 13 2021 Have you considered putting this up on code.dlang.org? Probably
- jfondren (3/15) Sep 13 2021 Looks like a different implementation, but there's
- Steven Schveighoffer (4/20) Sep 13 2021 Sure, just like *everyone* uses std.utf.byCodeUnit to avoid
- H. S. Teoh (7/27) Sep 13 2021 [...]
- Steven Schveighoffer (10/36) Sep 13 2021 We have intpromote queued to go into the language. But it's even worse
- H. S. Teoh (14/23) Sep 13 2021 I agree.
- Guillaume Piolat (13/19) Sep 13 2021 What is achieve is that people can review the place where -x and
- Steven Schveighoffer (34/56) Sep 13 2021 Why should I review all uses, when the compiler can trivially prove it's...
- Alexey (10/12) Sep 13 2021 It's also not exactly clear why:
- bauss (15/27) Sep 13 2021 1. It's fairly clear why. Because a lot of the D ecosystem
- Alexey (37/62) Sep 14 2021 The ability of D to parse C code, doesn't mean it necessarily
- jfondren (28/38) Sep 14 2021 I did this just the other day, translating 500 lines of a C
- Alexey (22/32) Sep 14 2021 Ok.
- Mike Parker (15/19) Sep 14 2021 Obviously not. That's why there are C constructs that do not
- Dukc (5/7) Sep 14 2021 That it's you who says it makes sense speaks strongly for it. You
- Alexey (14/23) Sep 14 2021 and here
- Stefan Koch (32/44) Sep 14 2021 Yes it will.
- H. S. Teoh (11/13) Sep 14 2021 [...]
- Paul Backus (2/8) Sep 14 2021 Technically it does now, with ImportC.
- Guillaume Piolat (23/31) Sep 14 2021 A lot of the current D ecosystem (that wants to be simple to
- Steven Schveighoffer (22/31) Sep 14 2021 This is missing the point.
- Adam D Ruppe (24/33) Sep 14 2021 Not if you actually understand what a ushort and the - operator
```d import std.stdio; import std.meta; void main() { int nbad; foreach(T; AliasSeq!(short, ushort)) { foreach(int i; T.min .. T.max + 1) { T x = cast(T)i; T y = ~x; T newy = cast(T)~cast(int)x; if(y != newy) { writefln("%s: x: %s, y: %s, newy: %s", T.stringof, x, y, newy); ++nbad; } } } writeln("Number of affected cases: ", nbad); } ``` Output: ``` onlineapp.d(11): Deprecation: integral promotion not done for `~x`, use '-preview=intpromote' switch or `~cast(int)(x)` onlineapp.d(11): Deprecation: integral promotion not done for `~x`, use '-preview=intpromote' switch or `~cast(int)(x)` Number of affected cases: 0 ``` Note that with `-de` these become errors. With the -preview=intpromote switch, the uncasted negation compiles and runs as expected. Right now, the deprecation is telling users *under penalty of not compiling* to do something that will achieve nothing when intpromote is enabled. -Steve
Sep 12 2021
On 9/12/2021 7:14 AM, Steven Schveighoffer wrote:Right now, the deprecation is telling users *under penalty of not compiling* to do something that will achieve nothing when intpromote is enabled.The question for ~x is to promote x to an int and then complement, or complement and then promote.. Those are not equivalent. The idea is to move towards doing it the C way, which is promote and then complement.
Sep 12 2021
On Sunday, 12 September 2021 at 18:13:14 UTC, Walter Bright wrote:On 9/12/2021 7:14 AM, Steven Schveighoffer wrote:But is this really ok to change variable size for simple bit flipping? maybe there should be exception at least for ~ operation? ```D void main() { ushort a = 0b100; ushort b = ~a; } ``` ```txt t.d(5): Deprecation: integral promotion not done for `~a`, use '-preview=intpromote' switch or `~cast(int)(a)` ```Right now, the deprecation is telling users *under penalty of not compiling* to do something that will achieve nothing when intpromote is enabled.The question for ~x is to promote x to an int and then complement, or complement and then promote.. Those are not equivalent. The idea is to move towards doing it the C way, which is promote and then complement.
Sep 12 2021
On 9/12/2021 11:12 PM, Alexey wrote:But is this really ok to change variable size for simple bit flipping?The idea is that C like expressions should behave like C.
Sep 13 2021
On 9/13/21 3:41 AM, Walter Bright wrote:On 9/12/2021 11:12 PM, Alexey wrote:C allows exactly what he wrote, and it already works the same as it does in C. -SteveBut is this really ok to change variable size for simple bit flipping?The idea is that C like expressions should behave like C.
Sep 13 2021
On 9/13/2021 4:42 AM, Steven Schveighoffer wrote:C allows exactly what he wrote, and it already works the same as it does in C.Allowing it is one thing, behaving the same is another. I found the problem *because* a difference in behavior popped up.
Sep 13 2021
On 9/13/21 3:55 PM, Walter Bright wrote:On 9/13/2021 4:42 AM, Steven Schveighoffer wrote:The behavior is the same in this case. When you flip the bits in a ushort and assign to another ushort, you don't care about the behavior of the other bits at all. To reiterate, intpromote is going to require lots of casts, most of which wouldn't change any behavior that is currently happening. The cases where the behavior is different is going from 8 or 16-bit integers to higher bit numbers. IMO, intpromote should focus on those, and leave the others alone. I agree that the following is nonsense, and C gets it right. ```d ushort x = 500; int y = -x; assert(y == 65036); ``` But fixing this problem doesn't mean we have to break all existing code for the purpose of busywork to insert casts to achieve the current behavior. I just realized, the deprecation doesn't even say how to replicate current behavior. It says to cast to int before applying the operator, but that's not what current behavior does, it's what the *new* behavior does. Typically, deprecations identify how to adjust your code so it continues to do the same thing. This does the opposite. -SteveC allows exactly what he wrote, and it already works the same as it does in C.Allowing it is one thing, behaving the same is another. I found the problem *because* a difference in behavior popped up.
Sep 13 2021
On 9/13/2021 1:35 PM, Steven Schveighoffer wrote:To reiterate, intpromote is going to require lots of casts, most of which wouldn't change any behavior that is currently happening.Intpromote has been there for many years, it hasn't caused a big problem.The cases where the behavior is different is going from 8 or 16-bit integers to higher bit numbers. IMO, intpromote should focus on those, and leave the others alone.The thing is, if b is a ubyte: ~b is supposed to be an int, not a ubyte. It's not just about getting the bits right.But fixing this problem doesn't mean we have to break all existing code for the purpose of busywork to insert casts to achieve the current behavior.It needs to move to C behavior.I just realized, the deprecation doesn't even say how to replicate current behavior. It says to cast to int before applying the operator, but that's not what current behavior does, it's what the *new* behavior does. Typically, deprecations identify how to adjust your code so it continues to do the same thing. This does the opposite.The message is about inuring your code so it will work as intended regardless of the switch setting.
Sep 15 2021
On 9/15/21 11:58 PM, Walter Bright wrote:On 9/13/2021 1:35 PM, Steven Schveighoffer wrote:It's clear that you aren't going to budge at all on this, but just to respond to this -- `-preview=intpromote` is *not* required. It's not a default, and it's not used by default in dub. People are complaining about the excessive casting recommended by the compiler, even though their code works as expected now, and would work as expected after intpromote is the default.To reiterate, intpromote is going to require lots of casts, most of which wouldn't change any behavior that is currently happening.Intpromote has been there for many years, it hasn't caused a big problem.It needs to move to C behavior.In C: ```c unsigned short a2 = ~a1; ``` is valid. Why are we not continuing to replicate that behavior? -Steve
Sep 16 2021
On 9/12/21 2:13 PM, Walter Bright wrote:On 9/12/2021 7:14 AM, Steven Schveighoffer wrote:I'm fine with the C way, I'm fine with what intpromote is trying to accomplish. Yet, maybe you didn't understand what my point is. This code: ```d short s = 5; short t = ~s; writeln("t is ", t); ``` Compile without -preview=intpromote, you get the output: ``` onlineapp.d(6): Deprecation: integral promotion not done for `~s`, use '-preview=intpromote' switch or `~cast(int)(s)` t is -6 ``` Compile with -preview=intpromote, you get the output: ``` t is -6 ``` In other words, the deprecation is suggesting I do something that is unnecessary. That's a terrible message to send. Now, in my original rant, I erred in saying that ushort also works like this -- it doesn't. ushort requires a cast because `~cast(int)someUshort` is not going to fit into a ushort. I could have sworn I tested this, but it definitely fails without the cast. However, the larger point, which I talked about [last year](https://forum.dlang.org/post/rn6hk1$1gii$1 digitalmars.com), is that anyone who has this code is going to be super-annoyed that they have to insert casts. If they want to get rid of the deprecation they need to insert *two* casts, one which can be removed after adding intpromote. But the point is that if you are assigning a small int to the result of another small int negation or complement, the intpromote rules don't fix anything. They just get in the way. But this time, I'll just focus on the ~short, (and ~byte) which should be assignable to its own type, regardless of whether you promote first or not. I think we can have a solution that allows code that behaves the same to continue to compile without deprecation, while deprecating the code that will change with -preview=intpromote. -SteveRight now, the deprecation is telling users *under penalty of not compiling* to do something that will achieve nothing when intpromote is enabled.The question for ~x is to promote x to an int and then complement, or complement and then promote.. Those are not equivalent. The idea is to move towards doing it the C way, which is promote and then complement.
Sep 13 2021
On Monday, 13 September 2021 at 11:41:29 UTC, Steven Schveighoffer wrote:I think we can have a solution that allows code that behaves the same to continue to compile without deprecation, while deprecating the code that will change with -preview=intpromote.It could also help with finally turning it into an error and then making it the default. It's been almost 4 years now since [the Pull Request introducing it](https://github.com/dlang/dmd/pull/7013) was merged.
Sep 13 2021
On 9/12/21 10:14 AM, Steven Schveighoffer wrote:With the -preview=intpromote switch, the uncasted negation compiles and runs as expected.I thought I had tested this, but I must have been wrong. With -preview=intpromote, only the `short` version compiles, the `ushort` version complains that you can't fit an `int` into a `ushort`. Which is unfortunate, because most people would not use bitwise negate on a `short`, they would do it on a `ushort`. Still, I feel like D should allow what C allows here (and what currently working code expects). -Steve
Sep 13 2021
On Sun, Sep 12, 2021 at 10:14:03AM -0400, Steven Schveighoffer via Digitalmars-d wrote: [...]``` onlineapp.d(11): Deprecation: integral promotion not done for `~x`, use '-preview=intpromote' switch or `~cast(int)(x)` onlineapp.d(11): Deprecation: integral promotion not done for `~x`, use '-preview=intpromote' switch or `~cast(int)(x)` Number of affected cases: 0 ```[...] The integer promotion situation in D is a mess. My personal preference is: -------- module nopromote; enum isNarrowInt(T) = is(T : int) || is(T : uint); /** * A wrapper around a built-in narrow int that truncates the result of * arithmetic operations to the narrow type, overriding built-in int promotion * rules. */ struct Np(T) if (isNarrowInt!T) { T impl; alias impl this; /** * Truncating binary operator. */ Np opBinary(string op, U)(U u) if (is(typeof((T x, U y) => mixin("x " ~ op ~ " y")))) { return Np(cast(T) mixin("this.impl " ~ op ~ " u")); } /** * Truncating unary operator. */ Np opUnary(string op)() if (is(typeof((T x) => mixin(op ~ "cast(int) x")))) { return Np(cast(T) mixin(op ~ " cast(int) this.impl")); } /** * Infectiousness: any expression containing Np should automatically use Np * operator semantics. */ Np opBinaryRight(string op, U)(U u) if (is(typeof((T x, U y) => mixin("x " ~ op ~ " y")))) { return Np(cast(T) mixin("u " ~ op ~ " this.impl")); } } /** * Returns: A lightweight wrapped type that overrides built-in arithmetic * operators to always truncate to the given type without promoting to int or * uint. */ auto np(T)(T t) if (isNarrowInt!T) { return Np!T(t); } // Test binary ops safe unittest { ubyte x = 1; ubyte y = 2; auto z = x.np + y; static assert(is(typeof(z) : ubyte)); assert(z == 3); byte zz = x.np + y; assert(zz == 3); x = 255; z = x.np + y; assert(z == 1); } safe unittest { byte x = 123; byte y = 5; auto z = x.np + y; static assert(is(typeof(z) : byte)); assert(z == byte.min); byte zz = x.np + y; assert(zz == byte.min); } safe unittest { import std.random; short x = cast(short) uniform(0, 10); short y = 10; auto z = x.np + y; static assert(is(typeof(z) : short)); assert(z == x + 10); short s = x.np + y; assert(s == x + 10); } // Test unary ops safe unittest { byte b = 10; auto c = -b.np; static assert(is(typeof(c) : byte)); assert(c == -10); ubyte ub = 16; auto uc = -ub.np; static assert(is(typeof(uc) : ubyte)); assert(uc == 0xF0); } -------- ;-) T -- Let's call it an accidental feature. -- Larry Wall
Sep 13 2021
On Monday, 13 September 2021 at 15:38:44 UTC, H. S. Teoh wrote:The integer promotion situation in D is a mess. My personal preference is: -------- module nopromote; [...]Have you considered putting this up on code.dlang.org? Probably easier for people to find it there than by searching through old forum posts.
Sep 13 2021
On Monday, 13 September 2021 at 16:00:35 UTC, Paul Backus wrote:On Monday, 13 September 2021 at 15:38:44 UTC, H. S. Teoh wrote:Looks like a different implementation, but there's https://code.dlang.org/packages/nopromoteThe integer promotion situation in D is a mess. My personal preference is: -------- module nopromote; [...]Have you considered putting this up on code.dlang.org? Probably easier for people to find it there than by searching through old forum posts.
Sep 13 2021
On 9/13/21 11:38 AM, H. S. Teoh wrote:On Sun, Sep 12, 2021 at 10:14:03AM -0400, Steven Schveighoffer via Digitalmars-d wrote: [...]Sure, just like *everyone* uses std.utf.byCodeUnit to avoid autodecoding, right? -Steve``` onlineapp.d(11): Deprecation: integral promotion not done for `~x`, use '-preview=intpromote' switch or `~cast(int)(x)` onlineapp.d(11): Deprecation: integral promotion not done for `~x`, use '-preview=intpromote' switch or `~cast(int)(x)` Number of affected cases: 0 ```[...] The integer promotion situation in D is a mess. My personal preference is: -------- module nopromote;
Sep 13 2021
On Mon, Sep 13, 2021 at 01:49:25PM -0400, Steven Schveighoffer via Digitalmars-d wrote:On 9/13/21 11:38 AM, H. S. Teoh wrote:[...] It's a solution (or half-solution hack) that works today, as opposed to a wishful solution that may or may not happen in the future, if ever. T -- Trying to define yourself is like trying to bite your own teeth. -- Alan WattsOn Sun, Sep 12, 2021 at 10:14:03AM -0400, Steven Schveighoffer via Digitalmars-d wrote: [...]Sure, just like *everyone* uses std.utf.byCodeUnit to avoid autodecoding, right?``` onlineapp.d(11): Deprecation: integral promotion not done for `~x`, use '-preview=intpromote' switch or `~cast(int)(x)` onlineapp.d(11): Deprecation: integral promotion not done for `~x`, use '-preview=intpromote' switch or `~cast(int)(x)` Number of affected cases: 0 ```[...] The integer promotion situation in D is a mess. My personal preference is: -------- module nopromote;
Sep 13 2021
On 9/13/21 1:54 PM, H. S. Teoh wrote:On Mon, Sep 13, 2021 at 01:49:25PM -0400, Steven Schveighoffer via Digitalmars-d wrote:We have intpromote queued to go into the language. But it's even worse than the current status quo. If we are going to change the rules, we might as well change them to be better (at least do what the user expects). That's all I'm saying. We don't need more hacks that almost nobody will use. Sorry to be blunt, but the problem with such things is that it gives an excuse to allow the horror show to continue "if you don't like it, you can just use this library!" -SteveOn 9/13/21 11:38 AM, H. S. Teoh wrote:[...] It's a solution (or half-solution hack) that works today, as opposed to a wishful solution that may or may not happen in the future, if ever.On Sun, Sep 12, 2021 at 10:14:03AM -0400, Steven Schveighoffer via Digitalmars-d wrote: [...]Sure, just like *everyone* uses std.utf.byCodeUnit to avoid autodecoding, right?``` onlineapp.d(11): Deprecation: integral promotion not done for `~x`, use '-preview=intpromote' switch or `~cast(int)(x)` onlineapp.d(11): Deprecation: integral promotion not done for `~x`, use '-preview=intpromote' switch or `~cast(int)(x)` Number of affected cases: 0 ```[...] The integer promotion situation in D is a mess. My personal preference is: -------- module nopromote;
Sep 13 2021
On Mon, Sep 13, 2021 at 02:05:39PM -0400, Steven Schveighoffer via Digitalmars-d wrote: [...]We have intpromote queued to go into the language. But it's even worse than the current status quo.I agree.If we are going to change the rules, we might as well change them to be better (at least do what the user expects). That's all I'm saying. We don't need more hacks that almost nobody will use. Sorry to be blunt, but the problem with such things is that it gives an excuse to allow the horror show to continue "if you don't like it, you can just use this library!"[...] You're welcome to push for change. I'll even support you. But currently I'm not holding out much hope that intpromote will turn out for the better. From what I've seen of it (and this thread proves it), it will be a disaster. This isn't the first time complaints about intpromote came up. But since Walter seems dead-set on pushing it through, it will probably get through anyway. At least D still lets you use hacks like nopromote.d to shove the problem under the rug. T -- All problems are easy in retrospect.
Sep 13 2021
On Sunday, 12 September 2021 at 14:14:03 UTC, Steven Schveighoffer wrote:With the -preview=intpromote switch, the uncasted negation compiles and runs as expected. Right now, the deprecation is telling users under penalty of not compiling to do something that will achieve nothing when intpromote is enabled.What is achieve is that people can review the place where -x and ~x were used, and see if there was bug there ; because it is a real possibility that C code was ported and then it has a different semantics. The end game of it is: A. "when you paste C code and it builds then it's the same" instead of: B. "when you paste C code and it builds then it's the same, EXCEPT -x and ~x who don't promote their operand to int" when people of the future come to D in 2030 they will enjoy the proposition A instead of B.
Sep 13 2021
On 9/13/21 5:03 PM, Guillaume Piolat wrote:On Sunday, 12 September 2021 at 14:14:03 UTC, Steven Schveighoffer wrote:Why should I review all uses, when the compiler can trivially prove it's fine for most of them, and warn on the cases that will need attention? It already doesn't warn for ~int or -int, so it's not just usage of that operator that is problematic, but specific uses. Note that D already does the right thing for all the code I've pointed out here.With the -preview=intpromote switch, the uncasted negation compiles and runs as expected. Right now, the deprecation is telling users under penalty of not compiling to do something that will achieve nothing when intpromote is enabled.What is achieve is that people can review the place where -x and ~x were used, and see if there was bug there ; because it is a real possibility that C code was ported and then it has a different semantics.The end game of it is: A. "when you paste C code and it builds then it's the same" instead of: B. "when you paste C code and it builds then it's the same, EXCEPT -x and ~x who don't promote their operand to int"C allows assigning ints to shorts. When you have: ```d short x = -y; ``` It's exactly the same as C. There's no reason to deprecate this. When you build without using intpromote, it does what C does. When you build using intpromote, you have to cast to a short, which.... does what C does.when people of the future come to D in 2030 they will enjoy the proposition A instead of B.It all depends on if your opinion is that when you paste C code, it shouldn't compile. Because basically that's what's happening here. D gets away with requiring a cast here or there without being annoying, because VRP takes care of many cases, and op= cases work even though the written out form would not. But that won't be true here, and I can say there's probably a decent chunk of bit manipulation with ushorts. I'd propose that: 1. In cases where the behavior is already the same as C, and would not require casts after intpromote is enabled, do not warn. 2. In cases where a type is being assigned to the negation of the same type, do not require a cast, and do not warn. 3. In cases where the behavior is NOT the same as C, issue a warning and corrective action recommendation (i.e. either `~cast(int)(val)` to get rid of the warning and accept new behavior, or `cast(ushort)~(val)` to keep existing behavior). I honestly don't think casts should be necessary anywhere they aren't already required after intpromote is enabled. This would achieve your goal (warn people so they can inspect problematic cases) without ruining most valid code. -Steve
Sep 13 2021
On Monday, 13 September 2021 at 21:03:41 UTC, Guillaume Piolat wrote:On Sunday, 12 September 2021 at 14:14:03 UTC, Steven Schveighoffer wrote:It's also not exactly clear why: 1. D should be backward compatible with C, which is 50 years old soon. 2. why exactly somebody should copy / paste (how many? thousands?) many lines of code without thinking and rechecking. Probably D can't be and shouldn't be compatible with C / C++ to that distinct. 3. Is really backward comparability with C/C++ so important?
Sep 13 2021
On Monday, 13 September 2021 at 22:27:11 UTC, Alexey wrote:On Monday, 13 September 2021 at 21:03:41 UTC, Guillaume Piolat wrote:1. It's fairly clear why. Because a lot of the D ecosystem depends on C such as libraries etc. a lot of C code is/will be ported to D and it's impossible to do so if there are unclear/major behavior differences. D promotes itself with "betterC" which means it needs to behave like C to be a better C. 2. It's not necessarily copy-pasting but when you port code you don't go through it line-for-line and verify because that will take a very long time. There are even tools for D that allows porting C to D code and when using those tools you will not be able to verify the code that easy. Since a lot of the ecosystem depends on those tools then the behavior should be consistent with C. 3. Yes, see the first point about the ecosystem heavily relying on C.On Sunday, 12 September 2021 at 14:14:03 UTC, Steven Schveighoffer wrote:It's also not exactly clear why: 1. D should be backward compatible with C, which is 50 years old soon. 2. why exactly somebody should copy / paste (how many? thousands?) many lines of code without thinking and rechecking. Probably D can't be and shouldn't be compatible with C / C++ to that distinct. 3. Is really backward comparability with C/C++ so important?
Sep 13 2021
On Tuesday, 14 September 2021 at 06:03:24 UTC, bauss wrote:On Monday, 13 September 2021 at 22:27:11 UTC, Alexey wrote:On Monday, 13 September 2021 at 21:03:41 UTC, Guillaume Piolat wrote:On Sunday, 12 September 2021 at 14:14:03 UTC, Steven Schveighoffer wrote:It's also not exactly clear why:1. It's fairly clear why. Because a lot of the D ecosystem depends on C such as libraries etc.The ability of D to parse C code, doesn't mean it necessarily should use same rules in it's own D code.a lot of C code is/will be ported to Dmythical possibilityand it's impossible to do so if there are unclear/major behavior differences.how is it unclear? - because C coders doesn't want to learn D? - this is the reason D should be like C? there's also many other languages, which can (to some distinct) understand C/C++ (like Go, Rust, Java, Python and so on). But they are not necessarily gain same promotion rules (and they shouldn't, because those are separate languages)D promotes itself with "betterC" which means it needs to behave like C to be a better C.to my understanding, betterC - is an option. if user selects this option, maybe then D should work like C. but many people also going to D because it isn't C/C++ - how about them, them who doesn't like C/C++?2. It's not necessarily copy-pasting but when you port code you don't go through it line-for-line and verify because that will take a very long time.In any case, such port will require also types transition and many more things. In any case such a porter will should recheck codeThere are even tools for D that allows porting C to D codethis just says what such tools could rewrite code to D's conformationsand when using those tools you will not be able to verify the code that easy.why is this?Since a lot of the ecosystem depends on those tools then the behavior should be consistent with C.what you just said, is "D depends on C, because D should depend on C"3. Yes, see the first point about the ecosystem heavily relying on C.---- all this doesn't answer why D should be like C. or is it like: * C++ is C with classes * D is C++ with GC , yes? so if C++ will gain GC - D will become unneeded? also, as somebody apparently mentioned earlier, such a radical change in behavior, will probably require a major version number change. - will D become the second Python with version 2 and 3 support for next 10 years and consequent BDFL expel? I will conclude with following: I heard what D developers stated one day what D will accept C code; but I don't think this is necessary and I will not judge D developers for not achieving this. Not to say C already has it primary successors (Limbo and Go (which for some reason decided not to look like C)).
Sep 14 2021
On Tuesday, 14 September 2021 at 07:01:02 UTC, Alexey wrote:On Tuesday, 14 September 2021 at 06:03:24 UTC, bauss wrote:I did this just the other day, translating 500 lines of a C raylib implementation of Asteroids into D. Method: copy&paste and fix errors. The most annoying bit was the extensive use of C99 struct initializers, a lot of ```c player.collider = (Vector3){math, math, math}; ``` into ```d player.collider = Vector3(math, math, math); ``` The "if it compiles it's valid" is a very helpful rule for C code. https://github.com/raysan5/raylib-games/blob/master/classics/src/asteroids.c https://gist.github.com/jrfondren/7459713e2a4ad8d62d297abd4b0949d8a lot of C code is/will be ported to Dmythical possibilityall this doesn't answer why D should be like CD being like D includes the idea that C code either compiles with the same meaning or it fails to compile. If not for that, why should D look C-like at all? But putting C aside, is this even a behavior that you want? ```d ushort x = 53; int y = -x; assert(y == 65483); ```. or is it like: * C++ is C with classes * D is C++ with GC , yes? so if C++ will gain GC - D will become unneeded?C++ needs to lose a lot, not just gain. For a fresh example, C++ needs to lose easily incoherent and tedious operator overloading: https://forum.dlang.org/post/mailman.283.1631549561.21945.digitalmars-d-learn puremagic.com
Sep 14 2021
On Tuesday, 14 September 2021 at 07:29:39 UTC, jfondren wrote:On Tuesday, 14 September 2021 at 07:01:02 UTC, Alexey wrote:Ok. We have the situation, what in the code ```C #include <stdio.h> int main(int argc, char* argv[]) { unsigned char a = 0b100; unsigned int b = ~a; return 0; } ``` in line `unsigned int b = ~a;` a is promoted to int before it's bit's flipped. we also know what compiler should not silently to data transformations: for this reason D issues errors and warnings if it isn't sure what to do. but C, in example above, silently promotes a to int. - is this a good behavior? - is this behavior which D should inherit? C can do also many other bad things silently - so what, should D support such behavior too? maybe D should silently support pointer magic, so C coder could easily copy-paste he's code to D?On Tuesday, 14 September 2021 at 06:03:24 UTC, bauss wrote:I did this just the other day, translating 500 lines of a C raylib implementation of Asteroids into D. Method: copy&paste and fix errors. The most annoying bit was the extensive use of C99 struct initializers, a lot ofa lot of C code is/will be ported to Dmythical possibility
Sep 14 2021
On Tuesday, 14 September 2021 at 08:42:20 UTC, Alexey wrote:C can do also many other bad things silently - so what, should D support such behavior too? maybe D should silently support pointer magic, so C coder could easily copy-paste he's code to D?Obviously not. That's why there are C constructs that do not compile in D. From the inception of D, a general rule has been that if C code is copied into a D source module _and it compiles_, then it should behave like C. This isn't about being "backward compatible" with C. It's about minimizing bugs in ported code. For example, when you're using a C library and you copy an example into your D code, if it compiles and then behaves differently, you've potentially introduced a silent bug. In the early days, D programs were highly dependent on C libraries because D libraries didn't exist. So this loose rule that Walter tried to follow made a lot of sense. Today, we have more D libraries, but we still frequently make use of C libraries. The rule still makes sense, IMO.
Sep 14 2021
On Tuesday, 14 September 2021 at 09:04:02 UTC, Mike Parker wrote:Today, we have more D libraries, but we still frequently make use of C libraries. The rule still makes sense, IMO.That it's you who says it makes sense speaks strongly for it. You have so often warned about programming in D as if it was some other language, so if you say it still makes sense to be C-like despite the pitfalls, that speaks a lot.
Sep 14 2021
On Tuesday, 14 September 2021 at 08:42:20 UTC, Alexey wrote:```C #include <stdio.h> int main(int argc, char* argv[]) { unsigned char a = 0b100; unsigned int b = ~a; return 0; } ```and here ```C #include <stdio.h> int main(int argc, char* argv[]) { unsigned char a = 0b100; unsigned char b = ~a; return 0; } ``` will C also silently promote a to int and silently truncate it to uchar? - should those under-carpet things also happen in D just to save C's behavior?
Sep 14 2021
On Tuesday, 14 September 2021 at 09:07:24 UTC, Alexey wrote:```c #include <stdio.h> int main(int argc, char* argv[]) { unsigned char a = 0b100; unsigned char b = ~a; return 0; } ``` will C also silently promote a to int and silently truncate it to uchar? - should those under-carpet things also happen in D just to save C's behavior?Yes it will. you can convince yourself if you run this. ```c #include <stdio.h> #include <stdbool.h> char* binPrint(int v, char* buffer); #define bits(v) (sizeof(v) * 8) int main(int argc, char* argv[]) { char buffer[bits(int) + 1]; unsigned char a = 0b100; printf("a: %d -- %s\n", a, binPrint(a, &buffer[0])); unsigned char b = ~a; unsigned int c = ~a; printf("uchar b: %u -- %s\n", b, binPrint(b, &buffer[0])); printf("uint c: %u -- %s\n", c, binPrint(c, &buffer[0])); } char* binPrint(int v, char* buffer) { int last_set_bit; for(int bit_idx = 0; bit_idx < bits(v); bit_idx++) { bool bit_set = (v & (1 << bit_idx)); buffer[bits(v) - bit_idx] = bit_set ? '1' : '0'; if (bit_set) last_set_bit = bit_idx; } buffer[bits(v) + 1] = '\0'; return &buffer[bits(v) - last_set_bit]; } #undef bits ```
Sep 14 2021
On Tue, Sep 14, 2021 at 07:01:02AM +0000, Alexey via Digitalmars-d wrote: [...]The ability of D to parse C code, doesn't mean it necessarily should use same rules in it's own D code.[...] You're mistaken, D does not parse C code. D was just designed in such a way that when a piece of C code happens to parse like D code without syntax errors, it behaves exactly like the equivalent C code. A lot of C code, however, does not parse as D code (you will get syntax errors). In that case, D is free to diverge from C semantics. T -- Let X be the set not defined by this sentence...
Sep 14 2021
On Tuesday, 14 September 2021 at 16:53:44 UTC, H. S. Teoh wrote:On Tue, Sep 14, 2021 at 07:01:02AM +0000, Alexey via Digitalmars-d wrote: [...]Technically it does now, with ImportC.The ability of D to parse C code, doesn't mean it necessarily should use same rules in it's own D code.[...] You're mistaken, D does not parse C code.
Sep 14 2021
On Monday, 13 September 2021 at 22:27:11 UTC, Alexey wrote:It's also not exactly clear why: 1. D should be backward compatible with C, which is 50 years old soon.A lot of the current D ecosystem (that wants to be simple to build) relies on translated C: bindings, and stuff like codecs are especially hard to translate error-free. So it is valuable to be backward compatible with C, in the sense that a copy-paster C expression should work or not build. Note that this isn't still the case, for example: int fun(int[4] a) { // stuff } void foo() { int[4] b; fun(a); // passed by value in D, passed by pointer in C } ImportC will help a lot here, for example if like me you'd like a WebP decoder in pure D there are none, it is just too big to translate.2. why exactly somebody should copy / paste (how many? thousands?) many lines of code without thinking and rechecking. Probably D can't be and shouldn't be compatible with C / C++ to that distinct.It's very labor intensive to translate C to D, and a little mistake can bury the effort.3. Is really backward comparability with C/C++ so important?C and C++ are different languages, the one reason C++ has succeeded is "C/C++", being able to compile C code.
Sep 14 2021
On 9/13/21 6:27 PM, Alexey wrote:On Monday, 13 September 2021 at 21:03:41 UTC, Guillaume Piolat wrote:This is missing the point. Yes, part of the rationale of intpromote (which despite its flaws, I happen to agree with the main thrust of), is that we want D code that looks like C and compiles to behave like C. But also, the C behavior is what people who have no cares about C would expect. In other words, if you have: ```d ushort x = 500; int y = -x; ``` you would expect y to be -500. But in D it's 65036. Which makes almost no sense at all. Another alternative would be to disable negation on unsigned types. That would be also extremely disruptive. We have a chance here to 1. Make D compatible with C 2. Continue to compile code that is correct in C, and makes sense in D (i.e. `short y = -someShort`) 3. Warn and fix surprising results that are 99% likely bugs. If we do it smartly. -SteveOn Sunday, 12 September 2021 at 14:14:03 UTC, Steven Schveighoffer wrote:It's also not exactly clear why: 1. D should be backward compatible with C, which is 50 years old soon. 2. why exactly somebody should copy / paste (how many? thousands?) many lines of code without thinking and rechecking. Probably D can't be and shouldn't be compatible with C / C++ to that distinct. 3. Is really backward comparability with C/C++ so important?
Sep 14 2021
On Tuesday, 14 September 2021 at 11:53:48 UTC, Steven Schveighoffer wrote:In other words, if you have: ```d ushort x = 500; int y = -x; ``` you would expect y to be -500. But in D it's 65036. Which makes almost no sense at all.Not if you actually understand what a ushort and the - operator does. And if you don't understand that, maybe you should not use ushort. I'd note the same thing happens if you do an assign from uint to long. uint a = 500; long b = -a; writeln(b); // 4294966796 No deprecation warning either. But yeah if you were copy/pasting from C I can see how it would be an unpleasant surprise. .... but then again speaking of long, if you copy/paste code from C that uses `long` to D, you are in for an unpleasant surprise since the size is different. sooooo meh.Another alternative would be to disable negation on unsigned types. That would be also extremely disruptive.The negation operator could also implicitly cast it to the signed version of the same size. Of course then you are liable to carry the one at the end but like at a certain point people need to understand what they're actually doing and just use plain int if they don't know. but like if it would just stop complaining and making me double cast every operation i'd prolly be happy enough the status quo is absurd
Sep 14 2021