Commits

Michael Gottesman committed 41747b6ce2c
[+0 self] Enforce the retain/copy, call, release/destroy pattern for @guaranteed and @in_guaranteed parameters. This means: 1. In_Guaranteed when preparing accessor base args is like @in not @inout. This is because @in_guaranteed parameters are immutable. We were not miscompiling since we were not inserting cleanups for these parameters. Now with 2, we perform the copy so we have the immutable property and then destroy_addr the result after the call. 2. If we have a guaranteed parameter, we put the destroy value right after the call instead of at the end of expression. The reason 2 is necessary is that if we destroy the value at the end of scope situations like the following cause COW to fail: struct Foo { let object: AnyObject var rawObject: Builtin.RawPointer { return Builtin.bridgeToRawPointer(object) // Psuedoname of builtin. } mutating func isUnique() -> Bool { return isUnique(rawObject) } } What happens is that because Foo.isUnique is mutating, Foo is passed in @inout. Since @inout is a guarantee related to memory, SILGen has to increment the refcount of self to guarantee self's lifetime. Before this patch we would have (in pseudo-sil). %self = load %ptr_self retain_value %self %0 = getRawObject() // guaranteed call. %result = isUnique(%0) release_value %self This causes the COW check to always fail. There is no reason to extend the lifetime of %self so far, guaranteed only means that the object's lifetime is guaranteed over the call in question. So now instead, we release after the call. <rdar://problem/20094305> <rdar://problem/20234910> Swift SVN r26351