D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 2434 - Need a way to add casts into array operations.
Summary: Need a way to add casts into array operations.
Status: RESOLVED WORKSFORME
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86 All
: P2 enhancement
Assignee: No Owner
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2008-10-28 18:11 UTC by Jarrett Billingsley
Modified: 2019-09-09 15:05 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Jarrett Billingsley 2008-10-28 18:11:27 UTC
T[] a = [1, 2, 3, 4, 5];
a[] = 1 op a;

Replace T with byte, ubyte, short, or ushort.  Replace op with / or %.  For example:

byte[] a = [1, 2, 3, 4, 5];
a[] = 1 / a;

All possible combinations give errors like this when -w is enabled:

warning - Error: implicit conversion of expression (cast(int)c0 / cast(int)(p1[p])) of type int to byte can cause loss of data

The c0, p1, and p variables are what the compiler uses for internal names when converting array operations into code, so this is an error in the generated code.

Similar things happen if you have something like:

T[] b = [1, 2, 3, 4, 5];
a[] = b[] op a[];
Comment 1 yebblies 2011-06-10 05:07:30 UTC
Currently dmd (1.068 and 2.052) fails to compile these with the following message:

testx.d(4): Error: incompatible types for ((1) / (a)): 'int' and 'byte[]'
Comment 2 Jarrett Billingsley 2011-07-13 11:50:47 UTC
So the compiler now requires that I put [] on operands in array operations, but the bug has NOT been fixed.

T[] a = [1, 2, 3, 4, 5];
a[] = 1 op a[];

Still fails with the same warning when -w is thrown, and the last example still fails as well.
Comment 3 Steven Schveighoffer 2011-07-13 12:37:32 UTC
hm... shouldn't the calculation follow the same rules as an individual operation?

for example 

byte b;
b = 1 / b;

This has the same error message, so I would assume that an array operation must obey the same rules.

The biggest issue here is, how does one create an expression which circumvents the requirement?

In my above example, you can do:

b = cast(byte)(1 / b);

but this doesn't work:

a[] = cast(byte)(1 / a[]);
or
a[] = cast(byte[])(1 / a[]);

So essentially there is no way to insert a cast into the array expression.  I think we almost need a new syntax for this (maybe cast[](byte)? )

I'm going to rename the bug (and adjust properties accordingly) because the code you wrote is *supposed* to give an error.  The issue is that there's no way to cast out of it!

Note the reason D2 does not give an error (with or without -w) on your original code is because of range propagation.
Comment 4 Jarrett Billingsley 2011-07-13 12:40:02 UTC
Range propagation "fixes" it, but the bug only manifests in D1 because of the ridiculous rules regarding integer math. (1 / a) where a is a ubyte is of type "int", not of type "ubyte". But the problem doesn't manifest with 32- or 64-bit integers.
Comment 5 Steven Schveighoffer 2011-07-13 12:46:35 UTC
Hm, I take it back.  This doesn't compile on D2, so maybe range propagation isn't smart enough.

int x = 1;
byte b = 1 / x;

Same error reported

Now I really don't know why D2 passes the array operation...

I still think the right solution is allowing casting in an array expression.
Comment 6 kennytm 2011-07-13 13:09:26 UTC
(In reply to comment #5)
> Hm, I take it back.  This doesn't compile on D2, so maybe range propagation
> isn't smart enough.
> 

There is no way VRP will support this. After the statement 'int x = 1', the information that 'x == 1' is lost. We don't have data flow analysis. So in the expression '1 / x', x is treated as having the complete range of 'int'.

In the current implementation of VRP, since the divisor contains 0, the result will be the complete range, so '1 / x' still gives the complete range of 'int', not [-1, 1].

</off-topic>

> int x = 1;
> byte b = 1 / x;
> 
> Same error reported
> 
> Now I really don't know why D2 passes the array operation...
> 
> I still think the right solution is allowing casting in an array expression.
Comment 7 Steven Schveighoffer 2011-07-13 13:27:56 UTC
(In reply to comment #6)
> There is no way VRP will support this. After the statement 'int x = 1', the
> information that 'x == 1' is lost. We don't have data flow analysis. So in the
> expression '1 / x', x is treated as having the complete range of 'int'.

I was taking this into account.

if the divisor is zero, you get a floating point exception (i.e. SIGFPE), so VRP is able to safely use [-1, 1] as the range.

Technically, the set of possible values is [1, -1, undefined], and we can simply ignore the undefined part for VRP.

Indeed the example is quite questionable, but I suppose if you know none of the values are 0, it's valid code.

In any case, I don't think VRP is the answer to the problem.
Comment 8 RazvanN 2019-09-09 15:05:56 UTC
This bug does not manifest in D2. Closing as WORKSFORME.