[Proposal: 
https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.md
 
<https://github.com/apple/swift-evolution/blob/master/proposals/0176-enforce-exclusive-access-to-memory.md>]

I have severe concerns about these revisions because they make 
withoutActuallyEscaping harder to reason about.

+  - Programmers using ``withoutActuallyEscaping`` should take
+    care not to allow the result to be recursively invoked.

+[…] if they are certain that their code will
+not violate the NRR, use ``withoutActuallyEscaping`` to disable
+the NPCR check.

I think this constitutes a violation of the user model for 
withoutActuallyEscaping, because withoutActuallyEscaping hasn't historically 
meant withoutBeingReentrant. The proposal "should take care" is a very mild way 
of saying we're introducing a new rule under which the compiler can silently do 
something different than what you wrote (with no "unsafe" in sight). Similarly, 
using withoutActuallyEscaping to mean withoutActuallyViolatingExclusivity seems 
like it'll come back to haunt us, the kind of thing where people ask on Stack 
Overflow why the Swift people didn't design something that said what it did.

When I first brought this up on an Apple-internal list, John let me know that 
we could introduce checking for it. This helps assuage my concerns quite a bit, 
but I'm not sure how we would do so without modifying the original closure, and 
if we can modify the original closure I'm not sure we've saved anything over 
proper dynamic checking.  John, can you clarify for the list how we might check 
for this? Like withoutActuallyEscaping, it doesn't have to be something we 
implement right away as long as we have the ability to do so without changing 
the ABI.

Thanks,
Jordan

P.S. Devin and I had previously discussed an additional example that does not 
seem to be forbidden by these rules. Is that correct and will this program 
continue to print "2 2"?

func invoke(_ callback: /*nonescaping*/ () -> Void) {
  callback()
}
class Foo {
  var op: () -> Void = {}
  var prop = 0
  func test() {
    var x = 0
    self.op = { x = 1; self.prop = 1 }
    invoke { self.op(); x += 1; self.prop += 1 }
    print(x, self.prop)
  }
}
Foo().test()

_______________________________________________
swift-evolution mailing list
swift-evolution@swift.org
https://lists.swift.org/mailman/listinfo/swift-evolution

Reply via email to