Skip to content

[Sema] Crash fix for nested type named identically to coding key #14548

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

Merged
merged 1 commit into from
Feb 12, 2018

Conversation

gregomni
Copy link
Contributor

Code to derive Codable was assuming any decl lookup of a coding key would be a VarDecl, now does the right thing in the presence of identically named other declarations (like nested types).

Resolves SR-6886.

… be a

VarDecl, now does the right thing in the presence of identically named other
declarations (like nested types).
@gregomni
Copy link
Contributor Author

@swift-ci Please smoke test and merge.

@swift-ci swift-ci merged commit d3e0284 into swiftlang:master Feb 12, 2018
@itaiferber
Copy link
Contributor

I agree that crashing is bad, but how is this going to affect ill-formed code which used to crash but might now compile? i.e. we could be skipping over more "local" invalid decls which should produce diagnostics until we happen to find some VarDecl found in an outer scope, and synthesize based on that, no?

I'm trying to think of a concrete example, but it would be nice to verify with more extensive unit tests I think — at the very least some more deeply nested structs which might happen to find VarDecls from outer scopes even though decls closer by would be invalid and we should diagnose on.

@itaiferber
Copy link
Contributor

itaiferber commented Feb 14, 2018

To assuage my own concerns here — this only affects property lookup after CodingKeys validation is done. The following code fails validateCodingKeysEnum because that does direct property lookup via target->getStoredProperties:

struct Foo {
    struct Bar {
        struct Baz : Codable {
            private enum CodingKeys : CodingKey {
                case Bar
            }
        }
    }

    var Bar: String
}

The above produces

NestedStruct.swift:3:16: error: type 'Foo.Bar.Baz' does not conform to protocol 'Decodable'
        struct Baz : Codable {
               ^
Swift.Decodable:9:12: note: protocol requires initializer 'init(from:)' with type 'Decodable'
    public init(from decoder: Decoder) throws
           ^
NestedStruct.swift:5:22: note: CodingKey case 'Bar' does not match any stored properties
                case Bar
                     ^
NestedStruct.swift:3:16: error: type 'Foo.Bar.Baz' does not conform to protocol 'Encodable'
        struct Baz : Codable {
               ^
Swift.Encodable:12:17: note: protocol requires function 'encode(to:)' with type 'Encodable'
    public func encode(to encoder: Encoder) throws
                ^
NestedStruct.swift:5:22: note: CodingKey case 'Bar' does not match any stored properties
                case Bar
                     ^

I was afraid that case Bar would reach out to match var Bar from Foo, but that isn't the case here.

I still think this is worth adding a unit test for so we don't regress in the future, but this has already been merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants