Typed throws is finally here with Swift 6 in Xcode 16b1. However, it isn't very useful since you can't actually catch any typed errors without the FullTypedThrows
experimental feature or Swift 6 mode. However, I can't seem to activate that part of the feature. Neither the experimental flag nor the full Swift 6 mode seem to enable the behavior. Was it removed?
I can even write my own MyResult
type and the compiler knows the as SomeError
is redundant in the catch
, and doesn't force me to write a fallback catch
, yet the type still comes out as any Error
.
enum SomeError: Error {
case first
}
func doThing() throws(SomeError) -> String {
"string"
}
let result = Result { try doThing() }
enum MyResult<Success, Failure: Error> {
case success(Success), failure(Failure)
init(catching: () throws(Failure) -> Success) {
do {
self = .success(try catching())
} catch let error as Failure { // 'as' test is always true
self = .failure(error)
}
}
}
let myResult = MyResult { try doThing() }
print(type(of: result), type(of: myResult))
// prints Result<String, Error> MyResult<String, Error>
Ah, I can get a typed error if I pass the throwing function directly: let result = Result(catching: doThing)
is properly typed as Result<String, SomeError>
. However, even in that case get()
throws any Error
.
This is not the behavior I am seeing.
I am finding that it is necessary to be explicit more than it should be, requiring this sort of annotation in some cases:
do throws(SomeError)
All you’re doing is getting an unspoiled function reference there, you’re not actually capturing an error or calling get()
.
That still doesn't show the feature works.
In any case, it appears that FullTypedThrows
hasn't been completed. Can experimental features be accessed from Apple toolchains in the first place? Is there anyway to use it in Xcode 16 at all, or will it need to be completed as an upcoming feature first? (@hborla)
Tangentially, note that enabling FullTypedThrows
in the WWDC Swift build typically causes the compiler to use hundreds of gigabytes of RAM and effectively spin forever, for non-trivial packages. It's clearly not ready for broad use - probably not outside the compiler team. (possibly top of tree is better, I haven't checked)
I’m not sure it does anything at all, or whether experimental features are enabled at all for Xcode’s toolchain.
"Works" is a spectrum. I appreciate that you're frustrated, and I'm sure you have code that's exhibiting problems, but it's unclear from what you've said so far what the problems are. It would be useful to the rest of us if you could demonstrate what we should be on the lookout for. (From what @wadetregaskis says, maybe it just takes scale for things to break down.)
I've already provided an example that I'd expect to work but doesn't (error types in closures, creation in the init method). I see no difference in behavior no matter what flags I have.
What's listed in the proposal under Closure thrown type inference is not working for me either, but implicit typing is not necessary, just a definite nice-to-have.
The FullTypedThrows
experimental feature is currently enable-able in Xcode 16 Beta 1. As in, you can enable it explicitly with -enable-experimental-feature FullTypedThrows
. However, I believe this was accidental, as FullTypedThrows
isn't ready to be enabled in a real-world project yet, and I'm currently preparing a PR to make it only enable-able in asserts toolchains (e.g. in development snapshots from Swift.org).
Good to know, thanks. When it comes back will it be an experimental or upcoming feature? And since it's not part of 6 that means it can't be enabled by default until Swift 7 (or whatever the next mode is called) right?
It'll come back as an upcoming feature.
Yes, when FullTypedThrows
is available as an upcoming feature, it won't be enabled by default in the Swift 6 language mode. It'll be enabled by default in whatever the next language mode is along with ExistentialAny
and InternalImportsByDefault
.