Thanks Doug, I’m writing a proposal about it. - Torin
> On 31 Jan 2017, at 07:20, Douglas Gregor <dgre...@apple.com> wrote: > > >> On Jan 28, 2017, at 10:43 PM, Rod Brown via swift-evolution >> <swift-evolution@swift.org> wrote: >> >> I agree that there is an issue here. >> >> While I understand that the initialiser avoids the full setter for direct >> access, I would expect the attribute to mean that the substituted direct >> access still applied the attribute you marked the API with. I would consider >> the fact that it doesn't work as a dangerous gap in the API. >> >> It is also concerning if we consider how this will work with Property >> Behaviours that are planned for Swift in the future. If we made NSCopying a >> property behaviour, the direct access would mean it too would not be invoked >> at initial access so I'm not sure how the best way to get around this is - >> should we do compiler magic to copy in the initialiser, or should we warn if >> we don't detect a call to copy() or copy(with:) in the initialiser? > > I think we should be doing the compiler magic to call copy(with:) in the > initializer, because that seems like the most direct way to maintain the > @NSCopying contract without changing the underlying direct-storage model. > >> I think we at least need to do something here. It's a very convoluted piece >> of logic to say the @NSCopying attribute doesn't work in an initialiser and >> it's hardly intuitive despite the fair reasoning. > > I agree that we need to do something here. It feels like it’s just a bug—that > this is the only way that @NSCopying makes sense in an attribute. Might even > be a good starter bug for someone who wants to dip their tows into the type > checker! > > - Doug > >> >> Rod >> >>> On 29 Jan 2017, at 4:47 pm, Torin Kwok via swift-evolution >>> <swift-evolution@swift.org> wrote: >>> >>> Yep, I also admit the design of forbidding calling a setter before full >>> class initialization is reasonable and what's really annoying is the >>> inconsistency. >>> >>> However, making @NSCopying attribute not subjects to the fact that >>> setters would not be invoked in initializers perhaps is viable too. In >>> the other words, assigning a value to a property whether or not by >>> calling a setter has no influence on whether @NSCopying semantic'd work: >>> copying should always take place after a property has been declared as >>> @NSCopying. >>> >>> Jean-Daniel writes: >>> >>>>> Le 28 janv. 2017 à 05:34, Torin Kwok via swift-evolution >>>>> <swift-evolution@swift.org> a écrit : >>>>> >>>>> Hello guys, >>>>> >>>>> Note: This issue has been originally presented inswift-usersmailling list >>>>> <https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20170123/004552.html>. >>>>> And then I post it again here at the suggestion >>>>> <https://lists.swift.org/pipermail/swift-users/Week-of-Mon-20170123/004561.html> >>>>> of Jordan Rose: >>>>> >>>>> It might be reasonable to change this behavior, but it probably deserves >>>>> a bit of discussion on swift-evolution; it's not 100%, for-sure a bug. >>>>> --- the original content follows this line --- >>>>> >>>>> I encountered a strange behavior when I declared a property with the >>>>> @NSCopying attribute: >>>>> >>>>> // `Person` class inherits from `NSObject` class and conforms to >>>>> `NSCopying` protocol >>>>> @NSCopying var employee: Person >>>>> and then assigned an external instance of Person class protocol to this >>>>> property within the designated init methods: >>>>> >>>>> // Designated initializer of `Department` class >>>>> init( employee externalEmployee: Person ) { >>>>> self.employee = externalEmployee >>>>> super.init() >>>>> >>>>> // Assertion would fail since Swift do not actually copy the value >>>>> assigned to this property >>>>> // even though `self.employee` has been marked as `@NSCoyping` >>>>> // assert( self.employee !== externalEmployee ) >>>>> } >>>>> If I indeed require the deep copying behavior during the init process, >>>>> instead of taking advantage of @NSCopying attribute, I would have to >>>>> invoke the copy() method manually: >>>>> >>>>> init( employee externalEmployee: Person ) { >>>>> // ... >>>>> self.employee = externalEmployee.copy() as! Person >>>>> // ... >>>>> } >>>>> In fact, what really makes me confusing is that @NSCopying semantic does >>>>> work properly within the other parts of the class definition such as >>>>> normal instance methods, or external scope. For instance, if we're >>>>> assigning an external instance of Person to the self.employee proper of >>>>> Department directly through setter rather than initializer: >>>>> >>>>> department.employee = johnAppleseed >>>>> then self.employee property and johnAppleseed variable will no longer >>>>> share the same underlying object now. In the other words, @NSCopying >>>>> attribute makes sense. >>>>> >>>>> After I looked through a great deal of results given by Google, and >>>>> dicussions on StackOverflow, I finally end up with nothing helpful — the >>>>> vast majority of articles, documentations as well as issues talking about >>>>> this similar topics only focus on the basic concepts and effects of >>>>> @NSCopying itself but do not mentioned this strange behavior at all — >>>>> besides one radar descriping the same problem (rdar://21383959 >>>>> <rdar://21383959>) and a final conclusion mentioned in a guy's Gist >>>>> comment: ... values set during initialization are not cloned ... >>>>> >>>>> That is, @NSCopying semantic has no effect in initializers. >>>>> >>>>> Then, what I want to figure out is the reason why @NSCopying semantic >>>>> will become effectless implicitly whithin initializers of a class, and >>>>> the special considerations behind this behavior, if any. >>>>> >>>>> --- END --- >>>>> >>>>> Jordan: >>>>> >>>>> Your observation is correct: @NSCopying currently does not affect >>>>> initializers. This is because accessing a property in an initializer >>>>> always does direct access to the storage rather than going through the >>>>> setter. >>>>> I have tested the identical logic in Objective-C and the NSCopying >>>>> semantic works perfectly within Obj-C's class initializer. >>>>> >>>> This is because Obj-C guarantee that all ivars are zero initialized and >>>> does not enforce initializer safety (but forcing initialization of ivars >>>> before calling other methods). >>>> >>>> Calling a setter (like any other method) before full class initialization >>>> is unsafe as the setter may be overridden or simply customized, and may >>>> need to access to the class or subclasses ivars. >>>> >>>> That said, I’m not sure what is the best way to solve that inconsistency. >>> >>> >>> -- >>> Torin Kwok (郭桐) >>> OpenPGP/GnuPG: https://keybase.io/kwok >>> _______________________________________________ >>> swift-evolution mailing list >>> swift-evolution@swift.org >>> https://lists.swift.org/mailman/listinfo/swift-evolution >> _______________________________________________ >> swift-evolution mailing list >> swift-evolution@swift.org >> https://lists.swift.org/mailman/listinfo/swift-evolution >
smime.p7s
Description: S/MIME cryptographic signature
_______________________________________________ swift-evolution mailing list swift-evolution@swift.org https://lists.swift.org/mailman/listinfo/swift-evolution