Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.
/ druntime Public archive

Comments

Add scope to invertCompToken#3472

Merged
dlang-bot merged 1 commit intodlang:stablefrom
dkorpel:dassert-scope
May 14, 2021
Merged

Add scope to invertCompToken#3472
dlang-bot merged 1 commit intodlang:stablefrom
dkorpel:dassert-scope

Conversation

@dkorpel
Copy link
Contributor

@dkorpel dkorpel commented May 14, 2021

It gets called from _d_assert_fail with a scope string. The reason it currently compiles is because it's pure, so Issue 20150 applies. Blocker for dlang/dmd#12010.

@dlang-bot
Copy link
Contributor

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 verify that your PR follows this checklist:

  • My PR is fully covered with tests (you can see the coverage diff by visiting the details link of the codecov check)
  • My PR is as minimal as possible (smaller, focused PRs are easier to review than big ones)
  • I have provided a detailed rationale explaining my changes
  • New or modified functions have Ddoc comments (with Params: and Returns:)

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 references

Your 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 locally

If 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Contributor

@MoonlightSentinel MoonlightSentinel May 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume it works here because the array is assigned to a scope parameter and hence promoted to the stack.

Copy link
Contributor Author

@dkorpel dkorpel May 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume it works here because the array is assigned to a scope parameter 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 */
}

Copy link
Contributor

@MoonlightSentinel MoonlightSentinel May 14, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I put the operator in the middle argument of combine, side-stepping the issue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Btw nice catch @aG0aep6G! I think the relevant bugzilla issue is this:
https://issues.dlang.org/show_bug.cgi?id=20505

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants