DIP69 - Implement scope for escape proof references

Walter Bright via Digitalmars-d digitalmars-d at puremagic.com
Fri Dec 12 21:11:04 PST 2014


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 use cases are, but when you're explicitly managing 
memory, every damn pointer needs to be carefully evaluated as to what exactly 
it's pointing two and who owns it. Scope is not a magic solution to this, 
neither is shared_ptr, neither are Rust's annotations.

The only scheme that absolves the user of having to deal with this is - GC.



More information about the Digitalmars-d mailing list