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

[SUGGESTION] Definite first assignment to return this #368

Closed
JohelEGP opened this issue Apr 14, 2023 · 8 comments
Closed

[SUGGESTION] Definite first assignment to return this #368

JohelEGP opened this issue Apr 14, 2023 · 8 comments

Comments

@JohelEGP
Copy link
Contributor

At #366 (comment),
we discovered that a definite first assignment has type void.

Returning an lvalue reference to the object parameter
is only a convention in user-provided operator= (C++𝘕).
That's the language's default,
and what is expected of a regular type.

There should be worth in Cpp2 unifying not only syntax,
but also the semantics of its operator=.

This should eliminate future guidance
around a first assignment behaving differently on whether it's definite.

It should be worth noting that
the C++1 methods to delay object creation
return a reference or pointer to the created object.
The C++ standard library follows suit,
and I can't come up with a reason for Cpp2 not to.

@JohelEGP
Copy link
Contributor Author

JohelEGP commented Aug 8, 2023

This does mean that,
like assignment,
an initializing = expression-statement will have to be discarded.

s: std::string;
_ = s = "";

@hsutter
Copy link
Owner

hsutter commented Aug 11, 2023

There should be worth in Cpp2 unifying not only syntax,
but also the semantics of its operator=.

Thanks. I agree with being consistent.

But (contrarian here) I was actually thinking of going the other way:

Option 1: Have assignment return void which would disallow chained assignments. I vaguely remember discussing that here in another issue(?) where I think someone came up with an example where operator= returning non-void was useful for something other than chaining, but I don't remember it now. But, as you point out, an operator= that returns void breaks std::assignable_from.

and/or

Option 2: Leave assignment alone for Cpp1 compatibility, but disallow writing chained assignments in Cpp2 code.

I think Option 2 is a good thing to do regardless, so I'll do that now...


Re this:

This does mean that, like assignment, an initializing = expression-statement will have to be discarded.

s: std::string;
_ = s = "";

I don't understand? Assignment does not have to be discarded, s = ""; is fine.

I agree that whatever is done here, we should not require discarding the result of an = value-set statement, whether it's a definite first use or not. Having to discard an assignment would be weird. (And Option 2 above would actually ban writing that, which I think is an improvement.)

@JohelEGP
Copy link
Contributor Author

Re this:

This does mean that, like assignment, an initializing = expression-statement will have to be discarded.

s: std::string;
_ = s = "";

I don't understand? Assignment does not have to be discarded, s = ""; is fine.

I agree that whatever is done here, we should not require discarding the result of an = value-set statement, whether it's a definite first use or not. Having to discard an assignment would be weird. (And Option 2 above would actually ban writing that, which I think is an improvement.)

You're right.
I was actually thinking of compound assignment,
which do require discarding: https://cpp2.godbolt.org/z/rGddsxGcK.

@JohelEGP
Copy link
Contributor Author

I vaguely remember discussing that here in another issue(?) where I think someone came up with an example where operator= returning non-void was useful for something other than chaining, but I don't remember it now.

I remember isocpp/CppCoreGuidelines#1988.
A quick look suggests that's your reference.

@hsutter
Copy link
Owner

hsutter commented Aug 11, 2023

You're right.
I was actually thinking of compound assignment,

Yes, my commit just now "fixes" that for ?= too. 😎 So this is a consistency improvement where = and ?= are now treated the same.

@hsutter
Copy link
Owner

hsutter commented Aug 11, 2023

I remember isocpp/CppCoreGuidelines#1988.
A quick look suggests that's your reference.

That was it, thanks! Browsing that, the additional use case mentioned there was using the result as an lvalue, such as while ((ch=getchar()) != EOF).

So I think the remaining question for this issue, after the above commit to make assignment and discarding more regular, is whether we want to keep the issue open to allow definite first uses like this:

s: std::string;
(s = "xyzzy").append(" or plugh");

I see arguments for both that the above should be supported and that the above should be banned...?

@hsutter
Copy link
Owner

hsutter commented Aug 12, 2023

Adding to the previous comment:

The specific use case of while ((ch=getchar()) != EOF) could not be a definite first use anyway, because it's in a loop.

So I think I've come down to that a definite first use initialization should be a whole statement, not a subexpression. TODO: I should create a diagnostic for that so that a violation gets a nice readable error message

@JohelEGP
Copy link
Contributor Author

That's certainly consistent with definite first use initialization of data members in operator=.

zaucy pushed a commit to zaucy/cppfront that referenced this issue Dec 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants