digitalmars.D.learn - Operator declaration
- Dom Disc (20/20) Apr 23 ```d
- H. S. Teoh (16/38) Apr 23 I hate D's policy on integer conversions. That's why I wrote
- Dom Disc (7/22) Apr 23 Ah, cool. I'll have a look.
- Dennis (4/11) Apr 23 While m = m ^^ m may promote to int and raise an error about
- Meta (7/47) Apr 23 Now that we have ImportC, maybe he he can be convinced to soften
- Dom Disc (3/9) Apr 24 Indeed. Maybe I should start another round to fix
- Nick Treleaven (8/15) Apr 24 Just to note that there are rationale points for integer
- Meta (11/26) Apr 24 The arguments from that section are:
- Dom Disc (7/15) Apr 24 Even without optimization: nothing prevents the compiler from
- Richard (Rikki) Andrew Cattermole (16/24) Apr 25 Its mostly 1 cycle these days, but 2 cycles for 64bit integer ops is
- Nick Treleaven (7/21) Apr 25 That was the argument Walter made in 2022 'this has carried over
- Meta (3/10) Apr 25 This is about the integer promotion rules, that people have been
- Dom Disc (8/9) Apr 24 The funny fact is: during CTFE this promotion to int is NOT done.
- Nick Treleaven (12/22) Apr 24 It's an infinite loop at runtime. `i == 256` never happens, it
- Adam D. Ruppe (5/6) Apr 24 I imagine some value range propagation that reports if a
```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
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
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]Ah, cool. I'll have a look.==> 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.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
On Thursday, 23 April 2026 at 18:20:23 UTC, Dom Disc wrote: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/23023It'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
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: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.```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
Apr 23
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
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_expressionsHis 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
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: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.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_expressionsHis 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
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.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.What if you want to port the C code to D so you can refactor and develop it using D features?
Apr 24
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
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: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.On Thursday, 23 April 2026 at 20:30:04 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.Now that we have ImportC, maybe he he can be convinced to soften his stance a bit.- 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
On Saturday, 25 April 2026 at 10:49:35 UTC, Nick Treleaven wrote:This is about the integer promotion rules, that people have been complaining about for years.- 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
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
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:Can we make `i < 256` a compile-time error?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.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
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









Dennis <dkorpel gmail.com> 