>
> 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/CAKRmVH_viS-EX%3Dc-wd%3D_RvUDUKXjWk9R4MOJeGghPYp3%2B_-yDQ%40mail.gmail.com.

Reply via email to