Skip to content

Expression form basics #5545

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

Open
wants to merge 10 commits into
base: trunk
Choose a base branch
from

Conversation

geoffromer
Copy link
Contributor

@geoffromer geoffromer commented May 27, 2025

This proposal introduces the concept of a form, which is a generalization of
"type" that encompasses all of the information about an expression that's
visible to the type system, including type and expression category. Forms can be
composed into tuple forms and struct forms, which lets us track the
categories of individual tuple and struct literal elements.

@github-actions github-actions bot added the documentation An issue or proposed change to our documentation label May 27, 2025
@geoffromer geoffromer added the proposal draft Proposal in draft, not ready for review label May 28, 2025
@github-actions github-actions bot added the proposal A proposal label May 28, 2025
@@ -727,6 +727,18 @@ of `x` and instance binding is performed if an instance member is found.

If instance binding is performed:

- For a field member of a struct type, `x` is required to have that struct
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it isn't quite right for taking the member of a struct form, like a struct literal.

Suggested change
- For a field member of a struct type, `x` is required to have that struct
- For a field member of a struct type or form, `x` is required to have that struct

(similarly below)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By my reading of the rest of this doc, M will never be a member of a struct form: x isn't a type, facet, package, or namespace, so member resolution searches for y in the type of x, and impl lookup can't produce a field of a struct type or a struct form. Am I wrong about that?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Being able to do member access into a struct literal as a form without converting it to a struct type (thus forcing it to have consistent category and phase) was the requested goal of this proposal.

We absolutely want to support operations on forms. Member access is the first example but there will be others.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Helpful context here is the discussion on 05-07b, in particular look for the phrase "Looks in the form of y for G"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, but with different phrasing.

(I believe one upshot of the 05-29 open discussion is that there's no way for M to be a struct form as of this proposal, but future proposals are expected to change that, so we might as well be future-proof.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was confused, see my other comment. I agree we don't need to do instance binding on a form, but we do need to do instance bindings on expressions that have a form, like struct and tuple literals. This is the case that I would like clarified.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's the case that I tried to clarify with the last round of edits. Can you say more about what's still unclear?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I've struggled with this because I never read it as talking about y. And actually it isn't even y, but the result of looking up y. I've offered another suggestion above that would make this clearer.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, I took that suggestion, but also linked it back to M from line 108.

geoffromer and others added 3 commits May 28, 2025 17:14
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
@geoffromer geoffromer marked this pull request as ready for review May 29, 2025 00:17
@geoffromer geoffromer added proposal rfc Proposal with request-for-comment sent out and removed proposal draft Proposal in draft, not ready for review labels May 29, 2025
@github-actions github-actions bot requested a review from zygoloid May 29, 2025 00:18
Comment on lines +191 to +193
### Types, forms, and facets

If the first operand is a type or facet, it must be a compile-time constant.
This disallows member access into a type except during compile-time, see leads
issue [#1293](https://github.com/carbon-language/carbon-lang/issues/1293).
If the first operand is a type, form, or facet, it must be a compile-time
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been a bit confused in my review. There are two things:

  • The analogy of a type, which we are calling a form. The proposal I'm working on is needed before you can have an operand that is a form, since without that there are no form literals. Without those, I don't think we yet have a way for an operand to be a form.
  • The analogy of a value or object, which I don't have a name for, but I've also sometimes have been thinking of as forms, but that has led to my confusion. Literals like (...) and {...} can make these, so it is relevant to talk about member access into.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've been a bit confused in my review. There are two things:

  • The analogy of a type, which we are calling a form. The proposal I'm working on is needed before you can have an operand that is a form, since without that there are no form literals. Without those, I don't think we yet have a way for an operand to be a form.

I know, but I figured it made sense to lay the groundwork for that here. Would you prefer me to revert this bit and let you add it in your proposal?

  • The analogy of a value or object, which I don't have a name for, but I've also sometimes have been thinking of as forms, but that has led to my confusion. Literals like (...) and {...} can make these, so it is relevant to talk about member access into.

I agree, and I think the "Values" section implicitly does that.

@@ -727,6 +727,18 @@ of `x` and instance binding is performed if an instance member is found.

If instance binding is performed:

- For a field member of a struct type, `x` is required to have that struct
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was confused, see my other comment. I agree we don't need to do instance binding on a form, but we do need to do instance bindings on expressions that have a form, like struct and tuple literals. This is the case that I would like clarified.

@geoffromer geoffromer requested a review from josh11b June 4, 2025 17:53
Copy link
Contributor

@josh11b josh11b left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for taking so long to figure out what was going on here. I think I understand the path forward better now.

@@ -727,6 +727,18 @@ of `x` and instance binding is performed if an instance member is found.

If instance binding is performed:

- For a field member of a struct type, `x` is required to have that struct
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I've struggled with this because I never read it as talking about y. And actually it isn't even y, but the result of looking up y. I've offered another suggestion above that would make this clearer.

- For an element member of a tuple form, `x` is required to have that tuple
form. Then, the form of `x.f` is the value of the corresponding element of
the tuple form, and `x.f` evaluates to the corresponding element of `x`.
- For an element member of a tuple type, `x` is required to have that tuple
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is a bit unclear that ((T, U) as type).1 is a legal expression that gives you the second element member of the tuple type (T, U) as type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I don't follow. I agree that it's unclear, I just don't understand why you're bringing it up here. Are you saying this phrasing assumes that expression is legal? If so, how?

geoffromer and others added 3 commits June 5, 2025 11:17
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
Co-authored-by: josh11b <15258583+josh11b@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation An issue or proposed change to our documentation proposal rfc Proposal with request-for-comment sent out proposal A proposal
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants