Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uncontrollable blitting should be preventable for proper elaborate copy semantics #19633

Open
dlangBugzillaToGithub opened this issue Oct 25, 2019 · 3 comments

Comments

@dlangBugzillaToGithub
Copy link

Suleyman Sahmi (سليمان السهمي) reported this on 2019-10-25T22:33:26Z

Transferred from https://issues.dlang.org/show_bug.cgi?id=20321

CC List

  • kinke

Description

The same symptoms of issue #17448 but with copy semantics as well.

Even though D supports elaborate copy with the copy constructor and the postblit, the compiler(s) still move(s) objects in certain cases in an unpreventable manner, which blocks certain practices that require strict copy control such as saving internal pointers.

Following is an example which fails on DMD, GDC, and LDC as of date.

Note that every case in the following example is a copy operation not a move, i.e the source is an lvalue.

https://run.dlang.io/is/qomDRU

```
/** Container with internal pointer
 */
struct Container
{
    long[3] data;
    void* p;

    this(int) { p = &data[0]; }
    this(ref inout Container) inout { p = &data[0]; }

    /** Ensure the internal pointer is correct */
    void check(int line = __LINE__, string file = __FILE__)()
    {
        if (p != &data[0])
        {
            import core.stdc.stdio : printf;
            printf("%s(%d): %s
", file.ptr, line, "error".ptr);
        }
    }
}

void func(Container c) { c.check(); } // error

Container get()
{
    auto a = Container(1);
    auto b = a;
    a.check(); // ok
    b.check(); // ok
    // no nrvo
    if (1)
        return a;
    else
        return b;
}

Container get2()
out(r){}
do
{
    auto v = Container(1);
    v.check(); // ok
    return v;
}

void main()
{
    Container v = Container(1);
    v.check(); // ok

    func(v);
    auto r = get();
    r.check(); // error

    auto r2 = get2();
    r.check(); // error

    Container[1] slit = [v];
    slit[0].check(); // error

    Container[] dlit = [v];
    dlit[0].check(); // error

    auto b = B(v);
    b.m.check(); // error
}

struct B
{
    Container m;
}
```

output:
---
test.d(22): error
test.d(53): error
test.d(56): error
test.d(59): error
test.d(62): error
test.d(65): error
---

expected: no output
@dlangBugzillaToGithub
Copy link
Author

kinke commented on 2019-10-26T02:30:08Z

Thx, I've just hacked LDC to get this testcase green (on Win64 at least): https://github.com/ldc-developers/ldc/pull/3204

@dlangBugzillaToGithub
Copy link
Author

sahmi.soulaimane commented on 2019-10-26T03:26:48Z

DMD PR https://github.com/dlang/dmd/pull/10510

@dlangBugzillaToGithub
Copy link
Author

dlang-bot commented on 2019-11-20T22:37:29Z

@SSoulaimane updated dlang/dmd pull request #10539 "Fix the concat assign case of Issue 20321 in a frontend solution" mentioning this issue:

- Issue 20321 - Move CatElemAssign logic to the frontend
  
  Solves one of the cases of issue 20321 which wasn't straight forward to solve in the backend since elablorate copy semantics are currently understood by the semantic phase only.
  
  See issues 17448 and 20321.
  
  The problem is solved by avoiding `doCopyOrMove()` which only partially helps the backend with elaborate copy.
  
  This goes hand in hand with the effort being spent on templatizing druntime, this benefit from that effort actually.

https://github.com/dlang/dmd/pull/10539

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant