Swift pitch would mark closures that run exactly once
A second language proposal would let APIs promise a closure runs once, so it can consume noncopyable values and move non-Sendable ones.
Swift's language team has returned with a second proposal for function types that the compiler treats as running exactly once, or at most once. The point is to stop rejecting closures that consume noncopyable values or re-send non-Sendable ones, which today are blocked because the compiler cannot prove the closure will not run again.
Tim Shortli wrote that exactly-once is the common case in APIs, and that modeling it now could also support later work on user-defined linear types. Waiting, he argued, would force a second costly migration. The earlier attribute for at-most-once functions has been renamed, and a new exactly-once attribute sits beside it. An internal protocol captures the destruction rules those types need, and a standard-library helper would convert an exactly-once function into an at-most-once one by replacing a static proof with a runtime check.
That helper is the main design argument. John McCall wrote that some APIs really do call a completion exactly once, but the compiler cannot see it, for example when success and failure handlers are split and only one of them runs. Without a dynamic downgrade, those APIs would have to advertise an ordinary, callable-any-number-of-times closure and lose the contract. "There are APIs that call their parameter function exactly once for which we have no reasonable hope of proving that automatically," McCall wrote.
Imported C and Objective-C parameters marked as called once would be wrapped so Swift still traps if the closure is invoked twice or destroyed unused. Reviewers asked whether passing the same value back and forth could stack those wrappers and hurt performance. Contributors noted Swift already grows similar thunks in pure Swift code, and that recognizing a wrapper across something like a C++ function object is representation-dependent, so a shared fix is not obvious.
Shortli also said he would keep consuming as the default for these parameters, add an async form of the conversion helper, and spell out that an inout exactly-once closure can be called only if the callee puts a fresh one back before returning. The caller still owes a single use.