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

Multiple in arguments will generate exponential number of calls #76

Closed
seanbaxter opened this issue Oct 14, 2022 · 5 comments
Closed

Multiple in arguments will generate exponential number of calls #76

seanbaxter opened this issue Oct 14, 2022 · 5 comments
Assignees
Labels
bug Something isn't working

Comments

@seanbaxter
Copy link

seanbaxter commented Oct 14, 2022

The D0708/A.4 Section "Multiple in and/or forward in the same definite last use" section has wording for avoiding an exponential number of function calls, but I don't think it does that.

In cpp2:

void func(auto&& w, auto&& x, auto&& y, auto&& z);

f: (in w : std::string, in x : std::string, in z : std::string, in w : std::string) = {
  func(w, x, y, z);
}

I would expect a 16-way switch here, as each of the four invented parameters of func will be deduced as either std::string or const std::string&. What is the utility of the four bullet-point subsumption language? You have to perform OR for each combination of argument value categories, and you're necessarily locked into the bad brute-force implementation.

@seanbaxter seanbaxter added the bug Something isn't working label Oct 14, 2022
@JohelEGP
Copy link
Contributor

It is an optimization for when not all combinations are possible. In this case, they are, so you get the worst case.

@seanbaxter
Copy link
Author

The proposal says "it would not be scalable to implement a combinatorial set of branches for every combination of arguments" and yet that's what we should expect from this design. The proposal is quite misleading on this point.

@hsutter hsutter self-assigned this Oct 14, 2022
@hsutter
Copy link
Owner

hsutter commented Oct 14, 2022

Right, that's not what cppfront implements. This is the main change to parameter passing since the d0708 paper, and I haven't updated the paper yet.

For several reasons (including the one you give), cppfront implements separate in and copy parameters. This avoids having to have in have a notional "bit" to remember whether the argument was an rvalue (move candidate) or not, by letting the function author declare their intent to take a copy of the argument (on some or all paths). cppfront currently generates the move from definite last use for copy parameters, but not in parameters.

See the parameter passing part of the talk, particularly this 1-min clip from the talk about copy parameters.

@hsutter hsutter closed this as completed Oct 14, 2022
@seanbaxter
Copy link
Author

Herb can I ask, do you think the paper's treatment of in was a bad idea? Or was it a practical issue of it being hard to do with a transpiler?

@hsutter
Copy link
Owner

hsutter commented Oct 18, 2022

@seanbaxter There were several reasons I split in into the pair of in and copy. The combinatorial most-last-use issue was one, but there were more important principled reasons. The top two reasons are:

  • The top feedback I got on the parameter passing proposal, including from heavyweights like Titus Winters and Tim Sweeney, was that they felt it was important to be able to declaratively say "I'm taking a copy" -- for a variety of reasons including but not limited to immunity from side effects for safety reasoning and concurrency use cases.
  • This actually aligned well with what we've already been teaching, including notably my CppCon 2014 talk which distinctly separated in and in+copy parameter passing guidance (see my CppCon 2014 talk starting at 55:17 and also the C++ Core Guidelines Parameter Passing section which is a direct derivative of that 2014 talk, both of them explicitly distinguish in and in+copy as having their own meaning and guidance)

So what happened was that I recognized this in and copy distinction as important in 2014, then starting in 2015 I basically tried to resist distinguishing the two to explore whether this was really an important distinction, and I ended up rediscovering on multiple levels why they really want to be distinguished.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants