Is it possible to capture a `borrowing` parameter in a non-escaping closure?

Hmm... from the review on Noncopyable structs:

So I think the thing I want to do should be allowed (a nonescaping closure should borrow its capture, so it's fine that the captured value is itself also borrowed from the caller).

And from the review of borrow/take parameter modifiers:

(I don't see that there was any answer to that question, but I also think it's sensible thing to allow explicit ownership modifiers in capture lists).

The fact that captures are able to perform implicit copies seems like a straight bug, as it's possible to use it to crash the compiler (nightly):

struct Foo<T: ~Copyable>: ~Copyable {}

func huh<T: ~Copyable>(_ source: borrowing Foo<T>) {
  let process: (borrowing Foo<T>) -> () -> Void = {
    s in { _ = consume s }  // This should not be valid!
  }
  process(source)()
}

/swift-frontend: /home/build-user/swift/lib/SILGen/SILGenFunction.cpp:910: void swift::Lowering::SILGenFunction::emitCaptures(swift::SILLocation, swift::SILDeclRef, swift::Lowering::CaptureEmission, SmallVectorImpl<swift::Lowering::ManagedValue> &): Assertion `val->getType().isAddress() && "no address for captured var!"' failed.

Godbolt

For copyable types it does not crash (as shown in the previous post), but the implicit copy behaviour is actually less desirable than crashing IMO, because it means it would be a source-breaking change if we wanted to fix this and remove the implicit copying.

1 Like