June 22, 2022

On Wednesday, 22 June 2022 at 21:07:50 UTC, Ola Fosheim Grøstad wrote:

>

On Wednesday, 22 June 2022 at 20:48:13 UTC, Steven Schveighoffer wrote:

>

The part about scope being shallow. This is a problem.

One thing that will be confusing to most users is that it appears to be using "taint" rather than proper flow analysis on the pointed-to-object?

int* test(int arg1, int arg2) {
    int* p = null;
    p = &arg1;
    p = new int(5);
    return p;  // complains about p being scope
}

I'd personally prefer if variable scope auto-inference worked only in the declaration, not later assignments. I guess the intention is to break less existing code.

Your solution would break even less, but it'd mean the language rules depend on flow analysis.

Because the rules are now "official", probably best to leave them as is to avoid confusion.

June 22, 2022

On Wednesday, 22 June 2022 at 21:20:33 UTC, Steven Schveighoffer wrote:

>

Full flow analysis will be defeatable by more complex situations:

int *p = null;
if(alwaysEvaluateToFalse()) p = &arg;
else p = new int(5);
return p;

That would take a lot of effort just to prove it shouldn't be scope.

I guess this is the wrong forum, but two quick points.

Some C programmers reuse variables extensively, those programmers will be confused or annoyed.

The analysis can be done after an optimization pass, so at least the simple cases go through smoothly.

June 22, 2022

On Wednesday, 22 June 2022 at 20:48:13 UTC, Steven Schveighoffer wrote:

>

On 6/21/22 11:05 AM, Mike Parker wrote:
The part about scope being shallow. This is a problem.

Is there any plan to address this other than "just use @system"?

-Steve

I think a custom struct containing a GC:d slice of scope arrays could be done. The struct itself needs @system code of course but could be @safe from outwards perspective, unless there's some issue I haven't thought of.

A relatively quick-and-dirty solution would be to use a static array for this, if you know some upper size the array can't exceed. Kinda cheap but probably better than @system.

June 22, 2022

On 6/22/22 5:58 PM, Dukc wrote:

>

On Wednesday, 22 June 2022 at 20:48:13 UTC, Steven Schveighoffer wrote:

>

On 6/21/22 11:05 AM, Mike Parker wrote:
The part about scope being shallow. This is a problem.

Is there any plan to address this other than "just use @system"?

I think a custom struct containing a GC:d slice of scope arrays could be done. The struct itself needs @system code of course but could be @safe from outwards perspective, unless there's some issue I haven't thought of.

A relatively quick-and-dirty solution would be to use a static array for this, if you know some upper size the array can't exceed. Kinda cheap but probably better than @system.

You mean like a system function which removes the scope-ness of an array? Let me introduce you to my other thread: https://forum.dlang.org/thread/t7qd45$1lrb$1@digitalmars.com

-Steve

June 22, 2022

On 6/22/22 5:44 PM, Dukc wrote:

>

On Wednesday, 22 June 2022 at 21:07:50 UTC, Ola Fosheim Grøstad wrote:

>

On Wednesday, 22 June 2022 at 20:48:13 UTC, Steven Schveighoffer wrote:

>

The part about scope being shallow. This is a problem.

One thing that will be confusing to most users is that it appears to be using "taint" rather than proper flow analysis on the pointed-to-object?

int* test(int arg1, int arg2) {
    int* p = null;
    p = &arg1;
    p = new int(5);
    return p;  // complains about p being scope
}

I'd personally prefer if variable scope auto-inference worked only in the declaration, not later assignments. I guess the intention is to break less existing code.

I think this is the better option. Either that, or that when it returns p that trumps any possible scope inference.

Imagine you have a function like this:

int foo()
{
   int x = 0;
   x = long.max;
   x = 2;
   return x;
}

Now today, this causes an error on the assignment to long.max, because obviously x is an int. But what if, instead, the compiler decides to backtrack and say "actually, if I make x a long, then it works!", and now, at the end, says "Oh, actually, you can't return a long as an int, what were you thinking?!"

This is the equivalent here, you declare something without scope, assign it to something that is not scope, and then because sometime later you assigned it to something that is scope, it goes back and rewrites the declaration as if you did make it scope, and then complains to you that the magic trick it tried is not valid.

This is going to be one of the most confusing features of DIP1000.

-Steve

June 23, 2022

On Thursday, 23 June 2022 at 00:45:09 UTC, Steven Schveighoffer wrote:

>

On 6/22/22 5:44 PM, Dukc wrote:

>

On Wednesday, 22 June 2022 at 21:07:50 UTC, Ola Fosheim Grøstad wrote:

>

On Wednesday, 22 June 2022 at 20:48:13 UTC, Steven Schveighoffer wrote:

>

The part about scope being shallow. This is a problem.

One thing that will be confusing to most users is that it appears to be using "taint" rather than proper flow analysis on the pointed-to-object?

int* test(int arg1, int arg2) {
    int* p = null;
    p = &arg1;
    p = new int(5);
    return p;  // complains about p being scope
}

I'd personally prefer if variable scope auto-inference worked only in the declaration, not later assignments.

I agree.

>

I think this is the better option. Either that, or that when it returns p that trumps any possible scope inference.

Imagine you have a function like this:

int foo()
{
   int x = 0;
   x = long.max;
   x = 2;
   return x;
}

Now today, this causes an error on the assignment to long.max, because obviously x is an int. But what if, instead, the compiler decides to backtrack and say "actually, if I make x a long, then it works!", and now, at the end, says "Oh, actually, you can't return a long as an int, what were you thinking?!"

This is the equivalent here, you declare something without scope, assign it to something that is not scope, and then because sometime later you assigned it to something that is scope, it goes back and rewrites the declaration as if you did make it scope, and then complains to you that the magic trick it tried is not valid.

This is going to be one of the most confusing features of DIP1000.

Plus that the error message just sounds like a compiler bug. It says that variable p is scope, but nowhere in the source does it say that. The error message should say that assignment p = &arg1; makes the variable scope.
(An alternative is to give a warning on p = &arg1;.)

-Johan

June 23, 2022

On Thursday, 23 June 2022 at 00:45:09 UTC, Steven Schveighoffer wrote:

>

I think this is the better option. Either that, or that when it returns p that trumps any possible scope inference.

Imagine you have a function like this:

int foo()
{
   int x = 0;
   x = long.max;
   x = 2;
   return x;
}

Now today, this causes an error on the assignment to long.max, because obviously x is an int. But what if, instead, the compiler decides to backtrack and say "actually, if I make x a long, then it works!", and now, at the end, says "Oh, actually, you can't return a long as an int, what were you thinking?!"

This is the equivalent here, you declare something without scope, assign it to something that is not scope, and then because sometime later you assigned it to something that is scope, it goes back and rewrites the declaration as if you did make it scope, and then complains to you that the magic trick it tried is not valid.

This is going to be one of the most confusing features of DIP1000.

It is confusing because it introduces flow typing without having flow typing. So this is messing up the user’s mental model of the type system, this is a basic usability flaw.

Track the object instead and don’t change the type of the pointer to scope.

If D wants to do flow typing, do it properly and make it clear to the user. It would be a good feature to have, but it would become D3.

June 23, 2022

On Thursday, 23 June 2022 at 06:36:23 UTC, Ola Fosheim Grøstad wrote:

>

Track the object instead and don’t change the type of the pointer to scope.

I guess this is flow typing too, but it is less intrusive to say that the object is either of type «scope» or type «heap» and that regular pointers can hold both than to change the concrete pointer type.

Specified concrete types should not change.

June 23, 2022

On Thursday, 23 June 2022 at 06:52:48 UTC, Ola Fosheim Grøstad wrote:

>

On Thursday, 23 June 2022 at 06:36:23 UTC, Ola Fosheim Grøstad wrote:

>

Track the object instead and don’t change the type of the pointer to scope.

I guess this is flow typing too, but it is less intrusive to say that the object is either of type «scope» or type «heap» and that regular pointers can hold both than to change the concrete pointer type.

Specified concrete types should not change.

For people interested in getting more intuition for flow typing:

https://www.typescriptlang.org/docs/handbook/2/narrowing.html

or chapter 3:

https://whiley.org/pdfs/GettingStartedWithWhiley.pdf

June 23, 2022

On Wednesday, 22 June 2022 at 21:58:07 UTC, Ola Fosheim Grøstad wrote:

>

Some C programmers reuse variables extensively, those programmers will be confused or annoyed.

And rightly so. Misra says since 30 years or longer: don't reuse variables if possible (and it should almost always be possible).
If there exists now another way to shoot in your foot with this bad habit, so what?