sure, i’m probably holding them wrong, noncopyable types are just… not fun.
here’s a noncopyable struct:
@frozen public
struct DiagnosticContext<Symbolicator>:~Copyable
{
@usableFromInline internal
var diagnostics:[Diagnostic]
}
and then here’s an intermediate abstraction that contains a stored property of that noncopyable struct:
import Diagnostics
extension StaticLinker
{
struct Tables:~Copyable
{
var diagnostics:DiagnosticContext<StaticSymbolicator>
...
}
}
and now here’s a toplevel type that contains the intermediate type
struct StaticLinker:~Copyable
{
private
var tables:Tables
....
}
now i’m trying to do
extension StaticLinker
{
consuming
func diagnostics() -> DiagnosticContext<StaticSymbolicator>
{
self.tables.diagnostics
}
}
but that doesn’t work
error: cannot partially consume 'self'
nor does
(consume self).tables.diagnostics
error: cannot partially consume 'unknown'
this doesn’t parse
(consume (consume self).tables).diagnostics
this crashes the compiler
var diagnostics:DiagnosticContext<StaticSymbolicator>
{
_read
{
yield self.tables.diagnostics
}
}
COW-proofing is a lot harder than i thought…
Joe_Groff
(Joe Groff)
2
Partial consumption is coming but the read coroutine is probably closer to what you want. That ought to work, I'll look into a fix.
1 Like
oof, just ran into a compiler segfault when building in release mode only. details here:
argh! i’m running into this again, except this time i actually do need to partially consume the field.
i have a type Table and a second type TableWrapper:
struct Table:~Copyable {}
struct TableWrapper:~Copyable
{
var table:Table
}
i can create the TableWrapper by transferring to it an instance of Table, but i am totally stumped as to how to get the Table back out of the TableWrapper when i am done with it. surely there is something obvious i am missing?
Can't you add a consuming get function to the wrapper?
no, the access in the body of the getter is still considered a partial consumption
Alejandro
(Alejandro Alonso)
7
struct Table: ~Copyable {}
struct TableWrapper: ~Copyable {
var table: Table
consuming func intoTable() -> Table {
table
}
}
this works fine using the latest nightly 
Just to make sure I'm understanding properly, this does not compile?
struct TableWrapper: ~Copyable {
var table: Table
consuming func get() -> Table {
return table
}
}
var table = Table()
let wrapper = TableWrapper(table: table)
// Do stuff with wrapper
table = wrapper.get()
no it does not, which is why @Alejandro was careful to specify latest nightly where it does compile.
Swift version 5.10 (swift-5.10-RELEASE)
Target: x86_64-unknown-linux-gnu
<stdin>:5:16: error: cannot partially consume 'self'
return table
^
1 Like
Joe_Groff
(Joe Groff)
10
This should just work now in Swift 6.0 nightlies. In earlier versions, the best you could do is swap in a dummy value to replace the one you want to get out, like:
struct Table:~Copyable {
init(dummy: ()) {}
mutating func swapWithDummy() -> Table {
let value = self
self = .init(dummy: ())
return value
}
}
struct TableWrapper:~Copyable
{
var table:Table
mutating func takeTable() -> Table {
return self.table.swapWithDummy()
}
}
2 Likes
that works! i had forgotten that mutating also lets you temporarily consume noncopyable self…