Okay, good to know. That doesn't sound so bad in Go; it sounds *harder *to have a naming conflict, but still possible.
So, I suppose the question is: does that IDL semantic need to persist in Edition 2026 if all protos are scoped? Like, should that IDL constraint only exist if the feature is set to a pre-2026 value? -Max On Tue, Jan 6, 2026 at 9:21 AM Em Rauch <[email protected]> wrote: > Go is the other big language that doesn't have scoped-enum concept in the > language, by virtue of not even having enum as a first class concept in the > language. GoProto prefixes values which would partially mitigate, but IIRC > it would also break at least in some cases today if we simply relaxed the > scoping restriction rule. > > Just FYI protoc will defensively prevent you from making enums which are > in the scope with enum values whose name collide in the same .proto file. > Formally we might say that "the values not being scoped to their containing > enum is the .proto IDL semantic, unrelated to any language", > pragmatically the main reason we don't relax it is to prevent you from > accidentally making a definition that would break in C++Proto. I think to > disable that check you would have to vendor and patch protoc to remove it, > and any downstream implications of that would obviously be on you at that > point. > > As long as you don't actually create such a value name collision in the > same .proto file protoc won't stop you though (it doesn't enforce the enum > value name prefixing or anything, that's just a style guide to try to avoid > collisions) > > > > On Mon, Jan 5, 2026 at 11:46 PM Max Kanat-Alexander <[email protected]> > wrote: > >> Okay, that makes sense. So basically, my enums won't change their format >> in code when they are scoped, but they will behave correctly in C++. Is C++ >> the only language with the problem? I don't expect to need a C++ parser any >> time soon, so if that's the only place where it's a problem today, maybe I >> will just make top-level enums now and switch them to scoped when 2026 >> comes out. >> >> -Max >> >> On Mon, Jan 5, 2026 at 10:04 AM Em Rauch <[email protected]> wrote: >> >>> So how would that look? Like say today I have: >>>> message Wrapper { >>>> enum Foo { >>>> UNSPECIFIED = 1; >>>> BAR = 1; >>>> } >>>> } >>>> Today I would be referring to that as Wrapper::Foo::BAR, IIRC (I >>>> haven't done C++ proto in a long time) or Wrapper.Foo.BAR in Python/Java >>>> (IIRC?). What does "enum Foo" at the top level look like instead? >>> >>> >>> Scoped enums would actually require no other behavior change in many of >>> the languages like Java, as the gencode actually uses a language enum which >>> is already scoped anyway. So in Java you're just going to get `Foo.BAR` >>> like you want without us having to do much special there. >>> >>> The C++ case is actually fairly odd today, basically what happens with >>> the wrapping type is that there's first an enum which manually prefixes >>> everything with the nested scope basically like this (the C++ enum semantic >>> is that all of the constants inside are not scoped by the containing enum) >>> >>> enum Wrapper_Foo : int { >>> Wrapper_Foo_UNSPECIFIED = 0; >>> Wrapper_Foo_BAR = 1; >>> } >>> >>> And then later the actual message class has `using` statements that >>> expose the type and names under that scape, like: >>> >>> class Wrapper { >>> using Foo = Wrapper_Foo; >>> static constexpr Foo UNSPECIFIED = Wrapper_Foo_UNSPECIFIED; >>> static constexpr Foo BAR = Wrapper_Foo_BAR; >>> } >>> >>> So today it is possible to write the enum type as either `Wrapper_Foo` >>> or `Wrapper::Foo`, and possible to name the values as either `Wrapper::BAR` >>> or `Wrapper_Foo_Bar`. You can see that this still would have the name >>> collisions if you had 2 enums nested in the same message and the value >>> names collided, since the values are also 'directly' underneath `Wrapper` >>> without any `Foo` in them there. >>> >>> C++ the language added scoped enums all the way back in C++11 (they look >>> like `enum class Foo {}`) so its far overdue for us to be able to have the >>> gencode use it there, then we can start to emit it as: >>> >>> enum class Foo : int { >>> UNSPECIFIED = 0; >>> BAR = 1; >>> } >>> >>> And you can finally write Foo::UNSPECIFIED like you naturally want to. >>> >>> All that to say, with scoped enums you will want to put them at top >>> level instead of synthetically-nested in a message and the 'spelling' >>> won't match. It's also a possibility that we could have some sort of shim >>> migration mode to facilitate people trying to incrementally move off the >>> nested-message-to-scope-pattern onto proper-scoped-enums but I'm not >>> exactly sure what it could look like to be a super smooth migration. >>> >>> On Mon, Jan 5, 2026 at 9:28 AM Max Kanat-Alexander <[email protected]> >>> wrote: >>> >>>> Ha, thanks Em! Wasn't sure anybody would recognize my name, still. :) >>>> >>>> Scoped by default sounds good. And I think that timeline would work for >>>> me, actually. And for what I'm working on, I can pick any edition I want; >>>> it's essentially green-field work where I get to define the format. >>>> >>>> So how would that look? Like say today I have: >>>> >>>> message Wrapper { >>>> enum Foo { >>>> UNSPECIFIED = 1; >>>> BAR = 1; >>>> } >>>> } >>>> >>>> Today I would be referring to that as Wrapper::Foo::BAR, IIRC (I >>>> haven't done C++ proto in a long time) or Wrapper.Foo.BAR in Python/Java >>>> (IIRC?). What does "enum Foo" at the top level look like instead? >>>> >>>> Basically I'm wondering: if I want to prepare for it now, can I name >>>> the empty messages in a particular way that will help me stay >>>> forward-compatible. >>>> >>>> Oh, and prototiller sounds cool. :) >>>> >>>> -Max >>>> >>>> On Mon, Jan 5, 2026 at 9:07 AM Em Rauch <[email protected]> wrote: >>>> >>>>> Always nice to recognize a xoogler name 🙂 >>>>> >>>>> Broadly, the plan is for a future Edition number to have enums be >>>>> treated as scoped by default, but with a feature setting that opts back in >>>>> to current behavior for people who want to upgrade the Edition number of >>>>> preexisting .proto files perfectly-behavior-preserving >>>>> (behavior-preserving >>>>> uprades should be tool assisted with a tool called Prototiller, whose OSS >>>>> implementation is unfortunately still not stabilized yet as we are >>>>> rewriting it to Go). >>>>> >>>>> Scoped enums is close to the top of the candidates list for Edition >>>>> 2026 which is targeted for 2026-Q3, but we don't have any firm commitments >>>>> around Edition 2026 details at the moment. >>>>> >>>>> We don't intend to change the enum behavior on >>>>> proto2/proto3/Edition-2023/Edition-2024 files (or even support an option >>>>> there to do so), as our forward Editions strategy is to generally treat >>>>> the >>>>> behavior of older syntax IDL inputs as fixed as the way to avoid the >>>>> ecosystem problems that come from even adding new options that old >>>>> impls/infrastructure won't know about. So unfortunately anyone who plans >>>>> to >>>>> stay on Proto3 forever won't get the new goodness, you'll need to continue >>>>> to just wrap each enum in an empty message if you want to avoid the stupid >>>>> value name collision problems. >>>>> >>>>> > Is that actually on a roadmap anywhere? I don't see it in Issues. >>>>> >>>>> We mostly don't use Issues for tracking our roadmap work, primarily >>>>> Issues is for handling external bugs/requests/discussion (unlike gRPC >>>>> which >>>>> has community-driven CNCF governance, Protobuf is still a Google project). >>>>> If you want to open it on Issues so you can be notified when it moves >>>>> forward, free to open and I'll tag the issue appropriately and we can try >>>>> to remember to keep it up to date. >>>>> >>>>> Thanks! >>>>> >>>>> On Mon, Jan 5, 2026 at 8:49 AM Max Kanat-Alexander < >>>>> [email protected]> wrote: >>>>> >>>>>> Hey proto team! :) The current docs say that scoped enums will be >>>>>> part of a future edition. Is that actually on a roadmap anywhere? I don't >>>>>> see it in Issues. I'm mostly just wondering if I should expect it by some >>>>>> vague date. >>>>>> >>>>>> I'm playing around with defining a configuration language based on a >>>>>> strict subset of textproto, and scoped enums would help a ton so that >>>>>> users >>>>>> could just write `state: ACTIVE` instead of the unintuitive `state: >>>>>> STATE_ACTIVE` in their config files. I know that I can accomplish that >>>>>> today by nesting enums inside of messages, but what I'm curious about is >>>>>> if >>>>>> the future potential implementation of scoped enums will break backwards >>>>>> compatibility with that in some way. >>>>>> >>>>>> -Max >>>>>> >>>>>> -- >>>>>> You received this message because you are subscribed to the Google >>>>>> Groups "Protocol Buffers" group. >>>>>> To unsubscribe from this group and stop receiving emails from it, >>>>>> send an email to [email protected]. >>>>>> To view this discussion visit >>>>>> https://groups.google.com/d/msgid/protobuf/25fac6eb-2e5f-43e3-bcd2-3ec3df783b56n%40googlegroups.com >>>>>> <https://groups.google.com/d/msgid/protobuf/25fac6eb-2e5f-43e3-bcd2-3ec3df783b56n%40googlegroups.com?utm_medium=email&utm_source=footer> >>>>>> . >>>>>> >>>>> -- You received this message because you are subscribed to the Google Groups "Protocol Buffers" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion visit https://groups.google.com/d/msgid/protobuf/CACHWaZnW%2BzEq6XhRwvy7YxpOgihnb2RunNwALKJFUqtzkM9Tww%40mail.gmail.com.
