Sorry if this should be clear already, but are you suggesting that @patch would allow patching of final or sealed types thus making them more palatable as defaults? This would surprise me, but if that is not what you are suggesting I don't follow how it relates to the final / sealed discussion.
Matthew Sent from my iPad > On Dec 31, 2015, at 1:13 PM, Joe Groff via swift-evolution > <swift-evolution@swift.org> wrote: > > A lot of the discussion around the final/sealed-by-default issue focused on > the ability in ObjC to extend frameworks or fix bugs in unforeseen ways. > Framework developers aren't perfect, and being able to patch a broken > framework method can be the difference between shipping and not. On the other > hand, these patches become compatibility liabilities for libraries, which > have to contend not only with preserving their own designed interface but all > the undesigned interactions with shipping apps based on those libraries. The > Objective-C model of monkey-patchable-everything has problems, but so does > the buttoned-down everything-is-static C++ world many of us rightly fear. > However, with the work we're putting into Swift for resilience and strong > versioning support, I think we're in a good position to try to find a > reasonable compromise. I'd like to sketch out a rough idea of how that might > look. Public interfaces fundamentally correspond to one or more dynamic > library symbols; the same resilience that lets a new framework version > interact with older apps gives us an opportunity to patch resilient > interfaces at process load time. We could embrace this by allowing > applications to provide `@patch` implementations overriding imported > non-fragile public APIs at specific versions: > > import Foundation > > extension NSFoo { > @patch(OSX 10.22, iOS 17) > func foo() { ... } > } > > By tying the patch to a specific framework version, we lessen the > compatibility liability for the framework; it's clear that, in most cases, > the app developer is responsible for testing their app with new framework > versions to see if their patch is still needed with each new version. Of > course, that's not always possible—If the framework developer determines > during compatibility testing that their new version breaks a must-not-break > app, and they aren't able to adopt a fix on their end for whatever reason (it > breaks other apps, or the app's patch is flawed), the framework could declare > that their new version accepts patches for other framework versions too: > > // in Foundation, OSX 10.23 > public class NSFoo { > // Compatibility: AwesomeApp patched the 10.22 version of NSFoo.foo. > // However, RadicalApp and BodaciousApp rely on the unpatched 10.22 > behavior, so > // we can't change it. > @accepts_patch_from(AwesomeApp, OSX 10.22) > public func foo() { ... } > } > > A sufficiently smart dynamic linker could perhaps resolve these patches at > process load time (and probably summarily reject patches for dylibs loaded > dynamically with dlopen), avoiding some of the security issues with arbitrary > runtime patching. For public entry points to be effectively patchable, we'd > have to also avoid any interprocedural optimization of the implementations > within the originating module, so there is a performance cost to allowing > this patching by default. Sufficiently mature (or arrogant) interfaces could > perhaps declare themselves "unpatchable" to admit IPO within their own > module. (Note that 'fragile' interfaces which admit cross-module inlining > would inherently be unpatchable, and those are likely to be the most > performance-sensitive interfaces to begin with.) > > -Joe > > _______________________________________________ > 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