ref is unsafe
Nick Treleaven
ntrel-public at yahoo.co.uk
Mon Dec 31 06:44:56 PST 2012
On 30/12/2012 22:01, Jonathan M Davis wrote:
> On Sunday, December 30, 2012 17:32:40 Nick Treleaven wrote:
>> I think the compiler needs to be able to mark foo as a function that
>> returns its input reference. Then, any arguments to foo that are locals
>> should cause an error at the call site (e.g. in baz). So legal calls to
>> foo can always be @safe.
>>
>> To extend the above code:
>>
>> ref int quux(ref int i)
>> {
>> return foo(i);
>> }
>>
>> Here the compiler already knows that foo returns its input reference. So
>> it checks whether foo is being passed a local - no; but it also has to
>> check if foo is passed any ref parameters of quux, which it is. The
>> compiler now has to mark quux as a function that returns its input
>> reference.
>>
>> Works?
>
> No. There's no guarantee that the compiler has access to the function's body,
> and the function being called could be compiled after the function which calls
> it. There's a reason that attribute inferrence only works with templated
> functions. In every other case, the programmer has to mark it. We're _not_
> going to get any kind inferrence without templates. D's compilation model
> doesn't allow it.
I was aware attributes would be needed for .di files. I suppose
attribute inference for non-template functions is not doable.
> The closest that we could get to what you suggest would be to add a new
> attribute similar to nothrow but which guarantees that the function does not
> return a ref to a parameter. So, you'd have to mark your functions that way
> (e.g. with @norefparamreturn). Maybe the compiler could infer it for templated
> ones, but this attribute would basically have to work like other inferred
> attributes and be marked manually in all other cases. Certainly, you can't
> have the compiler figuring it out for you in general, because D's compilation
> model allows the function being called to be compiled separately from (and
> potentially after) the function calling it.
As you suggested below that, I would have the attribute mean the
opposite, @refparamreturn. Functions that need it but don't have it can
be detected by recompiling them. The syntax could be 'in ref':
in ref int quux(ref int i);
> And when you think about what this attribute would be needed for, it gets a
> bit bizarre to have it. The _only_ time that it's applicable is when a
> function takes an argument by ref and returns the same type by ref. In all
> other cases, the compiler can guarantee it just based on the type system.
As jerro and Michel Fortin pointed out, 'in ref' would be needed for
returning input struct members, and capturing inputs with delegates and
slices. So the feature might pull its weight.
I think detecting all these situations would be essentially the same as
the checks needed for a scope parameter, so if/when scope parameters get
implemented, 'in ref' might not be hard to bolt on.
If a simpler solution doesn't disallow any sensible uses of ref returns,
that would be preferable. But I don't think we've found it yet.
> I suppose that we could have an attribute that indicated that a function _did_
> return a ref to one of its params and then have the compiler give an error if
> it were missing, which means that the foo function
>
> ref int foo(ref int i)
> {
> return i;
> }
>
> would end up with an error for not having the attribute, whereas a function
> like baz
>
> ref int baz(int i)
> {
> return foo(i);
> }
>
> would not end up with the error unless foo had the attribute on it. But that's
> very different from any attribute that we currently have. It would be like
> having a throw attribute instead of a nothrow attribute. I suppose that it is
> a possible solution though. I could also see an argument that the attribute
> should go on the parameter rather than the function, in which case you could
> have more fine-grained control over it, but it does complicate things further.
I suppose a parameter attribute might be useful to allow passing locals
to other ref parameters which aren't returned, and as documentation.
More information about the Digitalmars-d
mailing list