The specifics of our compiler with regard to overlapping conditional conformances and whether or not this could be achieved under the hood is not something I can speak to with confidence. “Unimplementable in Swift” is different from “incoherent” (not that you ever accused it of being incoherent).
I would disagree that Codable
conformance for Never
is either harmful or a shortcut. Instead, I think it's helpful to recognize that there's nothing truly exceptional about Never
— it really is only a type that has no instances, just like any no-case enum
that you could create yourself. (What makes Never
distinct is that it's declared in the standard library, so it's available to use at the API level without defining the type yourself.)
There's no inconsistency with having an uninstantiable type like Never
conform to a protocol that requires a throwing initializer, just as there would be none that requires a failable initializer, or a method that's impossible to call, because it's an instance method (like Hashable
requires, which Never
already conforms to) or a static method that takes an instance as a parameter (like Equatable
; ditto).
In all of these cases, we can provide implementations that fulfill both the implementation requirements and semantic requirements of the protocol. There isn't a disconnect in having Never
provide a failable or throwing initializer, because returning nil
and throwing an error are well-defined outcomes of calling those. There would be a different conversation about conformance to a protocol like RangeReplaceableCollection
or ExpressibleByStringLiteral
, where creating an instance is a core part of how the protocol is defined and used.
I believe I’m already thoroughly aware of the nature of Never
as it relates to this discussion and that that's not what's causing any sensations of not being on the same page.
A fine point. Throwing initializer requirements are semantically compatible with Never
.
I just realized that the above comments actually moved the goal posts without me noticing it in the moment.
All I wanted to know was if the reason for the relative silence about my proposed alternative was:
-- A) It has some fundamental flaw that I am missing and therefore was not ever really an alternative.
-- B) It is seen as a worse (but coherent) alternative.
-- C) Something else.
I think the answer is option B. That’s all I wanted to know. I was surprised that no one had at least acknowledged that it was a genuine and coherent (even if demonstrably worse) alternative, which made me wonder if maybe it wasn't. I was especially surprised at the lack of acknowledgment since I thought I had a pretty convincing argument that in the philosophical realm it is the correct answer, even if it's not worth the time to engineer it.
If the answer is option B and someone besides me has any interest in exploring whether or not my suggestion is definitely worse, that would be the point at which to try to make an argument that the current pitch is “harmful” or that my pitch is more “philosophically correct”. But I was only meaning to elicit the answer to the question “A, B or C?”, which is why I say that challenging me in that moment to prove that the current pitch is harmful was moving the goal posts.
On the issue of how much I have lengthened the discussion in this thread ...
On the one hand I don't at all like the feeling of single-handedly dragging out what might have been a simple and concise review thread into something arduous, especially if it's also fruitless in the end.
On the other hand, in general, I put a lot my own energy and thought into all kinds of things on these forums and as far as I understand it is generally appreciated that the we the enthusiastic users of Swift are willing to do that for free, so when I have the sensation of having my main point either completely ignored or responded to in ways that demonstrate that the point was missed I feel a strong urge to try to clarify, if nothing else just to maintain my belief that as long as I'm carefully articulate here on the forums then my cohort of like-minded peers will discern my point and we'll all work together to make sure that as many valid arguments as possible are on the table before making a decision. If that belief were to erode I believe I would quickly stop contributing.
Anyway, I'm very open to the idea that I took the counter-argumentation too far here, though I'm not currently sure exactly what change in my behavior would be appropriate to implement, specifically because of what I wrote in the previous paragraph.
IMO the conceptual simplicity of "the whole can synthesize a Codable
conformance when all its constituent parts do" as a rule is far more compelling than "the whole can synthesize a Codable
conformance when all its constituent parts either conform to Codable
or are Never
," so without a good reason why "Never
conforms to Codable
" is harmful or unsound, muddying the rule for Codable
synthesis seems like a nonstarter to me.
Pragmatically, I also don't think that an "unrecognized case" is a better error to communicate up the chain when erroneously attempting to decode Result.failure
from a Result<T, Never>
—at worst it appears to be a bug ("what do you mean, of course there's a .failure
case in Result
!") and at best the user is able to see that the error is really because of the Never
type parameter, which is what the typeMismatch
error will communicate directly.
Well put - I believe I agree with you. And now I feel much better, because I believe you both understood and dismantled all key parts of what I was arguing.
The crux of your argument—at least as you've stated it—is that the proposal under review is incorrect, or at least less correct than some other solution:
This argument (incorrectness) is indeed a perfectly fine issue to raise about a proposed solution. Inherent in every proposal of a feature is the alternative to not have the feature. However, it's not "moving the goalposts" to say that you'd need to make your case as to why.
I understand - my proposal is orthogonal to this one, and in this thread we’re talking about this one, meaning that the only thing to challenge me on here was my claim that this proposal is “harmful”. I think you’re right, I’m sorry I accused you of moving the goal posts when you were doing no such thing. (For the record I wasn’t thinking it was intentional).
If I had understood you correctly in the first place then I would have responded that the potential harm would firstly depend on my argument that there is a minor loss of quality in the error under the current pitch relative to my suggestion. If that’s not true then there’s no harm. If it is true then I would want to consider the argument that it could be somewhat harmful to officially sanction the use of Never
for encoding tricks like the ones @taylorswift described if later on we introduce the feature I’m suggesting for encouraging more “correct” decoding errors involving Never
.
However, @Jumhyn ’s point about the conceptual simplicity of “It’s Codable if its parts are” convinces me more than anything I’ve just written. I just think it’s valuable to put as many valid arguments on the table as possible.
I’m officially ready to drop it, because I’m pretty sure this last thing I’ve written was the last unsaid idea that I had floating around my head on this topic. Thank you @xwu and @Jumhyn very much for the thoughtful answers.
for me it was A, because it requires multiple exclusive conditional conformances, which don’t exist in the language. multiple exclusive conditional conformances are interesting to me, and i hope one day we have support for some cases of them, but it is a much larger feature that would make this proposal unlikely to be implemented in any realistic timeframe. so it was not really ever an alternative for me, because it depends on a nonexistent feature.
This proposal has been accepted. Thanks to all who participated!