www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why does intpromote spew warnings for ~ operator?

reply Steven Schveighoffer <schveiguy gmail.com> writes:
```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
next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
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
next sibling parent reply Alexey <invalid email.address> writes:
On Sunday, 12 September 2021 at 18:13:14 UTC, Walter Bright wrote:
 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.
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)` ```
Sep 12
parent reply Walter Bright <newshound2 digitalmars.com> writes:
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
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/13/21 3:41 AM, Walter Bright wrote:
 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.
C allows exactly what he wrote, and it already works the same as it does in C. -Steve
Sep 13
parent reply Walter Bright <newshound2 digitalmars.com> writes:
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
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/13/21 3:55 PM, Walter Bright wrote:
 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.
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. -Steve
Sep 13
parent reply Walter Bright <newshound2 digitalmars.com> writes:
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
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/15/21 11:58 PM, Walter Bright wrote:
 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.
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.
 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
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/12/21 2:13 PM, Walter Bright wrote:
 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.
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. -Steve
Sep 13
parent Dennis <dkorpel gmail.com> writes:
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
prev sibling next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
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
prev sibling next sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
next sibling parent reply Paul Backus <snarwin gmail.com> writes:
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
parent jfondren <julian.fondren gmail.com> writes:
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:
 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.
Looks like a different implementation, but there's https://code.dlang.org/packages/nopromote
Sep 13
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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:
 [...]
 ```
 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;
Sure, just like *everyone* uses std.utf.byCodeUnit to avoid autodecoding, right? -Steve
Sep 13
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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:
 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;
Sure, just like *everyone* uses std.utf.byCodeUnit to avoid autodecoding, right?
[...] 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 Watts
Sep 13
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
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:
 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:
 [...]
 ```
 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;
Sure, just like *everyone* uses std.utf.byCodeUnit to avoid autodecoding, right?
[...] 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.
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!" -Steve
Sep 13
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
prev sibling parent reply Guillaume Piolat <first.last gmail.com> writes:
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
next sibling parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/13/21 5:03 PM, Guillaume Piolat wrote:
 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.
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.
 
 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
prev sibling parent reply Alexey <invalid email.address> writes:
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
next sibling parent reply bauss <jj_1337 live.dk> writes:
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. 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?
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.
Sep 13
parent reply Alexey <invalid email.address> writes:
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 D
mythical possibility
 and 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 code
 There are even tools for D that allows porting C to D code
this just says what such tools could rewrite code to D's conformations
 and 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
next sibling parent reply jfondren <julian.fondren gmail.com> writes:
On Tuesday, 14 September 2021 at 07:01:02 UTC, Alexey wrote:
 On Tuesday, 14 September 2021 at 06:03:24 UTC, bauss wrote:
a lot of C code is/will be
 ported to D
mythical possibility
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/7459713e2a4ad8d62d297abd4b0949d8
 all this doesn't answer why D should be like C
D 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
parent reply Alexey <invalid email.address> writes:
On Tuesday, 14 September 2021 at 07:29:39 UTC, jfondren wrote:
 On Tuesday, 14 September 2021 at 07:01:02 UTC, Alexey wrote:
 On Tuesday, 14 September 2021 at 06:03:24 UTC, bauss wrote:
a lot of C code is/will be
 ported to D
mythical possibility
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
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?
Sep 14
next sibling parent reply Mike Parker <aldacron gmail.com> writes:
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
parent Dukc <ajieskola gmail.com> writes:
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
prev sibling parent reply Alexey <invalid email.address> writes:
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
parent Stefan Koch <uplink.coder googlemail.com> writes:
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
prev sibling parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
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
parent Paul Backus <snarwin gmail.com> writes:
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: [...]
 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.
Technically it does now, with ImportC.
Sep 14
prev sibling next sibling parent Guillaume Piolat <first.last gmail.com> writes:
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
prev sibling parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 9/13/21 6:27 PM, 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. 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?
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. -Steve
Sep 14
parent Adam D Ruppe <destructionator gmail.com> writes:
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