<div dir="ltr">This is an interesting proposal.<div><br></div><div>Would there be any interactions between this proposal and the covariant, contravariant, and invariant specifiers that Objective-C generics support on type parameters?</div><div><br></div><div>Austin</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Sat, Jan 9, 2016 at 3:50 PM, Douglas Gregor via swift-evolution <span dir="ltr"><<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word"><div style="background-color:rgb(255,255,255)"><div><div><div style="width:980px;margin-right:auto;margin-left:auto"><div><div style="margin-top:20px;margin-bottom:15px;border:1px solid rgb(221,221,221);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px"><div><h1 style="color:rgb(51,51,51);margin-right:0px;margin-bottom:16px;margin-left:0px;line-height:1.2;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);margin-top:0px!important"><span style="font-size:12px;font-weight:normal">Hi all,</span></h1><div style="color:rgb(51,51,51)"><span style="font-size:12px;font-weight:normal"><br></span></div><div><font color="#333333">Here’s a proposal I’m working on to import Objective-C lightweight generics as generic classes in Swift. It’s also available here:</font></div><div><font color="#333333"><br></font></div><div><font color="#333333"><span style="white-space:pre-wrap">        </span><a href="https://github.com/DougGregor/swift-evolution/blob/importing-objc-generics/proposals/0000-importing-objc-generics.md" target="_blank">https://github.com/DougGregor/swift-evolution/blob/importing-objc-generics/proposals/0000-importing-objc-generics.md</a></font></div><div><font color="#333333"><br></font></div><div><font color="#333333">Comments welcome!</font></div><div><font color="#333333"><br></font></div><div><font color="#333333"><span style="white-space:pre-wrap">        </span>- Doug</font></div><h1 style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:2.25em;margin-right:0px;margin-bottom:16px;margin-left:0px;line-height:1.2;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);margin-top:0px!important"><br></h1><h1 style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:2.25em;margin-right:0px;margin-bottom:16px;margin-left:0px;line-height:1.2;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);margin-top:0px!important"><br></h1><h1 style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:2.25em;margin-right:0px;margin-bottom:16px;margin-left:0px;line-height:1.2;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238);margin-top:0px!important">Importing Objective-C Lightweight Generics</h1><ul style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:16px"><li>Proposal: <a href="https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-importing-objc-generics.md" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">SE-NNNN</a></li><li>Author: <a href="https://github.com/DougGregor" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Doug Gregor</a></li><li>Status: <strong>Awaiting review</strong></li><li>Review manager: TBD</li></ul><h2 style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:1.75em;margin-top:1em;margin-bottom:16px;line-height:1.225;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238)"><a href="https://github.com/DougGregor/swift-evolution/tree/importing-objc-generics#introduction" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1" target="_blank"><span style="font-weight:normal;font-size:16px;line-height:1;font-family:octicons;display:inline-block;color:rgb(0,0,0);vertical-align:middle"></span></a>Introduction</h2><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">Objective-C's <em>lightweight generics</em> feature allows Objective-C classes to be parameterized on the types they work with, similarly to Swift's generics syntax. Their adoption in Foundation's collection classes allow Objective-C APIs to be bridged more effectively into Swift. For example, an <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSArray<NSString *> *</code> bridges to <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">[String]</code> rather than the far-weaker <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">[AnyObject]</code>. However, parameterized Objective-C classes lose their type parameters when they are imported into Swift, so uses of type parameters outside of bridged, typed collections (<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSArray</code>, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSDictionary</code>, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSSet</code>) don't benefit in Swift. This proposal introduces a way to import the type parameters of Objective-C classes into Swift.</p><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">Swift-evolution thread: <a href="https://lists.swift.org/pipermail/swift-evolution" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">TODO</a></p><h2 style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:1.75em;margin-top:1em;margin-bottom:16px;line-height:1.225;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238)"><a href="https://github.com/DougGregor/swift-evolution/tree/importing-objc-generics#motivation" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1" target="_blank"><span style="font-weight:normal;font-size:16px;line-height:1;font-family:octicons;display:inline-block;color:rgb(0,0,0);vertical-align:middle"></span></a>Motivation</h2><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">Cocoa and Cocoa Touch include a number of APIs that have adopted Objective-C lightweight generics to improve static type safety and expressiveness. However, because the type parameters are lost when these APIs are imported into Swift, they are effectively <em>less</em> type safe in Swift than in Objective-C, a situation we clearly cannot abide. This proposal aims to improve the projection of these Objective-C APIs in Swift.</p><h2 style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:1.75em;margin-top:1em;margin-bottom:16px;line-height:1.225;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238)"><a href="https://github.com/DougGregor/swift-evolution/tree/importing-objc-generics#proposed-solution" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1" target="_blank"><span style="font-weight:normal;font-size:16px;line-height:1;font-family:octicons;display:inline-block;color:rgb(0,0,0);vertical-align:middle"></span></a>Proposed solution</h2><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">A parameterized class written in Objective-C will be imported into Swift as a generic class with the same number of type parameters. The bounds on the type parameters in Objective-C will be translated into requirements on the generic type parameters in Swift:</p><ul style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:16px"><li>The generic type parameters in Swift will always be class-bound, i.e., the generic class will have the requirement <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">T : AnyObject</code>.</li><li>If the bound includes a class type (e.g., <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">T : NSValue *</code> in Objective-C), the generic Swift class will have the corresponding superclass requirement (<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">T : NSValue</code>).</li><li>If the bound includes protocol qualification (e.g., <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">T : id<NSCopying></code> in Objective-C), each protocol bound is turned into a conformance requirement (<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">T : NSCopying</code>) on the generic Swift class.</li></ul><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">The following Objective-C code:</p><pre style="color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;overflow:auto;margin-top:0px;margin-bottom:16px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal"><code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;padding:0px;margin:0px;background-color:transparent;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal;border:0px;display:inline;line-height:inherit;word-wrap:normal">@interface MySet<T : id<NSCopying>> : NSObject
-(MySet<T> *)unionWithSet:(MySet<T> *)otherSet;
@end
@interface MySomething : NSObject
- (MySet<NSValue *> *)valueSet;
@end
</code></pre><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">will be imported as:</p><div style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-bottom:16px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;word-break:normal"><span style="color:rgb(167,29,93)">class</span> MySet<span style="color:rgb(167,29,93)"><</span>T <span style="color:rgb(167,29,93)">:</span> NSCopying<span style="color:rgb(167,29,93)">></span> <span style="color:rgb(167,29,93)">:</span> NSObject {
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">unionWithSet</span>(otherSet: MySet<span style="color:rgb(167,29,93)"><</span>T<span style="color:rgb(167,29,93)">></span>) <span style="color:rgb(167,29,93)">-></span> MySet<T>
}
<span style="color:rgb(167,29,93)">class</span> MySomething <span style="color:rgb(167,29,93)">:</span> NSObject {
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">valueSet</span>() <span style="color:rgb(167,29,93)">-></span> MySet<NSValue>
}</pre></div><h3 style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:1.5em;margin-top:1em;margin-bottom:16px;line-height:1.43"><a href="https://github.com/DougGregor/swift-evolution/tree/importing-objc-generics#importing-unspecialized-types" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2" target="_blank"><span style="font-weight:normal;font-size:16px;line-height:1;font-family:octicons;display:inline-block;color:rgb(0,0,0);vertical-align:middle"></span></a>Importing unspecialized types</h3><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">When importing an unspecialized Objective-C type into Swift, we will substitute the bounds for the type arguments. For example:</p><pre style="color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;overflow:auto;margin-top:0px;margin-bottom:16px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal"><code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;padding:0px;margin:0px;background-color:transparent;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal;border:0px;display:inline;line-height:inherit;word-wrap:normal">@interface MySomething (ObjectSet)
- (MySet *)objectSet; // note: no type arguments to MySet
@end
</code></pre><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">will be imported as:</p><div style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-bottom:16px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> MySomething {
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">objectSet</span>() <span style="color:rgb(167,29,93)">-></span> MySet<NSCopying> // note: uses the type bound
}</pre></div><h3 style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:1.5em;margin-top:1em;margin-bottom:16px;line-height:1.43"><a href="https://github.com/DougGregor/swift-evolution/tree/importing-objc-generics#restrictions-on-uses-of-objective-c-parameterized-classes" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2" target="_blank"><span style="font-weight:normal;font-size:16px;line-height:1;font-family:octicons;display:inline-block;color:rgb(0,0,0);vertical-align:middle"></span></a>Restrictions on uses of Objective-C parameterized classes</h3><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">While the Swift and Objective-C generics systems look similar on the surface, they use fundamentally different semantic models. Specifically, Objective-C lightweight generics are based on <em>type erasure</em>, so we cannot in general recover the type arguments from the metaclass of an Objective-C parameterized class (i.e., because <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">MySet</code>, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">MySet<NSString *></code>, and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">MySet<NSNumber *></code> all share a metaclass). This leads to several restrictions:</p><ul style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:16px"><li><p style="margin-top:16px;margin-bottom:16px">Downcasting to an instance or metatype of a parameterized Objective-C class is inherently uncheckable, so we place limits on such casts. For example,</p><div style="margin-bottom:16px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;word-break:normal"><span style="color:rgb(167,29,93)">let</span> obj: <span style="color:rgb(0,134,179)">AnyObject</span> <span style="color:rgb(167,29,93)">=</span> <span style="color:rgb(167,29,93)">...</span>
<span style="color:rgb(167,29,93)">if</span> <span style="color:rgb(167,29,93)">let</span> set1 <span style="color:rgb(167,29,93)">=</span> obj <span style="color:rgb(167,29,93)">as?</span> MySet<span style="color:rgb(167,29,93)"><</span>NSCopying<span style="color:rgb(167,29,93)">></span> {
<span style="color:rgb(150,152,150)">// okay: every MySet is a MySet<NSCopying> by construction, so</span>
<span style="color:rgb(150,152,150)">// we're just checking that this is a 'MySet'.</span>
}
<span style="color:rgb(167,29,93)">if</span> <span style="color:rgb(167,29,93)">let</span> set2 <span style="color:rgb(167,29,93)">=</span> obj <span style="color:rgb(167,29,93)">as?</span> MySet<span style="color:rgb(167,29,93)"><</span>NSNumber<span style="color:rgb(167,29,93)">></span> {
<span style="color:rgb(150,152,150)">// error: conditional cast to specialized Objective-C instance</span>
<span style="color:rgb(150,152,150)">// doesn't check type argument 'NSNumber'</span>
}
<span style="color:rgb(167,29,93)">let</span> set3 <span style="color:rgb(167,29,93)">=</span> obj <span style="color:rgb(167,29,93)">as!</span> MySet<span style="color:rgb(167,29,93)"><</span>NSNumber<span style="color:rgb(167,29,93)">></span> <span style="color:rgb(150,152,150)">// okay: we assert that it is safe</span>
<span style="color:rgb(167,29,93)">if</span> <span style="color:rgb(167,29,93)">let</span> set4 <span style="color:rgb(167,29,93)">=</span> obj <span style="color:rgb(167,29,93)">as?</span> MySet<span style="color:rgb(167,29,93)"><</span>NSCopying<span style="color:rgb(167,29,93)">></span> {
<span style="color:rgb(167,29,93)">let</span> set5 <span style="color:rgb(167,29,93)">=</span> set4 <span style="color:rgb(167,29,93)">as!</span> MySet<span style="color:rgb(167,29,93)"><</span>NSNumber<span style="color:rgb(167,29,93)">></span> <span style="color:rgb(150,152,150)">// here's how to get a MySet<NSNumber></span>
}</pre></div></li><li><p style="margin-top:16px;margin-bottom:16px">Extensions of parameterized Objective-C classes cannot reference the type paramaeters in any way. For example:</p><div style="margin-bottom:16px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> MySet {
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">someNewMethod</span>(x: T) { <span style="color:rgb(167,29,93)">...</span> } <span style="color:rgb(150,152,150)">// error: cannot use `T`.</span>
}</pre></div></li></ul><h3 style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:1.5em;margin-top:1em;margin-bottom:16px;line-height:1.43"><a href="https://github.com/DougGregor/swift-evolution/tree/importing-objc-generics#opting-in-to-type-argument-discovery" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2" target="_blank"><span style="font-weight:normal;font-size:16px;line-height:1;font-family:octicons;display:inline-block;color:rgb(0,0,0);vertical-align:middle"></span></a>Opting in to type argument discovery</h3><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">Some Objective-C parameterized classes do carry information about their type arguments. When this is the case, it is possible to lift some of the restrictions described in the above section. There are two distinct cases:</p><ul style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:16px"><li><p style="margin-top:16px;margin-bottom:16px"><em>Abstract parameterized classes whose concrete subclasses are not parameterized</em>: <a href="https://developer.apple.com/library/mac/documentation/AppKit/Reference/NSLayoutAnchor_ClassReference/index.html#//apple_ref/occ/cl/NSLayoutAnchor" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank"><code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSLayoutAnchor</code></a> is one such example: it is parameterized on the anchor type, but there is a fixed set of such anchor types that are represented by subclasses: <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSLayoutXAxisAnchor</code> subclasses <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSLayoutAnchor<NSLayoutXAxisAnchor *></code>, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSLayoutDimension</code>subclasses <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSLayoutAnchor<NSLayoutDimension *></code>, etc. Therefore, the type arguments can be recovered by looking at the actual metaclass.</p></li><li><p style="margin-top:16px;margin-bottom:16px"><em>Parameterized classes that store their type arguments in instances</em>: <a href="https://developer.apple.com/library/ios/documentation/GameplayKit/Reference/GKComponentSystem_Class/" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank"><code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">GKComponentSystem</code></a> is one such example: it is parameterized on the component type it stores, but it's initializer (<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">-initWithComponentClass:</code>) requires one to pass the component type's metaclass. Therefore, every <em>instance</em> of <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">GKComponentSystem</code> knows its type arguments.</p></li></ul><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">A parameterized Objective-C class can opt in to providing information about its type argument by implementing a method<code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">classForGenericArgumentAtIndex:</code> either as a class method (for the first case described above) or as an instance method (for the second case described above). The method returns the metaclass for the type argument at the given, zero-based index.</p><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">For example, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSLayoutAnchor</code> would provide a class method <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">classForGenericArgumentAtIndex:</code> that must be implemented by each of its subclasses:</p><pre style="color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;overflow:auto;margin-top:0px;margin-bottom:16px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal"><code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;padding:0px;margin:0px;background-color:transparent;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal;border:0px;display:inline;line-height:inherit;word-wrap:normal">@interface NSLayoutAnchor<AnchorType> (SwiftSupport)
/// Note: must be implemented by each subclass
+(nonnull Class)classForGenericArgumentAtIndex:(NSUInteger)index;
@end
@implementation NSLayoutAnchor
+(nonnull Class)classForGenericArgumentAtIndex:(NSUInteger)index {
NSAssert(false, @"subclass must override +classForGenericArgumentAtIndex:");
}
@end
@implementation NSLayoutXAxisAnchor (SwiftSupport)
+(nonnull Class)classForGenericArgumentAtIndex:(NSUInteger)index {
return [NSLayoutXAxisAnchor class];
}
@end
@implementation NSLayoutYAxisAnchor (SwiftSupport)
+(nonnull Class)classForGenericArgumentAtIndex:(NSUInteger)index {
return [NSLayoutYAxisAnchor class];
}
@end
@implementation NSLayoutDimension (SwiftSupport)
+(nonnull Class)classForGenericArgumentAtIndex:(NSUInteger)index {
return [NSLayoutDimension class];
}
@end
</code></pre><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">On the other hand, <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">GKComponentSystem</code> would implement an instance method <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">classForGenericArgumentAtIndex:</code>:</p><pre style="color:rgb(51,51,51);font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;overflow:auto;margin-top:0px;margin-bottom:16px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal"><code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;padding:0px;margin:0px;background-color:transparent;border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal;border:0px;display:inline;line-height:inherit;word-wrap:normal">@interface GKComponentSystem<ComponentType : GKComponent *> (SwiftSupport)
- (nonnull Class)classForGenericArgumentAtIndex:(NSUInteger)index;
@end
@implementation GKComponentSystem (SwiftSupport)
- (nonnull Class)classForGenericArgumentAtIndex:(NSUInteger)index {
return self.componentClass;
}
@end
</code></pre><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">Note that many parameterized Objective-C classes cannot provide either of these methods, because they don't carry enough information in their instances. For example, an <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSMutableArray</code> has no record of what the element type of the array is intended to be.</p><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">However, when a parameterized class does provide this information, we can lift some of the restrictions from the previous section:</p><ul style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;padding:0px 0px 0px 2em;margin-top:0px;margin-bottom:16px"><li><p style="margin-top:16px;margin-bottom:16px">If the parameterized class provides an instance method <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">classForGenericArgumentAtIndex:</code>, the extension can use the type arguments in its instance methods, including accessors for instance properties and subscripts. For example:</p><div style="margin-bottom:16px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> GKComponentSystem {
<span style="color:rgb(167,29,93)">var</span> reversedComponents: [ComponentType] {
<span style="color:rgb(167,29,93)">return</span> components<span style="color:rgb(167,29,93)">.</span>reversed()
}
<span style="color:rgb(167,29,93)">static</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">notifyComponents</span>(components: [ComponentType]) {
<span style="color:rgb(150,152,150)">// error: cannot use `ComponentType` in a static method</span>
}
}</pre></div></li><li><p style="margin-top:16px;margin-bottom:16px">If the parametized class provides a class method <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">classForGenericArgumentAtIndex:</code>, the extension can use type arguments anywhere.</p><div style="margin-bottom:16px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> NSLayoutAnchor {
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">doSomething</span>(x: AnchorType) { <span style="color:rgb(167,29,93)">...</span> }
<span style="color:rgb(167,29,93)">class</span> <span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">doSomethingClassy</span>(x: AnchorType) { <span style="color:rgb(167,29,93)">...</span> }
}</pre></div></li></ul><h3 style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:1.5em;margin-top:1em;margin-bottom:16px;line-height:1.43"><a href="https://github.com/DougGregor/swift-evolution/tree/importing-objc-generics#subclassing-parameterized-objective-c-classes-from-swift" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1.2" target="_blank"><span style="font-weight:normal;font-size:16px;line-height:1;font-family:octicons;display:inline-block;color:rgb(0,0,0);vertical-align:middle"></span></a>Subclassing parameterized Objective-C classes from Swift</h3><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">When subclassing a parameterized Objective-C class from Swift, the Swift compiler will define <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">+classForGenericArgumentAtIndex:</code> and <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">-classForGenericArgumentAtIndex:</code>. The Swift compiler has the complete type metadata required, because it is stored in the (Swift) type metadata, so these definitions will be correct. For example:</p><div style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-bottom:16px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;word-break:normal"><span style="color:rgb(167,29,93)">class</span> Employee <span style="color:rgb(167,29,93)">:</span> NSObject { <span style="color:rgb(167,29,93)">...</span> }
<span style="color:rgb(167,29,93)">class</span> EmployeeArray <span style="color:rgb(167,29,93)">:</span> NSMutableArray<span style="color:rgb(167,29,93)"><</span>Employee<span style="color:rgb(167,29,93)">></span> {
<span style="color:rgb(150,152,150)">// +[EmployeeArray classForGenericArgumentAtIndex:] always returns</span>
<span style="color:rgb(150,152,150)">// ObjC type metadata for Employee</span>
}
<span style="color:rgb(167,29,93)">class</span> MyMutableArray<span style="color:rgb(167,29,93)"><</span>T <span style="color:rgb(167,29,93)">:</span> <span style="color:rgb(0,134,179)">AnyObject</span><span style="color:rgb(167,29,93)">></span> <span style="color:rgb(167,29,93)">:</span> NSMutableArray<span style="color:rgb(167,29,93)"><</span>T<span style="color:rgb(167,29,93)">></span> {
<span style="color:rgb(150,152,150)">// +[MyMutableArray classForGenericArgumentAtIndex:] returns the</span>
<span style="color:rgb(150,152,150)">// ObjC type metadata for T, extracted from the Swift metatype for</span>
<span style="color:rgb(150,152,150)">// `self`.</span>
}</pre></div><h2 style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:1.75em;margin-top:1em;margin-bottom:16px;line-height:1.225;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238)"><a href="https://github.com/DougGregor/swift-evolution/tree/importing-objc-generics#impact-on-existing-code" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1" target="_blank"><span style="font-weight:normal;font-size:16px;line-height:1;font-family:octicons;display:inline-block;color:rgb(0,0,0);vertical-align:middle"></span></a>Impact on existing code</h2><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">In Swift 2, parameterized Objective-C classes are imported as non-parameterized classes. Importing them as parameterized classes will break any existing references to the affecting APIs. There are a handful of cases where type inference may paper over the problems:</p><div style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-bottom:16px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;word-break:normal"><span style="color:rgb(167,29,93)">let</span> array: NSArray <span style="color:rgb(167,29,93)">=</span> [<span style="color:rgb(24,54,145)"><span>"</span>hello<span>"</span></span>, <span style="color:rgb(24,54,145)"><span>"</span>world<span>"</span></span>] <span style="color:rgb(150,152,150)">// okay, infer NSArray<NSString></span>
<span style="color:rgb(150,152,150)">// old</span>
<span style="color:rgb(167,29,93)">var</span> mutArray <span style="color:rgb(167,29,93)">=</span> NSMutableArray() <span style="color:rgb(150,152,150)">// error: need type arguments for NSMutableArray</span></pre></div><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">A migrator could introduce the type bounds as arguments, e.g., <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSArray</code> would get migrated to <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSArray<AnyObject></code>. It is not the best migration---many developers would likely want to tighten up the bounds to improve their Swift code---but it should migrate existing code.</p><h2 style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:1.75em;margin-top:1em;margin-bottom:16px;line-height:1.225;padding-bottom:0.3em;border-bottom-width:1px;border-bottom-style:solid;border-bottom-color:rgb(238,238,238)"><a href="https://github.com/DougGregor/swift-evolution/tree/importing-objc-generics#alternatives-considered" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none;display:inline-block;padding-right:2px;line-height:1" target="_blank"><span style="font-weight:normal;font-size:16px;line-height:1;font-family:octicons;display:inline-block;color:rgb(0,0,0);vertical-align:middle"></span></a>Alternatives considered</h2><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">The only major alternative design involves bringing type erasure into the Swift generics system as an alternative implementation. It would lift the restrictions on extensions of parameterized Objective-C classes by treating type parameters in such contexts as the type bounds:</p><div style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-bottom:16px"><pre style="overflow:auto;font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;margin-top:0px;margin-bottom:0px;line-height:1.45;padding:16px;background-color:rgb(247,247,247);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-wrap:normal;word-break:normal"><span style="color:rgb(167,29,93)">extension</span> MySet {
<span style="color:rgb(167,29,93)">func</span> <span style="color:rgb(121,93,163)">someNewMethod</span>(x: T) { <span style="color:rgb(167,29,93)">...</span> } <span style="color:rgb(150,152,150)">// okay: `T` is treated like `NSCopying`</span>
}</pre></div><p style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:16px">Doing so could allow the use of "unspecialized" generic types within Swift, e.g., <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSMutableArray</code> with no type bounds (possibly spelled <code style="font-family:Consolas,'Liberation Mono',Menlo,Courier,monospace;font-size:14px;padding:0.2em 0px;margin:0px;background-color:rgba(0,0,0,0.0392157);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px">NSMutableArray<*></code>), which would more accurately represent Objective-C semantics in Swift.</p><div style="color:rgb(51,51,51);font-family:'Helvetica Neue',Helvetica,'Segoe UI',Arial,freesans,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:16px;margin-top:0px;margin-bottom:0px!important">However, doing so comes at the cost of having two incompatible generics models implemented in Swift, which produces both a high conceptual burden as well as a high implementation cost. The proposed solution implies less implementation cost and puts the limitations on what one can express when working with parameterized Objective-C classes without fundamentally changing the Swift model.</div></div></div></div></div></div></div></div><div style="width:980px;margin-right:auto;margin-left:auto;color:rgb(51,51,51);font-family:Helvetica,arial,nimbussansl,liberationsans,freesans,clean,sans-serif,'Apple Color Emoji','Segoe UI Emoji','Segoe UI Symbol';font-size:13px;background-color:rgb(255,255,255)"><div style="margin-top:40px;padding-top:40px;padding-bottom:40px;font-size:12px;line-height:1.5;color:rgb(118,118,118);border-top-width:1px;border-top-style:solid;border-top-color:rgb(238,238,238)"><ul style="padding:0px;margin:0px;list-style:none;float:right"><li style="display:inline-block;line-height:16px"><a href="https://status.github.com/" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Status</a></li> <li style="display:inline-block;line-height:16px;margin-left:10px"><a href="https://developer.github.com/" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">API</a></li> <li style="display:inline-block;line-height:16px;margin-left:10px"><a href="https://training.github.com/" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Training</a></li> <li style="display:inline-block;line-height:16px;margin-left:10px"><a href="https://shop.github.com/" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Shop</a></li> <li style="display:inline-block;line-height:16px;margin-left:10px"><a href="https://github.com/blog" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Blog</a></li> <li style="display:inline-block;line-height:16px;margin-left:10px"><a href="https://github.com/about" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">About</a></li> <li style="display:inline-block;line-height:16px;margin-left:10px"><a href="https://github.com/pricing" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank">Pricing</a></li></ul><a href="https://github.com/" style="background-color:transparent;color:rgb(64,120,192);text-decoration:none" target="_blank"><span title="GitHub " style="font-size:24px;line-height:1;font-family:octicons;display:inline-block;color:rgb(204,204,204)"></span></a><ul style="padding:0px;margin:0px;list-style:none"><br></ul></div></div>
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=7XtDdMHRjqIUi4tzSjSp2pWQIyxYdP6woIWn4vwV5gee7WHkpMpYimtaW1ceZ63GrtEbevo4k9dcYveNddirKAbbJDRwd0BWvhJ2jbui79JwFk4636vvN0ndKYDpQ3vYLX-2BNr3ZOQ06lCMbVCwvIzP5QZ7sHjVBkIAY4zGXx9e7YSIxTYZ-2BFid-2FlpTd1sOGCjDvh3Uf-2Fr0XYq5rd-2FC-2FFWwr4H1ICPctpraVinPQevh0-3D" alt="" width="1" height="1" border="0" style="min-height:1px!important;width:1px!important;border-width:0!important;margin-top:0!important;margin-bottom:0!important;margin-right:0!important;margin-left:0!important;padding-top:0!important;padding-bottom:0!important;padding-right:0!important;padding-left:0!important">
</div>
<br>_______________________________________________<br>
swift-evolution mailing list<br>
<a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br>
<a href="https://lists.swift.org/mailman/listinfo/swift-evolution" rel="noreferrer" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br>
<br></blockquote></div><br></div>