-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
9ed9826
commit 576003f
Showing
2 changed files
with
28 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
576003f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adam-fowler Can I ask what the motivation was for this change?
It doesn't seem make any difference internally, and in my code which uses this library, it just makes the errors harder to catch.
Unless I'm missing something? I haven't seen any best-practices or anything swimming around the Swift forums, but maybe I've missed it.
576003f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@justinpawela the reason for the change is so the error type can be extended without generating a breaking change that requires a major version release.
Extending an enum ie adding a case is considered a breaking change. By changing the error to a struct we can add new errors without causing a breaking change.
576003f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For some context here is a pitch for extensible enums that never made it https://forums.swift.org/t/extensible-enumerations-for-non-resilient-libraries/35900
576003f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@adam-fowler Thanks for your time responding and for providing the link to the forums discussion. I understand what you mean about the breaking change. However...
To me, this feels like a circumvention of one of the benefits of Swift enums in control flow. To be able to exhaustively handle (or catch) all
DecodingError
s is a feature of Swift pattern matching, not a language hole to be worked around. If I, as a library user, care deeply enough about the specific case ofDecodingError
to try to handle (or catch) the cases individually, I want my code not to compile if the library adds a new case. If I didn't care, I wouldn't be examining the cases individually, and any new cases wouldn't affect my build anyway.I do realize this creates more burden on library users, but it should be a welcome burden. I also realize it creates more burden on library maintainers, but strong typing, type safety, and pattern matching exhaustivity are all core advantages of Swift, and working around them to avoid having to do a major version bump feels, to me, a bit like pushing the burden of uncertainty onto library users. With this change, if I care about catching specific cases of
DecodingError
, I will always have to check the release notes/source code when this package is updated, because I won't be able to rely on switch/catch exhaustivity checks.From my point of view, moving to a 1.0 release should be a time when we feel more comfortable with the group of error cases we expect to be throwing. Not a time to be adding an escape hatch to be able to add more error cases without doing major version bumps.
Also, a more concrete concern: I used to be able catch (or switch on) any
.invalidCharacter
error like this:or:
But now I cannot really handle or catch an
.invalidCharacter
error at all, because it is a function, not a value. Or I have to match specifically on each of the 191 remaining character codes. I can't even do ranges or anything because the storage is hidden away in the private_Internal
enum.Anyway, thanks for your time discussing this, for the contributions you've made to this package, and for your contributions to Swift server in general. You've made a big impact on the ecosystem.
576003f
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately extendable error types are a reality in Swift library development.
But given all that I may have made a mistake in this case. The pattern of replacing enum Errors with structs only really works for enums that don't have associated values. We have a number of options here.
Base64.DecodingError
and replace with original enuminvalidCharacter(UInt8)
and replace with a new case that doesn't include the characterinvalidCharacter(UInt8)
and replace with a new Error type