Const ref and rvalues again...

Jonathan M Davis jmdavisProg at gmx.com
Sat Nov 10 11:07:56 PST 2012


On Saturday, November 10, 2012 13:21:42 Manu wrote:
> I'm still not buying this. Here's a common struct I will pass by ref
> (perhaps the most common struct in my industry):
> 
> struct Vector { float, x,y,z,w; }
> struct Matrix { Vector xRow, yRow, zRow, wRow; }
> 
> Vector mul( scope const ref Matrix m, scope const Vector v)
> {
>   Vector v;
>   // perform a matrix multiply against the vector...
>   // this work uses every single field of the inputs given, but the result
> it produces has to references to the sources.
>   // everything is operated on and copied to the output struct, which is
> returned.
>   return result;
> }
> 
> Why should this be a problem?
> The majority of my work-horse structs apply to this pattern. This is what I
> imagine 'scope' to be for...
> The main advantage I expect is that I can have confidence that passing
> rvalues (temporaries) is safe, and that external code won't take references
> to memory that I may not own/control. Is that not the point?
> 
> Surely the problem that scope should be protecting against is a pointer to
> any part of the argument escaping. *Copies* of values contained in the
> argument/s are fine.

Hmmmm. scope on value types is pointless, because there are no references to 
escape, but if you pass by ref, then it does become possible for a pointer to 
the argument to escape, but I don't know that that's actually actually covered 
by scope. The description for scope in docs is that "ref­er­ences in the pa­
ra­me­ter can­not be es­caped (e.g. as­signed to a global vari­able)." And 
taking the address of a local variable (which is the only way that any sort of 
reference to the data could escape) is never @safe anyway. If you passed in a 
pointer, and scope were fully working, then you'd be protected against the 
pointer escaping, but passing by ref isn't really the same thing. I'd have 
thought that taking the address of a variable passed by ref would fall into 
pretty much the same camp as taking the address of any other local variable, 
which is completely unsafe to escape to the point that I'm not sure that 
there's any point in protecting against it. It's just completely stupid to do 
anyway and is definitely @system. Outside of taking the address of a ref 
parameter, taking the address of a local variable and escpaing it is _always_ 
going to result in garbage, and ref parameters aren't really references in the 
normal sense, so I don't know.

You bring up a good point, but I don't know if it's applicable. Certainly, 
without the ref there (like is the case with the Vector that you're passing 
in), scope would never do anything, because it doesn't even theoretically have 
anything to do. It's purely a value type that's not even being passed by ref.

In general though, putting scope on struct parameters would cause a lot of 
problems, because of arrays that they might hold and whatnot. Slices wouldn't 
be able to escape (and so copies of the struct wouldn't be able escape without 
deep copying, let alone the array itself). So, while scope may be very useful 
in some such cases (assuming that it worked), it's not necessarily something 
that you'd want as a matter of course. Part of it probably depends on your 
programming style though. If you have a lot of functions that take arguments 
and don't return anything that was in them ever, then scope is less of a big 
deal, but that's the sort of thing that happens a _lot_ in my experience, so 
scope would very quickly become extremely annoying.

And actually, to make matters worse, I'm not sure that scope on delegates is 
working correctly. I thought that it was, but this code compiles:

import std.stdio;

void delegate() global;

void foo(scope void delegate() del)
{
    global = del;
}

void main()
{
    {
        char[5] bar = "hello";
        foo((){writeln(bar);});
    }
    char[7] baz = "goodbye";

    global();
}

It also prints out "hello", and if a closure had not been allocated, I would 
have at least half-expected it to print out "goodb", because I'd have thought 
that baz would have been taking up the same memory that bar had been. So, it 
looks like scope may be completely and utterly broken at this point. I don't 
know.

- Jonathan M Davis


More information about the Digitalmars-d mailing list