this() not executing code on structs

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Thu Oct 22 11:01:34 PDT 2009


grauzone wrote:
> Andrei Alexandrescu wrote:
>> grauzone wrote:
>>> dsimcha wrote:
>>>> == Quote from grauzone (none at example.net)'s article
>>>>> Andrei Alexandrescu wrote:
>>>>> I'd really like to know why "scope x = new X();" is "unsafe", while
>>>>> encouraging doing exactly the same with structs seems to be a 
>>>>> perfectly
>>>>> fine idea. Allocating structs on the stack is obviously not any safer
>>>>> than with classes. I don't remember the exact reasons why you 
>>>>> wanted to
>>>>> turn "scope" into a library feature, but I think I remember something
>>>>> about discouraging it for safety reasons; please forgive me is this is
>>>>> wrong.
>>>>
>>>> Because classes in D are always passed by pointer.  (Technically 
>>>> references, but
>>>> really they're just pointers under the hood.)  Returning a scope 
>>>> (stack-allocated)
>>>> class from a function is equivalent to escaping a pointer to a stack 
>>>> variable.
>>>> Returning a struct is done by value, just like returning an int.
>>>
>>> (I'm talking about scope classes as declared in "scope class T { ... }")
>>>
>>> But you can't return scope classes from a function. You can't pass 
>>> them as ref parameters either. They're designed to be safe.
>>
>> I wish it was as easy as it sounds. In fact you don't need to pass 
>> scope classes as ref parameters - it's enough to pass them "by value" 
>> because they are implicitly references.
>>
>> You can't even safely call a method on a scope class object because 
>> that method may assign "this" to something escaping the scope of the 
>> method.
>>
>> Save for using some flavor of interprocedural escape analysis and/or 
>> making "scope" a function attribute, I'm not seeing how scope can be 
>> made safe and reasonably useful.
> 
> OK, but the user of that class is still forced to use it safely. It's 
> the implementor's responsibility to make sure he doesn't to unsafe 
> things. It's the same with structs, at least in normal D (not SafeD).
> 
>>> On the other hand, you can pass struct pointers all the way you want 
>>> around, and it's damn unsafe.
>>>
>>> I don't get this "structs are safe because they are value types" 
>>> argument anyway, because the this pointer for structs is a 
>>> pointer/reference anyway. If it's trivial to break that "safety", can 
>>> you really call it "safety"?
>>
>> The point is that you can disable address taking altogether and still 
>> write a great deal of good code in D. If address taking is verboten 
>> (e.g. in SafeD), ref parameters can never be escaped (they will be 
>> scoped) and therefore they become safe, too. So within SafeD, structs 
>> become safe, but scope class objects still couldn't be made safe 
>> without heroic effort.
> 
> I wonder about that. How will the following example will be made safe? 
> Right now, ref parameters _can_ escape with the help of ref returns.
> 
> import std.stdio;
> 
> ref int foo(ref int z, int something) {
>     return z;
> }
> 
> ref int foo2() {
>     int u = 123;
>     return foo(u, 0);
> }
> 
> void main() {
>     writefln("%s", foo(foo2(), {char[20] tmp;  return 0; }()));
> }
> 
> It's probably not minimal, but it demonstrates how you can return 
> references to outdated stack locations without explicitly taking 
> pointers. That delegate literal overwrites the stack, so that writefln 
> outputs garbage.
> 
> How to solve this? Disallow ref arguments or ref returns in SafeD, 
> because they are hidden "address taking"?
> 
> Or is this all besides the point?

It's right to the point. I keep on forgetting about that corner case, 
Steve pointed it to me a long time ago. In the call foo(u, 0) the 
compiler must conservatively assume that the scope of the returned value 
is the same as the scope of u, and therefore disallow compilation of foo2.


Andrei



More information about the Digitalmars-d mailing list