January 11, 2023

On Wednesday, 11 January 2023 at 13:51:43 UTC, jmh530 wrote:

>

The problem is the combination with assignment, which is what makes it seem like a bug. According to [1], "the right operand is implicitly converted to the type of the left operand, and assigned to it."

[1] https://dlang.org/spec/expression.html#simple_assignment_expressions

The relevant section of the spec here is the one about "Assignment Operator Expressions" [2], which states that

>

For arguments of built-in types, assignment operator expressions such as

a op= b

are semantically equivalent to:

a = cast(typeof(a))(a op b)

If we rewrite deadalnix's example using this equivalence, we get the following code:

ushort ee = 1028;
ee = cast(ushort)(ee << 5U);
ee = cast(ushort)(ee >> 5U);
writeln(ee);

...which prints 1028. So the behavior of the original example is unambiguously a violation of the language spec.

[2] https://dlang.org/spec/expression.html#assignment_operator_expressions

January 11, 2023

On Wednesday, 11 January 2023 at 20:55:33 UTC, Paul Backus wrote:

>

[snip]
...which prints 1028. So the behavior of the original example is unambiguously a violation of the language spec.

[2] https://dlang.org/spec/expression.html#assignment_operator_expressions

So someone file a bug report...

January 11, 2023

On Wednesday, 11 January 2023 at 20:57:00 UTC, jmh530 wrote:

>

On Wednesday, 11 January 2023 at 20:55:33 UTC, Paul Backus wrote:

>

[snip]
...which prints 1028. So the behavior of the original example is unambiguously a violation of the language spec.

[2] https://dlang.org/spec/expression.html#assignment_operator_expressions

So someone file a bug report...

I filed one last night

January 11, 2023
On 1/11/2023 12:55 PM, Paul Backus wrote:
> If we rewrite deadalnix's example using this equivalence, we get the following code:
> 
>      ushort ee = 1028;
>      ee = cast(ushort)(ee << 5U);
>      ee = cast(ushort)(ee >> 5U);
>      writeln(ee);
> 
> ...which prints 1028. So the behavior of the original example is unambiguously a violation of the language spec.

That's right. It also happens for ubyte operations.

January 11, 2023
On 1/11/2023 2:31 PM, max haughton wrote:
> I filed one last night

Thank you. Link?
January 11, 2023

On Wednesday, 11 January 2023 at 23:22:04 UTC, Walter Bright wrote:

>

On 1/11/2023 12:55 PM, Paul Backus wrote:

>

If we rewrite deadalnix's example using this equivalence, we get the following code:

    ushort ee = 1028;
    ee = cast(ushort)(ee << 5U);
    ee = cast(ushort)(ee >> 5U);
    writeln(ee);

...which prints 1028. So the behavior of the original example is unambiguously a violation of the language spec.

That's right. It also happens for ubyte operations.

    ubyte u = 128;
    u.writef!"%08b: "; writeln(u);
    typeof(u >> 1U).stringof.writeln;
    u >>= 1U;
    u.writef!"%08b: "; writeln(u);

    byte b = -128;
    b.writef!"%08b: "; writeln(b);
    typeof(b >> 1U).stringof.writeln;
    b >>= 1U;
    b.writef!"%08b: "; writeln(b);

The problem is that it shift via int first. Then the type is converted to whatever it is, right? I think there is no error because >>> should be used instead of >>

    u >>>= 1U;
    assert( u == 64 );

SDB@79

January 12, 2023
On Wednesday, 11 January 2023 at 23:22:45 UTC, Walter Bright wrote:
> On 1/11/2023 2:31 PM, max haughton wrote:
>> I filed one last night
>
> Thank you. Link?

https://issues.dlang.org/show_bug.cgi?id=23618
January 11, 2023
On 1/11/23 15:54, Salih Dincer wrote:

> The problem is that it shift via int first.

Yes but it shouldn't because one of the operands is uint and the 'int' operand should be converted to uint and the operation should have uint semantics.

> I think there is no error

This is a bug because the >> operator should not perform sign extension for unsigned types.

> because >>> should
> be used instead of >>

>>> could be used but it is the same as >> operator for unsigned types.

import std;

void main() {
    int i = 0x8000_0000;
    assert(i >>  31 == 0xffff_ffff);  // sign extended
    assert(i >>> 31 == 0x0000_0001);  // different for int

    uint u = 0x8000_0000;
    assert(u >>  31 == 0x0000_0001);  // no extension
    assert(u >>> 31 == 0x0000_0001);  // no difference for uint
}

Ali

January 12, 2023
On Thursday, 12 January 2023 at 02:05:14 UTC, max haughton wrote:
> On Wednesday, 11 January 2023 at 23:22:45 UTC, Walter Bright wrote:
>> On 1/11/2023 2:31 PM, max haughton wrote:
>>> I filed one last night
>>
>> Thank you. Link?
>
> https://issues.dlang.org/show_bug.cgi?id=23618

It must be noted that the problem seems to be fixed in recent compiler, but CircleCI uses a compiler that is busted.

The reason I did not go the bug repport road is because I expect this bug to be marked as fixed because it is indeed fixed, but that wouldn't address the CircleCI issue.
January 12, 2023
On Thursday, 12 January 2023 at 08:55:50 UTC, deadalnix wrote:
> [...] I expect this bug to be marked as fixed because it is indeed fixed, [...]

```
$ dmd --version
DMD64 D Compiler v2.101.1
Copyright (C) 1999-2022 by The D Language Foundation, All Rights Reserved written by Walter Bright
$ cat bug23618.d
unittest {
   ubyte ub;
   ub = 0x80;
   ub >>= 1u;
   assert (ub == 0x40);
   ushort us;
   us = 0x8000;
   us >>= 1u;
   assert (us == 0x4000);
}
$ dmd -O -checkaction=context -unittest -main -run bug23618.d
1 modules passed unittests
$ dmd -checkaction=context -unittest -main -run bug23618.d
bug23618.d(5): [unittest] 192 != 64
1/1 modules FAILED unittests

```