| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,216 @@ | ||
| /* | ||
| REQUIRED_ARGS: -transition=safe | ||
| PERMUTE_ARGS: | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/retscope.d(23): Error: scope variable p may not be returned | ||
| fail_compilation/retscope.d(33): Error: escaping reference to local variable j | ||
| fail_compilation/retscope.d(46): Error: scope variable p assigned to non-scope q | ||
| fail_compilation/retscope.d(48): Error: cannot take address of local i in @safe function test2 | ||
| fail_compilation/retscope.d(49): Error: variadic variable a assigned to non-scope b | ||
| fail_compilation/retscope.d(50): Error: reference to stack allocated value returned by (*fp2)() assigned to non-scope q | ||
| --- | ||
| */ | ||
|
|
||
|
|
||
|
|
||
|
|
||
| int* foo1(return scope int* p) { return p; } // ok | ||
|
|
||
| int* foo2()(scope int* p) { return p; } // ok, 'return' is inferred | ||
| alias foo2a = foo2!(); | ||
|
|
||
| int* foo3(scope int* p) { return p; } // error | ||
|
|
||
| int* foo4(bool b) | ||
| { | ||
| int i; | ||
| int j; | ||
|
|
||
| int* nested1(scope int* p) { return null; } | ||
| int* nested2(return scope int* p) { return p; } | ||
|
|
||
| return b ? nested1(&i) : nested2(&j); | ||
| } | ||
|
|
||
| /************************************************/ | ||
|
|
||
| struct S2 { int a,b,c,d; } | ||
|
|
||
| @safe S2 function() fp2; | ||
|
|
||
| void test2(scope int* p, int[] a ...) @safe | ||
| { | ||
| static int* q; | ||
| static int[] b; | ||
| q = p; | ||
| int i; | ||
| q = &i; | ||
| b = a; | ||
| q = &fp2().d; | ||
| } | ||
|
|
||
| /**************************************************/ | ||
|
|
||
| /* | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/retscope.d(76): Error: function retscope.HTTP.Impl.onReceive is @nogc yet allocates closures with the GC | ||
| fail_compilation/retscope.d(78): retscope.HTTP.Impl.onReceive.__lambda1 closes over variable this at fail_compilation/retscope.d(76) | ||
| --- | ||
| */ | ||
|
|
||
|
|
||
| struct Curl | ||
| { | ||
| int delegate() dg; | ||
| } | ||
|
|
||
| struct HTTP | ||
| { | ||
| struct Impl | ||
| { | ||
| Curl curl; | ||
| int x; | ||
|
|
||
| @nogc void onReceive() | ||
| { | ||
| auto dg = ( ) { return x; }; | ||
| curl.dg = dg; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /***********************************************/ | ||
|
|
||
| /* | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/retscope.d(97): Error: reference to local variable sa assigned to non-scope parameter a calling retscope.bar8 | ||
| --- | ||
| */ | ||
| // https://issues.dlang.org/show_bug.cgi?id=8838 | ||
|
|
||
| int[] foo8() @safe | ||
| { | ||
| int[5] sa; | ||
| return bar8(sa); | ||
| } | ||
|
|
||
| int[] bar8(int[] a) @safe | ||
| { | ||
| return a; | ||
| } | ||
|
|
||
|
|
||
| /*************************************************/ | ||
|
|
||
| /* | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/retscope.d(124): Error: escaping reference to local variable tmp | ||
| --- | ||
| */ | ||
|
|
||
| char[] foo9(char[] a) @safe pure nothrow @nogc | ||
| { | ||
| return a; | ||
| } | ||
|
|
||
| char[] bar9() @safe | ||
| { | ||
| char[20] tmp; | ||
| foo9(tmp); // ok | ||
| return foo9(tmp); // error | ||
| } | ||
|
|
||
| /*************************************************/ | ||
|
|
||
| /* | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/retscope.d(143): To enforce @safe compiler allocates a closure unless the opApply() uses 'scope' | ||
| --- | ||
| */ | ||
|
|
||
| struct S10 | ||
| { | ||
| static int opApply(int delegate(S10*) dg); | ||
| } | ||
|
|
||
| S10* test10() | ||
| { | ||
| foreach (S10* m; S10) | ||
| return m; | ||
| return null; | ||
| } | ||
|
|
||
| /************************************************/ | ||
|
|
||
| /* | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/retscope.d(159): Error: scope variable this may not be returned | ||
| --- | ||
| */ | ||
|
|
||
| class C11 | ||
| { | ||
| @safe C11 foo() scope { return this; } | ||
| } | ||
|
|
||
|
|
||
| /****************************************************/ | ||
|
|
||
| /* | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/retscope.d(178): Error: address of variable i assigned to p with longer lifetime | ||
| --- | ||
| */ | ||
|
|
||
|
|
||
|
|
||
| void foo11() @safe | ||
| { | ||
| int[] p; | ||
| int[3] i; | ||
| p = i[]; | ||
| } | ||
|
|
||
| /************************************************/ | ||
| /* | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/retscope.d(198): Error: scope variable e may not be returned | ||
| --- | ||
| */ | ||
|
|
||
| struct Escaper | ||
| { | ||
| void* DG; | ||
| } | ||
|
|
||
| void* escapeDg1(scope void* d) @safe | ||
| { | ||
| Escaper e; | ||
| e.DG = d; | ||
| return e.DG; | ||
|
There was a problem hiding this comment. Interesting, how does this work @WalterBright? Does the field get tainted by the assignment of a scoped value? There was a problem hiding this comment. Assignment to s.field is the same as an assignment to s, as far as scope rules go. |
||
| } | ||
|
|
||
| /*************************************************/ | ||
| /* | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/retscope.d(213): Error: scope variable p assigned to non-scope e | ||
| --- | ||
| */ | ||
| struct Escaper3 { void* e; } | ||
|
|
||
| void* escape3 (scope void* p) @safe { | ||
| Escaper3 e; | ||
| scope dg = () { return e.e; }; | ||
| e.e = p; | ||
| return dg(); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| /* REQUIRED_ARGS: -dip25 -transition=safe | ||
| PERMUTE_ARGS: | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/test14238.d(21): Error: scope variable fn may not be returned | ||
| fail_compilation/test14238.d(29): Error: escaping reference to stack allocated value returned by &baz | ||
| --- | ||
| */ | ||
| // https://issues.dlang.org/show_bug.cgi?id=14238 | ||
|
|
||
| @safe: | ||
|
|
||
| alias Fn = ref int delegate(); | ||
|
|
||
| ref int foo(return scope Fn fn) | ||
| { | ||
| return fn(); // Ok | ||
| } | ||
|
|
||
| ref int foo2(scope Fn fn) { | ||
| return fn(); // Error | ||
| } | ||
|
|
||
| ref int bar() { | ||
| int x; | ||
| ref int baz() { | ||
| return x; | ||
| } | ||
| return foo(&baz); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| /* | ||
| REQUIRED_ARGS: -transition=safe | ||
| PERMUTE_ARGS: | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/test15544.d(21): Error: reference to local this assigned to non-scope _del in @safe code | ||
| fail_compilation/test15544.d(23): Error: reference to local this assigned to non-scope _del in @safe code | ||
| --- | ||
| */ | ||
|
|
||
| // https://issues.dlang.org/show_bug.cgi?id=15544 | ||
|
|
||
| void delegate() @safe _del; | ||
|
|
||
| struct S { | ||
| int x = 42; | ||
|
|
||
| @safe void test() | ||
| { | ||
| void foo() { assert(x == 42); } | ||
| _del = &foo; | ||
|
|
||
| _del = { assert(x == 42); }; | ||
| } | ||
| } | ||
|
|
||
| /* | ||
| TEST_OUTPUT: | ||
| --- | ||
| fail_compilation/test15544.d(47): Error: reference to local y assigned to non-scope dg in @safe code | ||
| --- | ||
| */ | ||
|
|
||
| int delegate() dg; | ||
|
|
||
| void testClosure1() | ||
| { | ||
| int* x; | ||
| int bar() { return *x; } | ||
| dg = &bar; | ||
| } | ||
|
|
||
| @safe void testClosure2() | ||
| { | ||
| scope int* y; | ||
| int bar() { return *y; } | ||
| dg = &bar; // Error | ||
| auto dg2 = &bar; | ||
| } | ||
|
|
||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2783,7 +2783,7 @@ struct S9985 | |
|
|
||
| static void* ptr; | ||
| } | ||
| auto ref makeS9985() @system | ||
| { | ||
| S9985 s; | ||
| s.b = s.buf.ptr; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't this unset STCreturn if that doesn't apply?