hsutter / cppfront

A personal experimental C++ Syntax 2 -> Syntax 1 compiler
Other
5.46k stars 238 forks source link

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

Closed JohelEGP closed 2 days ago

hsutter commented 1 week ago

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:

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.

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 commented 1 week ago

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?

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 commented 1 week ago
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 commented 1 week ago

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 commented 1 week ago
* **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 commented 1 week ago

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 commented 1 week ago

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 commented 2 days ago

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 commented 2 days ago

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

hsutter commented 2 days ago

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

JohelEGP commented 2 days ago

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.