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

Add named arguments to struct literals #14776

Merged
merged 15 commits into from
Jan 17, 2023
Merged

Conversation

dkorpel
Copy link
Contributor

@dkorpel dkorpel commented Jan 2, 2023

Best reviewed per commit, because the big copy-paste Move out resolveStructLiteralNamedArgs does not give a pleasant diff.

  • Add named argument parsing. This time with a separate Array!Identifier instead of a NamedArgExp, which was disliked in Add named argument parsing support #14475
  • Make initsem of StructInitializer re-usable
  • Use the logic in expsemantic of a CallExp on a constructor-less struct

This PR does not do function calls / constructors, that's #14575, which is stalled because checking which of two overloads is more specialized still needs to be adjusted for named parameters.

I haven't started on named template arguments.

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

@dkorpel
Copy link
Contributor Author

dkorpel commented Jan 2, 2023

Currently fails with tuples:

void main() {
    auto t = tuple("H", "I");
}

Tuple!T tuple(T...)(T values)
{
    return Tuple!T(values); // < (param1, param2) gets rewritten to (null, paramX)
}

struct Tuple(T...)
{
    T values;
    alias values this;
}

Will look at it tomorrow

@dkorpel dkorpel force-pushed the named-arg-struct branch 5 times, most recently from ddec9a4 to b5650db Compare January 13, 2023 19:15
@dkorpel dkorpel marked this pull request as ready for review January 14, 2023 11:47
@dkorpel dkorpel requested a review from ibuclaw as a code owner January 14, 2023 11:47
@dkorpel
Copy link
Contributor Author

dkorpel commented Jan 14, 2023

@RazvanN7 This is working now. Named arguments for functions are ignored as of this PR, the next step would be to rebase #14575 on top of this to fix that. That should be doable before the 2.103 release, otherwise I could add it behind a preview switch until it's all in a clean state.

compiler/src/dmd/expression.d Outdated Show resolved Hide resolved
foreach (i; 0..exps.length)
(*names)[i] = null;
}
if (exps.length != names.length)
Copy link
Contributor

Choose a reason for hiding this comment

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

Why keep the dead code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It catches bugs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Note that it's basically an assert, but using if and printf to give a more fluent assert message.

compiler/src/dmd/expression.d Show resolved Hide resolved
compiler/src/dmd/initsem.d Outdated Show resolved Hide resolved
compiler/src/dmd/initsem.d Show resolved Hide resolved
compiler/src/dmd/initsem.d Outdated Show resolved Hide resolved
compiler/test/fail_compilation/fail155.d Outdated Show resolved Hide resolved
compiler/test/fail_compilation/fail158.d Outdated Show resolved Hide resolved
@dkorpel
Copy link
Contributor Author

dkorpel commented Jan 17, 2023

@RazvanN7 Anything else?

// (UFCS/operator overloading) are fixed to take named arguments into account
names.setDim(exps.length);
foreach (i; 0..exps.length)
(*names)[i] = null;
Copy link
Contributor

Choose a reason for hiding this comment

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

What are the situations where names.length != exps.length? I assume from your comment that this is here to catch bugs in other places, however, why do you nullify the names array? Also, you're printing the elements in the next branch so you're putting yourself at risk of a segfault.

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 next branch won't be taken, because this branch does names.setDim(exps.length);. It nullifies them because setDim doesn't initialize new elements, and you don't want it to search a garbage identifier. I could just nullify the new elements, but it doesn't matter, the names aren't correct anyway. This is not a problem, because named arguments don't exist yet, so there's no code relying on it being correct. This whole branch is just scaffolding to make it not crash for various constructed CallExps.

I don't know all situations where names.length != exps.length. One of them was where a.fun(name: b) gets rewritten to fun(a, b) without also prepending a null name, but I fixed that. There are a lot more, but I'll defer them to the PR that implements named function arguments.

Copy link
Contributor

Choose a reason for hiding this comment

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

Ok, makes sense, thanks for the explanation.

{
if (length == 0)
{
names.remove(index);
Copy link
Contributor

Choose a reason for hiding this comment

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

This behavior should be documented in the spec PR. I agree that this is the most sane approach, but others might expect that the named arg is attached to the following argument after the empty AliasSeq (and error if the arg already has a name).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Okay

}
foreach (i; 1 .. length)
{
names.insert(index + i, cast(Identifier) null);
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
names.insert(index + i, cast(Identifier) null);
names.insert(index + i, null);

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That gives an ambiguity error, because insert also has an overload with an Array*

Copy link
Contributor

@RazvanN7 RazvanN7 left a comment

Choose a reason for hiding this comment

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

I guess you will post a documentation PR when named arguments are implemented. Just do not forget to mention that struct literals obey the same rules as any other function with named args.

@dkorpel dkorpel merged commit 42609ae into dlang:master Jan 17, 2023
@dkorpel dkorpel deleted the named-arg-struct branch January 17, 2023 12:08
@dkorpel
Copy link
Contributor Author

dkorpel commented Jan 17, 2023

I created a project to give an overview, and to help me remember:
https://github.com/orgs/dlang/projects/19/views/1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Status: Done
Development

Successfully merging this pull request may close these issues.

3 participants