State of Span/RawSpan

I would like to experiment with the new RawSpan type, particularly for embedded Swift. In this year’s WWDC session 312 by @nnnnnnnn, the following code is shown:

extension RawSpan {
	mutating func readByte() -> UInt8? {
		guard !isEmpty else { return nil }
		
		let value = unsafeLoadUnaligned(as: UInt8.self)
		self = self.extracting(droppingFirst: 1)
		return value
	}
}

(Changed from _extracting, as this is an ongoing process).

Compiling this causes an error:

$ swift build --swift-sdk swift-6.2-DEVELOPMENT-SNAPSHOT-2025-07-17-a_wasm-embedded
# ...
error: emit-module command failed with exit code 1 (use -v to see invocation)
file.swift:140:16: error: a mutating method cannot have a ~Escapable 'self'
138 | 
139 | extension RawSpan {
140 | 	mutating func readByte() -> UInt8? {
    |                `- error: a mutating method cannot have a ~Escapable 'self'
141 | 		guard !isEmpty else { return nil }
142 | 		
file.swift:140:16: error: a mutating method cannot have a ~Escapable 'self'
138 | 
139 | extension RawSpan {
140 | 	mutating func readByte() -> UInt8? {
    |                `- error: a mutating method cannot have a ~Escapable 'self'
141 | 		guard !isEmpty else { return nil }
142 | 		

(Same error when targeting regular, non-embedded WASM.)

Regarding the error: “a mutating method cannot have a ~Escapable 'self'”, how would I implement a parser using Span/RawSpan without mutation? Or is this part of the ongoing introduiction of the span types?

In order to define functions that produce new non-Escapable values, whether by returning a new value or mutating an existing one, you need to -enable-experimental-feature Lifetimes, and annotate these functions with the @_lifetime attribute. You can read more here:

3 Likes

Thanks for making the connection to lifetimes. I have now modified the code like so

extension RawSpan {
	@_lifetime(&self)
	mutating func readByte() -> UInt8? {
		guard !isEmpty else { return nil }
		
		let value = unsafeLoadUnaligned(as: UInt8.self)
		self = self.extracting(droppingFirst: 1)
		return value
	}
}

and enabled the Lifetimes experimental feature and compilation works!

1 Like