Re: DIP69 - Implement scope for escape proof references

2014-12-29 Thread Dicebot via Digitalmars-d

On Monday, 22 December 2014 at 20:51:46 UTC, Walter Bright wrote:

On 12/22/2014 12:04 AM, Dicebot wrote:
Point of transitive scope is to make easy to expose complex 
custom data

structures without breaking memory safety.


I do understand that. Making it work with the type system is 
another matter entirely - it's far more complex than just 
adding a qualifier. 'inout' looks simple but still has ongoing 
issues.


And the thing is, wrappers can be used instead of qualifiers, 
in the same places in the same way. It's much simpler.


Ok, lets consider some examples of code I'd want to work with 
wrapper approach.


Basic tree structure:

struct Node
{
Node* left, right;
Payload payload;
}

struct Tree
{
Node* root;
}

Restricting public access to nodes to prevent storing persistent 
node pointers.


Your proposed approach:

struct Wrapper(T)
{
scope T wrapped;
alias wrapped this;
}

struct Node
{
private:
Node* _left, _right;
public:
auto left() @property { return Wrapper!(Node*)(_left); }
auto right() @property { return Wrapper!(Node*)(_right); }

Payload payload;
}

struct Tree
{
private:
Node* _root;

public:
auto root() @property { return Wrapper!(Node*)(_root); }
}

Am I correct?

If yes, this is exactly the breakage issue I was speaking about : 
any code that looked like `is(typeof(Tree.root) == Node*)` will 
stop working.


With my latest proposal (pseudo-transitive storage class which is 
not part of a type) getters would look simply like `scope Node* 
root() @property { return _root; }` and `is(typeof(Tree.root) == 
Node*)` still remained true. Only impact on existing would be 
restriction of operations to take address or assign a pointer.


I am pretty sure I am missing many complicated parts here but 
this seems like a big deal in retro-fitting existing libraries to 
use scope after it was added.


Re: DIP69 - Implement scope for escape proof references

2014-12-22 Thread Dicebot via Digitalmars-d

On Monday, 22 December 2014 at 03:07:53 UTC, Walter Bright wrote:

On 12/21/2014 2:06 AM, Dicebot wrote:
No, it is exactly the other way around. The very point of what 
I am saying is
that you DOESN'T CARE about ownership as long as worst case 
scenario is
assumed.   I have zero idea why you identify it is conflating 
as ownership when

it is explicitly designed to be distinct.


The point of transitive scoping would be if the root owned the 
data reachable through the root.


Quoting myself:

For me scopeness is a property of view, not object itself - 
this also makes ownership method of actual data irrelevant. Only

difference between GC owned data and stack allocated one is that
former can have scoped view optionally but for the latter
compiler must force it as the only available.


It doesn't matter of root owns the data. We _assume_ that as 
worst case scenario and allowed actions form a strict subset of 
allowed actions for any other ownership situation. Such `scope` 
for stack/GC is same as `const` for mutable/immutable  - common 
denominator.


Point of transitive scope is to make easy to expose complex 
custom data structures without breaking memory safety.


Re: DIP69 - Implement scope for escape proof references

2014-12-22 Thread Walter Bright via Digitalmars-d

On 12/22/2014 12:04 AM, Dicebot wrote:

Point of transitive scope is to make easy to expose complex custom data
structures without breaking memory safety.


I do understand that. Making it work with the type system is another matter 
entirely - it's far more complex than just adding a qualifier. 'inout' looks 
simple but still has ongoing issues.


And the thing is, wrappers can be used instead of qualifiers, in the same places 
in the same way. It's much simpler.


Re: DIP69 - Implement scope for escape proof references

2014-12-21 Thread Dicebot via Digitalmars-d
On Saturday, 20 December 2014 at 21:39:44 UTC, Walter Bright 
wrote:

On 12/19/2014 9:44 PM, Dicebot wrote:
Such notion of view requires at least some elements of 
transitivity to be

practical in my opinion.


I have no idea how some elements of transitivity can even 
work. It's either transitive or its not. Please don't think of 
scope in terms of ownership, ownership is an orthogonal issue.


.. and here I was about you to do exactly the same :P What in 
example I show makes you think of ownership?


When I was speaking about some elements of transitivity I was 
thinking in a way of keeping scope storage class but transitively 
applying same restrictions to all data accessible through it AS 
IF it had scope storage class on its own - while still making 
illegal to use scope as a separate type qualifier.



Also with my definition in mind your example of tree
that stores scope nodes makes absolutely no sense unless whole 
tree itself is
scoped (and nodes are thus scoped transitively). Such view is 
always assumes
worst case about ownership and shouldn't persist in any form 
(as that would

require some serious ownership tracking).


This is definitely conflating scope and ownership.


No, it is exactly the other way around. The very point of what I 
am saying is that you DOESN'T CARE about ownership as long as 
worst case scenario is assumed.   I have zero idea why you 
identify it is conflating as ownership when it is explicitly 
designed to be distinct.


Re: DIP69 - Implement scope for escape proof references

2014-12-21 Thread Walter Bright via Digitalmars-d

On 12/21/2014 2:06 AM, Dicebot wrote:

No, it is exactly the other way around. The very point of what I am saying is
that you DOESN'T CARE about ownership as long as worst case scenario is
assumed.   I have zero idea why you identify it is conflating as ownership when
it is explicitly designed to be distinct.


The point of transitive scoping would be if the root owned the data reachable 
through the root.


Re: DIP69 - Implement scope for escape proof references

2014-12-20 Thread Walter Bright via Digitalmars-d

On 12/19/2014 9:44 PM, Dicebot wrote:

Such notion of view requires at least some elements of transitivity to be
practical in my opinion.


I have no idea how some elements of transitivity can even work. It's either 
transitive or its not. Please don't think of scope in terms of ownership, 
ownership is an orthogonal issue.




Also with my definition in mind your example of tree
that stores scope nodes makes absolutely no sense unless whole tree itself is
scoped (and nodes are thus scoped transitively). Such view is always assumes
worst case about ownership and shouldn't persist in any form (as that would
require some serious ownership tracking).


This is definitely conflating scope and ownership.



Re: DIP69 - Implement scope for escape proof references

2014-12-20 Thread Andrei Alexandrescu via Digitalmars-d

On 12/6/14 4:49 PM, Manu via Digitalmars-d wrote:

I need, at least, forceinline to complete it, but that one*is*
controversial - we've talked about this for years.


I'm still 883 messages behind so here's a drive-by comment - it's time 
to revisit this, I think the need has become a lot clearer. -- Andrei


Re: DIP69 - Implement scope for escape proof references

2014-12-20 Thread Andrei Alexandrescu via Digitalmars-d

On 12/6/14 4:49 PM, Manu via Digitalmars-d wrote:

In the situation where templates are involved, it would be nice to be
able to make that explicit statement that some type is ref or not at
the point of template instantiation, and the resolution should work
according to the well-defined rules that we are all familiar with.


Another drive-by comment: I understand the motivation for this and the 
difficulties involved. There needs to be a clear understanding that 
adding new type qualifiers is extremely intrusive and expensive. Because 
of that, I think we should best address binding generation via a set of 
tactical tools i.e. standard library artifacts that do all that mixin 
business in an encapsulated and reusable manner.


(As an aside forcing a template instantiation to decide ref vs. no ref 
should be easy but currently can't be done, i.e. this code should work 
but currently doesn't:


T fun(T)(ref T x) { return x + 1; }

void main(string[] group)
{
int function(int) f1 = fun!int;
int function(ref int) f2 = fun!int;
}

)


Andrei



Re: DIP69 - Implement scope for escape proof references

2014-12-19 Thread Dicebot via Digitalmars-d

On Tuesday, 16 December 2014 at 01:00:47 UTC, Walter Bright wrote:

On 12/15/2014 5:38 AM, deadalnix wrote:

On Monday, 15 December 2014 at 11:32:11 UTC, Dicebot wrote:
For me scopeness is a property of view, not object itself 
- this also
makes ownership method of actual data irrelevant. Only 
difference between GC
owned data and stack allocated one is that former can have 
scoped view
optionally but for the latter compiler must force it as the 
only available.


Ha finally something start to make sense here.


Well, the DIP does defined scope in terms of a 'view' in just 
this manner.


I am obviously terrible at explaining things.


Such notion of view requires at least some elements of 
transitivity to be practical in my opinion. Also with my 
definition in mind your example of tree that stores scope nodes 
makes absolutely no sense unless whole tree itself is scoped (and 
nodes are thus scoped transitively). Such view is always assumes 
worst case about ownership and shouldn't persist in any form (as 
that would require some serious ownership tracking).


I don't think you have explained your case that bad - we simply 
have a very different use cases in mind as primary use case.


Re: DIP69 - Implement scope for escape proof references

2014-12-17 Thread via Digitalmars-d

On Wednesday, 17 December 2014 at 07:48:52 UTC, bearophile wrote:

Walter Bright:


I'm afraid I don't understand at all what you wrote.


Perhaps reading about linear type systems could help:

http://en.wikipedia.org/w/index.php?title=Substructural_type_systemredirect=no#Linear_type_systems


But note that we want a relaxed linear type system. In general, 
we are fine with multiple aliases, although there are some 
applications where strict uniqueness is useful. Deadalnix' 
proposal goes in this direction.


Re: DIP69 - Implement scope for escape proof references

2014-12-17 Thread via Digitalmars-d

On Wednesday, 17 December 2014 at 11:13:02 UTC, Marc Schütz wrote:
On Wednesday, 17 December 2014 at 07:48:52 UTC, bearophile 
wrote:

Walter Bright:


I'm afraid I don't understand at all what you wrote.


Perhaps reading about linear type systems could help:

http://en.wikipedia.org/w/index.php?title=Substructural_type_systemredirect=no#Linear_type_systems


But note that we want a relaxed linear type system. In 
general, we are fine with multiple aliases, although there are


Pointer aliasing is an optimization killer, which is why C99 
added the «restrict» keyword. I think in most cases the use of 
stack allocated objects tend to be alias-free, so it is important 
that this knowledge is retained so that the compiler can make use 
of it.


http://en.wikipedia.org/wiki/Pointer_aliasing


Re: DIP69 - Implement scope for escape proof references

2014-12-17 Thread via Digitalmars-d
On Wednesday, 17 December 2014 at 05:28:35 UTC, Walter Bright 
wrote:
On 12/16/2014 5:37 AM, Ola Fosheim Grøstad 
ola.fosheim.grostad+dl...@gmail.com wrote:
The current proposal is either too limiting or not limiting 
enough.


I'm afraid I don't understand at all what you wrote.


Well, look at it this way: D1 took 1990s style C++ application 
programming model and made it more convenient with a GC. Having a 
GC-memory model with the possibility of stack/heap allocations as 
optimizations can keep the language simple. D2 is more of a 
library author's language, but without GC you need to deal with 
different types of ownership.


If you toss out the GC, and want the same level of safety and 
generality you either:


1. need to track ownership add dynamic runtime checks
2. provide a full blown proof system (not realistic)
3. provide means for the programmer to help the semantic 
analysis


What you want is a combination of 1 and 3, but you don't need to 
keep them separate. Since refcounting is expensive, you don't 
want that everywhere. For stack allocated objects you have an 
implicit refcounting in the nesting of scopes, you only need to 
track scope-depth.


If the compiler knows that a returned object is stack allocated, 
then it can check that by comparing against the stack frame 
address since the stack grows downwards in an ordered fashion. 
And in most cases it should be able to elide the check.


If you also maintain information about order (stack depth) among 
the stack allocated objects a function receives through reference 
parameters (for every function call), then you can safely combine 
the stack allocated objects you receive through parameters in 
aggregates, like inserting an stack allocated element into a 
container.


Since D is increasingly becoming a library author's language, you 
probably also would benefit more from strengthening the template 
support by having a templated ref-type rather than scope ref. 
You could define protocols (e.g. predefined UDAs) that tells the 
compiler what kind of key properties the library type provides, 
such as ownership. Then use that for a more generic approach to 
optimization and escape analysis and let the 
ownership-reference-types be library types. If semantic analysis 
gets rid of the dynamic aspects of a referencs (such as reference 
counting) then the compiler should be able to use the same 
function body, and in other cases just add a inferred wrapper to 
a generic function body. So the code bloat can be limited.


If all references to external resources (like the heap) in the 
stack allocated object is owned by the object, then you can treat 
those as a whole. But you need the compiler to understand what 
ownership is if it is to guarantee memory safety in the kind of 
situations where memory safety is known to be difficult to 
achieve.


The alternative is to state that @safe is not covering non-GC 
memory and that one should stick to vetted library code when 
writing @safe code that does not use the GC. I actually find that 
acceptable for D2. In D2 you would be better off spending the 
effort at finding ways to turn automatically turn GC allocations 
into stack allocations as optimizations. Then you can find a more 
general and powerful ownership-oriented approach for non-GC 
applications for a new major version of D.


It is not realistic that people will annotate with scope ref, 
and compiler inference could make updates to libraries break 
application code if you get false negatives. Function signatures 
are contracts, they ought to be explicit for libraries. So having 
library functions act as scope ref without it being explicit in 
the signature is not necessarily a good idea.


Re: DIP69 - Implement scope for escape proof references

2014-12-17 Thread via Digitalmars-d
On Wednesday, 17 December 2014 at 12:29:21 UTC, Ola Fosheim 
Grøstad wrote:
On Wednesday, 17 December 2014 at 11:13:02 UTC, Marc Schütz 
wrote:
On Wednesday, 17 December 2014 at 07:48:52 UTC, bearophile 
wrote:

Walter Bright:


I'm afraid I don't understand at all what you wrote.


Perhaps reading about linear type systems could help:

http://en.wikipedia.org/w/index.php?title=Substructural_type_systemredirect=no#Linear_type_systems


But note that we want a relaxed linear type system. In 
general, we are fine with multiple aliases, although there are


Pointer aliasing is an optimization killer, which is why C99 
added the «restrict» keyword. I think in most cases the use of 
stack allocated objects tend to be alias-free, so it is 
important that this knowledge is retained so that the compiler 
can make use of it.


http://en.wikipedia.org/wiki/Pointer_aliasing


I know, this is one of those applications. The one I was thinking 
of is const-borrowing (useful to prevent iterator invalidation 
and a bunch of other things).


I think that enforcing alias-freeness by default (the way a 
strict linear type system requires) doesn't fit too well into the 
existing language. Some way of signalling this to the compiler 
will therefore be required. It might be as simple as C's 
`restrict` keyword (but it needs to be enforced!), or better yet, 
an `unrestrict` keyword. Parameters would be alias-free by 
default unless explicitly specified otherwise. Local aliases 
(inside one function) are however ok, as long as not more than 
one is passed to another function at the same time.


Re: DIP69 - Implement scope for escape proof references

2014-12-17 Thread deadalnix via Digitalmars-d
On Wednesday, 17 December 2014 at 12:29:21 UTC, Ola Fosheim 
Grøstad wrote:
On Wednesday, 17 December 2014 at 11:13:02 UTC, Marc Schütz 
wrote:
On Wednesday, 17 December 2014 at 07:48:52 UTC, bearophile 
wrote:

Walter Bright:


I'm afraid I don't understand at all what you wrote.


Perhaps reading about linear type systems could help:

http://en.wikipedia.org/w/index.php?title=Substructural_type_systemredirect=no#Linear_type_systems


But note that we want a relaxed linear type system. In 
general, we are fine with multiple aliases, although there are


Pointer aliasing is an optimization killer, which is why C99 
added the «restrict» keyword. I think in most cases the use of 
stack allocated objects tend to be alias-free, so it is 
important that this knowledge is retained so that the compiler 
can make use of it.


http://en.wikipedia.org/wiki/Pointer_aliasing


If you have owner ship, you have free. If you have a pair 
alloc/free then you can promote on stack.


This is a much more powerful way to handle things, as this take 
advantage of inlining.


Re: DIP69 - Implement scope for escape proof references

2014-12-17 Thread via Digitalmars-d

On Wednesday, 17 December 2014 at 13:48:24 UTC, deadalnix wrote:
If you have owner ship, you have free. If you have a pair 
alloc/free then you can promote on stack.


This is a much more powerful way to handle things, as this take 
advantage of inlining.


More powerful than what?

Rather than thinking in terms of alloc/free it might be helpful 
to think about it more generally as resources, use, reuse and 
side-effects. On the stack you get to reuse memory when the 
variable is not longer live, meaning you junk writes if the 
results cannot be read and reuse the memory prematurely.


http://en.wikipedia.org/wiki/Live_variable_analysis

If you are saying that turning GC allocations automatically into 
stack allocations is a good direction for D2, then I agree.


Re: DIP69 - Implement scope for escape proof references

2014-12-17 Thread via Digitalmars-d

On Wednesday, 17 December 2014 at 13:35:53 UTC, Marc Schütz wrote:
I think that enforcing alias-freeness by default (the way a 
strict linear type system requires) doesn't fit too well into 
the existing language. Some way of signalling this to the 
compiler will therefore be required. It might be as simple as 
C's `restrict` keyword (but it needs to be enforced!), or 
better yet, an `unrestrict` keyword. Parameters would be 
alias-free by default unless explicitly specified otherwise. 
Local aliases (inside one function) are however ok, as long as 
not more than one is passed to another function at the same 
time.


Hmm, I kind of feel that D is having too many parameter 
keywords/types/qualifiers. Parameter specification is primarily 
useful where it provides information about constraints that the 
programmer need to know about when using a library.


restricted scope ref could be a useful default for 
non-templated functions, then use templated ownership reference 
typing or inference to go beyond it.


I think that if one improved the templating system so that it was 
capable of analysing similarities between instantiations and use 
heuristics to analyse when a new instance is profitable then you 
could make functions templated by default and propagate knowledge 
from the call site to the template-instantiation mechanism of the 
compiler. So if the reference is known to be aliasfree then the 
compiler can use heuristics to determine if it should instantiate 
a restricted version or use a slower general version of the 
templated function.


Similarily, if refcounters always are on offset 0 and destructors 
are virtual, then you only need a single container method 
template instance for refcouting references, even if you have 
many types using the same method. If refcounters are big enough, 
you can have a unique_ptr that just set it to a large value and 
use the same template instance for a unique_ptr and 
refcounted_ptr behind the scene when referencing objects that 
provide a refcount field.


There are also many other things that could be done to enhance 
the template system, like querying properties of the block in 
loops that iterate over a range, so that you can instantiate 
different optimized ranges depending on whether the loop 
contains a break statement or not. Or like Jonathan Blow's 
language, where you can issue a remove element and continue 
like statement within a foreach-loop,  which might require a 
different range iteration implementation.


Re: DIP69 - Implement scope for escape proof references

2014-12-16 Thread deadalnix via Digitalmars-d

On Tuesday, 16 December 2014 at 01:00:47 UTC, Walter Bright wrote:

On 12/15/2014 5:38 AM, deadalnix wrote:

On Monday, 15 December 2014 at 11:32:11 UTC, Dicebot wrote:
For me scopeness is a property of view, not object itself 
- this also
makes ownership method of actual data irrelevant. Only 
difference between GC
owned data and stack allocated one is that former can have 
scoped view
optionally but for the latter compiler must force it as the 
only available.


Ha finally something start to make sense here.


Well, the DIP does defined scope in terms of a 'view' in just 
this manner.


I am obviously terrible at explaining things.


No, I actually think the concept of view in the proposal is a 
good one. However, the proposal itself is too limiting.


Re: DIP69 - Implement scope for escape proof references

2014-12-16 Thread via Digitalmars-d

On Tuesday, 16 December 2014 at 01:00:47 UTC, Walter Bright wrote:

On 12/15/2014 5:38 AM, deadalnix wrote:

On Monday, 15 December 2014 at 11:32:11 UTC, Dicebot wrote:
For me scopeness is a property of view, not object itself 
- this also
makes ownership method of actual data irrelevant. Only 
difference between GC
owned data and stack allocated one is that former can have 
scoped view
optionally but for the latter compiler must force it as the 
only available.


Ha finally something start to make sense here.


Well, the DIP does defined scope in terms of a 'view' in just 
this manner.


I am obviously terrible at explaining things.


Don't you think there is a contradiction between this notion of 
view and being so focused on lifetimes? Does it make sense to 
explicitly throw away lifetime information and then spend a lot 
of effort on preventing lifetime-violating assignments to take 
place?


The current proposal is either too limiting or not limiting 
enough.


Too limiting, because programmers expect to gain something for 
making parameter types explicit. A naive make no assumptions 
view is more suitable as a default, then let the programmer 
specify the specifics where possible/needed, but you need to 
figure out the specifics first and let the make no assumptions 
view default be the leftovers…


The proposal is not limiting enough, because retaining knowledge 
about allocation order and aliasing brings important benefits:


An ordered linear parameter type would have properties such as:
- being aliasfree
- being on the stack, and cheaply checkable against the stack 
pointer


Sure, ref counting is fairly general for dynamic tracking, but it 
is also quite expensive. A check against the stack-pointer is 
much cheaper.


I think the uncanny valley metaphor that was brought up was quite 
good. If you are going to put in constraints on references, then 
do it in a manner that is easy to deal with and which brings 
benefits such as aliasfree references. If constraints become 
arbitrary then usability will suffer and it will seem pointless 
to put in extra work to use them.


You have already gone more or less wholesale for templates, so 
you might as well use it here as well, to bring substantial 
benefits to stack-allocation, because the current proposal is a 
very weak in terms of benefits.


Re: DIP69 - Implement scope for escape proof references

2014-12-16 Thread Walter Bright via Digitalmars-d
On 12/16/2014 5:37 AM, Ola Fosheim Grøstad 
ola.fosheim.grostad+dl...@gmail.com wrote:

The current proposal is either too limiting or not limiting enough.


I'm afraid I don't understand at all what you wrote.



Re: DIP69 - Implement scope for escape proof references

2014-12-16 Thread bearophile via Digitalmars-d

Walter Bright:


I'm afraid I don't understand at all what you wrote.


Perhaps reading about linear type systems could help:

http://en.wikipedia.org/w/index.php?title=Substructural_type_systemredirect=no#Linear_type_systems

Bye,
bearophile


Re: DIP69 - Implement scope for escape proof references

2014-12-15 Thread Dicebot via Digitalmars-d

On Monday, 15 December 2014 at 06:12:05 UTC, Walter Bright wrote:
C++ seems to do fine without it for const. It's a convenience 
feature.


C++ const does not really restrict or affect anything for real, 
it is non-existent feature. `scope` as proposed would result in 
inability to store result of predicates if those are ever to 
accept scope data - unless you defined two versions for each 
function that may possibly accept scope data with absolutely 
identical body.



2. This is what scope inference is all about.


Which only works with templates and lack of scope on arguments 
does not affect

function body - templates are not necessary, same as inout.


It also works with all the lambdas, since source for them is 
always available. I also wanted to make it (i.e. inference) 
work with auto functions, but Don Clugston was the primary 
objector :-)


This is not really answering my objections but side-stepping. I 
do support attribute inference. I would actually support full 
attribute inference in the language (and help convincing Don 
about it ;)) if it was introduced as foundation of the language 
and not arbitrary hack (== rethink the way .di interfaces and 
static libraries are defined)


I do view inference as something we need to extend to more 
functions.


That would help with many issues but it need careful design to be 
well-accepted. How about teaming up to do a DIP about it at some 
point where this discussion is over? :P


2) at least optional transitivity to be able to express to 
protect with scope
data referenced by slice or owned linked list referenced 
from root node.


1. that won't work unless scope is a type constructor


I know and this is why I am leaning toward it being qualifier 
despite all

related issues.


That would be a truly massive change to D, and I'm not at all 
sure it would be worth it. We've (i.e. Kenji) have been fixing 
bugs with inout for years, and idea that had seemed 
straightforward.


Yes, I know and this why I am leaning towards that path but 
willing to accept any storage-class based solution - as long as 
it fits my basic criteria. I wonder if some hybrid approach is 
possible - for example, keep it storage class but pretend 
anything transitively accessible though it as if it was of scope 
storage class on its own. But that quickly gets into exceptions 
for special cases land :(


2. it can be achieved by using wrappers that only allow 
by-scope references to

their data (RC is an example of such a wrapper)
It is viral approach and backwards incompatible one - we can't 
change signatures
of Phobos functions to return Wrapped!(char[]) instead of 
char[] for example.
While theoretically possible I can't call this approach 
practical - not until

see some convincing application example.


But you can change signatures to add annotations?


Such annotation would only prevent from compiling code which was 
already undefined by documentation. Changing return type (which 
wasn't Voldemort type before) may break any program that has 
lines akin to `char[] data = foo()` - perfectly legal working 
code.


This sounds totally against my understanding of scope. I want 
scope exactly to
prohibit such actions. However it is possible in slightly 
modified way - where
you don't directly insert pointer to AST but use public method 
of AST control
structure that checks if supplied scope pointer belongs to 
list of nodes it

owns  and casts away scope after that.


Wrappers do that, too.

I know that 'wrapper' sounds bad to you, but one of the goals 
of D's UDT's is to make it easy to adapt the behavior of a type 
by wrapping it in a struct, rather than build new behavior into 
the language.


Problem is that our UDT are simply not that good enough yet. 
Wrappers are fine in general but I want to wrap for less common 
cases and support more common ones natively. I suppose this is 
your intention too but we disagree on what is actually the common 
case and what is the special case.


Re: DIP69 - Implement scope for escape proof references

2014-12-15 Thread John Colvin via Digitalmars-d

On Sunday, 14 December 2014 at 23:27:15 UTC, Walter Bright wrote:
I think I said that clearly: What do you get when you take a 
pointer

of a function with an auto-ref
arg? ...an error, because it's not actually a function!


What's baffling to me is why even declare a function pointer 
parameter as auto-ref? I don't use floating point to index 
strings, either, that doesn't mean floating point is a failed 
concept.


That's not what he's talking about. My understanding is that Manu 
is talking about something like this:


void foo(auto ref someConcreteType) { ... }

auto fooP = foo; //error, foo is not a function


Re: DIP69 - Implement scope for escape proof references

2014-12-15 Thread via Digitalmars-d

On Monday, 15 December 2014 at 01:44:27 UTC, Dicebot wrote:
On Saturday, 13 December 2014 at 00:10:07 UTC, Walter Bright 
wrote:
The proposal provides escape proof passing of arguments. This 
is necessary in order to make rc safe, for example.


What are you looking for?


I am looking for a tool to prevent escaping references to 
user-defined entities / resources from specific scope. RC case 
is not interesting at all to me though I recognize the 
potential benefits of tweaking the scope system to help with 
it. But there is a big difference between tweak for one 
specific use case or designing feature around it (so it becomes 
almost useless in other cases).


I have already provided you an example of code I want to be 
enforced with scope and two major issues with existing proposal 
that make it lacking. This example is akin to litmus test for 
any scope proposal - if it doesn't allow to express such 
design, that proposal is simply not good enough.


In case you have forgotten, I am reminding about two critical 
points that are necessary to make it fly:


1) inout analog for scope to be able to deduce borrowship of 
return values based on borrowship of input arguments. Current 
system is conservative and results in template bloat 
(complicated by the fact that it is storage class thus not 
actually part of a type)


Is it be possible to make `inout` a more general tool for type 
erasure? I don't think yet another ad-hoc mechanism should be 
introduced.




2) at least optional transitivity to be able to express to 
protect with scope data referenced by slice or owned linked 
list referenced from root node.


--

In your tree example I would have never wanted scope protection 
of one specific node of such tree - but a transitive scope 
protection of whole tree view available through on of node 
pointers/references. It doesn't matter who and how owns the 
data for borrowship implementation - only thing that matters 
that _it is not me_.


I think there are two cases that are relevant. 1) the tree nodes 
don't own their children, instead they are managed by - let's say 
- a region allocator, and 2) the tree nodes do own their 
children. In both cases, they can declare the children as scope 
members (assuming a proposal that allows that).


The only case I can think of where the children should not be 
scope members is when they are GC managed. But in this case, you 
don't need to worry about references to them escaping.


Therefore, I don't see a use case for transitivity of scope, from 
a conceptional point of view. If a particular design makes 
transitivity necessary, this points to a flaw in the design, IMO.


Re: DIP69 - Implement scope for escape proof references

2014-12-15 Thread Dicebot via Digitalmars-d

On Monday, 15 December 2014 at 11:23:28 UTC, Marc Schütz wrote:
I think there are two cases that are relevant. 1) the tree 
nodes don't own their children, instead they are managed by - 
let's say - a region allocator, and 2) the tree nodes do own 
their children. In both cases, they can declare the children as 
scope members (assuming a proposal that allows that).


The only case I can think of where the children should not be 
scope members is when they are GC managed. But in this case, 
you don't need to worry about references to them escaping.


Therefore, I don't see a use case for transitivity of scope, 
from a conceptional point of view. If a particular design makes 
transitivity necessary, this points to a flaw in the design, 
IMO.


Actually I think in neither case children should be declared as 
scope members. Instead those should be declared as private 
members but methods that return pointers/references to children 
would be declared to return (transitive) scope 
pointers/references.


For me scopeness is a property of view, not object itself - 
this also makes ownership method of actual data irrelevant. Only 
difference between GC owned data and stack allocated one is that 
former can have scoped view optionally but for the latter 
compiler must force it as the only available.


Re: DIP69 - Implement scope for escape proof references

2014-12-15 Thread via Digitalmars-d

On Monday, 15 December 2014 at 06:12:05 UTC, Walter Bright wrote:

On 12/14/2014 7:41 PM, Dicebot wrote:
Being forced to duplicate every single function in two flavors 
to actually make

scope system usable? This is as much critical as it can be.


C++ seems to do fine without it for const. It's a convenience 
feature.




It's more than that. It has the potential (well, could have) to 
be used for type erasure, which is a useful and worthwhile 
concept by itself.


I know and this is why I am leaning toward it being qualifier 
despite all

related issues.


That would be a truly massive change to D, and I'm not at all 
sure it would be worth it. We've (i.e. Kenji) have been fixing 
bugs with inout for years, and idea that had seemed 
straightforward.


To be honest, I think one reason for those bugs is the awkward 
implementation. I had a look at mtype.c to see how difficult it 
would be to add another type modifier. It's no fun - the current 
implementation requires a dozen groups of helper functions to be 
written for every possible combination of type modifiers. 
Therefore there are helpers like `makeConst`, `makeImmutable`, 
`makeShared`, `makeSharedConst`, `makeWild` (this is `inout`), 
`makeWildConst`, `makeSharedWild`, `makeSharedWildConst`, and 
`makeMutable`. There are also some monster switch statements in 
the same fashion.


No wonder this is error prone. I suspect that with a cleaner 
implementation most of these problems will go away.


Re: DIP69 - Implement scope for escape proof references

2014-12-15 Thread via Digitalmars-d

On Monday, 15 December 2014 at 11:32:11 UTC, Dicebot wrote:

On Monday, 15 December 2014 at 11:23:28 UTC, Marc Schütz wrote:
I think there are two cases that are relevant. 1) the tree 
nodes don't own their children, instead they are managed by - 
let's say - a region allocator, and 2) the tree nodes do own 
their children. In both cases, they can declare the children 
as scope members (assuming a proposal that allows that).


The only case I can think of where the children should not be 
scope members is when they are GC managed. But in this case, 
you don't need to worry about references to them escaping.


Therefore, I don't see a use case for transitivity of scope, 
from a conceptional point of view. If a particular design 
makes transitivity necessary, this points to a flaw in the 
design, IMO.


Actually I think in neither case children should be declared as 
scope members. Instead those should be declared as private 
members but methods that return pointers/references to children 
would be declared to return (transitive) scope 
pointers/references.


I see this as the same thing, conceptually (module the 
transitive in in your parentheses). It's just a different 
mechanism. Scope members are just a short-cut instead of writing 
an accessor method that returns scope.




For me scopeness is a property of view, not object itself - 
this also makes ownership method of actual data irrelevant.


Yes, and this would be true for scope members just the same. (If 
the aggregate owns it's scope members, it will however get in 
trouble when it tries to free() them, therefore your mechanism is 
more appropriate in this case.)


Only difference between GC owned data and stack allocated one 
is that former can have scoped view optionally but for the 
latter compiler must force it as the only available.


Agreed.


Re: DIP69 - Implement scope for escape proof references

2014-12-15 Thread deadalnix via Digitalmars-d
On Saturday, 13 December 2014 at 20:45:53 UTC, Walter Bright 
wrote:

On 12/13/2014 2:10 AM, bearophile wrote:

Walter Bright:


struct Tree {
  RefCount!(Tree*) left;
  RefCount!(Tree*) right;
  ...
}


... I don't think I'd ever have a use for this code.


You have no use for tree structures?


Giving a reference counter to every pointer in a binary tree 
sounds a bit too much.


DMD, for example, uses ASTs where the nodes have multiple 
parents.


It is a DAG then.


Re: DIP69 - Implement scope for escape proof references

2014-12-15 Thread deadalnix via Digitalmars-d

On Monday, 15 December 2014 at 11:32:11 UTC, Dicebot wrote:
For me scopeness is a property of view, not object itself - 
this also makes ownership method of actual data irrelevant. 
Only difference between GC owned data and stack allocated one 
is that former can have scoped view optionally but for the 
latter compiler must force it as the only available.


Ha finally something start to make sense here.


Re: DIP69 - Implement scope for escape proof references

2014-12-15 Thread Walter Bright via Digitalmars-d

On 12/15/2014 3:34 AM, Marc Schütz schue...@gmx.net wrote:

No wonder this is error prone. I suspect that with a cleaner implementation most
of these problems will go away.


Sometimes, it isn't possible to see a cleaner way unless the dirty version is 
written first. Sometimes, there isn't a cleaner way :-(


But there are more issues with inout than are in mtype.c. The template 
implementation is full of it.


Re: DIP69 - Implement scope for escape proof references

2014-12-15 Thread Walter Bright via Digitalmars-d

On 12/15/2014 1:28 AM, Dicebot wrote:

On Monday, 15 December 2014 at 06:12:05 UTC, Walter Bright wrote:

C++ seems to do fine without it for const. It's a convenience feature.


C++ const does not really restrict or affect anything for real, it is
non-existent feature.


C++ programmers constantly copy/pasta functions for the sole purpose of having 
one with const and one without.




`scope` as proposed would result in inability to store
result of predicates if those are ever to accept scope data - unless you defined
two versions for each function that may possibly accept scope data with
absolutely identical body.


If that is necessary, it is no worse than C++ is with const. It isn't a critical 
issue, or C++ would not be usable. I'd like to wait and see how this plays out.




2. This is what scope inference is all about.


Which only works with templates and lack of scope on arguments does not affect
function body - templates are not necessary, same as inout.


It also works with all the lambdas, since source for them is always available.
I also wanted to make it (i.e. inference) work with auto functions, but Don
Clugston was the primary objector :-)


This is not really answering my objections but side-stepping.


Inference addresses the issue.



That would help with many issues but it need careful design to be well-accepted.
How about teaming up to do a DIP about it at some point where this discussion is
over? :P


Ok, sure.



Re: DIP69 - Implement scope for escape proof references

2014-12-15 Thread Walter Bright via Digitalmars-d

On 12/15/2014 5:38 AM, deadalnix wrote:

On Monday, 15 December 2014 at 11:32:11 UTC, Dicebot wrote:

For me scopeness is a property of view, not object itself - this also
makes ownership method of actual data irrelevant. Only difference between GC
owned data and stack allocated one is that former can have scoped view
optionally but for the latter compiler must force it as the only available.


Ha finally something start to make sense here.


Well, the DIP does defined scope in terms of a 'view' in just this manner.

I am obviously terrible at explaining things.


Re: DIP69 - Implement scope for escape proof references

2014-12-14 Thread Paolo Invernizzi via Digitalmars-d
On Sunday, 14 December 2014 at 00:45:06 UTC, Manu via 
Digitalmars-d wrote:

On 13 December 2014 at 15:11, Walter Bright via Digitalmars-d


A function template is a function that takes both compile-time 
args and
run-time args. C++ tried to make them completely different 
animals, when
they are not. Don't think template, think compile-time 
argument to a
function. I convinced Andrei to never mention template in 
his D book, as
it brings forth all kinds of connotations and expectations 
that impede understanding what D templates actually are. I 
think the result was successful.


You can spin it however you like, but it's exactly the same 
thing.
They are completely different animals. A function template is  
not a
function at all until it's instantiated. When it's 
instantiated, it
becomes a function, or even, one of a suite of functions. And 
it's not known to the author where the function is.
(Note: I define 'function' in this context to mean 'some code 
that is emitted')


Philippe Sigaud Excellent D Templates: A Tutorial...
the MANTRA...

XXX templates are not XXXs, they are templates. With XXX being 
any of (function, struct, class, interface, union).


---
/Paolo


Re: DIP69 - Implement scope for escape proof references

2014-12-14 Thread ketmar via Digitalmars-d
On Sun, 14 Dec 2014 09:04:58 +
Paolo Invernizzi via Digitalmars-d digitalmars-d@puremagic.com wrote:

 Philippe Sigaud Excellent D Templates: A Tutorial...
 the MANTRA...
 
 XXX templates are not XXXs, they are templates. With XXX being 
 any of (function, struct, class, interface, union).
and that still doesn't work. ;-)

as a somehow related example i recall my first expirience with C. my
first serious language was Pascal, and it has that nice range-checking
feature for arrays. it was very hard for me to understand that C has no
arrays at all, not to say range checking. why there is no arrays if i
have this nice indexing and all that?! what do you mean by that buffer
overflow nonsence? if it looks like an array it must be an array!


signature.asc
Description: PGP signature


Re: DIP69 - Implement scope for escape proof references

2014-12-14 Thread via Digitalmars-d
On Sunday, 14 December 2014 at 00:45:06 UTC, Manu via 
Digitalmars-d wrote:

Perhaps scope and RC are different things?
Solve scope purely for RC, and you've broken scope for other 
purposes

that it's useful; that is, inhibiting escaping of data.


Exactly. It shouldn't matter which type this data has - both 
references and value types are valid. I would define `scope` like 
this:


A value designated with `scope` may not be assigned to a 
variable (or parameter, ...) with a lifetime longer than its 
owner's lifetime.


Maybe there's a compromise. If we say scope isn't 
'transitive', but it

is transitive when it comes to aggregates?



One thing I've tried very hard to make work in D is have basic 
types /

aggregages / arrays be interchangeable.


It should only be applicable to whatever is explicitly marked as 
`scope`. For references, that's the reference itself, but not 
what it points to. For aggregates, it's the entire aggregate with 
all it's members. That way, all types will be treated uniformly.


Of course, this can only work with a type modifier, not with a 
storage class.




I'm looking for ways to make scope fit your proposed mould and 
be useful to me.

If I can't do this then my most common use case is unsatisfied:

struct Wrap
{
  OpaqueThing *ptr;

  this() {}
  ~this() {}  // - constructors that twiddle RC effectively.
  this(this) {}

  this() scope {}
  ~this() scope {}  // - Overloadable for 'scope', in which 
case,

don't twiddle the RC!
  this(this) scope {}

  // lots of operations on OpaqueThing wrapped up here...
}

void f(scope Wrap x) -- RC twiddling is effectively elided 
here due

to constructor overloads
{
}


If you can propose an alternative solution?
This is representative of my 99% case. Sometimes the struct is 
more

than a single pointer though.


Unfortunately Walter rejected this when I had proposed it.

In the current proposal, we cannot overload on scope. The 
proposed solution is to not borrow the wrapper, but only its 
payload.


But this is restrictive; even in the case of RC, there are 
use-cases that cannot be served with this technique, namely when 
the callee can only decide at runtime whether it wants to make a 
copy of an RC value it received. The correct solution would be to 
pass the RC wrapper itself as scope, as you show in your example, 
thereby delegating the decision of whether to adjust the refcount 
from the caller to the callee.


Re: DIP69 - Implement scope for escape proof references

2014-12-14 Thread Walter Bright via Digitalmars-d

On 12/8/2014 7:23 AM, Steven Schveighoffer wrote:

What I wanted to know was, when I see scope
ref, why is it there? When should I use it?


It's there to indicate a parameter is NOT returned by ref.




When should I use scope? What nasty
things are prevented if I use it? Examples would be preferable.


http://wiki.dlang.org/DIP69#Ref has examples of errors that are prevented.



Re: DIP69 - Implement scope for escape proof references

2014-12-14 Thread Walter Bright via Digitalmars-d

On 12/13/2014 4:44 PM, Manu via Digitalmars-d wrote:

On 13 December 2014 at 15:11, Walter Bright via Digitalmars-d
digitalmars-d@puremagic.com wrote:

On 12/12/2014 6:55 PM, Manu via Digitalmars-d wrote:


I did just give some examples, I'll repeat; auto ref fails when the
function is extern.



Don't make it extern, then.


Do you think I just interact with other languages for fun or something?


I'm not trying to insult you - but why need 'auto ref' for extern functions? The 
extern functions are ref or not-ref, and declare the interface to match. There's 
no point to auto ref there.




If there's source to the function, it'll often be inlined which will remove
the indirection.


Not if it's extern (applicable to ref, not auto-ref), or wrapped, or
if I ever want to capture a function pointer.
It's also semantically different; I can change the caller's value.


Again, if it is extern it has a fixed definition of ref or not. The D side 
doesn't decide if it's ref or not, it just follows whatever the extern 
declaration is.


This is why I do not understand why you are running into this issue everywhere.



What do you get when you take a pointer of a function with an auto-ref
arg? ...an error, because it's not actually a function!
So in a context where I'm dealing with functions and function pointers
(very, very frequent), I suddenly have something that's not a function
find it's way into my meta and I have to special-case the hell out of
it.



Why are function pointers and ints going to the same argument of a function?
I thought you weren't using templates?


I'm confused. I'm talking about capturing function pointers. Not about
function arguments.
Capturing pointers of functions with auto-ref args (aka, template
functions) is a serious nuisance, and impossible outside the site of
instantiation.


WHY are you doing this? I have no idea what coding pattern would need to pass 
functions by reference.




I wonder what is the need for the code that you are writing.


General function adaptation. There are lots of reasons to wrap
functions. Adaptation to existing or external API's is the most common
in my experience.


Are those API's all templated? My guess is no. If they're not, you don't need 
templates or auto-ref to interface to them.




Functions are what programs are! I really struggle to understand why
you have such trouble sympathising with my view here.


Because you don't provide any examples of why you need this stuff. You say I 
need this feature because I'm doing X, but I have no idea what X is or why you 
need X.


I.e. you present and advocate for particular solutions, but not the problems.



Languages generate code, which is packaged into blocks we call 'functions'...
and they require to adhere to strict ABI requirements. That is
programming in a nutshell. Surely it's reasonable to want to retain
complete control over this most primitive and basic of tasks.
One important aspect of that control is where the code is generated;
is it 'here', or 'there'?


Why is that important?



And that's a critical distinction between functions and templates.


You can control that with function templates, too. The compiler won't 
instantiate a template locally if the import instantiates it.




Look at LuaD. Lots of awkward cases have emerged there. There are many
more to come too; the known bug list are mostly nasty issues of this
nature that I've been putting off.
I can't offer any insight into my commercial code sadly, and I no
longer have access to it :/

Situations like this appear frequently:
https://github.com/JakobOvrum/LuaD/pull/76/files#diff-bcb370a5bc6fe75a9d5c04f2e1c17eb0R178

And something like this tends to appear as one aspect of the solution:
https://github.com/JakobOvrum/LuaD/pull/76/files#diff-bcb370a5bc6fe75a9d5c04f2e1c17eb0R68
'struct Ref(T)' leads to its own problems though, in that it's a
localised concept. No external code anywhere understands it as a
'ref', so if 3rd party code has any special treatment for ref, that
code now fails.

Then more magic like this:
https://github.com/JakobOvrum/LuaD/pull/76/files#diff-ec8c532aeca798240de4d70ee639fc16R90
Since we need to recognise 'ref' and substitute it for our magic
'struct Ref(T)'.


I've probably spent more hours wrangling D meta of this sort than most
people. This sort of thing always happens.
If Ref!T is the tool that resolves the situation, then it's clear
demonstration that ref should be part of the type.


I'll take a look at your references in a moment.



When I'm writing a function that's not a template, I intend, and
expect, to write a function that's _not a template_.
Templates and functions are different things. I think it's a massive
mistake to have created a way to write a template that looks nothing
like a template.



A function template is a function that takes both compile-time args and
run-time args. C++ tried to make them completely different animals, when
they are not. Don't think template, think compile-time 

Re: DIP69 - Implement scope for escape proof references

2014-12-14 Thread Dicebot via Digitalmars-d
On Saturday, 13 December 2014 at 00:10:07 UTC, Walter Bright 
wrote:
The proposal provides escape proof passing of arguments. This 
is necessary in order to make rc safe, for example.


What are you looking for?


I am looking for a tool to prevent escaping references to 
user-defined entities / resources from specific scope. RC case is 
not interesting at all to me though I recognize the potential 
benefits of tweaking the scope system to help with it. But there 
is a big difference between tweak for one specific use case or 
designing feature around it (so it becomes almost useless in 
other cases).


I have already provided you an example of code I want to be 
enforced with scope and two major issues with existing proposal 
that make it lacking. This example is akin to litmus test for any 
scope proposal - if it doesn't allow to express such design, that 
proposal is simply not good enough.


In case you have forgotten, I am reminding about two critical 
points that are necessary to make it fly:


1) inout analog for scope to be able to deduce borrowship of 
return values based on borrowship of input arguments. Current 
system is conservative and results in template bloat (complicated 
by the fact that it is storage class thus not actually part of a 
type)


2) at least optional transitivity to be able to express to 
protect with scope data referenced by slice or owned linked list 
referenced from root node.


--

In your tree example I would have never wanted scope protection 
of one specific node of such tree - but a transitive scope 
protection of whole tree view available through on of node 
pointers/references. It doesn't matter who and how owns the data 
for borrowship implementation - only thing that matters that _it 
is not me_.


Re: DIP69 - Implement scope for escape proof references

2014-12-14 Thread Walter Bright via Digitalmars-d

On 12/14/2014 5:44 PM, Dicebot wrote:

I am looking for a tool to prevent escaping references to user-defined entities
/ resources from specific scope. RC case is not interesting at all to me though
I recognize the potential benefits of tweaking the scope system to help with it.
But there is a big difference between tweak for one specific use case or
designing feature around it (so it becomes almost useless in other cases).

I have already provided you an example of code I want to be enforced with scope
and two major issues with existing proposal that make it lacking. This example
is akin to litmus test for any scope proposal - if it doesn't allow to express
such design, that proposal is simply not good enough.

In case you have forgotten, I am reminding about two critical points that are
necessary to make it fly:

1) inout analog for scope to be able to deduce borrowship of return values based
on borrowship of input arguments. Current system is conservative and results in
template bloat (complicated by the fact that it is storage class thus not
actually part of a type)


1. All inout actually does is reduce code copy/pasta, it is not critical.
2. This is what scope inference is all about.



2) at least optional transitivity to be able to express to protect with scope
data referenced by slice or owned linked list referenced from root node.


1. that won't work unless scope is a type constructor
2. it can be achieved by using wrappers that only allow by-scope references to 
their data (RC is an example of such a wrapper)




In your tree example I would have never wanted scope protection of one specific
node of such tree - but a transitive scope protection of whole tree view
available through on of node pointers/references. It doesn't matter who and how
owns the data for borrowship implementation - only thing that matters that _it
is not me_.


As I explained to Manu, transitive scope makes things like doing a symbol table 
lookup, then putting a pointer to the found symbol in an AST, not workable.




Re: DIP69 - Implement scope for escape proof references

2014-12-14 Thread Dicebot via Digitalmars-d

On Monday, 15 December 2014 at 02:45:04 UTC, Walter Bright wrote:
1. All inout actually does is reduce code copy/pasta, it is not 
critical.


Being forced to duplicate every single function in two flavors to 
actually make scope system usable? This is as much critical as it 
can be.



2. This is what scope inference is all about.


Which only works with templates and lack of scope on arguments 
does not affect function body - templates are not necessary, 
same as inout.


2) at least optional transitivity to be able to express to 
protect with scope
data referenced by slice or owned linked list referenced from 
root node.


1. that won't work unless scope is a type constructor


I know and this is why I am leaning toward it being qualifier 
despite all related issues.


2. it can be achieved by using wrappers that only allow 
by-scope references to their data (RC is an example of such a 
wrapper)


It is viral approach and backwards incompatible one - we can't 
change signatures of Phobos functions to return Wrapped!(char[]) 
instead of char[] for example. While theoretically possible I 
can't call this approach practical - not until see some 
convincing application example.


In your tree example I would have never wanted scope 
protection of one specific
node of such tree - but a transitive scope protection of whole 
tree view
available through on of node pointers/references. It doesn't 
matter who and how
owns the data for borrowship implementation - only thing that 
matters that _it

is not me_.


As I explained to Manu, transitive scope makes things like 
doing a symbol table lookup, then putting a pointer to the 
found symbol in an AST, not workable.


This sounds totally against my understanding of scope. I want 
scope exactly to prohibit such actions. However it is possible in 
slightly modified way - where you don't directly insert pointer 
to AST but use public method of AST control structure that checks 
if supplied scope pointer belongs to list of nodes it owns  and 
casts away scope after that.


Re: DIP69 - Implement scope for escape proof references

2014-12-14 Thread Walter Bright via Digitalmars-d

On 12/14/2014 7:41 PM, Dicebot wrote:

On Monday, 15 December 2014 at 02:45:04 UTC, Walter Bright wrote:

1. All inout actually does is reduce code copy/pasta, it is not critical.


Being forced to duplicate every single function in two flavors to actually make
scope system usable? This is as much critical as it can be.


C++ seems to do fine without it for const. It's a convenience feature.



2. This is what scope inference is all about.


Which only works with templates and lack of scope on arguments does not affect
function body - templates are not necessary, same as inout.


It also works with all the lambdas, since source for them is always available. I 
also wanted to make it (i.e. inference) work with auto functions, but Don 
Clugston was the primary objector :-)


I do view inference as something we need to extend to more functions.



2) at least optional transitivity to be able to express to protect with scope
data referenced by slice or owned linked list referenced from root node.


1. that won't work unless scope is a type constructor


I know and this is why I am leaning toward it being qualifier despite all
related issues.


That would be a truly massive change to D, and I'm not at all sure it would be 
worth it. We've (i.e. Kenji) have been fixing bugs with inout for years, and 
idea that had seemed straightforward.




2. it can be achieved by using wrappers that only allow by-scope references to
their data (RC is an example of such a wrapper)

It is viral approach and backwards incompatible one - we can't change signatures
of Phobos functions to return Wrapped!(char[]) instead of char[] for example.
While theoretically possible I can't call this approach practical - not until
see some convincing application example.


But you can change signatures to add annotations?

You're going to get one or the other.



This sounds totally against my understanding of scope. I want scope exactly to
prohibit such actions. However it is possible in slightly modified way - where
you don't directly insert pointer to AST but use public method of AST control
structure that checks if supplied scope pointer belongs to list of nodes it
owns  and casts away scope after that.


Wrappers do that, too.

I know that 'wrapper' sounds bad to you, but one of the goals of D's UDT's is to 
make it easy to adapt the behavior of a type by wrapping it in a struct, rather 
than build new behavior into the language.


Re: DIP69 - Implement scope for escape proof references

2014-12-13 Thread bearophile via Digitalmars-d

Walter Bright:


struct Tree {
   RefCount!(Tree*) left;
   RefCount!(Tree*) right;
   ...
}


... I don't think I'd ever have a use for this code.


You have no use for tree structures?


Giving a reference counter to every pointer in a binary tree 
sounds a bit too much.


Bye,
bearophile


Re: DIP69 - Implement scope for escape proof references

2014-12-13 Thread Max Samukha via Digitalmars-d
On Saturday, 13 December 2014 at 02:55:50 UTC, Manu via 
Digitalmars-d wrote:


Templates and functions are different things. I think it's a 
massive
mistake to have created a way to write a template that looks 
nothing

like a template.


That is a misconception spread by C++. Templates are pure 
functions applied at compile time. Function templates are 
functions partially applied at compile time.


Re: DIP69 - Implement scope for escape proof references

2014-12-13 Thread Jacob Carlborg via Digitalmars-d

On 2014-12-13 01:09, Walter Bright wrote:


The proposal provides escape proof passing of arguments. This is
necessary in order to make rc safe, for example.

What are you looking for?


Passing references to stack allocated data to functions safely is one 
idea that comes to mind.


--
/Jacob Carlborg


Re: DIP69 - Implement scope for escape proof references

2014-12-13 Thread Jacob Carlborg via Digitalmars-d

On 2014-12-13 06:11, Walter Bright wrote:


Don't make it extern, then.


He's said a couple of time he's interfacing with C and/or C++ code.


Why are function pointers and ints going to the same argument of a
function? I thought you weren't using templates?


I think he meant taking the address of a function with auto ref.

--
/Jacob Carlborg


Re: DIP69 - Implement scope for escape proof references

2014-12-13 Thread Walter Bright via Digitalmars-d

On 12/13/2014 8:01 AM, Jacob Carlborg wrote:

On 2014-12-13 01:09, Walter Bright wrote:


The proposal provides escape proof passing of arguments. This is
necessary in order to make rc safe, for example.

What are you looking for?


Passing references to stack allocated data to functions safely is one idea that
comes to mind.


'scope ref' does that.



Re: DIP69 - Implement scope for escape proof references

2014-12-13 Thread Walter Bright via Digitalmars-d

On 12/13/2014 2:10 AM, bearophile wrote:

Walter Bright:


struct Tree {
   RefCount!(Tree*) left;
   RefCount!(Tree*) right;
   ...
}


... I don't think I'd ever have a use for this code.


You have no use for tree structures?


Giving a reference counter to every pointer in a binary tree sounds a bit too 
much.


DMD, for example, uses ASTs where the nodes have multiple parents.


Re: DIP69 - Implement scope for escape proof references

2014-12-13 Thread Walter Bright via Digitalmars-d

On 12/13/2014 8:19 AM, Jacob Carlborg wrote:

On 2014-12-13 06:11, Walter Bright wrote:


Don't make it extern, then.


He's said a couple of time he's interfacing with C and/or C++ code.


Yes, and C++ code is either ref or not ref, and it is not a problem to insert 
'ref' or not, manually.




Why are function pointers and ints going to the same argument of a
function? I thought you weren't using templates?


I think he meant taking the address of a function with auto ref.


Right, but why is that even being attempted?



Re: DIP69 - Implement scope for escape proof references

2014-12-13 Thread Walter Bright via Digitalmars-d

On 12/13/2014 6:10 AM, Max Samukha wrote:

On Saturday, 13 December 2014 at 02:55:50 UTC, Manu via Digitalmars-d wrote:


Templates and functions are different things. I think it's a massive
mistake to have created a way to write a template that looks nothing
like a template.


That is a misconception spread by C++. Templates are pure functions applied at
compile time. Function templates are functions partially applied at compile 
time.


It took me an embarrassingly long time to get past the C++ notion that templates 
are something orthogonal from 'normal' functions and data declarations.


Even the C++ notion of a 'primary' template is wholly unnecessary, but is deeply 
embedded in how it handles the semantics of templates.


C++ did get right the partial ordering of templates, and D applied partial 
ordering to 'normal' functions as well.


Re: DIP69 - Implement scope for escape proof references

2014-12-13 Thread Manu via Digitalmars-d
On 13 December 2014 at 15:11, Walter Bright via Digitalmars-d
digitalmars-d@puremagic.com wrote:
 On 12/12/2014 6:55 PM, Manu via Digitalmars-d wrote:

 I did just give some examples, I'll repeat; auto ref fails when the
 function is extern.


 Don't make it extern, then.

Do you think I just interact with other languages for fun or something?


 It is also wrong that when I pass an int or float, it is passed by ref
 instead of by value... that is never what I want!


 If there's source to the function, it'll often be inlined which will remove
 the indirection.

Not if it's extern (applicable to ref, not auto-ref), or wrapped, or
if I ever want to capture a function pointer.
It's also semantically different; I can change the caller's value.


 What do you get when you take a pointer of a function with an auto-ref
 arg? ...an error, because it's not actually a function!
 So in a context where I'm dealing with functions and function pointers
 (very, very frequent), I suddenly have something that's not a function
 find it's way into my meta and I have to special-case the hell out of
 it.


 Why are function pointers and ints going to the same argument of a function?
 I thought you weren't using templates?

I'm confused. I'm talking about capturing function pointers. Not about
function arguments.
Capturing pointers of functions with auto-ref args (aka, template
functions) is a serious nuisance, and impossible outside the site of
instantiation.
You need information that's only available at the point of
instantiation. That changes the landscape quite a bit.


 The solution in this case is to wrap it in a non-auto-ref shim with
 the ref-ness explicitly stated in the way I expect... which is in
 itself another problem, because 'ref' is not part of the type! So the
 annoying de-auto-ref-ing shim must be a text mixin with some very
 complex, practically unreadable, definitely unmaintainable logic
 surrounding it. It's insanity on top of insanity!

 I also run the invisible risk of generating 2^num_args instances of
 the code for functions containing auto-ref args.


 I wonder what is the need for the code that you are writing.

General function adaptation. There are lots of reasons to wrap
functions. Adaptation to existing or external API's is the most common
in my experience.

Functions are what programs are! I really struggle to understand why
you have such trouble sympathising with my view here. Languages
generate code, which is packaged into blocks we call 'functions'...
and they require to adhere to strict ABI requirements. That is
programming in a nutshell. Surely it's reasonable to want to retain
complete control over this most primitive and basic of tasks.
One important aspect of that control is where the code is generated;
is it 'here', or 'there'? And that's a critical distinction between
functions and templates.


Look at LuaD. Lots of awkward cases have emerged there. There are many
more to come too; the known bug list are mostly nasty issues of this
nature that I've been putting off.
I can't offer any insight into my commercial code sadly, and I no
longer have access to it :/

Situations like this appear frequently:
https://github.com/JakobOvrum/LuaD/pull/76/files#diff-bcb370a5bc6fe75a9d5c04f2e1c17eb0R178

And something like this tends to appear as one aspect of the solution:
https://github.com/JakobOvrum/LuaD/pull/76/files#diff-bcb370a5bc6fe75a9d5c04f2e1c17eb0R68
'struct Ref(T)' leads to its own problems though, in that it's a
localised concept. No external code anywhere understands it as a
'ref', so if 3rd party code has any special treatment for ref, that
code now fails.

Then more magic like this:
https://github.com/JakobOvrum/LuaD/pull/76/files#diff-ec8c532aeca798240de4d70ee639fc16R90
Since we need to recognise 'ref' and substitute it for our magic
'struct Ref(T)'.


I've probably spent more hours wrangling D meta of this sort than most
people. This sort of thing always happens.
If Ref!T is the tool that resolves the situation, then it's clear
demonstration that ref should be part of the type.


 When I'm writing a function that's not a template, I intend, and
 expect, to write a function that's _not a template_.
 Templates and functions are different things. I think it's a massive
 mistake to have created a way to write a template that looks nothing
 like a template.


 A function template is a function that takes both compile-time args and
 run-time args. C++ tried to make them completely different animals, when
 they are not. Don't think template, think compile-time argument to a
 function. I convinced Andrei to never mention template in his D book, as
 it brings forth all kinds of connotations and expectations that impede
 understanding what D templates actually are. I think the result was
 successful.

You can spin it however you like, but it's exactly the same thing.
They are completely different animals. A function template is not a
function at all until it's instantiated. When it's 

Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Dicebot via Digitalmars-d

On Friday, 12 December 2014 at 06:57:54 UTC, deadalnix wrote:

On Friday, 12 December 2014 at 06:06:40 UTC, Dicebot wrote:
On Thursday, 11 December 2014 at 21:41:11 UTC, Walter Bright 
wrote:
Consider a ref counted type, RC!T. If scope were transitive, 
then you could not have, say, a tree where the edges were 
RC!T. I.e., the payload of an RC type should not be forced to 
be scope.


I don't see how this is related. It would be perfectly ok to 
declare root of such tree scope if it was transitive (as long 
as it only controls access and does not attempt early 
destruction).




That is my proposal. However, it is not as simply as you think 
it is without making it a type qualifier (which is not 
desirable).


In effect, that mean that you can see something that has 
infinite lifetime through a scope reference, so you need to 
track lifetime rvalue and lvalue differently.


I'm still for it. The current proposal is not powerful enough 
to pull its weight.


I don't hope it will be simple. It is all about making scope as 
simple as possible to keep it useful for idiomatic D code - but 
not simpler.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread deadalnix via Digitalmars-d

On Friday, 12 December 2014 at 07:48:21 UTC, Walter Bright wrote:
Are you suggesting two kinds of scope - transitive and 
non-transitive?




Non transitive scope can be added without any language extension. 
There is no point doing much with the scope keyword if 
indirection aren't in the loop.


The more I think about it, the more ref counting is the 
definitive case, as just about everything else can be explained 
in terms of how ref counting works.


ref counting is just one form of ownership.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Manu via Digitalmars-d
On 11 December 2014 at 23:22, ixid via Digitalmars-d
digitalmars-d@puremagic.com wrote:
 Manu have you shown Walter some of the code where ref is problematic? He
 seems to have asked to see examples repeatedly as he's not convinced there
 is a problem.

I have discussed issues here in the past, but possibly not as
concretely as would be useful to this discussion.
I want to take some time to contribute value to this issue, but I have
virtually no time at all lately, and I can't even keep up with this
posts thread, let alone sit and consider+craft a bunch of
demonstration cases.
This thread is moving faster than I am able to, so I'm not sure what I can do.

There's no TL;DR conversation, and almost all discussion happens
outside of my timezone, which wasn't such a problem when I was
nocturnal, but I have had to change lifestyle recently :/
I have about 30 posts to try and catch up on and understand right now
in 5 minutes before I have to leave _


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Manu via Digitalmars-d
On 11 December 2014 at 23:55, via Digitalmars-d
digitalmars-d@puremagic.com wrote:
 On Thursday, 11 December 2014 at 12:48:05 UTC, Manu via Digitalmars-d wrote:

 On 8 December 2014 at 07:29, Walter Bright via Digitalmars-d
 digitalmars-d@puremagic.com wrote:

 On 12/7/2014 6:12 AM, Dicebot wrote:


 But from existing cases it doesn't seem working good enough. For
 example,
 not
 being able to represent idiom of `scope ref int foo(scope ref int x) {
 return x;
 }` seems very limiting.



   scope ref int foo(ref int x);

 will do it.


 Will it? It looks like foo can't be called with scope data?


 This is a point that most people don't seem to understand yet, and which
 wasn't obvious for me either, at the beginning:

 * A `ref` parameter means that it cannot escape the function, _except_ by
 return.
 * A `scope ref` parameter means that it cannot escape the function  _ever_,
 not even by return.
 * A `scope ref` return means that it cannot leave the current statement.

 Therefore, a `scope ref` return value can be passed on to the next function
 as a `ref` argument. If that function again returns a reference (even if not
 explicitly designated as `scope`), the compiler will treat it as if it were
 `scope ref`.

Ummm. I reckon there's a good reason that people don't seem to
understand this... because it would have difficulty being any more
unintuitive!
It's contrary to the behaviour of basically everything else in D!
const, pure, nothrow, etc... they all work a reliable and consistent way.

Also, I still don't think I get it... a scope-ref return, which has a
restriction as you say, can be subverted by being piped through a
function that receives and returns it as ref?
What is the point?

 I'm also quite uneasy with the fact that scope would not be transitive
 as a storage class. What happens when it's applied to a value type,
 like a struct, that contains some pointers? An adaptation wrapper for
 a single pointer is super common; ie, a tiny struct passed by value
 with scope needs to have it's contained pointer receive the scope-ness
 of the argument.


 I agree, this is important. In my proposal, this works without transitivity.
 The wrapper stores the pointer as a `scope` member, then by copying the
 wrapper, the pointer gets copied implicitly, to which the normal scope
 restrictions apply (`scope` on members means will not outlive the
 aggregate). If it stored it as normal non-scope pointer, it couldn't get
 assigned in the first place. (Additionally, some higher level tricks are
 possible if we allow scope for value types and overloading on scope.)

How can a member be marked scope? Apparently it's a storage class, not
a type constructor... we can only attribute storage classes to
function args/results(?).


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/11/2014 11:55 PM, Dicebot wrote:

On Friday, 12 December 2014 at 07:48:21 UTC, Walter Bright wrote:

I don't see how this is related. It would be perfectly ok to declare root of
such tree scope if it was transitive (as long as it only controls access and
does not attempt early destruction).


Are you suggesting two kinds of scope - transitive and non-transitive?

The more I think about it, the more ref counting is the definitive case, as
just about everything else can be explained in terms of how ref counting works.


I don't see applicability of non-transitive scope because I don't understand the
problem with the tree or reference counting you have mentioned - that is why I
suggested to amend DIP to put explanation there.


Consider every pointer in a tree to be a ref counted pointer. There is no 
purpose to making scope transitive - traveling from one node to the next goes 
through the usual ref counting mechanism, and the ref counting wrapper can 
control that.


Also, consider a data structure:

A - B
C - B

If scope is transitive, how is C going to simultaneously access B?


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/12/2014 12:16 AM, deadalnix wrote:

On Friday, 12 December 2014 at 07:48:21 UTC, Walter Bright wrote:

Are you suggesting two kinds of scope - transitive and non-transitive?



Non transitive scope can be added without any language extension.


In order for it to work, the holes in the language that enabled escapes had to 
be plugged. That's what this proposal does - plug the holes.




ref counting is just one form of ownership.


My point is if that works with this proposal, then the other forms can work, 
too.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread deadalnix via Digitalmars-d

On Friday, 12 December 2014 at 08:44:56 UTC, Walter Bright wrote:

On 12/12/2014 12:16 AM, deadalnix wrote:
On Friday, 12 December 2014 at 07:48:21 UTC, Walter Bright 
wrote:
Are you suggesting two kinds of scope - transitive and 
non-transitive?




Non transitive scope can be added without any language 
extension.


In order for it to work, the holes in the language that enabled 
escapes had to be plugged. That's what this proposal does - 
plug the holes.




The holes covered by a non transitive scope are already undefined 
behavior.



ref counting is just one form of ownership.


My point is if that works with this proposal, then the other 
forms can work, too.


No, unless we wrap every single indirection (pointer, slice, 
classes, delegates) into a wrapper. That is not going to fly very 
far.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread via Digitalmars-d

On Friday, 12 December 2014 at 00:13:10 UTC, deadalnix wrote:
On Thursday, 11 December 2014 at 13:55:55 UTC, Marc Schütz 
wrote:
This is a point that most people don't seem to understand yet, 
and which wasn't obvious for me either, at the beginning:


* A `ref` parameter means that it cannot escape the function, 
_except_ by return.
* A `scope ref` parameter means that it cannot escape the 
function  _ever_, not even by return.
* A `scope ref` return means that it cannot leave the current 
statement.


Therefore, a `scope ref` return value can be passed on to the 
next function as a `ref` argument. If that function again 
returns a reference (even if not explicitly designated as 
`scope`), the compiler will treat it as if it were `scope ref`.




No, it understood.


Steven hadn't, evidently.


It is simply not useful.


I'm not convinced either.



I agree, this is important. In my proposal, this works without 
transitivity. The wrapper stores the pointer as a `scope` 
member, then by copying the wrapper, the pointer gets copied 
implicitly, to which the normal scope restrictions apply 
(`scope` on members means will not outlive the aggregate). 
If it stored it as normal non-scope pointer, it couldn't get 
assigned in the first place.


Wut ? You cante store anything with grear lifetime, including 
non scope things (as they'll have infinite lifetime). Meaning 
the only thing you know, is that thing are possibly scoped.


Meaning you have to assume infinite lifetime with every 
indirection, which make this proposal useless.


My comments above don't refer to this proposal, but my original 
one:


struct Wrapper(T) {
scope T payload;
// used to be:
// scope!this T payload;
}

scope int a;
auto w = Wrapper!(int*)(a); // ok
scope int b;
w.payload = b;  // error, w (and therefore 
w.payload)

 // lives longer than b
Wrapper!(int*) w2 = w;   // ok, lifetime(w2)  lifetime(w)
w = w2;  // error, equivalent to
 // w.payload = w2.payload

Therefore, wrapping is safe without transitivity of scope.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread via Digitalmars-d
On Friday, 12 December 2014 at 08:42:22 UTC, Manu via 
Digitalmars-d wrote:

On 11 December 2014 at 23:55, via Digitalmars-d
digitalmars-d@puremagic.com wrote:
This is a point that most people don't seem to understand yet, 
and which

wasn't obvious for me either, at the beginning:

* A `ref` parameter means that it cannot escape the function, 
_except_ by

return.
* A `scope ref` parameter means that it cannot escape the 
function  _ever_,

not even by return.
* A `scope ref` return means that it cannot leave the current 
statement.


Therefore, a `scope ref` return value can be passed on to the 
next function
as a `ref` argument. If that function again returns a 
reference (even if not
explicitly designated as `scope`), the compiler will treat it 
as if it were

`scope ref`.


Ummm. I reckon there's a good reason that people don't seem to
understand this... because it would have difficulty being any 
more

unintuitive!
It's contrary to the behaviour of basically everything else in 
D!
const, pure, nothrow, etc... they all work a reliable and 
consistent way.


Unfortunately I have to agree.



Also, I still don't think I get it... a scope-ref return, which 
has a
restriction as you say, can be subverted by being piped through 
a

function that receives and returns it as ref?
What is the point?


It cannot be subverted. As soon as you pass something into a 
function G() as `ref` that's been returned from a function F() 
via `scope ref`, the compiler needs to treat what is returned 
from G() as `scope ref`, even if it's only declared as `ref`.


As you say, it's unintuitive and non-obvious.



I'm also quite uneasy with the fact that scope would not be 
transitive
as a storage class. What happens when it's applied to a value 
type,
like a struct, that contains some pointers? An adaptation 
wrapper for
a single pointer is super common; ie, a tiny struct passed by 
value
with scope needs to have it's contained pointer receive the 
scope-ness

of the argument.



I agree, this is important. In my proposal, this works without 
transitivity.
The wrapper stores the pointer as a `scope` member, then by 
copying the
wrapper, the pointer gets copied implicitly, to which the 
normal scope
restrictions apply (`scope` on members means will not outlive 
the
aggregate). If it stored it as normal non-scope pointer, it 
couldn't get
assigned in the first place. (Additionally, some higher level 
tricks are
possible if we allow scope for value types and overloading on 
scope.)


How can a member be marked scope? Apparently it's a storage 
class, not

a type constructor... we can only attribute storage classes to
function args/results(?).


I was talking about my proposal here, where it's a type modifier, 
not a storage class.


deadalnix also brought up the problem of transitivity. This, too, 
would simply go away if it's a type modifier.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Manu via Digitalmars-d
On 12 December 2014 at 07:41, Walter Bright via Digitalmars-d
digitalmars-d@puremagic.com wrote:
 On 12/11/2014 4:47 AM, Manu via Digitalmars-d wrote:

 On 8 December 2014 at 07:29, Walter Bright via Digitalmars-d
 digitalmars-d@puremagic.com wrote:

 On 12/7/2014 6:12 AM, Dicebot wrote:


 But from existing cases it doesn't seem working good enough. For
 example,
 not
 being able to represent idiom of `scope ref int foo(scope ref int x) {
 return x;
 }` seems very limiting.



scope ref int foo(ref int x);

 will do it.


 Will it? It looks like foo can't be called with scope data?


 Yes, it can be.


 I don't have the perfect proposal, but I feel very strongly about 2
 things:
 1. It must not be a storage class; the concept was a disaster with
 ref, and I struggle with this more frequently than any other 'feature'
 in D.


 I simply do not understand why distinguishing beteen ref and not-ref is a
 cornerstone of everything you do.

I've said so many times, it's the single greatest regular frustration
I encounter, by far.
That is of course a relative measure. It's not the 'cornerstone of
everything I do'; I don't start discussions about things that are not
broken and otherwise painless.
It is the thing that is *the most broken*, and leads to the most edge
cases, general bloat, and text mixins.
It comes up the most frequently, and by that metric alone, I consider
it highest priority on my list.

I've also said many times before, it possibly stems from the fact that
one of the key cornerstones of almost everything I do in D is interact
with other languages.
This is a practical reality, I can't write all my code in D, and have
mountains of existing code to interact with.
Boilerplate is the result. D has powerful systems to automate
boilerplate, like a carrot dangling right in front of my face, but
it's almost always thwarted by ref, and almost exclusively so.

My recent work updating LuaD to support all the features I required
wasted about 80% of my time dealing with ref issues.
In my past C++ bindings solutions, much code, which was otherwise
simple, readable, and elegant, turned into a mess of text mixins,
almost exclusively because ref is broken.


 2. I feel it's a big mistake to separate it from the type system,
 which I think most agree, is D's greatest asset by far. Manipulating
 types is simple and convenient using the type system, and I think
 manipulating scope will be just as important as any other attribute as
 soon as even slightly complex use cases begin to arise.


 Consider a ref counted type, RC!T. If scope were transitive, then you could
 not have, say, a tree where the edges were RC!T. I.e., the payload of an RC
 type should not be forced to be scope.

I'm not sure I quite visualise this correctly...

It sounds like you're talking about the same problem where people
complain with respect to 'const' and you happily tell them to stop
whingeing and deal with it?
(FWIW, I think you made the right call on const. It's never caused me
any hair loss.)

So you're saying that a pointer itself shouldn't be able to escape a
call tree, but the thing it points to should be able to escape just
fine?
It feels like that kinda defeats the purpose... or at least makes the
concept about as reliable as 'const' is in C++.

I guess you're seeing a situation where 'scope' is almost exclusively
useful as a mechanism to tell the RC that it doesn't need to worry
about ref-fiddling, and the thing we're passing isn't interested in
scope restrictions at any level other than that RC optimisation?
I guess I can see your angle... but my reaction is if that's all you
are concerned about, maybe scope is the wrong tool for eliding ref
fiddling in that case :/

I can see how you arrived at the opinion from your other comment
(wherever it was) that you are kinda likening this whole problem to
the RC case, if that's how you're looking at it.
It sounds like what you want is something like head-scope, in the same
way that people often want head-const?


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Manu via Digitalmars-d
On 12 December 2014 at 08:53, John Colvin via Digitalmars-d
digitalmars-d@puremagic.com wrote:
 On Thursday, 11 December 2014 at 21:41:11 UTC, Walter Bright wrote:

 On 12/11/2014 4:47 AM, Manu via Digitalmars-d wrote:

 On 8 December 2014 at 07:29, Walter Bright via Digitalmars-d
 digitalmars-d@puremagic.com wrote:

 On 12/7/2014 6:12 AM, Dicebot wrote:


 But from existing cases it doesn't seem working good enough. For
 example,
 not
 being able to represent idiom of `scope ref int foo(scope ref int x) {
 return x;
 }` seems very limiting.



   scope ref int foo(ref int x);

 will do it.


 Will it? It looks like foo can't be called with scope data?


 Yes, it can be.


 I don't have the perfect proposal, but I feel very strongly about 2
 things:
 1. It must not be a storage class; the concept was a disaster with
 ref, and I struggle with this more frequently than any other 'feature'
 in D.


 I simply do not understand why distinguishing beteen ref and not-ref is a
 cornerstone of everything you do.


 Because he requires control over function ABIs for both inter-language
 communication and performance.

 In binding D to IDL (Interactive Data, not Interface Description) I found
 ref often required special casing.

Thank you. I feel like I'm just repeating myself over and over again.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Manu via Digitalmars-d
On 12 December 2014 at 22:18, via Digitalmars-d
digitalmars-d@puremagic.com wrote:
 On Friday, 12 December 2014 at 08:42:22 UTC, Manu via Digitalmars-d wrote:

 How can a member be marked scope? Apparently it's a storage class, not
 a type constructor... we can only attribute storage classes to
 function args/results(?).


 I was talking about my proposal here, where it's a type modifier, not a
 storage class.

Oh okay. Is that still on the table?


 deadalnix also brought up the problem of transitivity. This, too, would
 simply go away if it's a type modifier.

Just for clarity, does type modifier mean the same thing as type constructor?


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread via Digitalmars-d
On Friday, 12 December 2014 at 12:34:40 UTC, Manu via 
Digitalmars-d wrote:

On 12 December 2014 at 22:18, via Digitalmars-d
digitalmars-d@puremagic.com wrote:
On Friday, 12 December 2014 at 08:42:22 UTC, Manu via 
Digitalmars-d wrote:


How can a member be marked scope? Apparently it's a storage 
class, not

a type constructor... we can only attribute storage classes to
function args/results(?).



I was talking about my proposal here, where it's a type 
modifier, not a

storage class.


Oh okay. Is that still on the table?


Dunno, maybe? DIP69 doesn't look very well-received at the 
moment...





deadalnix also brought up the problem of transitivity. This, 
too, would

simply go away if it's a type modifier.


Just for clarity, does type modifier mean the same thing as 
type constructor?


Yes. Type modifier = const, shared, immutable, etc.; type 
constructor = the syntactical construct by which a type is 
constructed/modified. Andrei suggested this differentiation some 
time ago (sorry, don't have a reference at hand).


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread deadalnix via Digitalmars-d

On Friday, 12 December 2014 at 12:34:40 UTC, Manu via
Digitalmars-d wrote:
deadalnix also brought up the problem of transitivity. This, 
too, would

simply go away if it's a type modifier.


Just for clarity, does type modifier mean the same thing as 
type constructor?


It appears to me that scopeness is a completely different beast
than type qualifier, and type qualifier won't work.

I think type modifier was just made up here. And why not ? It is
more like some metadata (lifetime) being associated with value
and symbols, like a type would, but that isn't really per se a
type as D understands it right now.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread deadalnix via Digitalmars-d

On Friday, 12 December 2014 at 13:38:10 UTC, Marc Schütz wrote:
Yes. Type modifier = const, shared, immutable, etc.; type 
constructor = the syntactical construct by which a type is 
constructed/modified. Andrei suggested this differentiation 
some time ago (sorry, don't have a reference at hand).


That won't fly. scope turtle left, type qualifier turtle right.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread deadalnix via Digitalmars-d

On Friday, 12 December 2014 at 22:05:21 UTC, Walter Bright wrote:

 forms can work, too.
No, unless we wrap every single indirection (pointer, slice, 
classes, delegates)

into a wrapper. That is not going to fly very far.


The beauty of GC is that you don't have to do any of this. To 
have safe other methods of allocation, there has to be 
annotation everywhere or use a wrapped type in the same places.


The whole point of scope is to reduce that cost, both in term of
runtime (as copy can be elided) but also on the user.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/12/2014 2:28 AM, deadalnix wrote:

On Friday, 12 December 2014 at 08:44:56 UTC, Walter Bright wrote:

On 12/12/2014 12:16 AM, deadalnix wrote:

On Friday, 12 December 2014 at 07:48:21 UTC, Walter Bright wrote:

Are you suggesting two kinds of scope - transitive and non-transitive?



Non transitive scope can be added without any language extension.


In order for it to work, the holes in the language that enabled escapes had to
be plugged. That's what this proposal does - plug the holes.



The holes covered by a non transitive scope are already undefined behavior.


Right, but since the current compiler cannot detect them, it is a hole.



ref counting is just one form of ownership.

 My point is if that works with this proposal, then the other forms can work, 
too.
No, unless we wrap every single indirection (pointer, slice, classes, delegates)
into a wrapper. That is not going to fly very far.


The beauty of GC is that you don't have to do any of this. To have safe other 
methods of allocation, there has to be annotation everywhere or use a wrapped 
type in the same places.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/12/2014 4:19 AM, Manu via Digitalmars-d wrote:

I simply do not understand why distinguishing beteen ref and not-ref is a
cornerstone of everything you do.


I've said so many times, it's the single greatest regular frustration
I encounter, by far.
That is of course a relative measure. It's not the 'cornerstone of
everything I do'; I don't start discussions about things that are not
broken and otherwise painless.
It is the thing that is *the most broken*, and leads to the most edge
cases, general bloat, and text mixins.
It comes up the most frequently, and by that metric alone, I consider
it highest priority on my list.

I've also said many times before, it possibly stems from the fact that
one of the key cornerstones of almost everything I do in D is interact
with other languages.
This is a practical reality, I can't write all my code in D, and have
mountains of existing code to interact with.
Boilerplate is the result. D has powerful systems to automate
boilerplate, like a carrot dangling right in front of my face, but
it's almost always thwarted by ref, and almost exclusively so.

My recent work updating LuaD to support all the features I required
wasted about 80% of my time dealing with ref issues.
In my past C++ bindings solutions, much code, which was otherwise
simple, readable, and elegant, turned into a mess of text mixins,
almost exclusively because ref is broken.


You've said this before, many times, but what is lacking is an explanation of 
WHY. What is the pattern, and why do you need that pattern? You say you don't 
like auto ref because it doesn't give you exact control, but what are the cases 
where auto ref is wrong?




Consider a ref counted type, RC!T. If scope were transitive, then you could
not have, say, a tree where the edges were RC!T. I.e., the payload of an RC
type should not be forced to be scope.


I'm not sure I quite visualise this correctly...


struct Tree {
   RefCount!(Tree*) left;
   RefCount!(Tree*) right;
   ...
}



So you're saying that a pointer itself shouldn't be able to escape a
call tree, but the thing it points to should be able to escape just
fine?


Yes.



It feels like that kinda defeats the purpose...


You're arguing that a data structure with only one access point is the only kind 
of data structure in use. With transitive scope, such a data structure would be 
the only one possible!




I guess you're seeing a situation where 'scope' is almost exclusively
useful as a mechanism to tell the RC that it doesn't need to worry
about ref-fiddling, and the thing we're passing isn't interested in
scope restrictions at any level other than that RC optimisation?
I guess I can see your angle... but my reaction is if that's all you
are concerned about, maybe scope is the wrong tool for eliding ref
fiddling in that case :/


'scope' is a way to say that this use of a pointer does not escape this scope. 
That is incredibly useful.


Recall my statements that pervasive refcounting is a terrible performance 
problem because of all the inc/dec? Knowing that references cannot escape means 
an inc/dec pair can be elided.




Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/12/2014 4:20 AM, Manu via Digitalmars-d wrote:

On 12 December 2014 at 08:53, John Colvin via Digitalmars-d

Because he requires control over function ABIs for both inter-language
communication and performance.

In binding D to IDL (Interactive Data, not Interface Description) I found
ref often required special casing.


Thank you. I feel like I'm just repeating myself over and over again.



Example, please.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/12/2014 2:09 PM, deadalnix wrote:

On Friday, 12 December 2014 at 22:05:21 UTC, Walter Bright wrote:

 forms can work, too.
No, unless we wrap every single indirection (pointer, slice, classes, delegates)
into a wrapper. That is not going to fly very far.


The beauty of GC is that you don't have to do any of this. To have safe other
methods of allocation, there has to be annotation everywhere or use a wrapped
type in the same places.


The whole point of scope is to reduce that cost, both in term of
runtime (as copy can be elided) but also on the user.


Yes, I do understand that :-) but currently doing a safe refcounted type is 
impossible in D. This proposal fixes that.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread deadalnix via Digitalmars-d

On Friday, 12 December 2014 at 22:34:27 UTC, Walter Bright wrote:

On 12/12/2014 2:09 PM, deadalnix wrote:
Yes, I do understand that :-) but currently doing a safe 
refcounted type is impossible in D. This proposal fixes that.


Actually, no it doesn't. It allow to ensure that this is safe,
module the RC system is the only owner.

This proposal allow for easy to use and fast RC, but certainly do
not make it safe.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread deadalnix via Digitalmars-d
On Saturday, 13 December 2014 at 00:06:18 UTC, Walter Bright 
wrote:

How not?


scope a = new Stuff();
scope b = a;

auto rc1 = RC(a);
auto rc2 = RC(b);

// Enjoy the free when it comes !


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/12/2014 2:48 PM, deadalnix wrote:

On Friday, 12 December 2014 at 22:34:27 UTC, Walter Bright wrote:

On 12/12/2014 2:09 PM, deadalnix wrote:
Yes, I do understand that :-) but currently doing a safe refcounted type is
impossible in D. This proposal fixes that.


Actually, no it doesn't. It allow to ensure that this is safe,
module the RC system is the only owner.

This proposal allow for easy to use and fast RC, but certainly do
not make it safe.


How not?


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/11/2014 10:10 PM, Dicebot wrote:

So far I tend to agree, unfortunately. Considering all provided answers and
explanations suggested semantics are simply not powerful enough to be useful
even for relatively simple idiomatic D code and with no clear way of backward
compatible improvements this DIP does not pull own weight.
Those are not scopes you are looking for


The proposal provides escape proof passing of arguments. This is necessary in 
order to make rc safe, for example.


What are you looking for?


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/11/2014 4:13 PM, deadalnix wrote:

On Thursday, 11 December 2014 at 13:55:55 UTC, Marc Schütz wrote:

On Thursday, 11 December 2014 at 12:48:05 UTC, Manu via Digitalmars-d wrote:

On 8 December 2014 at 07:29, Walter Bright via Digitalmars-d
digitalmars-d@puremagic.com wrote:

On 12/7/2014 6:12 AM, Dicebot wrote:


But from existing cases it doesn't seem working good enough. For example,
not
being able to represent idiom of `scope ref int foo(scope ref int x) {
return x;
}` seems very limiting.



 scope ref int foo(ref int x);

will do it.


Will it? It looks like foo can't be called with scope data?


This is a point that most people don't seem to understand yet, and which
wasn't obvious for me either, at the beginning:

* A `ref` parameter means that it cannot escape the function, _except_ by 
return.
* A `scope ref` parameter means that it cannot escape the function  _ever_,
not even by return.
* A `scope ref` return means that it cannot leave the current statement.

Therefore, a `scope ref` return value can be passed on to the next function as
a `ref` argument. If that function again returns a reference (even if not
explicitly designated as `scope`), the compiler will treat it as if it were
`scope ref`.



No, it understood. It is simply not useful.


The use case is described in the DIP under the 'Scope Ref' heading.



I agree, this is important. In my proposal, this works without transitivity.
The wrapper stores the pointer as a `scope` member, then by copying the
wrapper, the pointer gets copied implicitly, to which the normal scope
restrictions apply (`scope` on members means will not outlive the
aggregate). If it stored it as normal non-scope pointer, it couldn't get
assigned in the first place.


Wut ? You cante store anything with grear lifetime, including non scope things
(as they'll have infinite lifetime). Meaning the only thing you know, is that
thing are possibly scoped.

Meaning you have to assume infinite lifetime with every indirection, which make
this proposal useless.


It means you'll have to wrap the next level of indirection in a ref counting (or 
equivalent) manner.


The great thing about GC is you can leave everything to the GC. But when 
explicitly managing memory, you have to decide for EVERY pointer who owns it, 
when it can be released, etc. Having a transitive scope is NOT going to resolve 
that for you, it isn't even going to help.




Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/12/2014 4:07 PM, deadalnix wrote:

On Saturday, 13 December 2014 at 00:06:18 UTC, Walter Bright wrote:

How not?


scope a = new Stuff();
scope b = a;

auto rc1 = RC(a);
auto rc2 = RC(b);

// Enjoy the free when it comes !


RC needs to take a type as a parameter, not a symbol.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/12/2014 4:07 PM, deadalnix wrote:

On Saturday, 13 December 2014 at 00:06:18 UTC, Walter Bright wrote:

How not?


scope a = new Stuff();
scope b = a;

auto rc1 = RC(a);
auto rc2 = RC(b);

// Enjoy the free when it comes !


What's the type signature of RC ?


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread deadalnix via Digitalmars-d
On Saturday, 13 December 2014 at 00:52:46 UTC, Walter Bright 
wrote:

On 12/12/2014 4:07 PM, deadalnix wrote:
On Saturday, 13 December 2014 at 00:06:18 UTC, Walter Bright 
wrote:

How not?


scope a = new Stuff();
scope b = a;

auto rc1 = RC(a);
auto rc2 = RC(b);

// Enjoy the free when it comes !


What's the type signature of RC ?


RCWrapper!T RC(T)(scope T t) or somethign along these lines.


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/12/2014 4:59 PM, deadalnix wrote:

On Saturday, 13 December 2014 at 00:52:46 UTC, Walter Bright wrote:

On 12/12/2014 4:07 PM, deadalnix wrote:

On Saturday, 13 December 2014 at 00:06:18 UTC, Walter Bright wrote:

How not?


scope a = new Stuff();
scope b = a;

auto rc1 = RC(a);
auto rc2 = RC(b);

// Enjoy the free when it comes !


What's the type signature of RC ?


RCWrapper!T RC(T)(scope T t) or somethign along these lines.


And how does RC assign it to the wrapper? (It will fail to compile, and so won't 
be a safety hole.)


Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Manu via Digitalmars-d
On 13 December 2014 at 08:14, Walter Bright via Digitalmars-d
digitalmars-d@puremagic.com wrote:
 On 12/12/2014 4:19 AM, Manu via Digitalmars-d wrote:

 I simply do not understand why distinguishing beteen ref and not-ref is a
 cornerstone of everything you do.


 I've said so many times, it's the single greatest regular frustration
 I encounter, by far.
 That is of course a relative measure. It's not the 'cornerstone of
 everything I do'; I don't start discussions about things that are not
 broken and otherwise painless.
 It is the thing that is *the most broken*, and leads to the most edge
 cases, general bloat, and text mixins.
 It comes up the most frequently, and by that metric alone, I consider
 it highest priority on my list.

 I've also said many times before, it possibly stems from the fact that
 one of the key cornerstones of almost everything I do in D is interact
 with other languages.
 This is a practical reality, I can't write all my code in D, and have
 mountains of existing code to interact with.
 Boilerplate is the result. D has powerful systems to automate
 boilerplate, like a carrot dangling right in front of my face, but
 it's almost always thwarted by ref, and almost exclusively so.

 My recent work updating LuaD to support all the features I required
 wasted about 80% of my time dealing with ref issues.
 In my past C++ bindings solutions, much code, which was otherwise
 simple, readable, and elegant, turned into a mess of text mixins,
 almost exclusively because ref is broken.


 You've said this before, many times, but what is lacking is an explanation
 of WHY. What is the pattern, and why do you need that pattern? You say you
 don't like auto ref because it doesn't give you exact control, but what are
 the cases where auto ref is wrong?

I did just give some examples, I'll repeat; auto ref fails when the
function is extern.

It is also wrong that when I pass an int or float, it is passed by ref
instead of by value... that is never what I want!

What do you get when you take a pointer of a function with an auto-ref
arg? ...an error, because it's not actually a function!
So in a context where I'm dealing with functions and function pointers
(very, very frequent), I suddenly have something that's not a function
find it's way into my meta and I have to special-case the hell out of
it.
The solution in this case is to wrap it in a non-auto-ref shim with
the ref-ness explicitly stated in the way I expect... which is in
itself another problem, because 'ref' is not part of the type! So the
annoying de-auto-ref-ing shim must be a text mixin with some very
complex, practically unreadable, definitely unmaintainable logic
surrounding it. It's insanity on top of insanity!

I also run the invisible risk of generating 2^num_args instances of
the code for functions containing auto-ref args.

When I'm writing a function that's not a template, I intend, and
expect, to write a function that's _not a template_.
Templates and functions are different things. I think it's a massive
mistake to have created a way to write a template that looks nothing
like a template.

auto-ref is not, and never has been a tool I have wanted. I don't have
any use for auto-ref, and it has only proven to make an already severe
problem worse. I've tried to use it before in some instances, but it
made ref's out of int's and floats, so even in the rare potentially
useful cases, I had to reject it.

At the time, you introduced auto-ref as a 'solution' to an issue that
I was the primary complainant (although the solution was mainly pushed
by Andrei iirc?). I absolutely rejected it then, and said it would
have the disastrous effect of setting ref in stone, which I was
already very critical about. I reject it even more now that I have had
some experience with it.
Who was the customer that you designed it for? (It wasn't me!)
What issue was it designed to address?


 Consider a ref counted type, RC!T. If scope were transitive, then you
 could
 not have, say, a tree where the edges were RC!T. I.e., the payload of an
 RC
 type should not be forced to be scope.


 I'm not sure I quite visualise this correctly...


 struct Tree {
RefCount!(Tree*) left;
RefCount!(Tree*) right;
...
 }

... I don't think I'd ever have a use for this code.
I've been using trees for a long time, and I can't imagine a situation
where each node in a tree would want to be ref counted.
It sounds like a disaster for performance, and I can't imagine any
advantage it would offer?
Perhaps in some complex graph structure... but I expect that sort of
thing would be far more specialised.

I can see common cases where nodes may contain a refcounted object as
node data, but that's different than the situation you demonstrate
here.
I'll need to think about how that situation would be affected in this case.


 So you're saying that a pointer itself shouldn't be able to escape a
 call tree, but the thing it points to should be able to escape just
 fine?


 Yes.



Re: DIP69 - Implement scope for escape proof references

2014-12-12 Thread Walter Bright via Digitalmars-d

On 12/12/2014 6:55 PM, Manu via Digitalmars-d wrote:

I did just give some examples, I'll repeat; auto ref fails when the
function is extern.


Don't make it extern, then.



It is also wrong that when I pass an int or float, it is passed by ref
instead of by value... that is never what I want!


If there's source to the function, it'll often be inlined which will remove the 
indirection.




What do you get when you take a pointer of a function with an auto-ref
arg? ...an error, because it's not actually a function!
So in a context where I'm dealing with functions and function pointers
(very, very frequent), I suddenly have something that's not a function
find it's way into my meta and I have to special-case the hell out of
it.


Why are function pointers and ints going to the same argument of a function? I 
thought you weren't using templates?




The solution in this case is to wrap it in a non-auto-ref shim with
the ref-ness explicitly stated in the way I expect... which is in
itself another problem, because 'ref' is not part of the type! So the
annoying de-auto-ref-ing shim must be a text mixin with some very
complex, practically unreadable, definitely unmaintainable logic
surrounding it. It's insanity on top of insanity!

I also run the invisible risk of generating 2^num_args instances of
the code for functions containing auto-ref args.


I wonder what is the need for the code that you are writing.



When I'm writing a function that's not a template, I intend, and
expect, to write a function that's _not a template_.
Templates and functions are different things. I think it's a massive
mistake to have created a way to write a template that looks nothing
like a template.


A function template is a function that takes both compile-time args and run-time 
args. C++ tried to make them completely different animals, when they are not. 
Don't think template, think compile-time argument to a function. I convinced 
Andrei to never mention template in his D book, as it brings forth all kinds 
of connotations and expectations that impede understanding what D templates 
actually are. I think the result was successful.




auto-ref is not, and never has been a tool I have wanted. I don't have
any use for auto-ref, and it has only proven to make an already severe
problem worse. I've tried to use it before in some instances, but it
made ref's out of int's and floats, so even in the rare potentially
useful cases, I had to reject it.


If it's a rare useful case, why is it a pervasive problem?



At the time, you introduced auto-ref as a 'solution' to an issue that
I was the primary complainant (although the solution was mainly pushed
by Andrei iirc?). I absolutely rejected it then, and said it would
have the disastrous effect of setting ref in stone, which I was
already very critical about. I reject it even more now that I have had
some experience with it.
Who was the customer that you designed it for? (It wasn't me!)
What issue was it designed to address?


I still have no idea what code you are developing that you need to send ints and 
function pointers to the same argument of a function template, yet you don't use 
function templates. Nor do I understand what pattern you need that simply must 
mix up ref and value parameters, and why that pattern appears pervasively in 
your code.




struct Tree {
RefCount!(Tree*) left;
RefCount!(Tree*) right;
...
}


... I don't think I'd ever have a use for this code.


You have no use for tree structures?



I've been using trees for a long time, and I can't imagine a situation
where each node in a tree would want to be ref counted.


You have more than one parent of a node. You never write data structures like 
that? dmd uses such pervasively (Type and Expression).




It sounds like a disaster for performance, and I can't imagine any
advantage it would offer?


How do you propose to manage the memory explicitly otherwise? Use a GC? :-)



I can see common cases where nodes may contain a refcounted object as
node data, but that's different than the situation you demonstrate
here.


That would fail if scope were transitive.



But there are more things than pointers which need to be protected
against escaping their scope, in particular, things that contain
pointers...


Solve it in the general case (this proposal) and RC now works.



Maybe there's a compromise. If we say scope isn't 'transitive', but it
is transitive when it comes to aggregates?


One thing I've tried very hard to make work in D is have basic types / 
aggregages / arrays be interchangeable.




Ie, you can apply scope to a by-val struct, and all aggregate members
have scope applied.
It is not transitive in the sense that it does not follow through
pointer members, but any such pointer members may not escape as if it
were a pointer argument alone.

This is unlike any other behaviour in D, but without that, I think
this proposal fails to suit my most common use cases.


I have no idea what your 

Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread deadalnix via Digitalmars-d
On Thursday, 11 December 2014 at 07:30:03 UTC, Walter Bright 
wrote:

On 12/10/2014 8:56 PM, deadalnix wrote:
On Thursday, 11 December 2014 at 03:27:08 UTC, Walter Bright 
wrote:
I disagree. It's critical for chaining one function to the 
next.


I one can't return, one can't chain.


I guess I'm not seeing the problem.


a.foo().bar() is the same as bar(foo(a)), that is, using the 
returned value as first parameter. If you can't return, you can't 
chain.


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread ketmar via Digitalmars-d
On Wed, 10 Dec 2014 23:06:13 -0800
Shammah Chancellor via Digitalmars-d digitalmars-d@puremagic.com
wrote:

  Was afraid that would break too much code.
 No, this is super important.  Break it all!
alas, not in this life. each break our code just making resistance
harder. ;-)


signature.asc
Description: PGP signature


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread Walter Bright via Digitalmars-d

On 12/10/2014 11:55 PM, deadalnix wrote:

On Thursday, 11 December 2014 at 07:30:03 UTC, Walter Bright wrote:

On 12/10/2014 8:56 PM, deadalnix wrote:

On Thursday, 11 December 2014 at 03:27:08 UTC, Walter Bright wrote:

I disagree. It's critical for chaining one function to the next.


I one can't return, one can't chain.


I guess I'm not seeing the problem.


a.foo().bar() is the same as bar(foo(a)), that is, using the returned value as
first parameter. If you can't return, you can't chain.


Right, and you can chain when the declarations are:

scope ref S foo(ref T a);
U bar(ref S s);

a.foo().bar(); // works


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread Walter Bright via Digitalmars-d

On 12/10/2014 10:43 PM, Dicebot wrote:

On Thursday, 11 December 2014 at 03:30:07 UTC, Walter Bright wrote:

If you want data to 'escape' from r.front, then it shouldn't be marked as
scope. Definitely, using scope successfully will require some rethinking of
how code is written.


Allowing or prohibiting escaping of r.front in that example depends on
definition of mapped range. There is nothing to rethink about it - case is
almost identical to const+inout.


One reason why with templates, they'll do scope inference.


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread via Digitalmars-d

On Thursday, 11 December 2014 at 00:35:46 UTC, deadalnix wrote:
It is always safe to consider scopeness of the retrun value (if 
marked scope) as being the intersection of the lifetime of 
parameters.


That should cover most bases, and we can still extends later if 
this is too limited (I suspect it is ok for most cases).


Linear typing is already extremely limiting, by limiting it even 
further you end up with something annoying. You basically get a 
version of memory safety that does not solve any typical memory 
unsafe situations.


By having pointers that do scope-depth-tracking you do at least 
get a generic solution that can be optimized away when possible. 
The D authors have to accept that you need to embed ownership in 
pointers if you want memory safety and convenience, or that you 
have to provide means to guide the semantic analysis. You need 
one or the other, or both, but you cannot pretend that you can do 
without.


Arbitrary constraints are annoying, not convenient. If I as a 
programmer know that something is safe, then the compiler should 
accept it, and the language should allow me express it.


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread zeljkog via Digitalmars-d

On 11.12.14 08:25, Shammah Chancellor wrote:

This is exactly why this feature should be default behavior with
compiler warnings generated when things escape scope.



It can be compiler switch escape=I(gnore)|W(arning)|E(rror).



Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread zeljkog via Digitalmars-d

On Thursday, 4 December 2014 at 10:00:37 UTC, Walter Bright wrote:

On 12/4/2014 1:51 AM, eles wrote:


Making it implicit and requiring an explicit escape for 
un-scoped variables?




Was afraid that would break too much code.


Compiler switch: escape=I(gnore)|W(arning)|E(rror).
For transition default Ignore.


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread Manu via Digitalmars-d
On 8 December 2014 at 07:29, Walter Bright via Digitalmars-d
digitalmars-d@puremagic.com wrote:
 On 12/7/2014 6:12 AM, Dicebot wrote:

 But from existing cases it doesn't seem working good enough. For example,
 not
 being able to represent idiom of `scope ref int foo(scope ref int x) {
 return x;
 }` seems very limiting.


   scope ref int foo(ref int x);

 will do it.

Will it? It looks like foo can't be called with scope data?


 I also don't consider `ref` design as a storage class any kind of success
 at all
 and generally agree with Manu on this topic. At the same time alternative
 proposals that make it a qualifier (like Marc did) do impact existing
 language
 much more and this no small concern.


 My experience with C++ ref as type qualifier is very, very bad. It's a
 special case EVERYWHERE. Doing type deduction with it is an exercise in a
 completely baffling set of rules and a different rule for every occasion -
 Scott Meyers has a great piece on this.

 There are probably only a handful of people on the planet who actually
 understand C++ ref. I wished very hard to avoid that with D ref.

I do completely sympathise with you on this point. I understand where
you were coming from on 'ref', and I do applaud the effort. Nobody
said that ref should be just the same as C++, but I am saying that the
D solution is not a success.
I'm all about a ref that improves on C++, but I don't think that's
what we have. We have something that's just complex and unwieldy in a
different (and for my money, even more frustrating) way.

I'm just saying, don't repeat that mistake with scope! There must be
another way...

I'm also quite uneasy with the fact that scope would not be transitive
as a storage class. What happens when it's applied to a value type,
like a struct, that contains some pointers? An adaptation wrapper for
a single pointer is super common; ie, a tiny struct passed by value
with scope needs to have it's contained pointer receive the scope-ness
of the argument.

I don't have the perfect proposal, but I feel very strongly about 2 things:
1. It must not be a storage class; the concept was a disaster with
ref, and I struggle with this more frequently than any other 'feature'
in D.
2. I feel it's a big mistake to separate it from the type system,
which I think most agree, is D's greatest asset by far. Manipulating
types is simple and convenient using the type system, and I think
manipulating scope will be just as important as any other attribute as
soon as even slightly complex use cases begin to arise.


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread ixid via Digitalmars-d
Manu have you shown Walter some of the code where ref is 
problematic? He seems to have asked to see examples repeatedly as 
he's not convinced there is a problem.


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread Nick Treleaven via Digitalmars-d
On 11/12/2014 09:07, Ola Fosheim Grøstad 
ola.fosheim.grostad+dl...@gmail.com wrote:

If I as a programmer know that something is safe, then the compiler
should accept it, and the language should allow me express it.


It will, use @system. Maybe this proposal will be supplemented later, 
but there are always costs to making the language more complicated. We 
need to be certain they are worth it before adding them. A cautious 
approach can be extended later, if the situation demands it.


Sometimes innovative workarounds are developed that are difficult to 
foresee in advance - e.g. in Rust their type system can be restrictive, 
but they rely on trusted library functions/types to make more things 
possible in a safe way.


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread via Digitalmars-d
On Thursday, 11 December 2014 at 12:48:05 UTC, Manu via 
Digitalmars-d wrote:

On 8 December 2014 at 07:29, Walter Bright via Digitalmars-d
digitalmars-d@puremagic.com wrote:

On 12/7/2014 6:12 AM, Dicebot wrote:


But from existing cases it doesn't seem working good enough. 
For example,

not
being able to represent idiom of `scope ref int foo(scope ref 
int x) {

return x;
}` seems very limiting.



  scope ref int foo(ref int x);

will do it.


Will it? It looks like foo can't be called with scope data?


This is a point that most people don't seem to understand yet, 
and which wasn't obvious for me either, at the beginning:


* A `ref` parameter means that it cannot escape the function, 
_except_ by return.
* A `scope ref` parameter means that it cannot escape the 
function  _ever_, not even by return.
* A `scope ref` return means that it cannot leave the current 
statement.


Therefore, a `scope ref` return value can be passed on to the 
next function as a `ref` argument. If that function again returns 
a reference (even if not explicitly designated as `scope`), the 
compiler will treat it as if it were `scope ref`.


I'm also quite uneasy with the fact that scope would not be 
transitive
as a storage class. What happens when it's applied to a value 
type,
like a struct, that contains some pointers? An adaptation 
wrapper for
a single pointer is super common; ie, a tiny struct passed by 
value
with scope needs to have it's contained pointer receive the 
scope-ness

of the argument.


I agree, this is important. In my proposal, this works without 
transitivity. The wrapper stores the pointer as a `scope` member, 
then by copying the wrapper, the pointer gets copied implicitly, 
to which the normal scope restrictions apply (`scope` on members 
means will not outlive the aggregate). If it stored it as 
normal non-scope pointer, it couldn't get assigned in the first 
place. (Additionally, some higher level tricks are possible if we 
allow scope for value types and overloading on scope.)


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread Nick Treleaven via Digitalmars-d

On 09/12/2014 16:25, Steven Schveighoffer wrote:

Will ref just automatically bind to any scoped reference?


A ref parameter essentially is a scope ref parameter, but it can also be 
returned:

http://forum.dlang.org/post/m64v3g$2bga$1...@digitalmars.com


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread John Colvin via Digitalmars-d

On Thursday, 11 December 2014 at 13:55:55 UTC, Marc Schütz wrote:
On Thursday, 11 December 2014 at 12:48:05 UTC, Manu via 
Digitalmars-d wrote:

On 8 December 2014 at 07:29, Walter Bright via Digitalmars-d
digitalmars-d@puremagic.com wrote:

On 12/7/2014 6:12 AM, Dicebot wrote:


But from existing cases it doesn't seem working good enough. 
For example,

not
being able to represent idiom of `scope ref int foo(scope 
ref int x) {

return x;
}` seems very limiting.



 scope ref int foo(ref int x);

will do it.


Will it? It looks like foo can't be called with scope data?


This is a point that most people don't seem to understand yet, 
and which wasn't obvious for me either, at the beginning:


* A `ref` parameter means that it cannot escape the function, 
_except_ by return.
* A `scope ref` parameter means that it cannot escape the 
function  _ever_, not even by return.
* A `scope ref` return means that it cannot leave the current 
statement.


Therefore, a `scope ref` return value can be passed on to the 
next function as a `ref` argument. If that function again 
returns a reference (even if not explicitly designated as 
`scope`), the compiler will treat it as if it were `scope ref`.




OH! I had totally misunderstood that. Cheers for the explanation.


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread via Digitalmars-d
On Thursday, 11 December 2014 at 13:43:07 UTC, Nick Treleaven 
wrote:

It will, use @system.


Yes…

Maybe this proposal will be supplemented later, but there are 
always costs to making the language more complicated. We need 
to be certain they are worth it before adding them. A cautious 
approach can be extended later, if the situation demands it.


Can it be extended later? Without breaking stuff?

You need to get it right from the start, otherwise you end up 
with N different, but incompatible ways of doing the same thing. 
That means you need to get ownership right first.


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread bearophile via Digitalmars-d

Nick Treleaven:

Sometimes innovative workarounds are developed that are 
difficult to foresee in advance - e.g. in Rust their type 
system can be restrictive, but they rely on trusted library 
functions/types to make more things possible in a safe way.


Ideally a type system should be flexible enough, in practice 
giving it a high flexibility has significant costs (in 
compilation times, amount of code that implements the system, 
bugs in such implementation, costs for the final programmer in 
inventing a way to express the semantics, etc), so most languages 
avoid a too much complex type system (even Haskell does this) and 
accept reasonable workarounds...


Bye,
bearophile


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread Steven Schveighoffer via Digitalmars-d
On 12/11/14 8:55 AM, Marc =?UTF-8?B?U2Now7x0eiI=?= schue...@gmx.net 
wrote:

On Thursday, 11 December 2014 at 12:48:05 UTC, Manu via Digitalmars-d
wrote:

On 8 December 2014 at 07:29, Walter Bright via Digitalmars-d
digitalmars-d@puremagic.com wrote:

On 12/7/2014 6:12 AM, Dicebot wrote:


But from existing cases it doesn't seem working good enough. For
example,
not
being able to represent idiom of `scope ref int foo(scope ref int x) {
return x;
}` seems very limiting.



  scope ref int foo(ref int x);

will do it.


Will it? It looks like foo can't be called with scope data?


This is a point that most people don't seem to understand yet, and which
wasn't obvious for me either, at the beginning:

* A `ref` parameter means that it cannot escape the function, _except_
by return.
* A `scope ref` parameter means that it cannot escape the function
_ever_, not even by return.
* A `scope ref` return means that it cannot leave the current statement.

Therefore, a `scope ref` return value can be passed on to the next
function as a `ref` argument. If that function again returns a reference
(even if not explicitly designated as `scope`), the compiler will treat
it as if it were `scope ref`.


Please, put this in the DIP! This is exactly the thing I had been asking 
for here: http://forum.dlang.org/post/m5sitd$1ki0$1...@digitalmars.com


Thanks, I'll re-read the proposal with this in mind.

-Steve


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread Walter Bright via Digitalmars-d

On 12/11/2014 8:26 AM, Steven Schveighoffer wrote:

Please, put this in the DIP! This is exactly the thing I had been asking for
here: http://forum.dlang.org/post/m5sitd$1ki0$1...@digitalmars.com

Thanks, I'll re-read the proposal with this in mind.


Marc is clearly better at explaining things than I am, as I've explained that 
point in this thread about 5 times now.


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread Walter Bright via Digitalmars-d

On 12/11/2014 4:47 AM, Manu via Digitalmars-d wrote:

On 8 December 2014 at 07:29, Walter Bright via Digitalmars-d
digitalmars-d@puremagic.com wrote:

On 12/7/2014 6:12 AM, Dicebot wrote:


But from existing cases it doesn't seem working good enough. For example,
not
being able to represent idiom of `scope ref int foo(scope ref int x) {
return x;
}` seems very limiting.



   scope ref int foo(ref int x);

will do it.


Will it? It looks like foo can't be called with scope data?


Yes, it can be.



I don't have the perfect proposal, but I feel very strongly about 2 things:
1. It must not be a storage class; the concept was a disaster with
ref, and I struggle with this more frequently than any other 'feature'
in D.


I simply do not understand why distinguishing beteen ref and not-ref is a 
cornerstone of everything you do.




2. I feel it's a big mistake to separate it from the type system,
which I think most agree, is D's greatest asset by far. Manipulating
types is simple and convenient using the type system, and I think
manipulating scope will be just as important as any other attribute as
soon as even slightly complex use cases begin to arise.


Consider a ref counted type, RC!T. If scope were transitive, then you could not 
have, say, a tree where the edges were RC!T. I.e., the payload of an RC type 
should not be forced to be scope.




Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread Dmitry Olshansky via Digitalmars-d

12-Dec-2014 00:41, Walter Bright пишет:

On 12/11/2014 4:47 AM, Manu via Digitalmars-d wrote:

On 8 December 2014 at 07:29, Walter Bright via Digitalmars-d
digitalmars-d@puremagic.com wrote:



I don't have the perfect proposal, but I feel very strongly about 2
things:
1. It must not be a storage class; the concept was a disaster with
ref, and I struggle with this more frequently than any other 'feature'
in D.


I simply do not understand why distinguishing beteen ref and not-ref is
a cornerstone of everything you do.



I would hazard a guess that const T is something lots of C++ got 
addicted to as the most common way of parameter passing. There is 
nothing exactly like that in D, auto ref was quite close but only for 
templates and it instantiates 2 distinct bodies for ref and non-ref at 
the moment.


It allows easy pass by ref for both r-values and l-values with logical 
const and is likely what Manu is referring(!) to.


Truth be told it's not always the fastest way, in fact Boost C++ has 
template for optimal parameter passing - call_traitsT::param_type  but 
it must be too cumbersome for actual use as I never seen it used in the 
wild.

http://www.boost.org/doc/libs/1_57_0/libs/utility/call_traits.htm

--
Dmitry Olshansky


Re: DIP69 - Implement scope for escape proof references

2014-12-11 Thread John Colvin via Digitalmars-d
On Thursday, 11 December 2014 at 21:41:11 UTC, Walter Bright 
wrote:

On 12/11/2014 4:47 AM, Manu via Digitalmars-d wrote:

On 8 December 2014 at 07:29, Walter Bright via Digitalmars-d
digitalmars-d@puremagic.com wrote:

On 12/7/2014 6:12 AM, Dicebot wrote:


But from existing cases it doesn't seem working good enough. 
For example,

not
being able to represent idiom of `scope ref int foo(scope 
ref int x) {

return x;
}` seems very limiting.



  scope ref int foo(ref int x);

will do it.


Will it? It looks like foo can't be called with scope data?


Yes, it can be.


I don't have the perfect proposal, but I feel very strongly 
about 2 things:
1. It must not be a storage class; the concept was a disaster 
with
ref, and I struggle with this more frequently than any other 
'feature'

in D.


I simply do not understand why distinguishing beteen ref and 
not-ref is a cornerstone of everything you do.


Because he requires control over function ABIs for both 
inter-language communication and performance.


In binding D to IDL (Interactive Data, not Interface Description) 
I found ref often required special casing.


  1   2   3   >