# CaseIterable for C-imported enums

**URL:** <https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116>\
**Category:** Using Swift\
**Created:** [September 5, 2023, 12:18am UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116 "2023-09-05T00:18:53Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![lhunath](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lhunath/32/18794_2.png) [@lhunath](https://forums.swift.org/u/lhunath)\
**Post date:** [September 5, 2023, 12:18am UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/1 "2023-09-05T00:18:53Z")

</div>

From [https://github.com/apple/swift-evolution/blob/main/proposals/0194-derived-collection-of-enum-cases.md](https://github.com/apple/swift-evolution/blob/main/proposals/0194-derived-collection-of-enum-cases.md) we learn that:

> - Enums imported from C/Obj-C headers will **not** participate in the derived CaseIterable conformance.

It appears that there has been no evolution in this area, nor have I been able to find any discussion on the topic.

We can learn a little more about how Swift imports C enums here: [https://github.com/apple/swift/blob/main/docs/HowSwiftImportsCAPIs.md#enums](https://github.com/apple/swift/blob/main/docs/HowSwiftImportsCAPIs.md#enums)  
And there has been some enum evolution here: [https://github.com/apple/swift-evolution/blob/main/proposals/0192-non-exhaustive-enums.md](https://github.com/apple/swift-evolution/blob/main/proposals/0192-non-exhaustive-enums.md)

Synthesizing `allCases` for C-imported enums remains unavailable, and it isn't possible to trigger it either, since we do not control the file declaring the imported enum:

```swift
extension SpectreKeyPurpose: CaseIterable {} // Extension outside of file declaring enum 'SpectreKeyPurpose' prevents automatic synthesis of 'allCases' for protocol 'CaseIterable'

```

Given that there is real value in iterating enum cases, in particular for well-defined enum types such as those that are frozen or based on `NS_ENUM`, can the Swift team share what was the original motivation for excluding `CaseIterable` conformance for C-imported enums, and is there any interest in revisiting this?

---

<div class="post-metadata">

**Author:** ![wadetregaskis](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/wadetregaskis/32/8494_2.png) [@wadetregaskis](https://forums.swift.org/u/wadetregaskis)\
**Post date:** [September 5, 2023, 12:53am UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/2 "2023-09-05T00:53:56Z")

</div>

Native Swift enums aren't automatically `CaseIterable` either, so maybe it's just for consistency? Not all enums make sense to be runtime-iterable, semantically.

And the more recent decision to disallow protocol conformances outside the original module might have just overlooked this case.

---

<div class="post-metadata">

**Author:** ![harlanhaskins](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/harlanhaskins/32/333_2.png) [@harlanhaskins](https://forums.swift.org/u/harlanhaskins)\
**Post date:** [September 5, 2023, 5:11am UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/3 "2023-09-05T05:11:21Z")

</div>

C enums are just a thin wrapper around a potentially arbitrary set of integers. There’s an argument to be made for `NS_CLOSED_ENUM`, but this isn’t possible for `NS_ENUM` since `MyEnum(rawValue: 0x20fb27ba)` might very well be a valid private enum case that’s understood by the C but not exposed in a header.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [September 5, 2023, 3:25pm UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/4 "2023-09-05T15:25:08Z")

</div>

So I was going to say that too, but CaseIterable never promises to return _every_ case, so having a default CaseIterable that returns “the public cases present at compilation time” wouldn’t be too weird. But then you run into trouble if a case is ever added, because you could use a library compiled a while ago with your brand new app and they’d disagree on what cases should be included. Since the conformance is synthesized on the use side, not in the system library, there’s no central place for it to be updated when a new case has been added.

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [September 5, 2023, 4:51pm UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/5 "2023-09-05T16:51:31Z")

</div>

> [@jrose](#):
>
> So I was going to say that too, but CaseIterable never promises to return _every_ case

Huh? From the [docs](https://developer.apple.com/documentation/swift/caseiterable/allcases-swift.type.property):

> # CaseIterable
> 
> A type that provides a collection of all of its values.

That seems pretty explicit that any possible value ought to be contained in the `allCases` collection (the docs for which reiterate the "all values" terminology).

---

<div class="post-metadata">

**Author:** ![allevato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/allevato/32/385_2.png) [@allevato](https://forums.swift.org/u/allevato)\
**Post date:** [September 5, 2023, 5:23pm UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/6 "2023-09-05T17:23:12Z")

</div>

Given that it's not possible in C/Objective-C itself to enumerate all the values of an `enum` (leading to the "define a case equal to the last case + 1" trick), the question I would ask is "_why_ do you want to iterate all of the cases?"

Since `CaseIterable` synthesis requires the conformance to be stated in the same file where the `enum` is declared, then that capability is effectively something that should be considered to be an innate characteristic of the type—like `Equatable` and `Hashable`, it's either there by design or it isn't. Given that it's impossible for the module that owns the `enum` to own the conformance(†), I think it would be an overreach to automatically synthesize in this case (especially due to the issue @jrose points out above).

(†) The _one_ situation where I could rationalize doing this synthesis would be if we were compiling a Swift overlay for an underlying Objective-C module.

---

<div class="post-metadata">

**Author:** ![jrose](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jrose/32/408_2.png) [@jrose](https://forums.swift.org/u/jrose)\
**Post date:** [September 5, 2023, 5:38pm UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/7 "2023-09-05T17:38:52Z")

</div>

Oh, fair enough. I was thinking about how the compiler can’t _guarantee_ that a custom implementation covers every value (say, for a struct), but the documentation does make it sound like an implementation shouldn’t be _excluding_ values, and with C enums other than `NS_CLOSED_ENUM` we could never be sure of that. So we’re back to what Harlan said, yeah.

---

<div class="post-metadata">

**Author:** ![lhunath](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/lhunath/32/18794_2.png) [@lhunath](https://forums.swift.org/u/lhunath)\
**Post date:** [September 5, 2023, 6:15pm UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/8 "2023-09-05T18:15:01Z")

</div>

> [@allevato](#):
>
> Since `CaseIterable` synthesis requires the conformance to be stated in the same file where the `enum` is declared, then that capability is effectively something that should be considered to be an innate characteristic of the type

By that same token, though, doesn't it stand to reason that synthesis of Swift code for C-imported types is exactly that area of responsibility which represents the innate characteristics of the type?

Certainly, I agree that there is no way for a C enum to "declare" itself as being case iterable, and as such, there is no inherent way for the C type to declare a desire for such a conformance to be synthesized, but that's purely a consequence of a Swift language feature that is missing in C – ie. it's not a deliberate type choice to be absent a case iterability.

As such, the only way for an original C type to declare its conformance with a Swift language feature such as CaseIterable, is for the conformance to be declared in a separate file shipped alongside the original in C — a separate file where CaseIterable is added in an extension and synthesized accordingly. Alternatively, a C-level type annotation would be necessary, or we can assume that NS\_CLOSED\_ENUM implies such a conformance (does such an assumption do any harm?).

---

<div class="post-metadata">

**Author:** ![allevato](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/allevato/32/385_2.png) [@allevato](https://forums.swift.org/u/allevato)\
**Post date:** [September 5, 2023, 6:26pm UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/9 "2023-09-05T18:26:14Z")

</div>

> [@lhunath](#):
>
> Alternatively, a C-level type annotation would be necessary, or we can assume that NS\_CLOSED\_ENUM implies such a conformance (does such an assumption do any harm?).

The bar for whether we allow something for C decls that we don't for Swift decls isn't "do[es no] harm", though. (I would argue that there is harm in treating some classes of declaration different from others, in terms of how you reason about the code.) Typically we shouldn't synthesize any conformances that aren't explicitly requested by the author, and when there are exceptions (like `Equatable/Hashable` being synthesized implicitly for raw-value enums), since those precede the ability to synthesize `Equatable/Hashable` in general, the broad view is that if the general synthesis had come _first_, then we wouldn't implicitly synthesize those either.

For what it's worth, there's a capability in ClangImporter that lets C/Objective-C code declare custom attributes that should be injected when it's imported into Swift. From NSObjCRuntime.h:

```swift
   // Indicates that the thing it is applied to should be imported as 'Sendable' in Swift:
   // * Type declarations are imported into Swift with a 'Sendable' conformance.
   // * Block parameters are imported into Swift with an '@Sendable' function type. (Write it in the same place you would put 'NS_NOESCAPE'.)
   // * 'id' parameters are imported into Swift as 'Sendable', not 'Any'.
   // * Other object-type parameters are imported into Swift with an '& Sendable' requirement.
# define NS_SWIFT_SENDABLE __attribute__ ((swift_attr("@Sendable")))

```

I wonder if some variation of this, which could be used to add a conformance to the originating _C_ declaration, might be more palatable than trying to make it work from Swift. (If that's a direction someone wanted to explore, it should still only apply to `NS_CLOSED_ENUM`.)

---

<div class="post-metadata">

**Author:** ![beccadax](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/beccadax/32/34217_2.png) [@beccadax](https://forums.swift.org/u/beccadax)\
**Post date:** [September 5, 2023, 6:52pm UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/10 "2023-09-05T18:52:39Z")

</div>

There are code size reasons to not automatically synthesize `CaseIterable`, or indeed other conformances like `Equatable`, `Hashable`, and `CustomStringConvertible`, on un-annotated imported types. Specifically, there are _two_ code size reasons, and their relationship is multiplicative:

1. Because of dynamic casting, you can't actually tell which types you need a conformance for, so you end up having to create conformances for every eligible type on the off chance there's an `as?` cast somewhere that needs it.
2. What's worse, there's no central place to emit these conformances where all clients of a given module will see it, so _every_ client has to emit a conformance for _every_ imported type it can see.

A typical AppKit/UIKit/SwiftUI app or framework imports thousands of Objective-C types and uses only a small fraction of them, so you can see how this would quickly balloon code size—and every time you split your project into smaller frameworks, the problem would get worse, because each of those frameworks would have to emit its own set of conformances.

Having said that, it _would_ be practical to make it so that the Swift overlay of an Objective-C module, or the Swift half of a mixed-language target, could declare an extension with a conformance and no implementation to apply the automatic synthesis logic that's used for pure Swift types. This would avoid both halves of the code-size issue: the code is only generated for types that opt in, and the generated code is emitted into one module and shared by all clients.

> [@allevato](#):
>
> (If that's a direction someone wanted to explore, it should still only apply to `NS_CLOSED_ENUM`.)

This approach—where only the module or its overlay would be able to synthesize the conformance—would work alright for `NS_ENUM` and `NS_TYPED_ENUM` too. After all, if the module added a case the automatic synthesis would update `allCases`, and the Swift implementation should always match the Objective-C frameworks in use in the process.

(And yes, it would still be valid to have private cases that wouldn't appear in `allCases`, but…so what? `CaseIterable` is a convenience; it doesn't promise that there are no values that would match `@unknown default`.)

---

<div class="post-metadata">

**Author:** ![Jumhyn](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/jumhyn/32/3891_2.png) [@Jumhyn](https://forums.swift.org/u/Jumhyn)\
**Post date:** [September 5, 2023, 7:42pm UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/11 "2023-09-05T19:42:45Z")

</div>

> [@beccadax](#):
>
> (And yes, it would still be valid to have private cases that wouldn't appear in `allCases`, but…so what? `CaseIterable` is a convenience; it doesn't promise that there are no values that would match `@unknown default`.)

Just want to reiterate from [above](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/5) that to my reading, this is contradicted by the docs. As currently presented, it would IMO be a violation of documented `CaseIterable` semantics for a type to admit values which do not appear in the `allCases` collection.

---

<div class="post-metadata">

**Author:** ![dnadoba](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/dnadoba/32/11438_2.png) [@dnadoba](https://forums.swift.org/u/dnadoba)\
**Post date:** [September 5, 2023, 8:23pm UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/12 "2023-09-05T20:23:54Z")

</div>

I have run into that recently as well while defining structs and enums in C that are shared between Metal and Swift. I'm owning these types and it would be nice to somehow get Equatable and Hashable conformance synthesised. I don't mind adding attributes to the C definition at all. This appears to be working for enums if I declare them using NS\_ENUM like that:

```plaintext
#ifdef __METAL_VERSION__
#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#else
#import <Foundation/Foundation.h>
#endif /* __METAL_VERSION__ */

typedef NS_ENUM(uint8_t, Foo) {
    bar,
    baz
};

```

but I haven't found a way to do the same with structs. I could image we could add another attribute to also make C enums conform to `CaseIterable`.

Edit: just resized that enums in Swift get this kind of for free anyway and you don't actually need the `NS_ENUM` but can use e.g. ` __attribute__ ((enum_extensibility(closed)));` instead.

---

<div class="post-metadata">

**Author:** ![FxFactory](https://sea2.discourse-cdn.com/swift/user_avatar/forums.swift.org/fxfactory/32/21398_2.png) [@FxFactory](https://forums.swift.org/u/FxFactory)\
**Post date:** [June 17, 2025, 3:18pm UTC](https://forums.swift.org/t/caseiterable-for-c-imported-enums/67116/13 "2025-06-17T15:18:51Z")

</div>

Since the original post, has there been any traction behind adding the following:

`# define NS_SWIFT_CASEITERABLE __attribute__ ((swift_attr("CaseIterable")))`

...to allow developers to explicitly ask for automatic `CaseIterable` conformance for C/Obj-C enums that are known to be needed in Swift, with CaseIterable conformance? Thx!
