www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Operator declaration

reply Dom Disc <dominikus scherkl.de> writes:
```d
struct MyType
{
    ubyte val;
    MyType opOpAssign(string op)(const MyType x) if(op =="^^")
    {
       val ^^= x.val;
    }
}

MyType m;
m ^^= m;
```

==> cannot implicitly convert expression 
`pow(cast(int)__powtmp1234, cast(int)x.val)` of type `int` to 
`ubyte`

This is one of the bugs that we bought with the strange policy 
that operators do NOT return same type as their operands.
"convert everything to int but not back" :-(

But in this special case I cannot see how to avoid this. Where do 
I need to put the cast to make this conversion explicit?!?
Apr 23
parent reply "H. S. Teoh" <hsteoh qfbox.info> writes:
On Thu, Apr 23, 2026 at 03:04:59PM +0000, Dom Disc via Digitalmars-d-learn
wrote:
 ```d
 struct MyType
 {
    ubyte val;
    MyType opOpAssign(string op)(const MyType x) if(op =="^^")
    {
       val ^^= x.val;
    }
 }
 
 MyType m;
 m ^^= m;
 ```
 
 ==> cannot implicitly convert expression `pow(cast(int)__powtmp1234,
 cast(int)x.val)` of type `int` to `ubyte`
 
 This is one of the bugs that we bought with the strange policy that
 operators do NOT return same type as their operands.
 "convert everything to int but not back" :-(
I hate D's policy on integer conversions. That's why I wrote nopromote.d which I posted somewhere in these forums, that lets you attach `.np` (for "no promote") to a short integer somewhere in an expression to "poison" it so that all arithmetic is done without promotion and assignable back to the original variable.
 But in this special case I cannot see how to avoid this. Where do I
 need to put the cast to make this conversion explicit?!?
Apparently you need to write it out explicitly: ``` val = cast(ubyte)(val ^^ x.val); ``` It's *really* b0rken IMO that you cannot even use `^^=` on a short integer! I'd file a bug, but Walter has said that he's not going change his stance on this. T -- Those who've learned LaTeX swear by it. Those who are learning LaTeX swear at it. -- Pete Bleackley
Apr 23
next sibling parent reply Dom Disc <dominikus scherkl.de> writes:
On Thursday, 23 April 2026 at 15:25:35 UTC, H. S. Teoh wrote:
 On Thu, Apr 23, 2026 at 03:04:59PM +0000, Dom Disc via 
 Digitalmars-d-learn wrote:
[much too complicated example]
 ==> cannot implicitly convert expression 
 `pow(cast(int)__powtmp1234,
 cast(int)x.val)` of type `int` to `ubyte`
 
I hate D's policy on integer conversions. That's why I wrote nopromote.d which I posted somewhere in these forums, that lets you attach `.np` (for "no promote") to a short integer somewhere in an expression to "poison" it so that all arithmetic is done without promotion and assignable back to the original variable.
Ah, cool. I'll have a look.
 It's *really* b0rken IMO that you cannot even use `^^=` on a 
 short integer!  I'd file a bug, but Walter has said that he's 
 not going change his stance on this.
Yeah, you can't use it at all. ubyte m; m ^^= m; // doesn't work So this is a serious bug, not a policy anymore.
Apr 23
parent Dennis <dkorpel gmail.com> writes:
On Thursday, 23 April 2026 at 18:20:23 UTC, Dom Disc wrote:
 It's *really* b0rken IMO that you cannot even use `^^=` on a 
 short integer!  I'd file a bug, but Walter has said that he's 
 not going change his stance on this.
Yeah, you can't use it at all. ubyte m; m ^^= m; // doesn't work So this is a serious bug, not a policy anymore.
While m = m ^^ m may promote to int and raise an error about truncation, m op= m should not in general. That's a bug indeed. https://github.com/dlang/dmd/pull/23023
Apr 23
prev sibling next sibling parent reply Meta <jared771 gmail.com> writes:
On Thursday, 23 April 2026 at 15:25:35 UTC, H. S. Teoh wrote:
 On Thu, Apr 23, 2026 at 03:04:59PM +0000, Dom Disc via 
 Digitalmars-d-learn wrote:
 ```d
 struct MyType
 {
    ubyte val;
    MyType opOpAssign(string op)(const MyType x) if(op =="^^")
    {
       val ^^= x.val;
    }
 }
 
 MyType m;
 m ^^= m;
 ```
 
 ==> cannot implicitly convert expression 
 `pow(cast(int)__powtmp1234,
 cast(int)x.val)` of type `int` to `ubyte`
 
 This is one of the bugs that we bought with the strange policy 
 that
 operators do NOT return same type as their operands.
 "convert everything to int but not back" :-(
I hate D's policy on integer conversions. That's why I wrote nopromote.d which I posted somewhere in these forums, that lets you attach `.np` (for "no promote") to a short integer somewhere in an expression to "poison" it so that all arithmetic is done without promotion and assignable back to the original variable.
 But in this special case I cannot see how to avoid this. Where 
 do I need to put the cast to make this conversion explicit?!?
Apparently you need to write it out explicitly: ``` val = cast(ubyte)(val ^^ x.val); ``` It's *really* b0rken IMO that you cannot even use `^^=` on a short integer! I'd file a bug, but Walter has said that he's not going change his stance on this. T
Now that we have ImportC, maybe he he can be convinced to soften his stance a bit. His argument is that people will paste C code into a .d file and expect it to work the same as in C. However, now they can just take that C code and compile it directly with DMD, and use it seemlessly from D. So IMO his reasoning doesn't hold that much weight anymore.
Apr 23
next sibling parent Dom Disc <dominikus scherkl.de> writes:
On Thursday, 23 April 2026 at 20:30:04 UTC, Meta wrote:
 Now that we have ImportC, maybe he he can be convinced to 
 soften his stance a bit. His argument is that people will paste 
 C code into a .d file and expect it to work the same as in C. 
 However, now they can just take that C code and compile it 
 directly with DMD, and use it seemlessly from D. So IMO his 
 reasoning doesn't hold that much weight anymore.
Indeed. Maybe I should start another round to fix https://github.com/dlang/dmd/issues/17504
Apr 24
prev sibling parent reply Nick Treleaven <nick geany.org> writes:
On Thursday, 23 April 2026 at 20:30:04 UTC, Meta wrote:
 Now that we have ImportC, maybe he he can be convinced to 
 soften his stance a bit.
Just to note that there are rationale points for integer promotions here, in addition to ease of porting C: https://dlang.org/spec/type.html#integer-promotions `op=` is supposed to work without error: https://dlang.org/spec/expression.html#assignment_operator_expressions
 His argument is that people will paste C code into a .d file 
 and expect it to work the same as in C. However, now they can 
 just take that C code and compile it directly with DMD, and use 
 it seemlessly from D. So IMO his reasoning doesn't hold that 
 much weight anymore.
What if you want to port the C code to D so you can refactor and develop it using D features?
Apr 24
parent reply Meta <jared771 gmail.com> writes:
On Friday, 24 April 2026 at 14:59:25 UTC, Nick Treleaven wrote:
 On Thursday, 23 April 2026 at 20:30:04 UTC, Meta wrote:
 Now that we have ImportC, maybe he he can be convinced to 
 soften his stance a bit.
The arguments from that section are: - 32-bit integer operations are often faster than smaller integer types for single variables on modern architectures. I'm not an expert in modern CPU architecture, but I'm extremely skeptical of this claim. I doubt the difference is even noticeable with modern compiler optimization techniques. - Promotion helps avoid accidental overflow which is more common with small integer types. I got 3 words for you: Value Range Propagation. We pay for it, so we should use it wherever possible.
 Just to note that there are rationale points for integer 
 promotions here, in addition to ease of porting C:
 https://dlang.org/spec/type.html#integer-promotions

 `op=` is supposed to work without error:
 https://dlang.org/spec/expression.html#assignment_operator_expressions

 His argument is that people will paste C code into a .d file 
 and expect it to work the same as in C. However, now they can 
 just take that C code and compile it directly with DMD, and 
 use it seemlessly from D. So IMO his reasoning doesn't hold 
 that much weight anymore.
What if you want to port the C code to D so you can refactor and develop it using D features?
Apr 24
next sibling parent Dom Disc <dominikus scherkl.de> writes:
On Friday, 24 April 2026 at 21:00:52 UTC, Meta wrote:
 The arguments from that section are:
 - 32-bit integer operations are often faster than smaller 
 integer types for single variables on modern architectures.

 I'm not an expert in modern CPU architecture, but I'm extremely 
 skeptical of this claim. I doubt the difference is even 
 noticeable with modern compiler optimization techniques.
Even without optimization: nothing prevents the compiler from calculating in the machine-words size, but the result should be truncated to the the largest of the operands sizes.
 What if you want to port the C code to D so you can refactor 
 and develop it using D features?
Then you should take the (more sane) rules of D into account. I think if you plan to develop the code further, you should be well aware of where strange C edge-cases are used and fix this.
Apr 24
prev sibling next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 25/04/2026 9:00 AM, Meta wrote:
 I'm not an expert in modern CPU architecture, but I'm extremely 
 skeptical of this claim. I doubt the difference is even noticeable with 
 modern compiler optimization techniques.
Its mostly 1 cycle these days, but 2 cycles for 64bit integer ops is still in common use. However that only covers the big $$$ cpu's, who knows about MCU's or cheaper processors.
   * Promotion helps avoid accidental overflow which is more common with
     small integer types.
 
 I got 3 words for you: Value Range Propagation. We pay for it, so we 
 should use it wherever possible.
Yeah if you write code like the following, it'll use data flow analysis to use the smaller bitwidth (tested): ```d int calc(int arg) { assert(arg <= 10); long value = 1 + (arg * 3); return cast(int)value; } ``` After 30 years Walter's arguments surrounding 32bit int's is only now starting to wane, give it another 30 and yeah then it should be gone. But until then I'm listening to Walter as it has the widest applicability.
Apr 25
prev sibling parent reply Nick Treleaven <nick geany.org> writes:
On Friday, 24 April 2026 at 21:00:52 UTC, Meta wrote:
 On Friday, 24 April 2026 at 14:59:25 UTC, Nick Treleaven wrote:
 On Thursday, 23 April 2026 at 20:30:04 UTC, Meta wrote:
 Now that we have ImportC, maybe he he can be convinced to 
 soften his stance a bit.
The arguments from that section are: - 32-bit integer operations are often faster than smaller integer types for single variables on modern architectures. I'm not an expert in modern CPU architecture, but I'm extremely skeptical of this claim. I doubt the difference is even noticeable with modern compiler optimization techniques.
That was the argument Walter made in 2022 'this has carried over into modern CPUs': https://forum.dlang.org/post/stk4sr$97t$1 digitalmars.com I don't know enough to comment on that.
 - Promotion helps avoid accidental overflow which is more 
 common with small integer types.

 I got 3 words for you: Value Range Propagation. We pay for it, 
 so we should use it wherever possible.
How would that fix the problem? And ideally in a way that doesn't break existing working code.
Apr 25
parent Meta <jared771 gmail.com> writes:
On Saturday, 25 April 2026 at 10:49:35 UTC, Nick Treleaven wrote:
 - Promotion helps avoid accidental overflow which is more 
 common with small integer types.

 I got 3 words for you: Value Range Propagation. We pay for it, 
 so we should use it wherever possible.
How would that fix the problem? And ideally in a way that doesn't break existing working code.
This is about the integer promotion rules, that people have been complaining about for years.
Apr 25
prev sibling parent reply Dom Disc <dominikus scherkl.de> writes:
On Thursday, 23 April 2026 at 15:25:35 UTC, H. S. Teoh wrote:

 I hate D's policy on integer conversions.
The funny fact is: during CTFE this promotion to int is NOT done. for(ubyte i = 0; i<256; ++i) ... This works, because i is promoted to int so it can an will reach 256. But during CTFE this is an infinite loop, because an ubyte is always <256 One of the bugs that caught me on surprise.
Apr 24
parent reply Nick Treleaven <nick geany.org> writes:
On Friday, 24 April 2026 at 09:49:31 UTC, Dom Disc wrote:
 On Thursday, 23 April 2026 at 15:25:35 UTC, H. S. Teoh wrote:

 I hate D's policy on integer conversions.
The funny fact is: during CTFE this promotion to int is NOT done. for(ubyte i = 0; i<256; ++i) ...
Can we make `i < 256` a compile-time error?
 This works, because i is promoted to int so it can an will 
 reach 256.

 But during CTFE this is an infinite loop, because an ubyte is 
 always <256

 One of the bugs that caught me on surprise.
It's an infinite loop at runtime. `i == 256` never happens, it can't. ```d void main() { import std.stdio; for(ubyte i = 0; i<256; ++i) i.writeln; } ```
Apr 24
parent Adam D. Ruppe <destructionator gmail.com> writes:
On Friday, 24 April 2026 at 14:52:46 UTC, Nick Treleaven wrote:
 Can we make `i < 256` a compile-time error?
I imagine some value range propagation that reports if a comparison is always true or false is possible. But making it an error is going to be similar to the unreachable code errors and be a huge pain sometimes. idk if worth.
Apr 24