Skip to content

feat: add _type-id_ production for decltype - #921

Merged
hsutter merged 2 commits into
hsutter:mainfrom
JohelEGP:decltype_type_id
Oct 4, 2024
Merged

hsutter merged 2 commits into
hsutter:mainfrom
JohelEGP:decltype_type_id

Conversation

@JohelEGP

@JohelEGP JohelEGP commented Jan 8, 2024 •

Copy link
Copy Markdown
Contributor

No description provided.

@hsutter

hsutter commented Sep 25, 2024 •

Copy link
Copy Markdown
Owner

Thanks! Sorry for the lag.

It seems like the motivation overlaps with the later discussion in #714 which starts to add decltype(auto), though only for single-expression bodies.

Perhaps this and #876 are underscoring that there need to be three (not two) return styles, which has come up in my mind several times before:

  • by value, which is currently default or can be explicitly spelled move... maybe this should be spelled copy?
  • by reference to support string::operator[] use cases, which is currently spelled forward... maybe this should be spelled something like ref (*)?
  • by perfect backwarding, which currently has no spelling but the natural name would be forward and lower to decltype(auto)?

What do you think? That would bottom out on both #714 and #876, and be instead of this PR?


(*) There's a longer story here: For many years, the best candidate names I've considered for "in/out" parameters are inout and ref.

  • ref has the advantage of symmetry: The same word could be directly used for both parameters and returns that are lvalue references. However, a major disadvantage is that it's about "how" to pass the parameter, not "what" the parameter is for.
  • inout has the (IMO compelling) advantage of "what" not "how": Plus it connotes explicit data-flow. It's just perfect for parameters IMO. However, inout doesn't feel quite right as a return from string::operator[].

I liked the idea of trying to make the return styles be a subset of the parameter styles, but maybe it's time to reconsider that it doesn't quite work. If we keep inout for lvalue reference parameters, what's the right "what" word for what string::operator[] returns... what is a "what" word that describes what the callee/caller wants to do with it?

Edited to add: Brainstorming... loan? lend? show? share? actual? original? or maybe qualifier_forward?

Naming is hard.

@JohelEGP

Copy link
Copy Markdown
Contributor Author

That comment seems more appropriate for #876.
General support for decltype as a type-id is desirable (this PR),
even if we reject -> decltype(auto) in favor of -> forward as you suggest, which I like.

#714's gotten long and contentious (I'm a fan of the main branch's :(x) x standing for :(x) -> _ = x).
Can I have some specific links to comments?

Since main is only missing decltype(auto) for perfect backwarding,
I imagine this is about enhancing :(x) x to somehow specify x to return by something other than by value.

  • by value, which is currently default or can be explicitly spelled move... maybe this should be spelled copy?

    • by reference to support string::operator[] use cases, which is currently spelled forward... maybe this should be spelled something like ref (*)?

    • by perfect backwarding, which currently has no spelling but the natural name would be forward and lower to decltype(auto)?

What do you think?

  • Changing the default's spelling from -> move to -> copy makes sense.
  • -> forward does indeed work well for perfect backwarding.

As for string::operator[], how about this?

string: type = {
  operator[]: (this) -> this char; // Returns a `char` reference in the `in this` value, naturally by `const`.
  operator[]: (inout this) -> this char; // Returns a `char` reference in the `inout this` value, naturally non-`const`.
}

That also documents the provenance.
For a more global reach, continue using the concrete -> forward (https://cpp2.godbolt.org/z/f181eG3Wz):

get_cout: () -> forward std::ostream = std::cout;

@MaxSagebaum

Copy link
Copy Markdown
Contributor
string: type = {
  operator[]: (this) -> this char; // Returns a `char` reference in the `in this` value, naturally by `const`.
  operator[]: (inout this) -> this char; // Returns a `char` reference in the `inout this` value, naturally non-`const`.
}

It is a good idea, but could be easily miss read as a function returning this or a function which returns two arguments.

@JohelEGP

Copy link
Copy Markdown
Contributor Author

Yeah. So why not continue using concrete -> forward if it's still a thing?

string: type = {
  operator[]: (this) -> forward const char;
  operator[]: (inout this) -> forward char;
}

@JohelEGP

Copy link
Copy Markdown
Contributor Author
* **by reference** to support `string::operator[]` use cases, which is currently spelled `forward`... maybe this should be spelled something like `ref` (*)?

I'm fine with keeping (concrete) -> forward for return by reference.
By virtue of Cpp2 being safe, that will by returning a non-local object.

@hsutter

hsutter commented Sep 25, 2024

Copy link
Copy Markdown
Owner

That comment seems more appropriate for #876

Good point, I'll move replies there.

General support for decltype as a type-id is desirable (this PR),

OK. Do you want to refresh/rebase this branch for me to review?

Also, do we want specifically decltype semantics? Or decltype + remove_cvref semantics (which I would call typeof)?

@JohelEGP

Copy link
Copy Markdown
Contributor Author

General support for decltype as a type-id is desirable (this PR),

OK. Do you want to refresh/rebase this branch for me to review?

I'll do that.

Also, do we want specifically decltype semantics? Or decltype + remove_cvref semantics (which I would call typeof)?

I was assuming we'd be using the same decltype keyword as C++, in which case, it'd have the same behavior.
Were you perhaps thinking of spelling it -> forward(expression)?

-> decltype(expression) returns have their place in generic code.
There may be use cases where something like -> typeof(expression) might be more appropriate.
Do you think we should also allow that? Unfortunately, it seems it doesn't already work, due to the parentheses.

@hsutter

hsutter commented Oct 3, 2024

Copy link
Copy Markdown
Owner

What I was thinking was to make this PR exclusively about adding decltype() as a type-id. And not allow auto in there (auto is not a Cpp2 thing currently).

I have separate plans for the return type: To make Cpp1 -> decltype(auto) and -> auto&& spelled as Cpp2 -> forward and -> forward_ref.

@JohelEGP

JohelEGP commented Oct 3, 2024

Copy link
Copy Markdown
Contributor Author

OK. I'll just have to reject a decltype as the type-id of return-list.

@hsutter

hsutter commented Oct 3, 2024

Copy link
Copy Markdown
Owner

Great. I'll watch for conflicts to be resolved, then I'll take a review pass. Thanks!

@JohelEGP

JohelEGP commented Oct 3, 2024

Copy link
Copy Markdown
Contributor Author

I just noticed that we also don't have decltype(auto) for variables.
The best approximation are forward: _ parameters: https://cpp2.godbolt.org/z/MKsocP6bb.

Comment thread source/parse.h Outdated
@hsutter hsutter removed the question - further information requested Further information is requested label Oct 4, 2024
@hsutter
hsutter merged commit 4f399a7 into hsutter:main Oct 4, 2024
@JohelEGP
JohelEGP deleted the decltype_type_id branch October 4, 2024 02:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants