Re: DIP1000

2022-07-02 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Saturday, 2 July 2022 at 09:42:17 UTC, Loara wrote:
But you first said "The compiler should deduce if a `scope` 
pointer points to heap allocated data or not" and when someone 
tells you this should happen only for not `scope` pointers you 
say "But the compiler doesn't do that".


This discussion isn't going anywhere… :-)

(Please don't use quotation marks unless you actually quote.).



Re: DIP1000

2022-07-02 Thread Loara via Digitalmars-d-learn
On Thursday, 30 June 2022 at 21:30:39 UTC, Ola Fosheim Grøstad 
wrote:
I don't understand what you mean, it could, but it doesn't. And 
if it did then you would not need `scope`…


If the compiler doesn't optimize your code is a compiler issue. 
When you use the `scope` attribute you're [forcing the compiler 
to do a stack 
allocation](https://dlang.org/spec/attribute.html#scope-class-var), so the compiler forbids you from doing something stupid.


These are function pointer parameters, how could it trigger 
allocation on the heap?


When you declare `scope` function parameters you're saying that 
it may point both to heap allocated and stack allocated data, and 
the compiler choose the more restrictive option when it compiles 
your option, since at that time it doesn't know if your function 
arguments are heap allocated or stack allocated.



But that doesn't work.


But you first said "The compiler should deduce if a `scope` 
pointer points to heap allocated data or not" and when someone 
tells you this should happen only for not `scope` pointers you 
say "But the compiler doesn't do that".


No, the latter can most certainly point to any integer. It is 
just that scope/scope ref/return ref is to be checked in @safe. 
Unfortunately it is way too limiting. Even standard flow typing 
appears to be as strong or stronger.


No-one forbids you from writing an unsafe function that does 
unsafe operations, the `@system` and `@trusted` attributes are 
available yet. Simply you should control very well your code in 
order to avoid memory leaks and other issues since memory 
management without garbage collectors can't be safe without 
introducing a lot of restrictions.


If you decide to do so I recommend you this [very useful 
tool](https://valgrind.org/).


If there are destructors then you can think of each stack 
allocated variable as introducing a invisible scope, but the 
compiler can keep track of this easily.


So the compiler knows the ordering. So if my function imposes 
and order on the lifetimes of the parameters, then the compiler 
should be able to check that the ordering constraint is 
satisfied.


If you want the compiler to optimize your code you should remove 
any additional restriction, and declaring a pointer `scope` is an 
additional restriction not a relaxation. If you don't like it 
then you can always build a new compiler that do this if you need 
it so much, this is how open source software works.



But then it won't compile at all in @safe!


Find me an example of safe code that needs it and can't work 
without `scope` variables.


Anyway I strongly recommend you to read these 
[documentation](https://dlang.org/spec/attribute.html#scope) 
[pages](https://dlang.org/spec/function.html#scope-parameters) in 
order to understand how `scope` works.


If you don't like `scope` then don't use it.




Re: DIP1000

2022-06-30 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Thursday, 30 June 2022 at 19:56:38 UTC, Loara wrote:
The deduction can happen even if you don't use `scope` 
attribute.


I don't understand what you mean, it could, but it doesn't. And 
if it did then you would not need `scope`…


When you use `scope` attribute you're saying to compiler "You 
have to allocate this object on the stack, don't try to use 
heap allocation".


These are function pointer parameters, how could it trigger 
allocation on the heap?


If you want to let compiler to decide what is the best approach 
then don't use `scope`.


But that doesn't work.

So `scope int v;` is equal to `int v;` since `v` is not a 
pointer, whereas `scope int *p` is different from `int *v;` 
since the latter can't point to stack allocated integers. This 
is the difference.


No, the latter can most certainly point to any integer. It is 
just that scope/scope ref/return ref is to be checked in @safe. 
Unfortunately it is way too limiting. Even standard flow typing 
appears to be as strong or stronger.


Since stack allocated objects are destroyed in the reverse 
order allowing a recursive `scope` attribute is a bit dangerous 
as you can see in the following example:


If there are destructors then you can think of each stack 
allocated variable as introducing a invisible scope, but the 
compiler can keep track of this easily.


So the compiler knows the ordering. So if my function imposes and 
order on the lifetimes of the parameters, then the compiler 
should be able to check that the ordering constraint is satisfied.


Again if you want to let the compiler to deduce then don't use 
`scope`.


But then it won't compile at all in @safe!



Re: DIP1000

2022-06-30 Thread Loara via Digitalmars-d-learn
On Tuesday, 28 June 2022 at 21:58:48 UTC, Ola Fosheim Grøstad 
wrote:
Not when connect returns, but the scope that connect was called 
from. Still, this can be deduced, you just have to give the 
scopes an ordering.


The deduction can happen even if you don't use `scope` attribute. 
When you use `scope` attribute you're saying to compiler "You 
have to allocate this object on the stack, don't try to use heap 
allocation". If you want to let compiler to decide what is the 
best approach then don't use `scope`.


Well, that is a flaw, if the object is stack allocated then the 
fields are too.


No because:

`scope` variable === the variable is a pointer/reference that 
points to stack allocated data


So `scope int v;` is equal to `int v;` since `v` is not a 
pointer, whereas `scope int *p` is different from `int *v;` since 
the latter can't point to stack allocated integers. This is the 
difference.


Since stack allocated objects are destroyed in the reverse order 
allowing a recursive `scope` attribute is a bit dangerous as you 
can see in the following example:


```d

struct A{
  int *i;

  ~this(){
writeln(*i);
  }
}
...
 {
  A a;
  int i = 2;
  ...
  scope int *j = 
  scope A *b = 
  (*b).i = j;
 } // i is destroyed before a
```

The compiler could easily deduce it. It is not difficult to see 
what the life time constraint must be.


Again if you want to let the compiler to deduce then don't use 
`scope`.





Re: DIP1000

2022-06-29 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Wednesday, 29 June 2022 at 05:51:26 UTC, bauss wrote:
Not necessarily, especially if the fields aren't value types. 
You can have stack allocated "objects" with pointers to heap 
allocated memory (heap allocated "objects".)


Those are not fields, those are separate objects… The compiler 
knows which is a field (part of the object).


You can't, or rather you shouldn't have stack allocated fields 
within heap allocated "objects" however; as that will almost be 
guaranteed to lead to problems.


That is perfectly ok if you use RAII and manage life times.

Ex. from your example then even if the "node struct" you pass 
was allocated on the stack, then the memory the "next" pointer 
points to might not be allocated same place.


Unless I'm misunderstanding what you're trying to say.


You did :). If you look at the post I made in general about 
DIP1000 and flow typing you see that I annotate scope with a 
number to indicate life time ordering.


If you have `connect(int* a,int* b){a.next = b}` then the 
compiler can deduce that the signature with formal parameters 
should be `connect(scope!N(int*) a, scope_or_earlier!N(int*) b)`. 
The compiler then checks that the actual parameters at the call 
site are subtypes (same type or proper subtype).










Re: DIP1000

2022-06-28 Thread bauss via Digitalmars-d-learn
On Tuesday, 28 June 2022 at 21:58:48 UTC, Ola Fosheim Grøstad 
wrote:


not-scoped variable (`a.next` is not `scope` since this 
attribute is not transitive)


Well, that is a flaw, if the object is stack allocated then the 
fields are too.




Not necessarily, especially if the fields aren't value types. You 
can have stack allocated "objects" with pointers to heap 
allocated memory (heap allocated "objects".)


You can't, or rather you shouldn't have stack allocated fields 
within heap allocated "objects" however; as that will almost be 
guaranteed to lead to problems. I believe it's possible, but one 
should always refrain from it, but the same isn't true the for 
stack allocated "objects" with heap allocated fields.


Ex. from your example then even if the "node struct" you pass was 
allocated on the stack, then the memory the "next" pointer points 
to might not be allocated same place.


Unless I'm misunderstanding what you're trying to say.


Re: DIP1000

2022-06-28 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Tuesday, 28 June 2022 at 21:40:44 UTC, Loara wrote:
When `connect()` returns may happen that `b` is destroyed but 
`a` not, so `a.next` contains a dangling pointer that


Not when connect returns, but the scope that connect was called 
from. Still, this can be deduced, you just have to give the 
scopes an ordering.



not-scoped variable (`a.next` is not `scope` since this 
attribute is not transitive)


Well, that is a flaw, if the object is stack allocated then the 
fields are too.


is clearly dangerous since `connect` doesn't know which between 
`a` and `b` terminates first.


The compiler could easily deduce it. It is not difficult to see 
what the life time constraint must be.




Re: DIP1000

2022-06-28 Thread Loara via Digitalmars-d-learn
On Friday, 24 June 2022 at 18:31:14 UTC, Ola Fosheim Grøstad 
wrote:
The objects are in the calling function, not in the connect() 
function. So they are not destroyed when the connect() function 
returns.


When `connect()` returns may happen that `b` is destroyed but `a` 
not, so `a.next` contains a dangling pointer that will bring 
potential segmentation faults that could be detected only with 
tools like Valgrind, just consider


```d
node * calling(return scope node * a) @safe{
  scope node *b = new node(); //b is stack allocated
  connect(a, b);
  return a;
  //b destroyed but a not
}
```

The `scope` attribute tries to avoid these events preventing you 
from doing something potentially dangerous with stack allocated 
objects, and assigning a `scope` pointer to a not-scoped variable 
(`a.next` is not `scope` since this attribute is not transitive) 
is clearly dangerous since `connect` doesn't know which between 
`a` and `b` terminates first.





Re: DIP1000

2022-06-24 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Friday, 24 June 2022 at 17:53:07 UTC, Loara wrote:

Why you should use `scope` here?


I probably shouldn't. That is why I asked in the «learn» forum…

A `scope` pointer variable may refer to a stack allocated 
object that may be destroyed once the function returns.


The objects are in the calling function, not in the connect() 
function. So they are not destroyed when the connect() function 
returns.


Since a linked list should not contain pointers to stack 
allocated data you should avoid entirely the `scope` attribute 
and use instead `const`.


It was only an example. There is nothing wrong with connecting 
objects on the stack.




Re: DIP1000

2022-06-24 Thread Loara via Digitalmars-d-learn
On Thursday, 23 June 2022 at 16:08:01 UTC, Ola Fosheim Grøstad 
wrote:

How am I supposed to write this:

```d
import std;
@safe:

struct node {
node* next;
}

auto connect(scope node* a, scope node* b)
{
a.next = b;
}

void main()
{
node x;
node y;
connect(,);
}

```


Error: scope variable `b` assigned to non-scope `(*a).next`


Why you should use `scope` here? A `scope` pointer variable may 
refer to a stack allocated object that may be destroyed once the 
function returns.


Since a linked list should not contain pointers to stack 
allocated data you should avoid entirely the `scope` attribute 
and use instead `const`.





Re: DIP1000

2022-06-24 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Friday, 24 June 2022 at 09:08:25 UTC, Dukc wrote:
On Friday, 24 June 2022 at 05:11:13 UTC, Ola Fosheim Grøstad 
wrote:


No, the lifetime is the same if there is no destructor. Being 
counter intuitive is poor usability.


It depends on whether you expect the rules to be smart or 
simple. Smart is not necessarily better, as the Unix philosophy 
tells you. I'm sure you have experience about programs that are 
unpredictable and thus frustating to use because they try to be 
too smart.


If this feature is meant to be used by application developers and 
not only library authors then it has to match their intuitive 
mental model of life times. I would expect all simple value types 
to have the same lifetime as the scope.


The other option is to somehow instill a mental model in all 
users that simple types like ints also having default destructors.


If it only is for library authors, then it is ok to deviate from 
"intuition".




Re: DIP1000

2022-06-24 Thread Dukc via Digitalmars-d-learn
On Friday, 24 June 2022 at 05:11:13 UTC, Ola Fosheim Grøstad 
wrote:


No, the lifetime is the same if there is no destructor. Being 
counter intuitive is poor usability.


It depends on whether you expect the rules to be smart or simple. 
Smart is not necessarily better, as the Unix philosophy tells 
you. I'm sure you have experience about programs that are 
unpredictable and thus frustating to use because they try to be 
too smart.





Re: DIP1000

2022-06-23 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Friday, 24 June 2022 at 03:03:52 UTC, Paul Backus wrote:
On Thursday, 23 June 2022 at 21:34:27 UTC, Ola Fosheim Grøstad 
wrote:

On Thursday, 23 June 2022 at 21:05:57 UTC, ag0aep6g wrote:

It's a weird rule for sure.


Another slightly annoying thing is that it cares about 
destruction order when there are no destructors.


If there are no destructors the lifetime ought to be 
considered the same for variables in the same scope.


Having different lifetime rules for different types is worse UX 
than having the same lifetime rules for all types.


Imagine writing a generic function which passes all of your 
unit tests, and then fails when you try to use it in real code, 
because you forgot to test it with a type that has a destructor.


No, the lifetime is the same if there is no destructor. Being 
counter intuitive is poor usability.


If you want to help library authors you issue a warning for 
generic code only.




Re: DIP1000

2022-06-23 Thread Paul Backus via Digitalmars-d-learn
On Thursday, 23 June 2022 at 21:34:27 UTC, Ola Fosheim Grøstad 
wrote:

On Thursday, 23 June 2022 at 21:05:57 UTC, ag0aep6g wrote:

It's a weird rule for sure.


Another slightly annoying thing is that it cares about 
destruction order when there are no destructors.


If there are no destructors the lifetime ought to be considered 
the same for variables in the same scope.


Having different lifetime rules for different types is worse UX 
than having the same lifetime rules for all types.


Imagine writing a generic function which passes all of your unit 
tests, and then fails when you try to use it in real code, 
because you forgot to test it with a type that has a destructor.


Re: DIP1000

2022-06-23 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Thursday, 23 June 2022 at 21:05:57 UTC, ag0aep6g wrote:

It's a weird rule for sure.


Another slightly annoying thing is that it cares about 
destruction order when there are no destructors.


If there are no destructors the lifetime ought to be considered 
the same for variables in the same scope.





Re: DIP1000

2022-06-23 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Thursday, 23 June 2022 at 21:05:57 UTC, ag0aep6g wrote:
It means "may be returned or copied to the first parameter" 
(https://dlang.org/spec/function.html#param-storage). You 
cannot escape via other parameters. It's a weird rule for sure.


Too complicated for what it does… Maybe @trusted isn't so bad 
after all.




Re: DIP1000

2022-06-23 Thread ag0aep6g via Digitalmars-d-learn
On Thursday, 23 June 2022 at 20:27:44 UTC, Ola Fosheim Grøstad 
wrote:

On Thursday, 23 June 2022 at 19:38:12 UTC, ag0aep6g wrote:

```d
void connect(ref scope node a, return scope node* b)
```


Thanks, so the `return scope` means «allow escape», not 
necessarily return?


It means "may be returned or copied to the first parameter" 
(https://dlang.org/spec/function.html#param-storage). You cannot 
escape via other parameters. It's a weird rule for sure.


Re: DIP1000

2022-06-23 Thread Ola Fosheim Grøstad via Digitalmars-d-learn

On Thursday, 23 June 2022 at 19:38:12 UTC, ag0aep6g wrote:

```d
void connect(ref scope node a, return scope node* b)
```


Thanks, so the `return scope` means «allow escape», not 
necessarily return?


But that only works for this very special case. It falls apart 
when you try to add a third node. As far as I understand, 
`scope` cannot handle linked lists. A `scope` pointer cannot 
point to another `scope` pointer.


One can do two levels, but not three. Got it. Works for some 
basic data-structures.




Re: DIP1000

2022-06-23 Thread ag0aep6g via Digitalmars-d-learn
On Thursday, 23 June 2022 at 16:08:01 UTC, Ola Fosheim Grøstad 
wrote:

How am I supposed to write this:

```d
import std;
@safe:

struct node {
node* next;
}

auto connect(scope node* a, scope node* b)
{
a.next = b;
}

void main()
{
node x;
node y;
connect(,);
}

```


Error: scope variable `b` assigned to non-scope `(*a).next`


DMD accepts this:

```d
@safe:

struct node {
node* next;
}

void connect(ref scope node a, return scope node* b)
{
a.next = b;
}

void main()
{
node y;
scope node x;
connect(x, );
}
```

But that only works for this very special case. It falls apart 
when you try to add a third node. As far as I understand, `scope` 
cannot handle linked lists. A `scope` pointer cannot point to 
another `scope` pointer.


So as to how you're supposed to do it: with @system.


Re: dip1000 return scope dmd v 2.100

2022-05-07 Thread vit via Digitalmars-d-learn

On Friday, 6 May 2022 at 17:17:01 UTC, Dennis wrote:

On Friday, 6 May 2022 at 09:24:06 UTC, vit wrote:

[...]


They were recently updated to match the implementation in 2.100.


[...]


`return scope` means pointer members (such `this.ptr`, `C.ptr`) 
may not escape the function, unless they are returned. If you 
call `test()` on a `scope` variable, the return value will be a 
scope pointer.


[...]


Thanks


Re: dip1000 return scope dmd v 2.100

2022-05-06 Thread Dennis via Digitalmars-d-learn

On Friday, 6 May 2022 at 09:24:06 UTC, vit wrote:
 It look like examples at page 
https://dlang.org/spec/function.html#ref-return-scope-parameters are no longer relevant.


They were recently updated to match the implementation in 2.100.

What difference are between `return scope`, `scope return` and 
`return`?


`return scope` means pointer members (such `this.ptr`, `C.ptr`) 
may not escape the function, unless they are returned. If you 
call `test()` on a `scope` variable, the return value will be a 
scope pointer.


`scope return` on a struct member is `scope` + `return ref`, 
meaning pointer members may not escape the function (the `scope` 
part), but you can return a reference to the struct member itself 
(``, the `return ref` part). If you call `test()` on a 
local variable (`scope` or not), the return value will be a scope 
pointer.


Just `return` allows you to return a reference to the struct 
member itself (``), and also to escape pointer members 
(`this.ptr`) since there is no `scope`. However, that means you 
can't call `test` on `scope` variables.



```
int* test() scope return{
		return  // Error: returning `` escapes a 
reference to parameter `this`

}
}
```


I think you're using an older DMD version, the error should be 
gone in 2.100



Why void* ptr in struct change effect of scope return ?


`scope` is ignored when the struct has no pointers, and before 
2.100, the meaning of `return` + `scope` on `ref` parameters was 
very inconsistent.




Re: DIP1000 and immutable

2021-04-27 Thread jmh530 via Digitalmars-d-learn

On Tuesday, 27 April 2021 at 14:44:48 UTC, Adam D. Ruppe wrote:

On Tuesday, 27 April 2021 at 14:28:12 UTC, jmh530 wrote:

However, should it ever matter if you escape an immutable?


Your example is a pretty clear case of use-after-free if gloin 
actually did escape the reference and kept it after main 
returned.


I tried basically the same thing in Rust and it doesn't 
generate errors (their borrow checker should be assuming scope 
by default).


That means it treats gloin as if it is scope, so it isn't the 
same as your D code since the gloin there is NOT borrowing.


Hmmm, good points. Thanks.


Re: DIP1000 and immutable

2021-04-27 Thread Adam D. Ruppe via Digitalmars-d-learn

On Tuesday, 27 April 2021 at 14:28:12 UTC, jmh530 wrote:

However, should it ever matter if you escape an immutable?


Your example is a pretty clear case of use-after-free if gloin 
actually did escape the reference and kept it after main returned.


I tried basically the same thing in Rust and it doesn't 
generate errors (their borrow checker should be assuming scope 
by default).


That means it treats gloin as if it is scope, so it isn't the 
same as your D code since the gloin there is NOT borrowing.


Re: [DIP1000] Something I don't quite understand regarding 'scope'

2020-06-29 Thread Stanislav Blinov via Digitalmars-d-learn

On Monday, 29 June 2020 at 06:21:43 UTC, ag0aep6g wrote:

Since `local` and `writeln` are templates, the attributes for 
their parameters are inferred from their bodies. `local!(int*)` 
doesn't do anything with the parameter, so it's inferred as 
`scope`. `writeln!(int*)` apparently does something that 
prevents `scope` from being inferred.


Thanks. It would appear indeed that inference fails for some 
reason. Explicitly marking args as 'scope' for `writeln` and 
`File.write` lets them compile. I wonder if there's a way to find 
exactly what it is in either of those that prevents the compiler 
from inferring 'scope'.


Re: [DIP1000] Something I don't quite understand regarding 'scope'

2020-06-29 Thread ag0aep6g via Digitalmars-d-learn

On 29.06.20 02:28, Stanislav Blinov wrote:

void local(Args...)(Args args)
{
}

void main() @safe
{
     import std.stdio;
     scope int* p;
     local(p);   // Ok
     writeln(p); // Error: scope variable p assigned to non-scope 
parameter _param_0 calling std.stdio.writeln!(int*).writeln

}

The signatures of `std.stdio.writeln` and `local` are the same (see 
`writeln` [1]). Yet, with '$ dmd -preview=dip1000' the call to `local` 
compiles, while the call to `writeln` doesn't.


Since `local` and `writeln` are templates, the attributes for their 
parameters are inferred from their bodies. `local!(int*)` doesn't do 
anything with the parameter, so it's inferred as `scope`. 
`writeln!(int*)` apparently does something that prevents `scope` from 
being inferred.


Re: DIP1000 spec?

2020-06-15 Thread Avrina via Digitalmars-d-learn
On Friday, 12 June 2020 at 12:49:08 UTC, Steven Schveighoffer 
wrote:
I was just looking through the DIPs in the system, and noticed 
that DIP1000 is "superseded".


I thought that was odd, since it's in the compiler as a switch 
and is a major driver of discussion and hope for memory safety.


In the DIP it says [1]:

"This DIP did not complete the review process. It was left in 
Draft status for an extended period. During that time, an 
implementation of the proposal was released. It diverged 
significantly enough from the proposal that the decsion was 
made by the Language Maintainers, who are also coauthors of the 
DIP, to retire the DIP as "Superseded" rather than rewriting 
it."


So where is the documentation that describes what is actually 
implemented? The section on Scope and Return parameters [2] in 
the spec is pretty light compared to the DIP text, and only 
addresses parameters, not locals.


Without full documentation in the spec, it can be difficult to 
know whether something should or should not be a bug.


-Steve

[1] 
https://github.com/dlang/DIPs/blob/e64bd0adfd3f6617038e214c82bc5093f2d33aea/DIPs/other/DIP1000.md#formal-assessment


[2] 
https://dlang.org/spec/memory-safe-d.html#scope-return-params


This is the state of most of Walter's DIPs. He's just making it 
up as he goes, it's the same thing with the @live implementation. 
Just buckle up, hold your cheeks tight and hope for the best.


Re: DIP1000 spec?

2020-06-14 Thread Kagamin via Digitalmars-d-learn

Logic is apparently still in flux, too early to document.


Re: dip1000, perhaps annotate with return, and vibe-d

2019-07-25 Thread aliak via Digitalmars-d-learn

On Wednesday, 24 July 2019 at 16:23:48 UTC, Paul Backus wrote:

On Wednesday, 24 July 2019 at 12:54:51 UTC, aliak wrote:

[...]


It should go on the constructor's parameter; i.e.,

this(auto return ref T value) { /* ... */ }

Under the hood, a constructor actually returns the constructed 
value by reference, so the actual signature of the above 
constructor seen by the lifetime checker is:


ref Optional!T __ctor(auto return ref T value)

You can see this for yourself with something like `pragma(msg, 
typeof(Optional!T.__ctor))`.


Thanks! The under the hood stuff was good to know!

I was putting it in the right place but it seems to still have 
been complaining. Ah well. I guess an auto ref on a constructor 
doesn't really make sense anyway.


Re: dip1000, perhaps annotate with return, and vibe-d

2019-07-24 Thread Paul Backus via Digitalmars-d-learn

On Wednesday, 24 July 2019 at 12:54:51 UTC, aliak wrote:

Trying to get dip1000 flag in use. I have this error:

Error: returning Optional(null, false).this(value) escapes a 
reference to parameter value, perhaps annotate with return


in this function:

public auto some(T)(auto ref T value) {
return Optional!T(value); // <-- error on this line
}

And it's instantiated from here:

static Optional!T fromRepresentation(Json value) {
  if (value == Json.undefined) {
return no!T;
  }
  return some(deserializeJson!T(value)); // <-- instantiated 
from here

}

I put the qualifier "return" on the parameter to some, but did 
nothing. And I put it on Optional.this() as well, but I'm not 
sure where I'm supposed to put it.


It should go on the constructor's parameter; i.e.,

this(auto return ref T value) { /* ... */ }

Under the hood, a constructor actually returns the constructed 
value by reference, so the actual signature of the above 
constructor seen by the lifetime checker is:


ref Optional!T __ctor(auto return ref T value)

You can see this for yourself with something like `pragma(msg, 
typeof(Optional!T.__ctor))`.


Re: DIP1000: Should this compile

2019-05-16 Thread Max Haughton via Digitalmars-d-learn
On Thursday, 16 May 2019 at 21:56:52 UTC, Steven Schveighoffer 
wrote:

On 5/16/19 10:21 PM, Max Haughton wrote:

https://run.dlang.io/is/cKFsXh

Should this compile, or is return scope T* down to the user to 
not escape (Returning  directly does not compile)




Answer to subject: no. This is a bug. Please file.

Not sure what the solution is, because dip1000 makes scope a 
storage class. So there's no way to tag what the input 
parameter points at.


-Steve


The parameter pointer outlives the the , i.e. cannot be 
guaranteed that it doesn't escape, which is sufficient grounds to 
not allow the assignment. Hopefully, this is a implementation 
rather specification error (If my understanding of the DIP is 
correct)




Re: DIP1000: Should this compile

2019-05-16 Thread Simen Kjærås via Digitalmars-d-learn

On Thursday, 16 May 2019 at 21:21:51 UTC, Max Haughton wrote:

https://run.dlang.io/is/cKFsXh

Should this compile, or is return scope T* down to the user to 
not escape (Returning  directly does not compile)


This is a bug, as can be showed by repeating the call to 
(*boi).writeln - suddenly the output changes between calls. 
Filed: https://issues.dlang.org/show_bug.cgi?id=19881


--
  Simen


Re: DIP1000: Should this compile

2019-05-16 Thread Steven Schveighoffer via Digitalmars-d-learn

On 5/16/19 10:21 PM, Max Haughton wrote:

https://run.dlang.io/is/cKFsXh

Should this compile, or is return scope T* down to the user to not 
escape (Returning  directly does not compile)




Answer to subject: no. This is a bug. Please file.

Not sure what the solution is, because dip1000 makes scope a storage 
class. So there's no way to tag what the input parameter points at.


-Steve


Re: dip1000 rule 5

2018-11-27 Thread Mike Parker via Digitalmars-d-learn

On Tuesday, 27 November 2018 at 08:56:47 UTC, sclytrack wrote:


---
How is a person able to understand this DIP?



./dmd -betterC -dip1000 test.d


I'll repeat: the DIP does not currently match the implementation. 
I was not involved in any of it and have no idea what the diff 
actually is. Walter informed me a while back that he will update 
the DIP to match the implementation at some point. I'll discuss 
it with him after the new year and see where we are.





---

How many DIP manager are there?


I'll assume single person.


Yep, just me.




When is a DIP assigned a number?

---


As soon as I merge the PR. That's the point where it moves from 
Draft Review to the first round of Community Review (and I will 
update the procedures doc to reflect that). Which DIPs get merged 
when depends on a number of factors -- what is the state of each 
DIP, what's the priority, how many are currently under review in 
the post-Draft stages, is the author available to move forward, 
etc.





Re: dip1000 rule 5

2018-11-27 Thread sclytrack via Digitalmars-d-learn

On Monday, 26 November 2018 at 09:10:23 UTC, sclytrack wrote:

On Sunday, 25 November 2018 at 19:22:36 UTC, sclytrack wrote:

There are 4 rules listed.

https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md




What is rule 5?


int* global_ptr;

void abc() {
scope int* a;
int* b;
scope int* c = a;  // Error, rule 5
scope int* d = b;  // Ok
int* i = a;// Ok, scope is inferred for i
global_ptr = d;// Error, lifetime(d) < 
lifetime(global_ptr)
global_ptr = i;// Error, lifetime(i) < 
lifetime(global_ptr)

int* j;
global_ptr = j;// Ok, j is not scope
}



---

Are the following assumptions correct?


lifetime(a) < lifetime(b)
Means that b is older and lives longer than a. Or better, the 
data that b is pointing
to is older and lives longer than the one that a is pointing 
too. With the exception
of the null pointer which gets unlimited lifetime because it 
does not corrupt memory.


---

scope int * a;

The variable gets unlimited lifetime because the value it is 
pointing is assigned
null. And that throws exception when trying to access the 
memory and because
it does not corrupt memory it is assigned unlimited lifetime. 
Also once a variable
is assigned unlimited lifetime, then it retains that unlimited 
lifetime during

the entire reachability of the variable.

scope int * c = a;


works



The above is allowed. You are assigning a variable that 
according to the compiler
has unlimited lifetime. Therefore the variable c will be 
handled like it has

unlimited lifetime by the compiler.
lifetime(c) <= lifetime(a)
The dip talks about longer and shorter, but is equal okay too?

int * c = a;


works (compiles without error and is inferred scope)



The above can not be inferred because scope is only inferred 
when it is assigned

a limited lifetime. So it is an error.


Rule number 2 of the DIP1000 between quotes

"2. A variable is inferred to be scope if it is initialized with 
a value that has a non-∞ lifetime."


I made an error here. Once scope always scope. And will infer 
scope as much as
possible. Rule two is more for local variables that haven't even 
been marked

with scope. A pointer to them needs to be inferred scope.




---
How is a person able to understand this DIP?



./dmd -betterC -dip1000 test.d


---

How many DIP manager are there?


I'll assume single person.


When is a DIP assigned a number?

---






Re: dip1000 rule 5

2018-11-26 Thread sclytrack via Digitalmars-d-learn

On Sunday, 25 November 2018 at 19:22:36 UTC, sclytrack wrote:

There are 4 rules listed.

https://github.com/dlang/DIPs/blob/master/DIPs/DIP1000.md




What is rule 5?


int* global_ptr;

void abc() {
scope int* a;
int* b;
scope int* c = a;  // Error, rule 5
scope int* d = b;  // Ok
int* i = a;// Ok, scope is inferred for i
global_ptr = d;// Error, lifetime(d) < 
lifetime(global_ptr)
global_ptr = i;// Error, lifetime(i) < 
lifetime(global_ptr)

int* j;
global_ptr = j;// Ok, j is not scope
}



---

Are the following assumptions correct?


lifetime(a) < lifetime(b)
Means that b is older and lives longer than a. Or better, the 
data that b is pointing
to is older and lives longer than the one that a is pointing too. 
With the exception
of the null pointer which gets unlimited lifetime because it does 
not corrupt memory.


---

scope int * a;

The variable gets unlimited lifetime because the value it is 
pointing is assigned
null. And that throws exception when trying to access the memory 
and because
it does not corrupt memory it is assigned unlimited lifetime. 
Also once a variable
is assigned unlimited lifetime, then it retains that unlimited 
lifetime during

the entire reachability of the variable.

scope int * c = a;

The above is allowed. You are assigning a variable that according 
to the compiler
has unlimited lifetime. Therefore the variable c will be handled 
like it has

unlimited lifetime by the compiler.
lifetime(c) <= lifetime(a)
The dip talks about longer and shorter, but is equal okay too?

int * c = a;

The above can not be inferred because scope is only inferred when 
it is assigned

a limited lifetime. So it is an error.

---
How is a person able to understand this DIP?
---

How many DIP manager are there?
When is a DIP assigned a number?

---








Re: dip1000 rule 5

2018-11-25 Thread Mike Parker via Digitalmars-d-learn

On Sunday, 25 November 2018 at 21:22:09 UTC, sclytrack wrote:



Did DIP1000 go through any review process? I'm seeing it is a 
draft.


The previous DIP manager marked DIPs as Draft while they were 
under review. I don't use that anymore. I left DIP1000 untouched 
after I took over, however. Walter told me he'll revise it at 
some point to reflect the actual implementation.






https://github.com/dlang/DIPs/blob/master/PROCEDURE.md

Keeps talking about a Drafts subdirectory. I don't see any 
directory named

"Drafts".



It was originally my intention to push new DIPs into a Drafts 
subdirectory for the Draft Review stage, but it's more convenient 
to handle it in the pull request thread. I never edited the 
document to reflect that and didn't notice it when I've looked it 
over. Now that you've pointed it out, I'll revise it.


Re: dip1000 rule 5

2018-11-25 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 25 November 2018 at 21:22:09 UTC, sclytrack wrote:

Did DIP1000 go through any review process? I'm seeing it is a 
draft.


Review links are at the very end.


https://github.com/dlang/DIPs/blob/master/PROCEDURE.md

Keeps talking about a Drafts subdirectory. I don't see any 
directory named "Drafts".


Not sure about that one. Maybe Mike Parker could elaborate on 
this.


Re: dip1000 rule 5

2018-11-25 Thread sclytrack via Digitalmars-d-learn
On Sunday, 25 November 2018 at 19:49:03 UTC, Stanislav Blinov 
wrote:

On Sunday, 25 November 2018 at 19:22:36 UTC, sclytrack wrote:

There are 4 rules listed.
...
What is rule 5?
...
Wouldn't you call it D3 because of the name mangling of 
DIP1000 once activated by default?


That "rule 5" looks like a straight up mistake. As for D3... 
IMHO, no, not by a long shot. There's 1014 and 1016, 1008, 
there's `shared`, there are improved move-assignments, there's 
`__mutable` and `@__future`, there are tons of issues in 
Bugzilla, the standard library is long overdue for a huge 
look-over...



Did DIP1000 go through any review process? I'm seeing it is a 
draft.



https://github.com/dlang/DIPs/blob/master/PROCEDURE.md

Keeps talking about a Drafts subdirectory. I don't see any 
directory named

"Drafts".


I only see

accepted
archived //old stuff
rejected





Re: dip1000 rule 5

2018-11-25 Thread Stanislav Blinov via Digitalmars-d-learn

On Sunday, 25 November 2018 at 19:22:36 UTC, sclytrack wrote:

There are 4 rules listed.
...
What is rule 5?
...
Wouldn't you call it D3 because of the name mangling of DIP1000 
once activated by default?


That "rule 5" looks like a straight up mistake. As for D3... 
IMHO, no, not by a long shot. There's 1014 and 1016, 1008, 
there's `shared`, there are improved move-assignments, there's 
`__mutable` and `@__future`, there are tons of issues in 
Bugzilla, the standard library is long overdue for a huge 
look-over...


Re: dip1000: why can't the addressee come into existence later?

2018-11-10 Thread Neia Neutuladh via Digitalmars-d-learn
On Sat, 10 Nov 2018 16:25:40 +, Stanislav Blinov wrote:
> Yep, you just over-simplified the first case.

It is too simple to clearly illustrate why the code is invalid, but not so 
simple that the compiler accepts that code.

> Consider:
> 
> int* p;
> {
>  int i;
>  p = 
> }
> *p = 42;

In that example, the scope for i ends before the scope for p ends. It's 
not at all surprising that that code is wrong. In the other examples I 
gave, both i and p go out of scope at the same time.

But there's a total ordering for when variables' lifetimes end, which is 
the key (and non-obvious) difference between the two.


Re: dip1000: why can't the addressee come into existence later?

2018-11-10 Thread Stanislav Blinov via Digitalmars-d-learn
On Saturday, 10 November 2018 at 06:56:29 UTC, Neia Neutuladh 
wrote:

The following code doesn't work with @safe -dip1000:

int* p;
int i;
p = 

i has a shorter lifetime than p, the compiler complains.

But this code does:

int i;
int* p;
p = 

The compiler does this even in the absence of scope guards and 
destructors because simple, obvious rules will be easier to 
understand and implement than nuanced ones, even if it makes 
you reorder declarations sometimes.


Is this right?


Yep, you just over-simplified the first case. Consider:

int* p;
{
int i;
p = 
}
*p = 42;

or even:

module thing;

int* global;

void foo() {
int i;
global = 
}

...much simpler to just go by the lifetime, instead of attempting 
to do a complex analysis. Because for the latter, it would then 
*need* to be deep to be of any use at all. Especially in a 
language that has static ifs:


// parameter is not scope, function is not pure, etc.
void nasty(int* p) { /* ... */ }

void main() {
int *p;
int i;
p = 
static if (someCondition) nasty(p);
}



Re: dip1000: why can't the addressee come into existence later?

2018-11-10 Thread Neia Neutuladh via Digitalmars-d-learn
On Sat, 10 Nov 2018 11:47:24 +, Nicholas Wilson wrote:
> On Saturday, 10 November 2018 at 06:56:29 UTC, Neia Neutuladh wrote:
>> Is this right?
> 
> Are you sure you added @safe to the second example?
> https://run.dlang.io/is/2RbOwK fails to compile.

Maybe take another look at the post you're replying to? I was saying that, 
if the compiler allowed one thing that looked safe to me, it would either 
require nuance (check for scope guards, destructors, and the like before 
saying something is un-@safe) or allow other code that is obviously 
invalid.


Re: dip1000: why can't the addressee come into existence later?

2018-11-10 Thread Nicholas Wilson via Digitalmars-d-learn
On Saturday, 10 November 2018 at 06:56:29 UTC, Neia Neutuladh 
wrote:

Is this right?


Are you sure you added @safe to the second example?
https://run.dlang.io/is/2RbOwK fails to compile.


Re: dip1000 issue

2018-09-13 Thread Steven Schveighoffer via Digitalmars-d-learn

On 9/7/18 7:59 AM, Orfeo wrote:

On Friday, 7 September 2018 at 14:36:18 UTC, rikki cattermole wrote:

On 08/09/2018 2:29 AM, Orfeo wrote:
==> And why (maybe a silly question) `-dip1000` breaks  my project so 
badly without warning..


DIP 1000 is an experimental addition to D, that is yet to be complete.
It is a compiler switch for a reason, it isn't ready for usage, only 
some experimentation.


Thank you very much...
I agree with you, but if someone adds `dip1000` in a library and I link 
it,  my project inherits this setting.

What do you think? is it correct? Some suggestions to avoid it?


The sub-project is being compiled with dip1000. I don't know what the 
rules are for dip1000 and dub, but it's likely the flags are propagated.


One of the main drawbacks of dip1000 is that if you don't have it 
enabled on ALL projects, you will likely run into linker errors. It's 
like compiling 2 libraries with different versions and expecting them to 
link. It's probably the reason dub forwards the switches.


Separately, if dmd is failing with signal 11 (SEGFAULT), this is a 
compiler bug. The compiler should never segfault.


At this point, it's hard to tell from what you have given what may cause 
the error. But maybe if your project is open source, you can file a bug 
with the link to the project? Or if you can narrow down the code in your 
project to a minimum that causes the error, it can be diagnosed further.


-Steve


Re: dip1000 issue

2018-09-07 Thread Orfeo via Digitalmars-d-learn
On Friday, 7 September 2018 at 14:36:18 UTC, rikki cattermole 
wrote:

On 08/09/2018 2:29 AM, Orfeo wrote:
==> And why (maybe a silly question) `-dip1000` breaks  my 
project so badly without warning..


DIP 1000 is an experimental addition to D, that is yet to be 
complete.
It is a compiler switch for a reason, it isn't ready for usage, 
only some experimentation.


Thank you very much...
I agree with you, but if someone adds `dip1000` in a library and 
I link it,  my project inherits this setting.

What do you think? is it correct? Some suggestions to avoid it?


Re: dip1000 issue

2018-09-07 Thread rikki cattermole via Digitalmars-d-learn

On 08/09/2018 2:29 AM, Orfeo wrote:
==> And why (maybe a silly question) `-dip1000` breaks  my project so 
badly without warning..


DIP 1000 is an experimental addition to D, that is yet to be complete.
It is a compiler switch for a reason, it isn't ready for usage, only 
some experimentation.


Re: dip1000 issue

2018-09-07 Thread Orfeo via Digitalmars-d-learn

Sorry, I pressed send too quickly
On Friday, 7 September 2018 at 14:04:47 UTC, Orfeo wrote:

I've a project that link FuzzyCopy [1], that was compiled 
without problems.

So I add FuzzyCopy library [1], I update dmd, then:


==> I've a project that was compiled without problems.
So I add FuzzyCopy library [1], I update dmd, then:


And why (maybe a silly question) `-dip1000`dip1000  my project 
so badly without warning..


==> And why (maybe a silly question) `-dip1000` breaks  my 
project so badly without warning..




Re: -dip1000 @safe scope wrapper

2018-06-28 Thread Chris M. via Digitalmars-d-learn

On Thursday, 28 June 2018 at 13:29:58 UTC, vit wrote:

Hello,
Is it possible to create scope wrapper initialized by non 
default constructor with scope parameter?

something like this:

struct Wrapper{
int* p;

static Wrapper create(scope return int* p)@safe{
Wrapper w;
w.p = p;
return w;
}

/++ This doesn't work:
this(scope return int* p)@safe scope{
this.p = p;
}+/
}

void main()@safe{
scope int i;
scope Wrapper w1 = Wrapper.create();
scope Wrapper w2 = Wrapper();
}


I'm not sure why create works in this case either. I get the 
following when I uncomment the constructor


test.d(12): Error: scope variable p assigned to this with longer 
lifetime


Is there a subtle difference I'm missing?