Skip to content
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

Swift Archival & Serialization API #9004

Merged
merged 10 commits into from
Apr 29, 2017

Conversation

itaiferber
Copy link
Contributor

@itaiferber itaiferber commented Apr 25, 2017

What's in this pull request?
Now that the core types introduced by SE-0166 have been sunk into the Swift standard library, the stdlib and compiler portions of #8124 and #8125 can be combined into one PR (this one).

The features can be tested together; #8125 was previously not tested on its own since it required the presence of #8124.

The Foundation portions of #8124 will be put up in a subsequent PR.

rdar://problem/30472044

Itai Ferber added 2 commits April 25, 2017 13:04
Add Encodable and Decodable protocols, along with associated container
types, default implementations, and extensions to the standard library
* Allow CodingKey conformance to be automatically derived for enums
  which have no raw type (with no associated values) and which have
  a raw type of String or Int.
* Allow Encodable and Decodable conformance to be automatically derived
  for classes and structs with Encodable/Decodable properties
* Add initial unit tests for verifying derived conformance
Since all of the core types are now in the Swift stdlib, the tests no
longer rely on objc_interop or Foundation.
@itaiferber
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 22185d2
Test requested by - @itaiferber

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 22185d2
Test requested by - @itaiferber

@itaiferber
Copy link
Contributor Author

I'm not sure these test failures are actually related to my changes. On Linux we're getting failures like error: 'Iterator' is not a member type of 'Sequence', and on macOS, the failing tests are SourceKit. The Linux failures are more worrisome to me though; anyone know what's going on there?

@itaiferber
Copy link
Contributor Author

Let's try again

@itaiferber
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 22185d2
Test requested by - @itaiferber

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 22185d2
Test requested by - @itaiferber

/// - throws: `DecodingError.typeMismatch` if the encountered encoded value is not convertible to the requested type.
/// - throws: `DecodingError.keyNotFound` if `self` does not have an entry for the given key.
/// - throws: `DecodingError.valueNotFound` if `self` has a null entry for the given key.
func decode<T : Decodable>(_ type: T.Type, forKey key: Key) throws -> T

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@itaiferber great proposal, can't wait to start using this. But I have a question: wouldn't be better to drop the type from the parameters and just use inference here? Something like:

func decode<T : Decodable>(_ key: Key) throws -> T

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Obitow Thanks!

This point has been discussed at length on swift-evolution; dropping the type parameter can lead to ambiguous statements, which can be confusing and unintuitive. Please feel free to refer to those discussions for the full story.

@itaiferber
Copy link
Contributor Author

@atrick @gottesmm Looks like the tests are failing in SIL validation on Linux and the errors are kind of bizarre: e.g. error: 'Iterator' is not a member type of 'Sequence'. Any idea about what's going on here/how I can address this?

@itaiferber
Copy link
Contributor Author

Perhaps we can try the smoke tests at least?

@itaiferber
Copy link
Contributor Author

@swift-ci Please smoke test

@itaiferber
Copy link
Contributor Author

It's possible that Sequence : Swift.Sequence was causing ambiguity when generating SIL. I've changed that; let's see if that's caused any changes in the tests. Once more with vigor...

@itaiferber
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 53d82b1
Test requested by - @itaiferber

@itaiferber
Copy link
Contributor Author

Looks like the Sequence change did fix the SIL tests. The SourceKit tests are still failing though.

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 53d82b1
Test requested by - @itaiferber

Itai Ferber added 3 commits April 27, 2017 10:56
struct X : Codable {} should generate an encode(to:) which encodes an
empty keyed container, not an encode(to:) which does nothing
Extensions need not have nominal types, e.g.

    extension Int : Codable { ... }

where

    typealias Codable = Encodable & Decodable
@itaiferber
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 53d82b1
Test requested by - @itaiferber

@DougGregor
Copy link
Member

It seems like a bug like this in the actual AST (e.g., duplicated initializers) would cause everything to break horribly, so it feels like a SourceKit bug.

You shouldn't need to be Codable in order to get these implementations;
being either Encodable or Decodable should be enough to get the relevant
default implementation
@itaiferber
Copy link
Contributor Author

itaiferber commented Apr 28, 2017

This last commit doesn't fix the issue, but if I'm already looking at the extensions... (Let's split them up so you can benefit even by just being Encodable or Decodable.) Still waiting to hear back on SourceKit though.

///
/// - parameter lhs: The key to compare against.
/// - parameter rhs: The key to compare with.
public static func ==(_ lhs: CodingUserInfoKey, _ rhs: CodingUserInfoKey) -> Bool {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd meant to split this out into a different commit, but it made it in here anyway. CodingUserInfoKey was missing ==, but the compiler didn't complain.

@itaiferber
Copy link
Contributor Author

Per @akyrtzi's suggestion via email, going to update the test to prevent this from blocking us and file a Radar about it.

@itaiferber
Copy link
Contributor Author

@swift-ci Please test

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 4c23207
Test requested by - @itaiferber

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test Linux Platform
Git Commit - 4c23207
Test requested by - @itaiferber

@itaiferber
Copy link
Contributor Author

Build failed with an unrelated issue that's been reverted; let's try again.

@itaiferber
Copy link
Contributor Author

@swift-ci Please test

@itaiferber
Copy link
Contributor Author

For interested Apple folks, BTW, rdar://31896858

@swift-ci
Copy link
Contributor

Build failed
Jenkins build - Swift Test OS X Platform
Git Commit - 433c192
Test requested by - @itaiferber

@itaiferber
Copy link
Contributor Author

itaiferber commented Apr 28, 2017

Looks like a Migrator test is failing for the iOS simulator: Migrator/wrap_optional.swift
Looking into it.

@itaiferber
Copy link
Contributor Author

The builder is producing a module file for the incorrect target? error: module file was created for incompatible target x86_64-apple-macosx10.9

@itaiferber
Copy link
Contributor Author

@shahmishal @DougGregor This... Seems wrong. Any idea why this might happen?

@itaiferber
Copy link
Contributor Author

Seems like https://ci.swift.org/view/Pull%20Request/job/swift-PR-osx/ failed with this as well...

@itaiferber
Copy link
Contributor Author

Waiting on #9113 before testing again.

@itaiferber
Copy link
Contributor Author

Let's try that again

@itaiferber
Copy link
Contributor Author

@swift-ci Please test

@itaiferber
Copy link
Contributor Author

itaiferber commented Apr 29, 2017

Excellent. @parkera @DougGregor If either of you sees this, can you please merge it in?

@DougGregor DougGregor merged commit 447dce6 into swiftlang:master Apr 29, 2017
@itaiferber
Copy link
Contributor Author

Thanks @DougGregor!

@itaiferber itaiferber deleted the swift-archival-serialization branch April 29, 2017 03:03

// An implementation of _KeyedEncodingContainerBase and _KeyedEncodingContainerBox are given at the bottom of this file.
/// `KeyedEncodingContainer` is a type-erased box for `KeyedEncodingContainerProtocol` types, similar to `AnyCollection` and `AnyHashable`. This is the type which consumers of the API interact with directly.
public struct KeyedEncodingContainer<K : CodingKey> {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@itaiferber Should KeyedEncodingContainer declare KeyedEncodingContainerProtocol conformance?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can, but I don't see much of a benefit to doing so. When would you want to use it as KeyedEncodingContainerProtocol instead of the fully-typed KeyedEncodingContainer<K>?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, you are right. I can not think of such a scene.
I just wondered watching KeyedDecodingContainer declared asKeyedDecodingContainerProtocol.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — I don't think that's really necessary either. It doesn't hurt, but we should be consistent. I'll consider this; thanks!


/// Decodes a value of the given type for the given key, if present.
///
/// This method retu
Copy link
Contributor

@norio-nomura norio-nomura May 10, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@itaiferber Why is it mutating only for decode() of UnkeyedDecodingContainer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UnkeyedDecodingContainers need to maintain some form of state to keep track of where they are in decoding, whether an index into an array that's incrementing with every decode(...) call, an offset into a data blob or stream, etc. The methods are mutating to indicate that, and to allow the implementation to be a struct. This is as opposed to KeyedDecodingContainers and SingleValueDecodingContainers, which by design will almost certainly not need to do that. Is there a use case you have in mind for making those mutating as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Certainly, I could not think of any reason to make decode() of another protocol mutating as well.
Thank you for answering my boring questions. 🙏

Copy link
Contributor Author

@itaiferber itaiferber May 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not at all! Thank you for paying such close attention to this; it's the best way for us to get direct feedback on it, and I appreciate your efforts. 😄

@norio-nomura
Copy link
Contributor

I filed SR-4861 that request adding encode<T>(_:) and decode<T>(_:) to SingleValueEncodingContainer and SingleValueDecodingContainer.

@itaiferber
Copy link
Contributor Author

@norio-nomura Thanks, assigned that to myself. That change, among a few others, is planned, and going through some API review soon.

Copy link
Contributor

@Jceciliani Jceciliani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All committed changes appear correct after review.

let _ = SimpleChildClass.CodingKeys.self // expected-error {{'CodingKeys' is inaccessible due to 'private' protection level}}

// The enum should have a case for each of the vars.
// NOTE: This expectedxerror will need to be removed in the future.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Small text fix needed in comment. "//NOTE: This expected error will need to be removed in the future."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! #16749

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.

7 participants