On 10/18/2012 10:08 AM, Don Clugston wrote:
On 17/10/12 18:02, Timon Gehr wrote:
On 10/17/2012 01:49 PM, Don Clugston wrote:
...

That's the point -- *which* checks are missing from @safe?

Escaping stack data and arbitrarily freeing memory are not operations
found in memory safe languages.

HOW do you propose to check for escaping stack data?


Static escape analysis. Use the 'scope' qualifier to designate
data that is not allowed to be escaped in order to make it modular.

...

The implementation of the 'scope' storage class should be fixed. We
could then require an unsafe cast(scope) to disable prevention of stack
address escaping.

No we can't. f cannot know that the string it has been given is on the
stack. So main() must prevent it from being given to f() in the first
place. How can it do that?


f can know that it mustn't escape it, which is enough.

void foo(bool b, string y)
{
   immutable (char)[4] x = "abba";
   string s = b ? x : y;
   f(s);
}

Make it safe.


It is safe if the parameter to f is marked with 'scope'. (and this in
turn obliges f not to escape it.)

Analyze scope on the expression level.

The analysis would determine that x[] is 'scope'. It would
conservatively propagate this fact to (b ? x[] : y). Then the local
variable 's' will get the 'scope' storage class.

In general, use a fixed-point iteration to determine all local
variables that might refer to scope'd data and prevent that they get
escaped.


Rust's borrowed pointers may give some hints on how
to extend 'scope' to fields of structs.

I think it is more fundamental than that.

As to delete, delete is as unsafe when the involved data is immutable
as when it is mutable. Why require an additional cast in one case?

This is not about safety.
Modifying immutable data breaks the type system. Deleting mutable data
does not.
AFAIK it is safe to implement delete as a call to the
finalizer, followed by setting the memory to T.init.
...


Now I see where you are coming from. This is indeed a safe approach for
references to/arrays of fully mutable value types, but not for delete
in general.

Make sure to treat void* specially though.

struct S{ immutable int x; this(int x){this.x=x;}}

void main()@safe{
    void* s = new S(2);
    delete s;
}

Class instance memory does not have a T.init, because it is not
assigned a T. And even if it was, how would you know at compile time if
the bound instance has any immutable fields?
Should that be a runtime exception?

Reply via email to