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.

Reply via email to