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

Embed descriptors in generated code #743

Merged
merged 2 commits into from
Mar 13, 2024
Merged

Embed descriptors in generated code #743

merged 2 commits into from
Mar 13, 2024

Conversation

timostamm
Copy link
Member

This change allows us to provide custom options at runtime (#397), improve support for reflection-based operations, and to implement all edge cases of editions.

We decided to embrace the advantages of this change, and remove the intermediate layer of message types, enum types, and field information, for a much more simple system without classes. (Note that many details are subject to change - this PR is just the first step).

To be able to bootstrap the runtime until the change is complete, the updated runtime and plugin are added under the "next" moniker: protoc-gen-es-next is the updated plugin, @bufbuild/protobuf/next is the updated runtime.

Copy link
Member

@smaye81 smaye81 left a comment

Choose a reason for hiding this comment

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

Seems fine to me 😬 . Although I'd defer to someone who knows the ins and outs of the descriptors.

Copy link
Member

@srikrsna-buf srikrsna-buf left a comment

Choose a reason for hiding this comment

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

The public API so far looks great. I left comments of my understanding of why/what the code is doing, let me know if I am off track somewhere.

The reflect API could infer a little more, but I am yet to look at the followup PR #745

// TODO ServiceShape
// TODO MethodShape?

type MessageInit<T extends Message> = {
Copy link
Member

Choose a reason for hiding this comment

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

This is recursively removing the $desc and $typeName fields as they are not needed for the initializing a value.

Copy link
Member Author

Choose a reason for hiding this comment

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

And it also makes all properties optional. It's a replacement for PartialMessage with a more fitting name.

Arguably, proto2 required fields should not be optional when creating a message (#414). We can consider generating an "input shape" attached to TypedDescMessage for messages using proto2 required, and fall back to MessageInit. This might come with a lot of complication (also for users), and required fields are heavily discouraged. Best to punt on this decision for now.

O: O;
};

class brand<A, B = unknown> {
Copy link
Member

Choose a reason for hiding this comment

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

This is for added typesafety the class is actually not used anywhere except to brand types. Equivalent to opaque in Flow.

It could have similar effects as instanceof but because it is at the type level users should be fine as long as the generated code doesn't conflict. Maybe it will impact WKTs but unsure at this point.

};

// TODO docs
export type MessageShape<Desc extends DescMessage> =
Copy link
Member

Choose a reason for hiding this comment

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

I am assuming the loose constraint of DescMessage as opposed to TypedDescMessage is to allow for dynamic descriptors.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, that always needs to be possible.

@timostamm timostamm merged commit 0b7cee0 into v2 Mar 13, 2024
5 checks passed
@timostamm timostamm deleted the tstamm/embed-descriptors branch March 13, 2024 13:02
@timostamm
Copy link
Member Author

The public API so far looks great.

@srikrsna-buf, we're not out of the weeds yet. Besides the missing pieces (serialization, etc.) possibly surfacing issues, adding the $desc property to all messages is definitely problematic for many tools and frameworks.

The reflect API could infer a little more

We might actually want to dial it down more for practical use cases. For an extreme example, it's possible to narrow down map key type and map value type, but it's absolutely awkward to work with. For now, map fields aren't fully implemented in reflect (what we got doesn't have test coverage). It's good enough to start implementing the missing pieces, and decide on the final details for reflect after dogfooding it a bit.

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

Successfully merging this pull request may close these issues.

3 participants