Bug 17763 – [scope][DIP1000] The compiler treats implicit and explicit static array slicing differently

Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2017-08-19T16:56:56Z
Last change time
2017-08-27T02:26:29Z
Keywords
accepts-invalid, rejects-valid, safe
Assigned to
No Owner
Creator
ZombineDev

Comments

Comment #0 by petar.p.kirov — 2017-08-19T16:56:56Z
The problem is that the compiler disallows explicitly slicing a static array and passing the slice to a scope parameter, while if you rely on the implicit slicing it works without a problem. To reproduce: $ cat > scope_bug.d << DBUG @safe: struct Context { char[] str; } void use(scope Context[] c) { } void main() { char[1] s = '@'; Context[1] c; c[0].str = s; // <- If this line is commented, it all works. c[0] = Context(s); // <- this has the same effect as above. use(c); // OK - this compiles. use(c[]); // NG - doesn't compile, though should be // equivalent to the statement above. } DBUG $ dmd -dip1000 scope_bug.d scope_bug.d(11): Error: cannot take address of scope local c in @safe function main $ dmd --version DMD64 D Compiler v2.076.0-b1-master-32bb4ed
Comment #1 by petar.p.kirov — 2017-08-19T18:17:15Z
While previous case was rejects-valid, here's a similar one where the compile accepts invalid code: $ cat > scope_bug2.d << DBUG @safe: struct Context { char[] str; } void main() { Context[1] c; use(c); } Context[] global; void use(scope ref Context[1] c) { // global = c[]; // OK - this does not compile. global = c; // NG - this does compile, but it should not // as it is equivalent to the one above. } DBUG $ dmd -dip1000 scope_bug2.d $ echo $? 0
Comment #2 by bugzilla — 2017-08-27T00:08:32Z
(In reply to ZombineDev from comment #1) > While previous case was rejects-valid, here's a similar one where the > compile accepts invalid code: Reducing the case to: struct Context { char[] str; } void main() { Context[1] c; use(c); } Context[] global; void use(scope ref Context[1] c) @safe { global = c[]; global = c; } and compiling with no flags: test1.d(13): Error: address of variable c assigned to global with longer lifetime test1.d(14): Error: address of variable c assigned to global with longer lifetime compiling with -dip1000: test1.d(13): Error: cannot take address of scope parameter c in @safe function use test1.d(14): Error: address of variable c assigned to global with longer lifetime The different messages are because of the different order things happen due to the rewriting. But the error messages are still there and are correct. Perhaps you're testing with an older compiler?
Comment #3 by bugzilla — 2017-08-27T02:26:29Z
(In reply to ZombineDev from comment #0) > The problem is that the compiler disallows explicitly slicing a static array > and passing the slice to a scope parameter, while if you rely on the > implicit slicing it works without a problem. Let's examine: > use(c); // OK - this compiles. The address of c is implicitly taken by its coercion to the parameter type of Context[]. But this is allowed because the parameter is 'scope', and it cannot escape. > use(c[]); // NG - doesn't compile, though should be > // equivalent to the statement above. What's happening here is the semantic analysis is bottom up, meaning `c[]` is evaluated without regard to what context it appears in. The compiler doesn't see that the result is being passed as `scope`, and so assumes the worst, and issues an error. It is not a bug in the compiler. Trying to add some form of top down in addition to bottom up is a huge increase in complexity, and will produce all kinds of weird corner cases. You can reopen it as an enhancement request if you prefer, but I don't think it is practical to implement at least in the near future.