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

[SR-7057] Decoding typedef NSString #49605

Open
krzyzanowskim opened this issue Feb 22, 2018 · 11 comments
Open

[SR-7057] Decoding typedef NSString #49605

krzyzanowskim opened this issue Feb 22, 2018 · 11 comments
Assignees
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. Codable Area → standard library: `Codable` and co. compiler The Swift compiler in itself

Comments

@krzyzanowskim
Copy link
Contributor

Previous ID SR-7057
Radar None
Original Reporter @krzyzanowskim
Type Bug
Environment

Xcode 9.3 beta 3 (9Q117m)

Additional Detail from JIRA
Votes 0
Component/s Compiler
Labels Bug, ClangImporter, Codable
Assignee @itaiferber
Priority Medium

md5: 9368c6c21550e8abd87dedbbbda09089

Issue Description:

The struct imported from the Objective-C the code:

typedef NSString *Foo NS_TYPED_EXTENSIBLE_ENUM;
Foo const BarKey;

After import to Swift the `Foo` type is not Codable. It wasn't enforced in Swift 4.0, but it is in Swift 4.1

This can't be used with decoder (implementing

    public typealias RawValue = [Foo: Any]

    public init(from decoder: Decoder) throws {
        var unkeyedContainer = try decoder.unkeyedContainer()
        self.init(rawValue: try unkeyedContainer.decode(RawValue.self))!
    }

// error: type 'Foo' does not conform to protocol 'Encodable'

this code worked in Swift 4.0.3. Either it didn't work properly in Swift 4.0, or it isn't possible to import Foo as Codable. I'm feel confused.

@natecook1000
Copy link
Member

I don't think you can redefine the RawValue associated type like that—Foo gets imported as RawRepresentable with String as its RawValue. The following code compiles for me:

extension Foo : Codable {
  public init(from decoder: Decoder) throws {
    let unkeyedContainer = try decoder.singleValueContainer()
    self.init(try unkeyedContainer.decode(RawValue.self))
  }

  public func encode(to encoder: Encoder) throws {
    var container = encoder.singleValueContainer()
    try container.encode(self.rawValue)
  }
}

@natecook1000
Copy link
Member

You know what, I totally misread—you're talking about expecting Foo to be codable so that you can use it as the key in a codable dictionary.

That behavior has changed—in Swift 4.0 all dictionaries were "codable," but would fail at runtime if the keys weren't actually codable. In Swift 4.1 we have conditional conformance, so now only dictionaries with codable keys are themselves codable. It looks like that's what you're running into.

(It would make sense to me that enums imported from Objective-C would automatically be Codable, but I don't know if that's a regression from Swift 4.0 or not.)

@krzyzanowskim
Copy link
Contributor Author

Yea, totaly. I thing it could be codable for basic types.

also it shouldn't compile to you too as there is Any type in the dictionary.

@belkadan
Copy link
Contributor

Thanks, Marcin. The code you wrote can't have worked in Swift 4.0, because Any can't be decoded (even though that wasn't statically enforced). Can you find an example that actually did decode, so we know what we're looking for?

cc @itaiferber

@belkadan
Copy link
Contributor

@itaiferber: Currently a very limited set of protocols are mirrored over on NS_TYPED_EXTENSIBLE_ENUM wrappers – Equatable, Hashable, and ObjectiveCBridgeable. Should Codable be included as well?

@krzyzanowskim
Copy link
Contributor Author

@natecook1000 my fault, I extracted it from the code. right, for such type, I can't redefine the RawValue that way.

@krzyzanowskim
Copy link
Contributor Author

@belkadan I guess it never worked at runtime, just compiles. It'd be nice if it actually works automatically for basic types.

there is another though

```
@protocol Pro <NSObject>
@EnD
```

```
extension protocol Pro: Codable {}
```

the code compiles, but I believe it shouldn't unless there is some magic.

@itaiferber
Copy link
Contributor

@belkadan Potentially — I could see this being useful. However, other RawRepresentable types don't automatically get Codable conformance, so that'd be a bit magic. It's also relatively easy to create NS_TYPED_EXTENSIBLE_ENUM values which couldn't be Codable, so we'd need to be wary of that.

@itaiferber
Copy link
Contributor

@krzyzanowskim That code shouldn't compile — protocols can't be extended with conformance to other protocols. (Besides the syntax error of writing extension protocol.) Is that also in Swift 4.0.3? Doesn't work for me (correctly) in Swift 4.1

@krzyzanowskim
Copy link
Contributor Author

@itaiferber after deleting DerivedData it doesn't compile anymore (ufff) and presents the syntax error. Sorry about that, I was very confused.

@itaiferber
Copy link
Contributor

@krzyzanowskim That's alright — happens all the time. 🙂 In any case, about this issue specifically: I think we need to figure out a better way to make RawRepresentable things Codable by default. We have default implementations for primitive types, but you'd still have to write extension MyImportedEnum : Codable in order to benefit from it.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. Codable Area → standard library: `Codable` and co. compiler The Swift compiler in itself
Projects
None yet
Development

No branches or pull requests

4 participants