As I noted earlier, it's possible that there are source-compatibility issues here. It's already possible to have throwing and non-throwing variants of a function co-exist in an overload set, if they come from disjoint modules. Applying the async overloading to throws will change the meaning of some code. Here's a very contrived case:
// module A
public func f(_: Int) throws -> Int { ... }
// module B
public func f(_: Double) -> Int { ... }
// module C
import A
import B
func g() {
try! f(0) // currently calls A.f, will switch to calling B.f because we're in a non-`throws` context
}
I don't know how much it will matter in practice. Maybe we can get away with just making the change, or maybe we need to do it with a language version bump.
Regardless, I think applying this overloading rule to throws is a reasonable thing to consider, but I think it needs to be a separate proposal, because (1) throws has source-compatibility constraints that async need not worry about, and (2) async already has the "prefer to match on async-ness when type checking" overloading rule (that was part of SE-0296) that throws lacks.
Makes sense, you're right that there are considerations to figure out.
I still feel that taking this proposal without taking throws would introduce complexity in the language and it would be cleaner to take both at the same time. I see the concern above as rationale to figure out the model here, not to defer consistency.
While I agree that overloading on what is returned is semi-dubious, overloading on what is thrown seems to naturally fall out of desugaring throws to Result:
I think the rules for effects and return types should be the same. This also is another reason for async overloading to be allowed if we think of async desugaring to Task.Handle/Future (or whatever it's called right now).
While I agree on not allowing typed throw type changes in a world with typed throws, isnât a function that doesnât throw the same thing as throws Never, so allowing the basic case of signatures that differ in throws only is already technically doing that?
Correct. Unlike other languages, swift's effects (throws and async) are NOT sugar over a more verbose model. They are similar and interoperate, but are intentionally different.
Apologies for introducing that confusion. What I was ârememberingâ was not how it actually is but one possible direction for the design discussed in the Typed Throws pitch.