auto ref is on the docket
kinke via Digitalmars-d
digitalmars-d at puremagic.com
Sat Jun 27 06:46:26 PDT 2015
On Saturday, 27 June 2015 at 11:10:49 UTC, Marc Schütz wrote:
> On Saturday, 27 June 2015 at 01:18:19 UTC, Jonathan M Davis
> wrote:
>> That's a completely orthogonal issue to ref or auto ref.
>> That's an @system operation (since taking the address of a
>> local variable is @system), and it's up to you to not screw it
>> up. scope might cover that if it were fully ironed out, since
>> that does involve escaping, but it also might not, since it's
>> an @system operation and thus up to you not to screw it up.
>
> The point is that with scope, it _doesn't_ need to be @system
> anymore.
>
>> Regardless, it has nothing to do with whether the function
>> accepts lvalues and rvalues with the same parameter. You have
>> a safety issue regardless if you're talking about taking a
>> pointer to an argument (or to some portion of the argument),
>> since there's no guarantee that the lifetime of the pointer is
>> shorter than that of the argument.
>
> No, not with scope. [...] the problems you mention will no
> longer exist with scope.
Exactly, that's the whole point.
The relation with lvalue/rvalue reference parameters is that the
compiler should be able to statically detect and refuse escaping
rvalue bugs. Escaping lvalues with potential for dangling
pointers should be @system only, but preventing those bugs is a
whole different beast.
Still, to make (a) taking the address of ref params, locals &
globals and (b) using pointer params @safe, the compiler needs to
know whether the parameter escapes or not. I tend to let the
compiler figure that out in the future rather than having to use
`scoped` a lot for ref and pointer params.
>> We introduced the return attribute (currently only with
>> -dip25) to fix this problem. So, with that, we eliminate the
>> safety problem with ref itself, and we can safely have auto
>> ref accept rvalues by having it assign them to a temporary
>> variable first.
>
> Yes this is now possible, but why in all world do you want the
> keyword that enables it to be `auto ref`?
Exactly. For a function returning a ref parameter, it doesn't
matter whether it's an rvalue or lvalue. The important thing is
to propagate that distinction (automatically by the compiler), to
disallow binding a returned rvalue reference to an escaping ref
parameter (i.e., no `escape(forward(S(1)))`).
Where the distinction between lvalues and rvalues matters for a
function returning a ref parameter, as for any other function
with ref params, is whether the parameter escapes (i.e., by
storing a pointer somewhere). If it does, it should be `return
ref`, otherwise `return scope ref` (either explicitly or inferred
automatically by the compiler).
>> Any issues with taking pointers to arguments is firmly in
>> @system territory and is thus completely orthogonal. Even if
>> scope were to be implemented in a way that prevented it, it
>> would still have nothing to do with whether the function
>> accepted both rvalues and lvalues with the same parameter.
Of course it would if one made actually use of a scope system
(again, either explicit or as a result of compiler escape
analysis) to (a) rule out all escaping rvalue bugs and (b)
possibly warn about or highlight escaping lvalue params in
@system code. The main aim of the scope system would be to
enhance the flexibility of @safe code though.
>>> In the meantime, what about making all `ref` params accept
>>> rvalues
>>
>> Please, please, no. ref indicates that your intention is to
>> mutate the argument. Having it accept rvalues completely
>> destroys that and makes it that much harder to understand what
>> a function is supposed to do.
If that was the only reason for not accepting rvalues as `ref`
params, then rvalues should have been allowed for `const ref`
right from the beginning, as there's surely absolutely no
intention to mutate a `const ref` argument.
> I can accept that argument, although I see cases where it's
> still justified. For example, if the author of the function
> decided it wants to mutate the argument, but you (the caller)
> are not interested in the new value. But still, explicitly
> using a temporary named `dummy` is preferable because it even
> documents that you're going to ignore it.
I find letting the callee decide whether the caller needs to
provide an lvalue (`ref`) or not (non-templated `auto ref`),
based solely on making sure the mutations are directly visible by
the caller after the call, too much. I think it should be left to
the caller to decide what mutations it's interested in.
But now I see why some would oppose calling that `scope ref`, as
that really has nothing to do with scope or safety, that'd just
be an arbitrary way of classifying ref params in 'essential
output' (mutable lvalue `ref`s, mutations need to be visible by
caller) and some other category (lvalue/rvalue `auto ref`s, not
just for efficiency purposes). That really is an orthogonal and
incompatible semantic compared to what `scope ref` is all about,
and doesn't interest me at all. I find flexible @safe code and
detecting escaping bugs a kazillion times more important than
making sure a caller sees all mutations the callee deems
essential after the call.
More information about the Digitalmars-d
mailing list