Jump to page: 1 2 3
Thread overview
Providing implicit conversion of
Jan 22
bachmeier
Jan 22
bachmeier
Jan 23
Danilo
Re: Providing implicit conversion of - memory-safety
Jan 23
bachmeier
Jan 23
Renato
Jan 23
bachmeier
Jan 23
Renato
Jan 24
bachmeier
Jan 24
Renato
Jan 23
Danilo
Jan 24
bachmeier
Jan 24
Renato
Jan 23
Danilo
Jan 22
thinkunix
Jan 22
bachmeier
Jan 22
Danilo
January 21

The following code:

ulong charlie = 11;
long johnstone = std.algorithm.comparison.max(0, -charlie);
writeln(format!"johnstone %s"(johnstone));

Results in (without any warning(s)):
johnstone -11

However you choose to look at it, this means -11 > 0 (regardless of all arguments concerning implicit conversions, 1's and 2's complements, being efficient, etc).

The language should not allow unary unsigned anything.

January 22

On Sunday, 21 January 2024 at 16:05:40 UTC, Gavin Gray wrote:

>

The following code:

ulong charlie = 11;
long johnstone = std.algorithm.comparison.max(0, -charlie);
writeln(format!"johnstone %s"(johnstone));

Results in (without any warning(s)):
johnstone -11

However you choose to look at it, this means -11 > 0 (regardless of all arguments concerning implicit conversions, 1's and 2's complements, being efficient, etc).

The language should not allow unary unsigned anything.

This is unlikely to get fixed, just due to the nature of D's philosophy when it comes to C compatibility.

It would also break a lot of existing code.

-Steve

January 22

On Monday, 22 January 2024 at 01:14:06 UTC, Steven Schveighoffer wrote:

>

On Sunday, 21 January 2024 at 16:05:40 UTC, Gavin Gray wrote:

>

The following code:

ulong charlie = 11;
long johnstone = std.algorithm.comparison.max(0, -charlie);
writeln(format!"johnstone %s"(johnstone));

Results in (without any warning(s)):
johnstone -11

However you choose to look at it, this means -11 > 0 (regardless of all arguments concerning implicit conversions, 1's and 2's complements, being efficient, etc).

The language should not allow unary unsigned anything.

This is unlikely to get fixed, just due to the nature of D's philosophy when it comes to C compatibility.

It would also break a lot of existing code.

-Steve

Well there was no problem breaking my code for this (which you even proposed should be fixed):

foreach(int i, v; arr) {
  // i is not an int until you do i.to!int
}

The compiler knows it's converting from a ulong to a long:

ulong a = -11;
writeln(a);
// 18446744073709551605
long b = a;
writeln(b);
// -11

It's impossible for both to be the intended behavior. Anyone doing that on purpose (which I suspect is extremely rare) would be doing it because they want b equal to 18446744073709551605. I don't see why this should be treated the same as an int to long conversion because it very much changes the value.

There needs to be a safe arithmetic mode because the current behavior of double j = 10 / 3; is not what anyone expects and is a bug 100% of the time. I've said multiple times that it's silly to spend so much time on memory safety if the language is going to allow stuff like this without a simple way to prevent it.

January 22
Gavin Gray via Digitalmars-d-learn wrote:
> The following code:
> 
>    ulong charlie = 11;
>    long johnstone = std.algorithm.comparison.max(0, -charlie);
>    writeln(format!"johnstone %s"(johnstone));
> 
> Results in (without any warning(s)):
> johnstone -11
> 
> However you choose to look at it, this means -11 > 0 (regardless of all arguments concerning implicit conversions, 1's and 2's complements, being efficient, etc).
> 
> The language should not allow unary unsigned anything.
> 

I have no idea what your use case is for this but...
WHY are you doing this??

If you declared charlie as unsigned, why would you then attempt to
compare using a negative value?  If you even had the possibility that
charlie might be negative, why wouldn't you use a type that can accomodate the sign?

Using the proper type, you get a proper result:

        long b = 12;
        long n = std.algorithm.comparison.max(0, -b);
        long o = std.algorithm.comparison.max(0, b);
        writeln("n: ", n);              // prints 0
        writeln("o: ", o);              // prints 12

Seems obvious to me, but am I missing something?

scot
January 22

On Sunday, 21 January 2024 at 16:05:40 UTC, Gavin Gray wrote:

>

The following code:

ulong charlie = 11;
long johnstone = std.algorithm.comparison.max(0, -charlie);
writeln(format!"johnstone %s"(johnstone));

Results in (without any warning(s)):
johnstone -11

However you choose to look at it, this means -11 > 0 (regardless of all arguments concerning implicit conversions, 1's and 2's complements, being efficient, etc).

The language should not allow unary unsigned anything.

This returns -1:

import std;

void main() {
    ulong charlie = 11;
    long johnstone = std.algorithm.comparison.max(0, -charlie);
    writeln(format!"johnstone %s"(johnstone));
}

If you change the result type to auto johnstone, it returns 18446744073709551605:

module app;

import std;

void main() {
    ulong charlie = 11;
    auto johnstone = std.algorithm.comparison.max(0, -charlie);
    writeln(format!"johnstone %s"(johnstone));
}

So what happens is, max() correctly returns 18446744073709551605,
but if you explicitely receive a long, the ulong is converted to a long,
resulting in -11.

With auto johnstone or ulong johnstone the result is correct:

import std;

void main() {
    ulong charlie = 11;
    ulong johnstone = std.algorithm.comparison.max(0, -charlie);
    writeln(format!"johnstone %s"(johnstone));
}

If you take a bigger type, like Int128, it is also correct:

import std;

void main() {
    ulong charlie = 11;
    Int128 johnstone = std.algorithm.comparison.max(0, -charlie);
    writeln(format!"johnstone %s"(johnstone));
}
January 22
On Monday, 22 January 2024 at 06:43:17 UTC, thinkunix wrote:
> Gavin Gray via Digitalmars-d-learn wrote:
>> The following code:
>> 
>>    ulong charlie = 11;
>>    long johnstone = std.algorithm.comparison.max(0, -charlie);
>>    writeln(format!"johnstone %s"(johnstone));
>> 
>> Results in (without any warning(s)):
>> johnstone -11
>> 
>> However you choose to look at it, this means -11 > 0 (regardless of all arguments concerning implicit conversions, 1's and 2's complements, being efficient, etc).
>> 
>> The language should not allow unary unsigned anything.
>> 
>
> I have no idea what your use case is for this but...
> WHY are you doing this??
>
> If you declared charlie as unsigned, why would you then attempt to
> compare using a negative value?  If you even had the possibility that
> charlie might be negative, why wouldn't you use a type that can accomodate the sign?

I'm sure they would if the compiler had stopped and provided an error message to tell them what they were doing. Note that in this line

```
long johnstone = std.algorithm.comparison.max(0, -charlie);
```

there is no direct assignment of a negative number to an unsigned type. The comparison is carried out as ulong and then there's an implicit conversion of a ulong to long, even though that can give a very weird result. It's perfectly natural to expect that everything will be carried out as a long since that's what's specified, or that a language like D will forbid implicit conversions if they can possibly give the wrong answer. If you change the long to int, the code will no longer compile.

Aside from the general statement that programmers make mistakes, D is prone to these issues because of the heavy use of auto, and because unsigned types are used for things like the length of an array.
January 22

On Monday, 22 January 2024 at 03:53:54 UTC, bachmeier wrote:

>

There needs to be a safe arithmetic mode because the current behavior of double j = 10 / 3; is not what anyone expects and is a bug 100% of the time.

Don has a solution:
https://issues.dlang.org/show_bug.cgi?id=12452

>

I've said multiple times that it's silly to spend so much time on memory safety if the language is going to allow stuff like this without a simple way to prevent it.

Memory safety issues are a worse class of bug than arithmetic bugs. The latter are reproducible if you feed them the same input.

January 22

On Monday, 22 January 2024 at 01:14:06 UTC, Steven Schveighoffer wrote:

> >

The language should not allow unary unsigned anything.

This is unlikely to get fixed, just due to the nature of D's philosophy when it comes to C compatibility.

It would also break a lot of existing code.

I think the bigger issue is implicit conversion from unsigned to signed of the same bit size. In a future edition D could require a larger signed type in order to implicitly convert from unsigned. That would have caught the long johnstone = line.

Also signed should never convert to unsigned, though I don't think that's happening here.

January 22

On Monday, 22 January 2024 at 16:39:10 UTC, Nick Treleaven wrote:

> >

I've said multiple times that it's silly to spend so much time on memory safety if the language is going to allow stuff like this without a simple way to prevent it.

Memory safety issues are a worse class of bug than arithmetic bugs.

The required language changes are pretty small to catch arithmetic bugs relative to implementing memory safety. Ultimately, you want the compiler to help you catch bugs in any form, and I don't think someone that wants memory safety is likely to be okay with the type of bugs in this thread.

But for me, arithmetic bugs are a much larger problem than memory safety. I mostly use the GC plus calls into well-tested C libraries. I get incorrect results, and when I'm lucky, my program segfaults because I accessed something I shouldn't. When I'm not, it silently and happily gives me the wrong answer.

January 22

On Monday, 22 January 2024 at 16:39:10 UTC, Nick Treleaven wrote:

>

Memory safety issues are a worse class of bug than arithmetic bugs. The latter are reproducible if you feed them the same input.

Memory safety bugs are reproducible with the tools like valgrind. Whereas arithmetic overflow bugs are a real PITA to debug. Assuming that the incorrect results are even noticed.

« First   ‹ Prev
1 2 3