February 17, 2022
On Friday, 4 February 2022 at 20:31:58 UTC, H. S. Teoh wrote:
> On Fri, Feb 04, 2022 at 12:24:37PM -0800, Walter Bright via Digitalmars-d wrote:
>> On 2/4/2022 5:18 AM, Adam D Ruppe wrote:
>> > (and what C does doesn't make a whole lot of sense.)
>> 
>> C was developed on a PDP-11 and the integral promotions rules come about because of the way the -11 instructions work. It's the same for the float=>double promotion rules.
>
> PDP-11 instructions no longer resemble how modern machines work, though. What made sense back then may not necessarily make sense anymore today.
>
>
> T

Instruction sets really don't have changed much.
February 17, 2022

On Friday, 28 January 2022 at 02:15:51 UTC, Paul Backus wrote:

>

Unfortunately, this is also one of the areas of D that comes directly from C, so D programmers have to watch out for these as well.

Here's a lovely one I wrote about yesterday in Learn:

import std.conv, std.range, std.stdio;

void main() {
	writeln(iota(5, 0, -1));
	writeln(iota(5, -1, -1));
	writeln(iota(5.to!uint, -1, -1));
	writeln(iota(5.to!uint, 0, -1));
	writeln(-1.to!uint);
	auto z = -1;
	writeln(z.to!uint);
}

Which delivers the following output:

[5, 4, 3, 2, 1]
[5, 4, 3, 2, 1, 0]
[]
[5, 4, 3, 2, 1]
4294967295
std.conv.ConvOverflowException@/usr/include/dmd/phobos/std/conv.d(567): Conversion negative overflow
----------------
??:? pure @safe bool std.exception.enforce!(bool).enforce(bool, lazy object.Throwable) [0x555fe1c5c946]
??:? pure @safe uint std.conv.toImpl!(uint, int).toImpl(int) [0x555fe1c6f1ff]
??:? pure @safe uint std.conv.to!(uint).to!(int).to(int) [0x555fe1c6f1d0]
??:? _Dmain [0x555fe1c5594c]

All I wanted was a function that iterates through the elements of an array starting at the end. The only time you have a problem is if you want to include the first element of the array.

A simple solution is to add a -scottmeyers switch that retains full compatibility with C, but sets the default as a language that is productive.

February 17, 2022
On Thursday, 17 February 2022 at 17:53:58 UTC, bachmeier wrote:
> 	writeln(-1.to!uint);

This is -(1.to!uint).  Not (-1).to!uint.  Not really a WTF, imo; precedence is just something you have to know, and it works more or less the same way in most programming languages.
February 17, 2022
On Thursday, 17 February 2022 at 18:14:46 UTC, Elronnd wrote:
> On Thursday, 17 February 2022 at 17:53:58 UTC, bachmeier wrote:
>> 	writeln(-1.to!uint);
>
> This is -(1.to!uint).  Not (-1).to!uint.  Not really a WTF, imo; precedence is just something you have to know, and it works more or less the same way in most programming languages.

Setting aside the fact that this is maybe 1% of the point of my post, it's not about precedence. Write it like this if you want `writeln(-(1.to!uint))` and you'll get the same output. The language is more than happy to let someone take the negative of a uint without so much as a warning, even though the ratio of mistakes to legitimate uses is a gazillion to one.

But that was not the main point of my post. It's the behavior of iota silently converting good code to bad code when the second argument changes from 0 to -1. It's hard to trust the code you've written - something we already know from decades of writing C.
February 17, 2022

On 2/17/22 12:53 PM, bachmeier wrote:

>

A simple solution is to add a -scottmeyers switch that retains full compatibility with C, but sets the default as a language that is productive.

Let's try it in C:

for(unsigned int i = 5; i > -1; --i) printf("i is %d\n", i);

output is nothing.

-Steve

February 17, 2022

On Thursday, 17 February 2022 at 17:53:58 UTC, bachmeier wrote:

>

On Friday, 28 January 2022 at 02:15:51 UTC, Paul Backus wrote:

>

Unfortunately, this is also one of the areas of D that comes directly from C, so D programmers have to watch out for these as well.

Here's a lovely one I wrote about yesterday in Learn:

import std.conv, std.range, std.stdio;

void main() {
	writeln(iota(5, 0, -1));
	writeln(iota(5, -1, -1));
	writeln(iota(5.to!uint, -1, -1));
	writeln(iota(5.to!uint, 0, -1));
	writeln(-1.to!uint);
	auto z = -1;
	writeln(z.to!uint);
}

Yeah, implicit signed-to-unsigned conversion is really nasty. Even if we keep the rest of the C-style promotion rules, getting rid of that one would still be a big improvement.

February 17, 2022
On Thursday, 17 February 2022 at 20:11:07 UTC, Paul Backus wrote:
>
>
> Yeah, implicit signed-to-unsigned conversion is really nasty. Even if we keep the rest of the C-style promotion rules, getting rid of that one would still be a big improvement.

Implicit memory manipulation (e.g. type casting for example) can result in unintentional memory safety bugs, which in turn can result in adverse events. As such, it is not consistent with the concept of memory safety.

It would be great if D had a feature whereby I could annotate a function in such a way, that it disallowed implicit type conversions on its input arguments.

Regardless, I think this is another reason why D is unlikely to ever get widespread adoption. That is, the ship has sailed with regards to the pricipals of memory safety in programming languages, and the decisions Rust has made with regards to inherent safety, have resulted in the kind of language features programmers *will have to* work with in the future.

February 17, 2022
On Thursday, 17 February 2022 at 20:55:38 UTC, forkit wrote:
>

e.g.

This code would not compile:

(dic = disable implicit conversions)

// --

module test;
@safe:

import std;

void main()
{
    uint x = 4294967295;
    foo(x);
}


@dic void foo (int i)
{
    writeln(i); // will print -1 if this was allowed to compile.
}

// ---

February 17, 2022
On Thursday, 17 February 2022 at 20:55:38 UTC, forkit wrote:
> On Thursday, 17 February 2022 at 20:11:07 UTC, Paul Backus wrote:
>>
>>
>> Yeah, implicit signed-to-unsigned conversion is really nasty. Even if we keep the rest of the C-style promotion rules, getting rid of that one would still be a big improvement.
>
> Implicit memory manipulation (e.g. type casting for example) can result in unintentional memory safety bugs, which in turn can result in adverse events. As such, it is not consistent with the concept of memory safety.

Memory safety is about avoiding undefined behavior, not avoiding bugs in general. Implicitly casting an int to a uint can certainly cause bugs in a program, but it cannot introduce undefined behavior unless you are already doing something unsafe with the result (like indexing into an array without bounds checking).
February 17, 2022
On 2/17/2022 12:11 PM, Paul Backus wrote:
> Yeah, implicit signed-to-unsigned conversion is really nasty. Even if we keep the rest of the C-style promotion rules, getting rid of that one would still be a big improvement.

There is a simple solution you can use: never use unsigned integers. I'm not being facetious. Many languages do not have unsigned integer types.