-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Who can create an instance of a class type? #803
Comments
My position is that constructing an object is the same as writing its fields. If you can write its fields you are responsible for maintaining its invariants. |
I think constructing an object involves writing its fields, so we should require permission to do that, but that constructing an object should require additional permission beyond the permission to write all the fields, because there can be invariants that aren't captured by the fields. For example, there could be invariants about the state of the base class (that the derived class knows the base class won't violate if they are set up properly when constructing the base class) or there could be invariants involving state stored outside the object (such as, every instance of my class is registered in some global map). Classes with no (direct) fields at all can still maintain invariants. Perhaps we could handle this by having some syntax for specifying that constructing an object is a "private" operation, where the default is that constructing an object is a private operation only if the class has private fields (or perhaps only if the values of any private fields have non-default values specified?). But I think that might be the wrong default, and that instead we should require classes to have to explicitly opt into allowing public construction. |
We triage inactive PRs and issues in order to make it easier to find active work. If this issue should remain active or becomes active again, please comment or remove the |
I think requiring an opt-in for public construction is going to feel like cumbersome ceremony. I think the common case is that the access for construction is going to match the access for fields. Perhaps we can introduce an appropriately named zero-sized type that can be added as a private field of your class in the exceptional cases where these two don't match? I feel like the existing situation is a straightforward rule that is easy to understand. |
Within Carbon, I think it's probably somewhat common that we have types with no private members, and probably wouldn't want struct-to-type conversion to simply work. One example of this is SemIRLoc, which has constructors and factory methods, but only public members. The methods are constraining construction. Another thing to consider might be what it means for inheritance, where:
In such a scenario, should |
Given:
we want to permit
Make
to construct a value of typeX
by implicitly converting a struct literal to typeX
:What code should be able to do this?
Make
is a non-member function, should this be allowed?Make
is a non-member function andv
is private, should this be allowed?Make
is a non-member function andX
has a base class, should this be allowed?A class author often wants to ensure that their class maintains certain invariants. So I think at least in the case where
X
has either any non-public members or a base class, non-member (non-friend) functions should not be able to createX
instances in this way. A simple rule would be that only members and friends can createX
instances (even if all members are public and there are no invariants), but that would disallow the "simple struct with member functions" use case:The text was updated successfully, but these errors were encountered: