Re: @safe question

2022-01-11 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 12 January 2022 at 00:45:23 UTC, H. S. Teoh wrote:
IMNSHO, that @trusted lambda thing is an anti-pattern that 
should be avoided, needless to say already promoted.  It's 
papering over a problem that ought to be fixed instead of being 
pushed under the rug.


There's nothing wrong with @trusted lambdas. The recent FUD 
around them is almost entirely unjustified.


If it takes -dip1000 to compile the OP's code, then I say, by 
all means, use -dip1000.  It's not *that* hard to add a compile 
switch to your build.  I know dip1000 isn't quite there yet, 
but how is it supposed to "get there" if everyone is avoiding 
to use it?


The reason I hesitate to recommend -preview=dip1000 to a 
beginning D programmer is that because the documentation is 
incomplete, it can be very difficult to *debug* DIP 1000 errors, 
and because the implementation has several known bugs, you cannot 
simply rely on the compiler to tell you when you've gotten things 
right.


Re: @safe question

2022-01-11 Thread H. S. Teoh via Digitalmars-d-learn
On Wed, Jan 12, 2022 at 12:24:14AM +, forkit via Digitalmars-d-learn wrote:
> On Tuesday, 11 January 2022 at 21:50:00 UTC, Paul Backus wrote:
> > ..
> > If you know a particular bit of code is memory safe, but the compiler
> > can't prove it, you can mark that code as @trusted. For example:
> > 
> > () @trusted { pointers ~=  )();
> > 
> > This example uses an immediately-invoked function literal [1] (also
> > known as a "lambda") to apply the @trusted attribute to a single
> > statement.
> > ...
> 
> Thanks again. Really useful information.
> 
> The more I use D, the more I feel that I'm falling into a deep, deep,
> deeprabbit hole.

IMNSHO, that @trusted lambda thing is an anti-pattern that should be
avoided, needless to say already promoted.  It's papering over a problem
that ought to be fixed instead of being pushed under the rug.

If it takes -dip1000 to compile the OP's code, then I say, by all means,
use -dip1000.  It's not *that* hard to add a compile switch to your
build.  I know dip1000 isn't quite there yet, but how is it supposed to
"get there" if everyone is avoiding to use it?  We should rather be
pushing more people to use it so that more flaws are discovered and
fixed, rather than avoiding it and letting it languish, and 5 years
later the same old flaws continue to sit unfixed.


T

--
People walk. Computers run.


Re: @safe question

2022-01-11 Thread forkit via Digitalmars-d-learn

On Tuesday, 11 January 2022 at 21:50:00 UTC, Paul Backus wrote:

..
If you know a particular bit of code is memory safe, but the 
compiler can't prove it, you can mark that code as @trusted. 
For example:


() @trusted { pointers ~=  )();

This example uses an immediately-invoked function literal [1] 
(also known as a "lambda") to apply the @trusted attribute to a 
single statement.

...


Thanks again. Really useful information.

The more I use D, the more I feel that I'm falling into a deep, 
deep, deeprabbit hole.





Re: @safe question

2022-01-11 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 11 January 2022 at 21:38:58 UTC, forkit wrote:

On Tuesday, 11 January 2022 at 14:54:51 UTC, Paul Backus wrote:

..
If you compile with -preview=dip1000, the compiler will 
actually keep track of which pointers point to stack memory, 
and will allow your original code. But -preview=dip1000 is 
still somewhat experimental, and the documentation for it is 
pretty sparse, so you may have an easier time just working 
around the limitations of the default safety checks.


Thanks. Appreciate the explanation :-)

In the end though, correct code should just compile.

I shouldn't need a 'work around' :-(


In any statically typed language, there is always going to be 
code which you, the programmer, know is correct, but which the 
compiler can't automatically prove is correct. The same is true 
for safety.


If you know a particular bit of code is memory safe, but the 
compiler can't prove it, you can mark that code as @trusted. For 
example:


() @trusted { pointers ~=  )();

This example uses an immediately-invoked function literal [1] 
(also known as a "lambda") to apply the @trusted attribute to a 
single statement.


Of course, when you write @trusted code, you must be *very* sure 
that what you are doing cannot possibly lead to undefined 
behavior, no matter what happens in other parts of the program. 
There's a post on the official D blog, "How to Write @trusted 
Code in D," [2] that talks about some of the most common 
pitfalls, and gives advice for avoiding them.


[1] https://dlang.org/spec/expression.html#function_literals
[2] 
https://dlang.org/blog/2016/09/28/how-to-write-trusted-code-in-d/


Re: @safe question

2022-01-11 Thread forkit via Digitalmars-d-learn

On Tuesday, 11 January 2022 at 14:54:51 UTC, Paul Backus wrote:

..
If you compile with -preview=dip1000, the compiler will 
actually keep track of which pointers point to stack memory, 
and will allow your original code. But -preview=dip1000 is 
still somewhat experimental, and the documentation for it is 
pretty sparse, so you may have an easier time just working 
around the limitations of the default safety checks.


Thanks. Appreciate the explanation :-)

In the end though, correct code should just compile.

I shouldn't need a 'work around' :-(



Re: @safe question

2022-01-11 Thread Paul Backus via Digitalmars-d-learn

On Tuesday, 11 January 2022 at 10:57:28 UTC, forkit wrote:

On Monday, 10 January 2022 at 03:21:46 UTC, Paul Backus wrote:


Taking the address of a local variable is forbidden in @safe 
code. Even though str is a ref variable that points to a 
heap-allocated string, it is still considered a local variable 
because it is declared inside the body of a function.


but strings[] is also a local variable declared in the body of 
the same function, and yet within the foreach statement, @safe 
lets me do:


pointers ~= [i]; // safe

...but not this below, where str is just a reference to the 
exact same memory as the statement above... is it not? How is 
this below any more or less safe than the above statement.


pointers ~=   // not safe - ok, but why??


Because the compiler doesn't look at that much context, and it's 
possible to write code where `str` points to memory that's on the 
stack; for example:


string[3] strings = ["foo", "bar", "baz"];
foreach (ref str; strings) {
// ...
}

If you compile with -preview=dip1000, the compiler will actually 
keep track of which pointers point to stack memory, and will 
allow your original code. But -preview=dip1000 is still somewhat 
experimental, and the documentation for it is pretty sparse, so 
you may have an easier time just working around the limitations 
of the default safety checks.


Re: @safe question

2022-01-11 Thread forkit via Digitalmars-d-learn

On Monday, 10 January 2022 at 03:21:46 UTC, Paul Backus wrote:


Taking the address of a local variable is forbidden in @safe 
code. Even though str is a ref variable that points to a 
heap-allocated string, it is still considered a local variable 
because it is declared inside the body of a function.


but strings[] is also a local variable declared in the body of 
the same function, and yet within the foreach statement, @safe 
lets me do:


pointers ~= [i]; // safe

...but not this below, where str is just a reference to the exact 
same memory as the statement above... is it not? How is this 
below any more or less safe than the above statement.


pointers ~=   // not safe - ok, but why??



Re: @safe question

2022-01-09 Thread Paul Backus via Digitalmars-d-learn

On Monday, 10 January 2022 at 01:16:31 UTC, forkit wrote:

On Sunday, 9 January 2022 at 21:56:05 UTC, Salih Dincer wrote:


Try the @trusted and in/out:
...
..
.


thanks for introducing me to the in/out feature of D :-)

I'll certainly look into that feature more.

But my question still remains:

//pointers ~=  // why is this *not* allowed in @safe
pointers ~= [i]; // while this *is* allowed in @safe


Taking the address of a local variable is forbidden in @safe 
code. Even though str is a ref variable that points to a 
heap-allocated string, it is still considered a local variable 
because it is declared inside the body of a function.


Re: @safe question

2022-01-09 Thread forkit via Digitalmars-d-learn

On Sunday, 9 January 2022 at 21:56:05 UTC, Salih Dincer wrote:


Try the @trusted and in/out:
...
..
.


thanks for introducing me to the in/out feature of D :-)

I'll certainly look into that feature more.

But my question still remains:

//pointers ~=  // why is this *not* allowed in @safe
pointers ~= [i]; // while this *is* allowed in @safe



Re: @safe question

2022-01-09 Thread Salih Dincer via Digitalmars-d-learn

On Sunday, 9 January 2022 at 20:58:05 UTC, forkit wrote:
Do not understand why one line is not considered @safe, but the 
other is.


//

module test;

import std;

@safe void main()
{
immutable string[] strings = ["one", "one", "two"];

immutable(string)*[] pointers = null;

foreach(size_t i, ref str; strings)
{
if(str == "one")
{
//pointers ~=  // not allowed in @safe ??

pointers ~= [i]; // for @safe, I have to 
revert to using an index into strings.

}
i++;
}
}

//-


Try the @trusted and in/out:

```d
auto pro(in immutable string[]   strings,
out immutable(string)*[] pointers) @trusted {
foreach(i, ref str; strings)
{
if(str == "one")
{
//pointers ~= [i]/* ok
pointers ~= //*/
}
/* unnecessary:
i++;//*/
}
}

@safe void main()
{
immutable string[] strings = ["one", "one", "two"];

immutable(string)*[] pointers = null;

strings.pro(pointers);

assert(pointers[0] ==
   [0]); // ok

assert(pointers[1] ==
   [1]); // ok

}
```