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

Fix Issue 23337 - Wrongly elided postblit/copy ctor for array construction (_d_arrayctor lowering) #14442

Merged
merged 2 commits into from Oct 6, 2022

Conversation

kinke
Copy link
Contributor

@kinke kinke commented Sep 15, 2022

No description provided.

@dlang-bot
Copy link
Contributor

Thanks for your pull request and interest in making D better, @kinke! 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

Auto-close Bugzilla Severity Description
23337 regression Wrongly elided postblit/copy ctor for array construction (_d_arrayctor lowering)

⚠️⚠️⚠️ Warnings ⚠️⚠️⚠️

To target stable perform these two steps:

  1. Rebase your branch to upstream/stable:
git rebase --onto upstream/stable upstream/master
  1. Change the base branch of your PR to stable

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 "master + dmd#14442"

// only non-trivial array constructions may need to be lowered (non-POD elements basically)
Type t1e = t1b.nextOf();
TypeStruct ts = t1e.baseElemOf().isTypeStruct();
if (!ts || (!ts.sym.postblit && !ts.sym.hasCopyCtor && !ts.sym.dtor))
Copy link
Member

Choose a reason for hiding this comment

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

Isn't this just the same logic as isPOD?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Almost, and I don't really like this 'optimization' either: #14372 (comment) - especially after noticing yesterday that the same bug fixed in that PR (missing check for copy ctor) still holds for array assignments:

if (!ts || (!ts.sym.postblit && !ts.sym.dtor))

if (!ts || (!ts.sym.postblit && !ts.sym.hasCopyCtor && !ts.sym.dtor))
return setResult(res);
// don't lower ref-constructions etc.
if (!(t1b.ty == Tsarray || ae.e1.isSliceExp) ||
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The tests currently only test the static-array LHS case. I'm not sure about this isSliceExp check - do we really have ConstructExp with a slice[] LHS?

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

int[4] b = [1, 2, 3, 4];
struct A
{
    int[4] a;
    
    this(int c)
    {
        a[0 .. 4] = b;   
    }
}

Technically, a[0 .. 4] = b; should be a construct expression.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, even a[] = b is a construct expression. This is what isSliceExp is for.

// If ae.e2 is not a variable, construct a temp variable, as _d_arraysetctor requires `ref` access
if (!ae.e2.isVarExp)
// promote an rvalue RHS element to a temporary, it's passed by ref to _d_arraysetctor
if (!ae.e2.isLvalue)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

[This change is tested in line 66 (S[3] fromSingleLval = *p;), getting rid of an extra copy if the RHS is a non-var lvalue.]

@RazvanN7
Copy link
Contributor

@kinke why is this still a draft? Looks ready to me.

@kinke
Copy link
Contributor Author

kinke commented Sep 29, 2022

I'm on vacation and will get back to this, adding a test for the slice-exp lhs.

@kinke kinke marked this pull request as ready for review October 3, 2022 22:23
@kinke
Copy link
Contributor Author

kinke commented Oct 3, 2022

Okay, added the slice-expression LHS tests - which immediately showed a little regression in my previous logic, triggered by earlier implicit casts from static arrays to slices - so I'm afraid the overall logic doesn't seem to get any more elegant...

@RazvanN7
Copy link
Contributor

RazvanN7 commented Oct 4, 2022

~~ This is a bit risky to merge without the buildkite tester, although phobos passing is quite encouraging. ~~

Later edit: I restarted the buildkite failure, fingers crossed.

Which required further logic tweaks to prevent previously invisible
regressions for two such corner cases - wrong _d_arrayctor lowerings
with array literals and static-array rvalues, the latter implicitly
cast to slices.
@RazvanN7 RazvanN7 merged commit 5fadbf5 into dlang:master Oct 6, 2022
@RazvanN7
Copy link
Contributor

RazvanN7 commented Oct 6, 2022

Thanks @kinke !

@kinke kinke deleted the fix23337 branch October 6, 2022 09:57
kinke added a commit to kinke/ldc that referenced this pull request Oct 6, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
6 participants