Namespace ancillary codegen output into parallel kind-trees (view::, oneofs::, ext::)#54
Draft
Namespace ancillary codegen output into parallel kind-trees (view::, oneofs::, ext::)#54
Conversation
ae6dd3b to
e46e6b9
Compare
4 tasks
Moves generated types that previously collided with user-declared proto names into dedicated sub-modules, structurally deconflicting the codegen output from proto-derived names. Layout changes: - Views: `pkg::FooView` → `pkg::view::FooView` (top-level), and `pkg::foo::BarView` → `pkg::view::foo::BarView` (nested). Oneof view enums follow the same tree: `pkg::view::foo::KindView`. The `View` suffix is retained so that owned and view types can be imported into the same scope without renaming. - Extensions: `pkg::FOO` → `pkg::ext::FOO`, and per-file `pkg::register_types` → `pkg::ext::register_types`. - Oneof enums: `foo::KindOneof` → `foo::Kind`. The suffix is no longer needed for disambiguation; the owner message's sub-module provides the namespace. Oneof enums themselves remain in the owner message's sub-module (`pkg::foo::Kind`). The view-tree move makes several previously-illegal proto patterns legal — two regression tests in `naming.rs` capture this. Codegen internals: - `GeneratedFile` gains `kind: GeneratedFileKind` + `package: String` fields. Each generated proto now produces three sibling output files (`.rs`, `.__view.rs`, `.__ext.rs`); `generate_module_tree` coalesces them per package so multiple `.proto` files that share a Rust module (e.g. `google.rpc`) merge their `view::` / `ext::` blocks cleanly. - `generate_module_tree` signature widens from `&[(&str, &str)]` to `&[ModuleTreeEntry<'_>]` to carry the kind. - `MessageScope::deeper()` is used for depth-aware path resolution in the parallel view tree. Checked-in generated code regenerated (WKTs + bootstrap descriptor types). Conformance suite, googleapis stress test, and the existing test suite (1442 tests) all pass.
e46e6b9 to
8319105
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ancillary types emitted by
buffa-codegen— borrowed views, oneof enums, oneof view enums, extension consts, and the per-file registration fn — previously lived in the same Rust namespace as user-declared proto types and could collide with them. For example, amessage FooViewin a.protowould clash with the generated view type of siblingmessage Foo;message DataType { oneof data_type {...} }would put a struct and an enum of the same name side by side.This PR moves every ancillary generated type into a dedicated kind-namespaced parallel tree (
view::,oneofs::,ext::,view::oneofs::), structurally deconflicting the codegen output from proto-derived names. The design rule (now documented inDESIGN.md) is:Layout changes
pkg::FooViewpkg::view::FooViewpkg::foo::BarView(nested msg view)pkg::view::foo::BarViewpkg::foo::KindOneof(oneof enum)pkg::oneofs::foo::Kindpkg::foo::KindOneofView(oneof view enum)pkg::view::oneofs::foo::Kindpkg::FOO(extension const)pkg::ext::FOOpkg::register_typespkg::ext::register_typesSuffix policy
Viewsuffix (pkg::view::foo::FooView) — this is the one documented exception to the "tree disambiguates, so drop the suffix" rule. Rationale: users commonly import a message and its view into the same scope (use pkg::{Foo, view::FooView};), and a scope-level rename would be friction for every call site.Kind.Co-import ergonomics
Codegen internals
GeneratedFilegainskind: GeneratedFileKindandpackage: Stringfields.GeneratedFileKindhas five variants:Owned,View,Ext,Oneofs,ViewOneofs. Each proto produces five sibling output files (.rs,.__view.rs,.__ext.rs,.__oneofs.rs,.__view_oneofs.rs); empty bodies when the kind has no content for that proto.generate_module_treeaccepts&[ModuleTreeEntry<'_>]and coalesces per-package streams across multiple.protofiles so packages that span files (e.g.google.rpc) merge theirview::/ext::/oneofs::/view::oneofs::blocks into single wrappers per kind.CodeGenError::OneofNameConflictand the reserved-name machinery around oneof-vs-nested-type collisions are deleted — the collisions they guarded against are now structurally impossible.generate_views=false, so its.__view*.rssiblings are empty stubs; the file count is kept consistent for the module tree stitcher.Deconfliction wins
Patterns that were previously rejected at codegen time (or required
OneofNameConflicterrors with proto renames) now compile as-is:message DataType { oneof data_type {...} }message Foo { nested message Kind {...} oneof kind {...} }message M { nested message FooView {...} oneof foo {...} }my_fieldandmy_field_viewDESIGN.md
Adds a "Generated code layout — parallel trees per kind" section covering the formula, the five-sibling invariant, the path-table worked example for
my.pkg.Foo, theView-suffix exception with rationale, and the three structural benefits (collision-free / predictable / feature-gatable per kind).Migration for downstream consumers
Test plan
cargo check --workspacecleantask test— 1448 tests pass (18 suites), 0 failedtask test-codegen— snapshot tests passtask lint—cargo fmt --checkandcargo clippy --workspace --all-targets -- -D warningsboth cleantask lint-md— markdownlint cleantask conformance— 6CONFORMANCE SUITE PASSEDlines, baseline numbers match exactly (std 5549 / no_std 5529 / view 2797 binary+JSON; 883/883/0 text)task stress-googleapis— 235 files compile cleanly (including multi-filegoogle.rpc)tests/naming.rscollision tests are further updated tocoexistassertions;OneofNameConflicttest references removed with the variantDiff breakdown by category
Total: 113 files, +6339 / -3562.
buffa-codegen/src/*.rs, non-test)coexistregression tests for the deconfliction patterns. Net +162.buffa-buildAPI adaptationModuleTreeEntrythrough the build-script path. Net +61.buffa-testconsumer test suitebuffa-types/buffa-descriptorhand-maintainedlib.rs/mod.rshand-stitch thepub mod view { pub mod oneofs {} },pub mod oneofs,pub mod extwrappers. Net +59.addressbook,envelope,logging)loggingexample. Net +197.protoc-gen-buffa-packagingModuleTreeEntrys per proto. Net +31.gen_lib_rs.py)DESIGN.mdbuffa-types/src/generated/)buffa-descriptor/src/generated/)mod.rs+ sibling stubs. Net +34.examples/loggingoutputtask gen-logging-exampleoutput after the layout move. Net +1050.Human-authored change: ~2048 / 936 (32% / 26%) of the total. The rest is codegen-regenerated output where the file count expands because every proto now emits five siblings, but the per-file content shrinks correspondingly.
Breaking changes
API-breaking for downstream consumers of generated code. Pre-1.0 this is expected; the migration is mechanical (adjust import paths per the table above).