Ack! “Karl”, not you. For some reason I thought you were the OP until right after I clicked send. Sorry for the confusion.
- Dave Sweeris > On Jun 11, 2016, at 4:06 PM, David Sweeris via swift-users > <swift-users@swift.org> wrote: > >> >> On Jun 11, 2016, at 3:36 PM, Jens Alfke <j...@mooseyard.com >> <mailto:j...@mooseyard.com>> wrote: >> >> >>> On Jun 11, 2016, at 11:57 AM, David Sweeris via swift-users >>> <swift-users@swift.org <mailto:swift-users@swift.org>> wrote: >>> >>> You can’t pass a `let` as an `inout` argument. I’d guess that’s what’s >>> happening is the `arr[2]` part is creating a temporary var to which the `&` >>> part then provides a reference. >> >> But `arr` is a var, not a let. > > I know. You’d said that you "can't believe a let variable gets changed”. I > was just pointing out that you’re correct, in that the compiler will complain > if you try to pass one as an in-out argument. > > >>> `b` is then dutifully modified in the function, but there’s no mechanism >>> for copying it back into `arr` when `foo` returns >> >> No, it gets copied back using subscript assignment. Remember, `inout` isn’t >> really passing the address of the parameter (although the optimizer may >> reduce it to that.) It’s literally in-and-out: the caller passes the >> original value, the function returns the new value, the caller then stores >> the new value where the old value came from. > > I don’t think it can… My recollection is that in Swift the subscript operator > (`arr[2]` in this case) can refer to the setter xor the getter, but not both > within the same statement. If that’s correct, for there to be a value to pass > to the function, `arr[2]` must be referring to the getter version, which > means that there’s no setter to update the value when `foo` returns. > > >> I am not a Swift guru, but I think the problem in this example is that >> there’s a sort of race condition in that last post-return stage: the >> function has returned new values for both `arr` and arr[2]`, both of which >> get stored back where they came from, but the ordering is significant >> because arr[2] will have a different value depending on which of those >> assignments happens first. >> >> This smells like those C bugs where the result of an expression depends on >> the order in which subexpressions are evaluated — something like “x = i + >> (i++)”. The C standard formally declares this as undefined behavior. >> >> The part I’m still confused by is how `acopy` got modified within the `foo` >> function, since it’s declared as `let`. After staring at this for a while >> longer, I’m forced to conclude that the compiler decided it could optimize >> the `b` parameter by actually passing a pointer to the Int and modifying it >> directly, and that this has the side effect of modifying the Array object >> that `acopy` is pointing to, even though it’s supposed to be immutable. >> >> In other words, this looks like a compiler bug. I can reproduce it with >> Swift 2.2 (which is what my `swift` CLI tool says it is, even though I have >> Xcode 7.3.1 and I thought that was Swift 2.3?) > > Ah… I see what you mean about a `let` getting modified now… My mistake, I > thought you were wondering why `arr` wasn’t `[4, 5, 99]` after foo returned. > Yeah, I’m not sure about what’s happening within `foo`... Maybe someone who > knows more will come along and provide an explanation, but at the moment I’m > inclined to agree — both that you’ve found a bug, and with your guess and to > how it’s happening. > > - Dave Sweeris > _______________________________________________ > swift-users mailing list > swift-users@swift.org <mailto:swift-users@swift.org> > https://lists.swift.org/mailman/listinfo/swift-users > <https://lists.swift.org/mailman/listinfo/swift-users>
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users