That sounds fantastic, thank you Em. :)

-Max

On Tue, Jan 6, 2026 at 9:48 AM Em Rauch <[email protected]> wrote:

> > Like, should that IDL constraint only exist if the feature is set to a
> pre-2026 value?
>
> Definitely; the semantic will effectively be:
>
>    - protoc will resolve if the individual enum is resolved as scoped or
>    not (scoped = 2026 files or later, unless they affirmatively set the legacy
>    unscoped option for compatibility).
>       - If it is resolved as unscoped, protoc will try to check for value
>       name collisions between sibling enums, and generators are considered
>       'permitted' to emit the values unscoped.
>       - If it is resolved as scoped, protoc will not check for value
>       collisions, and generators will be required to always emit values scoped
>       (GoProto will just need to prefix the individual values with the enum 
> name
>       in all cases to guarantee the scoping).
>
>
> On Tue, Jan 6, 2026 at 9:33 AM Max Kanat-Alexander <[email protected]>
> wrote:
>
>> 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/CACHWaZnViFb0sYG4mdjHQ_Z1T4qqC%3DxGM_OKbpz42StuKns2-g%40mail.gmail.com.

Reply via email to