Bug 18282 – [Scope][DIP1000]Assignment of local variable to `scope` variable not recognized by compiler
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2018-01-23T01:50:21Z
Last change time
2018-03-18T23:23:19Z
Keywords
safe
Assigned to
No Owner
Creator
Mike Franklin
Comments
Comment #0 by slavo5150 — 2018-01-23T01:50:21Z
void main() @safe
{
string foo = "foo";
scope string*[] ls;
ls ~= &foo;
}
Compile with `-dip1000`
onlineapp.d(5): Error: reference to local variable foo assigned to non-scope ls
https://run.dlang.io/is/ecYAKZ
The compiler doesn't seem to recognize that ls is attributed with `scope`. However due to the way D's attributes are parsed, I'm not sure if it should actually be `scope string*[]`, `scope(string*)[]`, or `scope(string*[])`. Anyway, if you use `scope()` (i.e. with parens) the compiler confuses it with `scope(exit)` and friends.
void main() @safe
{
string foo = "foo";
scope(string*[]) ls;
ls ~= &foo;
}
Compile with `-dip1000`
onlineapp.d(4): Error: valid scope identifiers are exit, failure, or success, not string
https://run.dlang.io/is/ecYAKZ
Comment #1 by bugzilla — 2018-03-12T03:32:22Z
(In reply to Mike Franklin from comment #0)
> void main() @safe
> {
> string foo = "foo";
> scope string*[] ls;
> ls ~= &foo;
> }
>
> Compile with `-dip1000`
>
> onlineapp.d(5): Error: reference to local variable foo assigned to non-scope
> ls
While ls is scope, ls[] is not scope. Scope is not transitive, hence the compiler error.
> The compiler doesn't seem to recognize that ls is attributed with `scope`.
> However due to the way D's attributes are parsed, I'm not sure if it should
> actually be `scope string*[]`, `scope(string*)[]`, or `scope(string*[])`.
> Anyway, if you use `scope()` (i.e. with parens) the compiler confuses it
> with `scope(exit)` and friends.
>
>
> void main() @safe
> {
> string foo = "foo";
> scope(string*[]) ls;
> ls ~= &foo;
> }
>
> Compile with `-dip1000`
>
> onlineapp.d(4): Error: valid scope identifiers are exit, failure, or
> success, not string
Scope is a storage class, not a type constructor. (`const`, for example, is a type constructor, and `static` is a storage class.)
Comment #2 by ag0aep6g — 2018-03-12T11:20:25Z
(In reply to Walter Bright from comment #1)
> (In reply to Mike Franklin from comment #0)
> > void main() @safe
> > {
> > string foo = "foo";
> > scope string*[] ls;
> > ls ~= &foo;
> > }
> >
> > Compile with `-dip1000`
> >
> > onlineapp.d(5): Error: reference to local variable foo assigned to non-scope
> > ls
>
> While ls is scope, ls[] is not scope. Scope is not transitive, hence the
> compiler error.
I assume that you don't mean `ls[]` literally, but rather that the elements of `ls` aren't `scope`, right?
That means, it should be okay to return `ls[0]` because that's not `scope`, right? But that doesn't work:
----
string* f() @safe
{
scope string*[] ls;
return ls[0]; /* Error: scope variable ls may not be returned */
}
----
On the other hand, this works:
----
void main() @safe
{
string foo = "foo";
scope string*[] ls;
ls = ls ~ &foo;
}
----
The only difference from the original code is `ls ~= &foo;` -> `ls = ls ~ &foo;`. Those two assignments should be equivalent [1], no? Either both should be accepted, or both should be rejected.
[1] https://dlang.org/spec/expression.html#assignment_operator_expressions
(In reply to Walter Bright from comment #4)
> https://github.com/dlang/dmd/pull/8030
That seems to have fixed this snippet from comment #2:
----
string* f() @safe
{
scope string*[] ls;
return ls[0];
}
----
But the original test case still fails:
----
void main() @safe
{
string foo = "foo";
scope string*[] ls;
ls ~= &foo; /* Error. But this works: ls = ls ~ &foo; */
}
----
Looks like the actual issue hasn't been fixed. Reopening.