i had a function that looked like this:
{
public consuming
func response() -> HTTP.ServerResponse
{
let page:Page = { .init($0.batch, on: $0.date) } (self)
return .ok(page.resource())
}
}
why the funny closure expression? because Page.init(_:on:)
sorts the buffer:
extension Page
{
init(_ articles:consuming [Article], on date:Date)
{
articles.sort
{
$0.title < $1.title
}
self.init(articles: articles, date: date)
}
}
i was skeptical that this would actually do what i expected it to do, so i tried to test my assumption by calling a property on self
after constructing a Page
from it.
{
public consuming
func response() -> HTTP.ServerResponse
{
let page:Page = { .init($0.batch, on: $0.date) } (self)
let date:Date = self.date
return .ok(page.resource())
}
}
to my disappointment, this did compile, which indicated to me that the buffer was still being copied. instead, i needed to expand the closure to
let page:Page =
{
(self:consuming Self) in
.init(self.batch, on: self.date)
} (self)
to prevent the copy. (i do not know why this compiles, as it is consuming self
twice, but somehow it does.)
i was going to post this in Using Swift, but the issue is not that i do not understand why the compiler copies the array. by default, the closure infers $0
to be borrowing Self
, and this has a terrible interaction with the compiler-generated shim for init(_ articles:consuming [Article], on date:Date)
. you can also fool yourself into thinking you fixed the problem by adding consume self
to the argument expression, but that will still copy due to the compiler-generated shim on the closure itself.
so the compiler really is following its own rules, they are just really confusing and inconvenient rules.
although i often feel like the ownership keywords are always doing the opposite of what i would like them to do, it is probably too late to change how they behave. so i think the problem now is that we lack a lightweight syntax to indicate that $0
is consuming
, because we should not need to reformat the entire closure to use named arguments with explicit signatures to solve a COW issue.