[swift-dev] Question about implementation of closure capture lists

Greg Titus greg at omnigroup.com
Wed Dec 9 10:57:47 CST 2015


Hi all,

I thought I’d take a look at SR-153 "Bad fix suggestion for changing value of capture list constants" <https://bugs.swift.org/browse/SR-153>, and I’d really appreciate it if someone more familiar with the code could check my thoughts, rather than me jumping straight to submitting a pull request that might be going in the wrong direction.

First, an entry in a capture list should always be semantically a constant, correct? Right now, the VarDecl ‘isLet’ flag is being set to ownershipKind != Ownership::Weak, which means that a capture of [a] is treated as constant by the type checker, but a capture of [weak a] is not. Thus, this code compiles without error (and prints “nil” and “A" when run), which is certainly unexpected behavior to me:

class A {}
var a = A()
let f = {
    [weak a] in
    a = A()
    print(a)
}
f()
print(a)

I can imagine there being a good reason why a weak var shouldn’t be marked as isLet for optimization purposes, etc, since you can’t assume that it won’t change, but surely the programmer shouldn’t be explicitly using it as an lvalue, right?

I think the solution here is to add a VarDecl flag bit for InClosureCaptureList, set that when setting up the VarDecl in ParseExpr, and then return false from isSettable() (to fix the issue shown here), and early return from emitLetToVarNoteIfSimple() (to fix the original issue 153). These would be similar and in the same places as the existing isa<ParamDecl> checks.

Does all that sound okay?

Thanks!
	- Greg


More information about the swift-dev mailing list