New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SR-7897] Synthesized CodingKeys enum should conform to CaseIterable #50432
Comments
/cc @CodaFi, @itaiferber |
If we synthesize Even so, though, I don't think that making synthesized If we do do this, we should likely pitch this and go through the Swift Evo review process. |
I'm with Itai on this one. CaseIterable generates extra code that can't be optimized away (because it's part of the conformance). |
Comment by Nick DiZazzo (JIRA) It might make sense to be able to do something like: struct MyType: Codable {
var one: String = "a"
var two: Int = 1
}
extension MyType.CodingKeys: CaseIterable { }
let a = MyType()
print(a.CodingKeys.allCases) ... but this won't work. Even if you try to do something like: I was chatting with @DougGregor about this, and it seems like this should work... |
My concrete poor wording aside: there should be a way to make these features work together. If automatic conformance for all synthesized {{Codable}}s is undesirable for various reasons, there should be an alternative way to request this manually. Right now there isn't. |
@moiseev That I agree with — this is one case of a more general limitation of not being able to extend a private you don't have access too; I'm trying to hunt for a recent JIRA where we were discussing exactly this type of extension in a different context. I'll see if I can pull it up. It would be nice to be able to extend nested private types in the context where they're defined, or special-case synthesized types in this way if this isn't generalizable. |
@belkadan is there some reason why we can't extend a private type the way ndizazzo (JIRA User) and I tried? It seems to me like you should be able to extend a private type within the same file (under the Swift 4+ definition of private, of course). |
The logic is that the extension itself is at top-level, which is outside the type. I don't think that's so important in this case, but we'd want to be careful about it. Consider code like this:
or this
|
Right, we need to decide whether the types following the colon are in the file's access scope (so one cannot refer to private members) or in the extension's access scope. The latter is more permissive, and I don't think it causes any problems, but I also don't have a compelling use case for it. |
I found the discussion I'd tried to drag up earlier, BTW — it wasn't in JIRA, but on the Swift forums: Extensions to private nested types I don't know what would be a bigger departure here from the current state: permitting external extensions like Jordan brings up, or changing the grammar to allow for extensions of nested types within the scope that they're nested in, e.g. struct Foo : Codable {
private extension CodingKeys { /* ... */ }
} We currently only allow extensions at file scope, but we could skirt around the permissions issue by allowing extensions in nested scopes only for nested types (in a way that matches their existing visibility). |
That would be a pretty drastic change because extension binding happens before most of the rest of type-checking. That relies on being able to find all the extensions. |
Hmm. Would constraining this to require extensions on types to be at most as nested as the type itself be helpful in that regard? For instance, I don't think we should allow any of the following extensions: struct Foo {
struct Bar {
extension Foo { /* ... */ }
}
extension Foo { /* ... */ }
}
struct Baz {
extension Foo { /* ... */ }
} Conversely, you are allowed to extend a nested type outside of its nesting if visibility applies, as today. Or are you saying that we are going the other way around — we first look for all extensions, bind them, then go through type checking? (if so, then yes, this seems like a big departure no matter how we handle it. e.g. look through all file-scope extensions first, then start type checking, then apply nested extensions; or, search through all scopes everywhere for extensions, then do type-checking as usual; or, change the model to look at types and find all extensions in context; etc.) |
Comment by Alexander Zaytsev (JIRA) Might not be the right forum for this, so I apologize if so, but this bug is one of the top hits for `CodingKeys CaseIterable` on Google. What i found is that at least at runtime to iterate over the cases in the `private` CodingKeys we can use Mirror API, like so let mirror = Mirror(reflecting: self)
for child in mirror.children {
if let lbl = child.label {
print(Me.CodingKeys(stringValue: lbl))
}
} |
Comment by Adam Rocska (JIRA) zaitsman (JIRA User) 🙂 CaseITerable provides a static variable, what you describe is a runtime instance level thing. You can't reflect the enum cases on a Type level either, so that's also shot in the foot. Though of-course it's a nice construct and could have solved your issue, it still doesn't address the main issue. |
Additional Detail from JIRA
md5: 9bbce0d23efee7c88533a728306bd187
Issue Description:
These two features were added separately, but would actually be so much more useful when combined.
There is no simple way of getting a list of all the fields in this struct, even though
CodingKeys
enum gets synthesized.The text was updated successfully, but these errors were encountered: