D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 12936 - Some more @nogc cases for immediately iterated array literal
Summary: Some more @nogc cases for immediately iterated array literal
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 enhancement
Assignee: No Owner
URL:
Keywords: pull
Depends on:
Blocks:
 
Reported: 2014-06-16 16:59 UTC by bearophile_hugs
Modified: 2022-08-25 10:59 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 bearophile_hugs 2014-06-16 16:59:06 UTC
This is a spinoff of Issue 12932


See this code:


struct F { int x; }
void main() @nogc {
    foreach (       a; [F(1)]) {}           // Case#1 OK
    foreach (int[1] a; [[1]]) {}            // Case#2 Error
    foreach (const ref int[1] a; [[1]]) {}  // Case#3 Error
    foreach (       a; [[1]]) {}            // Case#4 Error
}



With dmd2.066alpha gives:

test.d(4,25): Error: array literal in @nogc function main may cause GC allocation
test.d(5,5): Error: argument type mismatch, int[] to ref const(int[1])
test.d(6,25): Error: array literal in @nogc function main may cause GC allocation


Currently the Case#1 works. I think Case#2 could work because it's supposed to be a dynamic array of int[1] values.

I am not sure we can also support the Case#4, this is more complex, and perhaps needs escape analisys. So not supporting Case#4 is acceptable for now.

Case#4 currently doesn't even compile even without @nogc, but perhaps it should without @nogc.
Comment 1 bearophile_hugs 2015-03-11 09:53:40 UTC
A different case where the compiler should avoid heap allocations and allow @nogc:


void main() @nogc {
    int[3] a;
    a[] = [1, 2, 3];
    a[0 .. 2] = [1, 2];
}


temp.d(3,11): Error: array literal in @nogc function main may cause GC allocation
temp.d(4,17): Error: array literal in @nogc function main may cause GC allocation
Comment 2 Kenji Hara 2016-05-19 13:05:57 UTC
(In reply to bearophile_hugs from comment #0)
> 
> struct F { int x; }
> void main() @nogc {
>     foreach (       a; [F(1)]) {}           // Case#1 OK
>     foreach (int[1] a; [[1]]) {}            // Case#2 Error
>     foreach (const ref int[1] a; [[1]]) {}  // Case#3 Error
>     foreach (       a; [[1]]) {}            // Case#4 Error
> }

For case#2, it's possible enhancement because int[1] a is a copy of iterated array literal element.

For case#3, it's not safe because an address of stack allocated array literal can escape out of the lifetime.

    const(int)* p;
    foreach (const ref int[1] a; [[1]]) { p = &a[0]; }
    // After the foreach, p wold point invalid stack address.

Note that similar situation is properly rejected.

    void foo(ref int[1] sa) {}
    void main() {
        foo([1]);   // array literal never become stack allocated because
                    // its address can escape out via the ref parameter.
    }

For case#4 supporting it would cause inconsistent type inference result.

    void foo() {
        foreach (a; [[1]]) { pragma(msg, typeof(a)); }  // prints int[]
    }
    void bar() @nogc {
        foreach (a; [[1]]) { pragma(msg, typeof(a)); }  // prints int[] or int[1]?
    }

I opened a compiler improvement for case#2:
https://github.com/dlang/dmd/pull/5795
Comment 3 github-bugzilla 2016-08-10 17:52:31 UTC
Commits pushed to master at https://github.com/dlang/dmd

https://github.com/dlang/dmd/commit/6a48d5bb77be35a3778c7ad673333de232b2e9c8
Issue 12936 - Some more @nogc cases for immediately iterated array literal

Support case#2 in bugzilla.

https://github.com/dlang/dmd/commit/46c35125b335354077c11973389c7e82686036ff
Merge pull request #5795 from 9rnsr/fix12936

Issue 12936 - Some more @nogc cases for immediately iterated array literal
Comment 4 github-bugzilla 2016-10-01 11:48:25 UTC
Commits pushed to stable at https://github.com/dlang/dmd

https://github.com/dlang/dmd/commit/6a48d5bb77be35a3778c7ad673333de232b2e9c8
Issue 12936 - Some more @nogc cases for immediately iterated array literal

https://github.com/dlang/dmd/commit/46c35125b335354077c11973389c7e82686036ff
Merge pull request #5795 from 9rnsr/fix12936