D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 7347 - scope attribute destruction & allocation issues
Summary: scope attribute destruction & allocation issues
Status: RESOLVED WORKSFORME
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-01-22 09:15 UTC by Denis Shelomovskii
Modified: 2022-08-16 10:44 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Denis Shelomovskii 2012-01-22 09:15:25 UTC
---
import std.stdio;

class C {
    int n;
    this(int n) { writefln(" this(%s) at %s", this.n = n, cast(void*)this); }
    ~this() { writefln("~this(%s) at %s", n, cast(void*)this); }
}

void main() {
    int i;
    writefln("Stack is at %s", &i);
    writefln("Heap  is at %s", (new void[1]).ptr);
    {
        C cHeap = new C(0); // will be destroyed on scope exit
        scope C c0 = cHeap;

        // C(1)-C(4) will be allocated in heap
        // C(1), C(2), and C(4) will be destroyed on scope exit
        // C(3) will be destroyed on garbage collection
        scope C c1 = cast(C)cast(void*)new C(1);
        scope C c2 = true ? new C(2) : null;
        scope C c3 = (new C(3), new C(4));
    }
    writefln("after scope");
}
---
As a result even if `C` is a `scope class` the program will compile without
`cHeap` and `c0`, but every `C` instance will be allocated in heap and C(3)
will be destroyed on garbage collection.
Comment 1 RazvanN 2022-08-16 10:44:56 UTC
(In reply to Denis Shelomovskii from comment #0)
> ---
> import std.stdio;
> 
> class C {
>     int n;
>     this(int n) { writefln(" this(%s) at %s", this.n = n, cast(void*)this); }
>     ~this() { writefln("~this(%s) at %s", n, cast(void*)this); }
> }
> 
> void main() {
>     int i;
>     writefln("Stack is at %s", &i);
>     writefln("Heap  is at %s", (new void[1]).ptr);
>     {
>         C cHeap = new C(0); // will be destroyed on scope exit
>         scope C c0 = cHeap;
> 
>         // C(1)-C(4) will be allocated in heap
>         // C(1), C(2), and C(4) will be destroyed on scope exit
>         // C(3) will be destroyed on garbage collection
>         scope C c1 = cast(C)cast(void*)new C(1);
>         scope C c2 = true ? new C(2) : null;
>         scope C c3 = (new C(3), new C(4));
>     }
>     writefln("after scope");
> }
> ---
> As a result even if `C` is a `scope class` the program will compile without
> `cHeap` and `c0`, but every `C` instance will be allocated in heap and C(3)
> will be destroyed on garbage collection.

The code now allocates C(0) and C(1) on the heap and C(2) on the stack. I could not test C(3) and C(4) since comma expressions are no longer supported. I think that this behavior is fine since a scope class does not necessarily mean that it will be allocated on the stack. The spec specifically tells "When a class is constructed with new and assigned to a local scope variable, it may be allocated on the stack and permitted in a @nogc context." [1]. Since the compiler does not do any dataflow analysis, it is hard to understand whether rhs directly calls new or it does other shenanigans (like the casts in the c1 initialization).

Therefore, I think that this bug report is invalid at this point. 

[1] https://dlang.org/spec/attribute.html#scope-class-var