Re-entrant modification of a variable

I have the following code (distillation of my actual program):

let failFence = false

func two( _ tail:()->Bool = {true} )->Bool
{
   return tail()
}

func one
(
   block:(()->Bool)->Bool,
   _ tail:()->Bool = {true}
)->Bool
{
   var result :Bool
    
   result =
         !failFence
      && block( tail )   // Passing a non-escaping function parameter...
      && !failFence
   return result
} // one


let result =
   one( block:two )

"Passing a non-escaping function parameter 'tail' to a call to a non-escaping function parameter can allow re-entrant modification of a variable" on specified line.

Granted, this is a bit convoluted, but ultimately it should set result in the main program to true.

The call to one (with a default trailing closure of {true}) should invoke "block" (which is two), two should invoke and return the value of one's trailing closure (which is {true}). Therefore, result inside one should be true, and one should return true.

Yes, in theory, this could produce a recursive call (though this example does not). However, I'm not seeing why I have to declare "tail" as @escaping. There is never a situation where any of the closures (trailing or otherwise) execute after one (or two) complete. Tail is always a trailing closure (or the default {true}), so I don't see how that could change. The trailing closures could, of course, change values, but that would be intended and I don't understand what this message is concerned about.

Given the error message, I think it might be an exclusivity violation concern?

func f(_ x: inout Bool, _ cb: () -> Bool) -> Bool {
  x = cb()
  return x
}

var x = true
one(
  block: { cb in
    f(&x, cb)
  },
  {
    x = false
    return x
  }
)

If the above were permitted to compile, it would be a guaranteed crash due to exclusivity violation, I believe. Making either of the callbacks @escaping prevents them from modifying x.

Okay, that makes sense. Though in my particular case I never use inout and always pass parameters by reference if I need non-pass-by-value semantics. However, that doesn't stop someone else from tweaking the code to use inout, resulting in an exclusivity issue.

It's supposedly a bug, but you can still do it.

let tail = tail
return !failFence && block(tail) && !failFence

This code does not crash with the above fix.

I stumbled across this, which I believe answers my questions: