-
Notifications
You must be signed in to change notification settings - Fork 460
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
Revisit Error handling #1223
Comments
#987 was tripped up by some of this. |
I think some of the other Apple OSS packages (ArgumentParser?, docs?), dodged some of this by dropping the enums and using structs with statics (or something like that). |
NIO has tried to adopt this as well. I'm in the process of trying to do some Thought Leadership(tm) about how to do this in the OSS ecosystem, but I wouldn't expect this to land in the near future. But yeah, |
@Lukasa any updates on guidance? |
Yeah so our preferred pattern now looks like something like this: struct ProtobufError: Error, Hashable, CustomStringConvertible {
public var errorCode: ErrorCode
public var sourceLocation: SourceLocation {
return self.backingStorage.sourceLocation
}
public var errorDescription: String {
return self.backingStorage.errorDescription
}
private let backing: BackingStorage
init(errorCode: ErrorCode, description: String, file: String = #file, line: UInt = #line, function: String = #function) {
self.errorCode = errorCode
self.sourceLocation = SourceLocation(file: file, line: line, function: function)
self.description = description
}
public static func ==(lhs: ProtobufError, rhs: ProtobufError) -> Bool {
return lhs.errorCode == rhs.errorCode
}
public static func hash(into hasher: inout Hasher) {
hasher.combine(errorCode)
}
public var description: String {
return "ProtobufError(errorCode: \(errorCode), description: \(description), file: \(sourceLocation.file), line: \(sourceLocation.line), function: \(sourceLocation.function))"
}
}
extension ProtobufError {
public struct ErrorCode: Hashable, CustomStringConvertible {
private enum Backing: Hashable {
case errorOne // your names go here
case errorTwo
}
private var backing: Backing
init(_ backing: Backing) {
self.backing = backing
}
public static let errorOne = Self(.errorOne)
public static let errorTwo = Self(.errorTwo)
public var description: String {
return String(describing: backing)
}
}
}
extension ProtobufError {
public struct SourceLocation {
public var file: String
public var line: UInt
public var function: String
}
}
extension ProtobufError {
final class BackingStorage {
var sourceLocation: SourceLocation
var errorDescription: String
init(errorDescription: String, sourceLocation: SourceLocation) {
self.sourceLocation = sourceLocation
self.errorDescription = errorDescription
}
}
} This is an annoyingly large amount of code but it maximises the utility of the error. The |
If we're going to do this, it seems logical to also look at #580 & #581 at the same time. So the meta question is of all of our different Error enums, which ones do we want to add the context like The current TextFormat and JSON parsing probably does't even have complete offset tracking (because of creating nested objects in contexts) let along line/column info. Binary errors could attempt context via byte offsets. And just about all of them might in theory be able to do something about a field number path to where the serialization/parsing failed, but that's potentially a lot of temp data to build/throw away in non error cases. @Lukasa I guess there is no way to do something like associated data since things aren't enums any more? So things like unknown enum names (TextFormat/JSON) would just go into the description? Or we just use 2.x to get away from @Lukasa @tbkka @allevato @FranzBusch thoughts? |
Broadly, yes. You can achieve some amount of this by having computed properties with optional return values where the return is only non- |
This is happening via #1612 |
I guess since we have a new model, we can call it this done and track the migration in the other issue. |
Since the library uses enums for errors, it means cases can't be added without breaking things; might be nice to revisit this model to see if something can be done to improve things.
The text was updated successfully, but these errors were encountered: