Conversation
|
Thanks for your pull request and interest in making D better, @dkorpel! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.
Please see CONTRIBUTING.md for more information. If you have addressed all reviews or aren't sure how to proceed, don't hesitate to ping us with a simple comment. Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. Testing this PR locallyIf you don't have a local development environment setup, you can use Digger to test this PR: dub run digger -- build "stable + druntime#3472" |
|
|
||
| // Inverts a comparison token for use in _d_assert_fail | ||
| private string invertCompToken(string comp) pure nothrow @nogc @safe | ||
| private string invertCompToken(scope string comp) pure nothrow @nogc @safe |
There was a problem hiding this comment.
I'm not sure if this should compile. Later in the function, we have [comp]. I.e., comp is copied to the heap. Usually, that's not allowed for scope variables.
There was a problem hiding this comment.
I assume it works here because the array is assigned to a scope parameter and hence promoted to the stack.
There was a problem hiding this comment.
The [comp] is passed to parameter const scope string[] valB of combine, so the literal is allocated on the stack
Edit: that's what Florian said, didn't see his message when I posted
There was a problem hiding this comment.
I assume it works here because the array is assigned to a
scopeparameter and hence promoted to the stack.
That might be DMD's reasoning. But it's unsound. It actually doesn't matter if the array is on the heap or on the stack. A scope is being lost.
comp.ptr is a scope pointer. valB.ptr is also a scope pointer. valB[0].ptr is not a scope pointer, because scope is not transitive. So valB = [comp]; cannot be allowed. It's assigning a scope pointer to a non-scope pointer.
Reduced code demonstrating memory corruption:
string invertCompToken(scope string comp) @safe
{
return combine([comp]); /* Should not compile. */
}
string combine(const scope string[] valB) @safe
{
return valB[0];
}
string f() @safe
{
immutable char[3] eq = "foo";
return invertCompToken(eq);
}
void main() @safe
{
import std.stdio;
string s = f();
writeln(s); /* prints garbage */
}There was a problem hiding this comment.
Fair enough, that's just another oddity of scope not being transitive.
But there's no corruption here because combine doesn't escape the string. So it should be fine to wrap the call in a @trusted lambda to avoid future problems.
EDIT: The current solution is even better
There was a problem hiding this comment.
I put the operator in the middle argument of combine, side-stepping the issue.
There was a problem hiding this comment.
Btw nice catch @aG0aep6G! I think the relevant bugzilla issue is this:
https://issues.dlang.org/show_bug.cgi?id=20505
It gets called from
_d_assert_failwith ascopestring. The reason it currently compiles is because it's pure, so Issue 20150 applies. Blocker for dlang/dmd#12010.