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

added Linux compatibility #132

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 18 additions & 19 deletions Sources/DecodingError.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,52 +9,52 @@
import Foundation

public enum DecodingError: Error, Equatable {

/// `DecodingError.Metadata` provides information about
/// where an `DecodingError` was thrown in the JSON
/// where an `DecodingError` was thrown in the JSON
/// object graph.
public struct Metadata: Equatable {

public init(path: [String] = [], object: Any, rootObject: Any? = nil) {
self.path = path
self.object = object
self.rootObject = rootObject
}

/// The JSON key path to the object that failed to be decoded
public var path: [String]

/// The JSON object that failed to be decoded
public let object: Any

/// The root JSON object for which the `path` can be used to find `object`
public var rootObject: Any?

/// Represents the path to the object that failed decoding with "." as a separator.
public var formattedPath: String {
return path.joined(separator: ".")
}
}

/// Thrown when optional casting from `Any` fails.
///
/// This can happen both when trying to access a key on a object
/// that isn't a `NSDictionary`, and failing to cast a `Castable`
/// primitive.
case typeMismatch(expected: Any.Type, actual: Any.Type, Metadata)

/// Thrown when a given, required, key was not found in a dictionary.
case missingKey(String, Metadata)

/// Thrown from the `RawRepresentable` extension when
/// `init(rawValue:)` returned `nil`.
case rawRepresentableInitializationError(rawValue: Any, Metadata)
/// When an error is thrown that isn't `DecodingError`, it

/// When an error is thrown that isn't `DecodingError`, it
/// will be wrapped in `DecodingError.other` in order to also provide
/// metadata about where the error was thrown.
case other(Error, Metadata)

public var metadata: Metadata {
get {
switch self {
Expand All @@ -68,7 +68,7 @@ public enum DecodingError: Error, Equatable {
return metadata
}
}

set {
switch self {
case let .typeMismatch(expected, actual, _):
Expand All @@ -83,7 +83,7 @@ public enum DecodingError: Error, Equatable {
}

}

public var debugDescription: String {
switch self {
case let .typeMismatch(expected, actual, metadata):
Expand All @@ -96,7 +96,7 @@ public enum DecodingError: Error, Equatable {
return "\(error)"
}
}

}


Expand All @@ -110,9 +110,9 @@ public func ~=<T>(lhs: T.Type, rhs: Any.Type) -> Bool {

// FIXME: I'm not sure about === equality
public func ==(lhs: DecodingError.Metadata, rhs: DecodingError.Metadata) -> Bool {
return lhs.object as AnyObject === rhs.object as AnyObject
return lhs.object as? AnyObject === rhs.object as? AnyObject
&& lhs.path == rhs.path
&& lhs.rootObject as AnyObject === rhs.rootObject as AnyObject
&& lhs.rootObject as? AnyObject === rhs.rootObject as? AnyObject
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

Looking at this change, the problem I see with it is if the cast to AnyObject fails for both sides, then the operator will return true even though they may be different objects.

I'm not sure, but with Swift 3, is it possible to use as Any instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Well, AnyObject is supposed to represent reference types. Technically, since DecodingError.Metadata(both lhs and rhs is a struct, this should fail 🤔. Can you confirm @Anviking ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Also, of note, this comment

// FIXME: I'm not sure about === equality
We may be right about this 😅

Copy link
Collaborator

Choose a reason for hiding this comment

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

Yeah, ok, so looking at this, the objects in the meta are Any, so this is trying to convert to a ref type so it can compare pointers (the === operator). I think. This may also be a holdover from the swift 2.x codebase that is no longer necessary.

I'll check to see if we can use === on Any in swift 3.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Ok, confirmed. One cannot use === on Any

We're going to have to think up a different bit of logic to make this right.

Copy link
Collaborator

Choose a reason for hiding this comment

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

The only real problem with the as? is that it generates a warning: "Any to AnyObject always succeeds"

Copy link
Contributor Author

@codeOfRobin codeOfRobin Nov 20, 2016

Choose a reason for hiding this comment

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

The only real problem with the as? is that it generates a warning: "Any to AnyObject always succeeds"

When you think about it, this shouldn't be true. What happens when you cast a struct to AnyObject ?

Copy link
Owner

@Anviking Anviking Nov 20, 2016

Choose a reason for hiding this comment

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

When you think about it, this shouldn't be true. What happens when you cast a struct to AnyObject ?

On linux, no, on macOS and iOS, yes:

 28> struct A {}
 29> let a = A()
a: A = {}
error: could not fetch result -- error: Couldn't apply expression side effects : Couldn't dematerialize a: corresponding symbol wasn't found

 30> a as AnyObject
$R2: AnyObject = {
  instance_type = 0x0000000101001220
}

This looks like a swift language bug/inconsistency to me. If nothing else, we could use #if os to limit warnings to linux.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, I think using if OS and adding an issue on https://github.com/apple/swift should be good enough for now.

Copy link
Owner

Choose a reason for hiding this comment

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

public func ==(lhs: DecodingError, rhs: DecodingError) -> Bool {
Expand Down Expand Up @@ -140,4 +140,3 @@ public func ==(lhs: DecodingError, rhs: DecodingError) -> Bool {
return false
}
}