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

Precedence diagram is missing partial operator #5010

Open
zygoloid opened this issue Feb 25, 2025 · 3 comments
Open

Precedence diagram is missing partial operator #5010

zygoloid opened this issue Feb 25, 2025 · 3 comments
Labels
leads question A question for the leads team

Comments

@zygoloid
Copy link
Contributor

Description of the bug:

The precedence diagram is missing the partial operator, and there are multiple choices for what should be added.

  • Same precedence group as const (non-associative): disallows const partial C, partial const C, and partial partial C.
  • Precedence group above const (either associative or non-associative): allows const partial C, disallows partial const C.
  • Precedence group below const (either associative or non-associative): allows partial const C, disallows const partial C.

Link to documentation:

Diagram: https://docs.carbon-lang.dev/docs/design/expressions/#precedence
Proposal #777, which added partial: https://docs.carbon-lang.dev/proposals/p0777.html
Documentation of partial: https://docs.carbon-lang.dev/docs/design/classes.html#partial-class-type

What should it say instead?

Two options seem reasonable here. Option 1:

const and partial are in the same precedence group, which is non-associative.

Rationale: while the operations performed by const and partial probably[*] commute, it would be surprising to apply both to the same type (much like const const T is surprising) and so rejecting may be preferable to accepting. However, this rule might be more of an "HOA rule" than a "building code".

Option 2:

partial is in a precedence group above const in the diagram -- that is, partial has higher precedence. Both are non-associative. const partial C is accepted, all other combinations with more than one of const and partial is rejected unless parenthesized.

Rationale: partial applies more "directly" to the type than const does, because partial applies only to classes whereas const is a general type operator. So if both can be applied in the same expression, partial should be applied to the type first.

Any other information, logs, or outputs that you want to share?

[*]: For a class type C, it's unclear whether it should be valid to apply partial to a type const C at all, such as in the expression partial (const C), or in a generic where partial T may be applied to a T that evaluates to const C. In particular, it's not obvious whether const C is a class type, or is close enough to being a class type, for partial to apply.

Additionally, it's not clear whether partial (partial C) should be valid and should decay to partial C (like const), or whether it should be invalid because partial C is not a class type. The design says:

The keyword partial is only valid for a base or abstract class. For final classes, there is no need for a second type.

... and even if partial C or const C is considered to be a class type, it's not clear whether it's a base or abstract class.

@zygoloid zygoloid added the leads question A question for the leads team label Feb 25, 2025
@zygoloid
Copy link
Contributor Author

Suggestion: for the time being, we take a restrictive stance, but are open to design changes in this area:

const and partial are in the same precedence group (as implemented in the toolchain #5009), and partial can only be applied to a type that is exactly a base or abstract class type -- not a const-qualified type, not a partial-qualified type.

Allowing const partial C or partial (const C) or partial (partial C) may be useful at some point, and it also might be useful to allow partial T where T is an arbitrary type within a generic (even if it's a final class), but we don't have use cases or a design for such functionality at this time.

This seems the direction that is most in line with the design described in #777.

@jonmeow
Copy link
Contributor

jonmeow commented Feb 25, 2025

Just a note in support of writing "const partial C", being able to have a helper fn MakeHelper(c: const partial C*) might help with type safety during construction: "this works with children of C, but does not modify C and does not use virtual functions".

@chandlerc
Copy link
Contributor

Just a note in support of writing "const partial C", being able to have a helper fn MakeHelper(c: const partial C*) might help with type safety during construction: "this works with children of C, but does not modify C and does not use virtual functions".

That wouldn't need const in most cases though: you often could instead have MakeHelper(c: partial C).

The const thing comes up if you or someone else have stored the address somewhere significant. Typically this would come up in a read-only context when the object is being used on multiple threads or something similar. That seems less likely for partial specifically I think?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
leads question A question for the leads team
Projects
None yet
Development

No branches or pull requests

3 participants