> On Jul 30, 2017, at 5:11 AM, David Hart via swift-users 
> <swift-users@swift.org> wrote:
> 
>> 
>> On 28 Jul 2017, at 18:55, Joe Groff <jgr...@apple.com 
>> <mailto:jgr...@apple.com>> wrote:
>> 
>>> 
>>> On Jul 28, 2017, at 12:06 AM, David Hart via swift-users 
>>> <swift-users@swift.org <mailto:swift-users@swift.org>> wrote:
>>> 
>>> Hello,
>>> 
>>> Indeed, I had reduced the code too much. John McCall was kind enough to 
>>> have a look and here’s the offending code:
>>> 
>>> func layoutHorizontally(leftRect: inout CGRect, rightRect: inout CGRect) {
>>>     let totalWidth = imageRect.size.width + titleRect.size.width + 
>>> contentSpacing
>>>     rightRect.origin.x = leftRect.maxX + contentSpacing
>>> }
>>> 
>>> The problem is that imageRect and titleRect are referenced both directly 
>>> and in the inout parameters.
>>> 
>>> But there’s something I’m not understanding. I went back to the ownership 
>>> manifesto and re-read the law of exclusivity to make sure I understand it:
>>> 
>>> If a storage reference expression evaluates to a storage reference that is 
>>> implemented by a variable, then the formal access duration of that access 
>>> may not overlap the formal access duration of any other access to the same 
>>> variable unless both accesses are reads.
>>> 
>>> So I tried to write a test to trigger the runtime error, but was 
>>> unsuccessful:
>>> 
>>> class MyClass {
>>>     var p: CGRect = .zero
>>> }
>>> 
>>> func trigger(a: MyClass, b: MyClass) {
>>>     a.p = b.p
>>> }
>>> 
>>> let m = MyClass()
>>> trigger(a: m, b: m)
>>> 
>>> Here, a storage reference expression (a.p) evaluates to a storage reference 
>>> that is implemented by a variable (the p property of an instance m of 
>>> MyClass) and its formal access duration (the trigger function) overlaps the 
>>> formal access duration of another access to the same variable (through the 
>>> b.p storage reference expression) and both accesses are not reads (a.p is 
>>> on the LHS of an assignment).
>>> 
>>> Why does this not trigger the Law of Exclusivity?
>> 
>> `b.p` is loaded before `a.p` is written to, so the accesses do not overlap 
>> even when a === b. Something like swap(&a.p, &b.p) (using the Swift 3 global 
>> definition of 'swap') would trigger an exclusivity trap when a === b, since 
>> the access to storage passed as an inout argument needs to last for the 
>> duration of the call.
> 
> Thanks for the explanation! It’s starting to make sense :) Is it possible to 
> trigger the exclusivity trap without an inout argument?
> 
>> -Joe


Users are probably more likely to run into problems with mutating methods, 
which are implicitly `inout`: 

struct S {
  var x = 1

  mutating func updateX(_ getOtherS: ()->S) {
    x += getOtherS().x
  }
}

class C {
  var s = S()
}

let c = C()
c.s.updateX( { c.s } )

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

Reply via email to