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

Type 'UInt64' does not conform to protocol 'IntegerNumber' #22

Open
nirmalpatidar123 opened this issue Aug 30, 2024 · 1 comment
Open

Comments

@nirmalpatidar123
Copy link

I'm getting error in my xcode project when I have used the latest version of Hedera SDK Swift so I checked it uses the latest version of NumberKit library which causing this issue.

Here is the link for issue created on Hedera SDK Swift

@objecthub
Copy link
Owner

This is related to a bug fix I did recently, which apparently has lead to a similar bug being introduced in the Hedera SDK (probably long ago). NumberKit used to contain the following code:

extension UInt64: IntegerNumber {
   public var doubleValue: Double {
     return Double(self)
   }
}

This is semantically incorrect, because IntegerNumber is representing signed integers (and uses the corresponding Swift protocols). Unfortunately, the Swift compiler wasn't able to detect this broken protocol compliance so far and the erroneous code was not noticed. With Swift 6 (which is the default soon), this broken compliance will be reported as a warning and my guess is that eventually, this will become an error.

Unfortunately, the Swift Hedera API contains a similar erroneous definition when extending Rational (these are signed rational numbers — see the comment in the NumberKit implementation of Rational):

extension Rational: ProtobufCodable where T == UInt64 {
    internal typealias Protobuf = Proto_Fraction

    internal init(protobuf proto: Protobuf) {
        self.init(UInt64(proto.numerator), UInt64(proto.denominator))
    }

    internal func toProtobuf() -> Protobuf {
        .with { proto in
            proto.numerator = Int64(self.numerator)
            proto.denominator = Int64(self.denominator)
        }
    }
}

And the fact that the code needs to cast the values multiple times between UInt64 and Int64 shows that negative rationals are guaranteed to crash the application. This is a bug that needs to be fixed in the Hedera API. My guess is that the following change will do the trick, but I have no idea if this is backward compatible:

extension Rational: ProtobufCodable where T == Int64 {
    internal typealias Protobuf = Proto_Fraction

    internal init(protobuf proto: Protobuf) {
        self.init(proto.numerator, proto.denominator)
    }

    internal func toProtobuf() -> Protobuf {
        .with { proto in
            proto.numerator = self.numerator
            proto.denominator = self.denominator
        }
    }
}

To silence the error you get for now, there are two options:

  1. You add the first code snippet of this post to your code/the Swift Hedera API: this is bringing back the broken compliance, but your code compiles. You will get the warning I talked about when switching to Swift 6.
  2. You replace this line in Package.swift of the Swift Hedera API: .package(url: "https://github.com/objecthub/swift-numberkit.git", from: "2.4.1") with .package(url: "https://github.com/objecthub/swift-numberkit.git", exact: "2.5.1"). Everything will work as before, but you won't automatically include further changes to NumberKit.

I'd also be willing to consider changes to NumberKit, e.g. by bringing back the broken protocol compliance if compiled with Swift 5.X. Let me know if this is preferred.

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

No branches or pull requests

2 participants