Andrei Alexandrescu wrote:
grauzone wrote:
dsimcha wrote:
== Quote from grauzone (n...@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?

(Hello world doesn't compile with -safe (Phobos issue), so I couldn't test it with -safe on dmd v2.032.)


Andrei

Reply via email to