Explicit capture semantics applied too broadly?

Compiling the following program generates error: reference to property 'i' in closure requires explicit 'self.' to make capture semantics explicit, which seems really strange to me. There’s clearly no semantic impact to the capture of self, here. It’s a value type, and besides, all the stored properties are immutable. Should we be more selective about emitting this error?

struct X {
    let i: Int
    var s: ()->Int { return { i } }
}
1 Like

I agree that in the case you present, there shouldn’t be any worries with implicitly capturing self – however things may become problematic if X had more properties. For example, consider:

class C {}

struct X {
  let i: Int
  let c = C()
  var s: () -> Int {
    return { i }
  }
}

If we allowed the implicit capturing of self here, we’d also be implicitly capturing a strong reference to c, keeping it alive as long as the closure lives, which may be unexpected (as it looks like we’re just capturing i). Forcing the user to say { self.i } makes this slightly more obvious.

1 Like

Indeed, the implicit self capture can be an issue, hence the error.
But I think the desired behaviour in this case was

var s: () -> Int {
    let i = self.i
    return { i }
}

which wouldn’t capture self, and the question was “why doesn’t this happen by default?”.

1 Like

Indeed, when self is an immutable value anyway, why not? And to write it more nicely,

var s: () -> Int { 
    return {[i=i] in i}
}
1 Like

let properties in structs are definitely the uncommon case, but I don’t think that’s really the salient point anyway; it’s that the property is stored. I’m not sure I want different rules for stored and computed properties, though.

4 Likes