<div dir="ltr">Hi Howard,<div><br></div><div>Making generics covariant by default would add even more of a burden to users. They would need to check the type property of a generic object any time they wanted to mutate that generic object or risk their program terminating.</div><div><br></div><div>I don't think the fact that array accesses are checked at runtime is a good example:</div><div><br></div><div>1. The Swift team has stated that subscripting into an array returns a non-optional at least in part because of performance issues. (Unfortunately, I think this was mentioned on the old Apple developer forums, which are now inaccessible, so don't take my word for it until someone with more insight says so one way or another :).</div><div>2. The fact that this specific aspect of Swift is checked at runtime doesn't provide insight as to whether or not another aspect of Swift should be compile-time or runtime-checked; it just indicates that there exists the possibility of some checks being done at runtime (and every mainstream statically typed language performs runtime checks to some extent, this isn't a novel conclusion).<br></div><div>3. Checking that an array access is in bounds is trivial from a conceptual standpoint. The index needs to be at least 0 and at most the length of the array - 1.</div><div>4. The length of a Swift array is not part of the type contract, whereas the type enclosed within a generic type is. Swift doesn't have fixed-length arrays.</div><div><br></div><div>I think a proposal to get rid of optionals and non-nullable types would be a better analogy. Here is a comparison to that hypothetical proposal:</div><div><br></div><div>1. The most popular objection to Swift's optional system seems to be either clutter (from the ?, ! sigils) and ease of use. (Your proposal cites the ugliness of variance annotations in other languages as a primary motivation.)</div><div>2. Removing the optional system would result in moving a compile-time check to a run-time check. (Your proposal states that the burden of ensuring the access is valid lies at the use site, which introduces the possibility of runtime failures that cannot be currently expressed.)</div><div>3. Removing optionals would keep the language type-safe, as an exception would occur whenever calling a method on nil occurred at runtime (your proposal also keeps the language type-safe, in the formal sense). </div><div>4. The possibility of a run-time check failing and terminating the program with an NPE can be mitigated by user code performing an explicit check for nil at the use site. (Your proposal would require user code to check against the metatype property whenever a generic type is mutated to ensure that no preconditions can fail.)</div><div>5. Removing the optional system would cause the type system to be more imprecise, since a variable of type T would contain either an instance of T or nil. (Your proposal would cause the type system to be more imprecise, since a T<U> might actually be a T<V>, where V is a subtype of U, in a context where V cannot substitute for U.)</div><div><br></div><div>I hope this explains my objections (and those expressed elsewhere within this thread) more clearly.</div><div><br></div><div>Best,</div><div>Austin</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jan 13, 2016 at 1:54 PM, Howard Lovatt 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 dir="ltr">@Simon,<div><br></div><div>In the Swift code below:</div><div><br></div><div><p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><span style="color:rgb(187,44,162)"> let</span> array = [<span style="color:rgb(39,42,216)">1</span>]</p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(79,129,135)"> array<span style="color:rgb(0,0,0)">[</span><span style="color:rgb(39,42,216)">0</span><span style="color:rgb(0,0,0)">]</span><span style="color:rgb(0,132,0)"> </span><span style="color:rgb(0,132,0)">// 1, OK</span></p>
<p style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"><font color="#008400"> </font><span style="color:rgb(79,129,135)">array</span><span style="color:rgb(0,0,0)">[</span><font color="#272ad8">1</font><span style="color:rgb(0,0,0)">]</span><font color="#008400"> // Error not detected by compiler but detected at runtime</font></p></div><div><br></div><div>you have an example of an error detected at runtime that terminates program execution, it doesn't return an optional.</div><div><br></div><div>In other languages this would be a type error, these languages are usually described as dependent type (<a href="https://en.wikipedia.org/wiki/Dependent_type" target="_blank">https://en.wikipedia.org/wiki/Dependent_type</a>). An example of the advantage of this would be vector (or matrix multiplication), e.g. imagine that Swift had dependent types:</div><div><br></div><div><div><p style="margin:0px;line-height:normal"><span style="font-family:Menlo;font-size:11px;color:rgb(187,44,162)"> let</span><font face="Menlo"><span style="font-size:11px"> row = RowVec(</span></font><span style="font-family:Menlo;font-size:11px;color:rgb(39,42,216)">1, 2) </span><font color="#008400" face="Menlo"><span style="font-size:11px">// Type: matrix of int with 1 row and 0 columns (note size is part of the type)</span></font></p><p style="margin:0px;line-height:normal"><span style="font-family:Menlo;font-size:11px;color:rgb(187,44,162)"> let</span><font face="Menlo"><span style="font-size:11px"> col = ColVec(3</span></font><span style="font-family:Menlo;font-size:11px;color:rgb(39,42,216)">) </span><font color="#008400" face="Menlo"><span style="font-size:11px">// Type: matrix of int with 0 rows and 1 column</span></font></p><p style="margin:0px;line-height:normal"><span style="font-family:Menlo;font-size:11px;color:rgb(187,44,162)"> let</span><font face="Menlo"><span style="font-size:11px"> scaler = row * col</span></font><span style="font-family:Menlo;font-size:11px;color:rgb(39,42,216)"> </span><span style="font-family:Menlo;font-size:11px;color:rgb(0,132,0)">// Compile time </span><font color="#008400" face="Menlo"><span style="font-size:11px">error because both vectors should be the same length</span></font></p></div></div><div><span style="color:rgb(0,132,0)"><br></span></div><div>At the moment if you wrote a matrix package in Swift the above example would be a runtime error and not a compile time error, but with dependent typing it would be a compile time error.</div><div><br></div><div>There is another discussion of Swift Evolution on calculable types that are closely related to dependent typing.</div><div><br></div><div>To me you just strike the balance, sometimes static checking is best sometimes runtime. You strike the balance by how practical it is to do the static checking, if the burden that the static checking adds to the users then it isn't worth it. This is the case with annotated variance in languages like Java and Scala, the annotations do not add much. Hence I am suggesting system that is simple to use, much like Swift arrays are easy to use but not totally, but largely, statically typed.</div><div><br></div><div>Hope that explains my reasoning for making most type error compile time checked but a small subset runtime checked,</div><div><br></div><div> -- Howard.</div><div><br></div></div><div class="gmail_extra"><div><div class="h5"><br><div class="gmail_quote">On 13 January 2016 at 14:01, Simon Pilkington <span dir="ltr"><<a href="mailto:simonmpilkington@icloud.com" target="_blank">simonmpilkington@icloud.com</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">I’d be interested in reading up on what the Oracle response was if you have links.<div><br></div><div>As you mentioned even Swift doesn’t get away from runtime type checking but in the two examples you mentioned - array out of bounds and casts - Swift makes use of the Optionals system to highlight that an operation may fail and allows the user to handle that failure. Covariance should have similar syntax support (for example use of optional chaining similar to optional protocol requirements to indicate that a call may fail due to incorrect types). For the compiler to understand when such failure is possible, some kind of covariance syntax would be required.<br><div><br></div><div>As a related question, do you see covariance syntax as such a burden?</div><span><font color="#888888"><div><br></div><div>-Simon</div></font></span><div><div><div><div><div><br></div><div><br><div><blockquote type="cite"><div>On 13 Jan 2016, at 12:47 PM, Howard Lovatt <<a href="mailto:howard.lovatt@gmail.com" target="_blank">howard.lovatt@gmail.com</a>> wrote:</div><br><div><div dir="ltr">Yes you can annotate for covariance, invariance, and contravariance, both Java and Scala, allow all three. The problem is that the code becomes splattered with variance annotations. The Java people themselves have publicly regretted this and wished that they had made covariance the default. If you look at generic code invariance and covariance are by far the most common requirements; this proposal would address these common use case without burdening the programmer.<div><br></div><div>Swift, and no usable language, is completely statically typed. Examples in Swift of runtime type checking are array out of bounds and casts. There are other examples of non-type related runtime checks is Swift: numerical overflow, throws, using optionals to signal errors, and using enums to signal errors. I say use what is appropriate, static type checking if it is easy to do, otherwise runtime type checking. Note I am not proposing an unsafe language like C, it is still type checked.</div><div><br></div><div>There is a strong positive precedence for a type check on write, Java arrays (not Java `List`s). Arrays in Java may be passed covariantly, and this is extensively used. However if you attempt to write the wrong type into the array you will get an `ArrayStoreException`. In practice you don't get many `ArrayStoreException`, non of my code has ever had one. Its just not something you do in practice, as noted before contravariance is rare.</div><div><br></div><div>Thanks for you comments and I hope this eases your concerns,</div><div><br></div><div> -- Howard.<br><div><br></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On 13 January 2016 at 11:33, Simon Pilkington <span dir="ltr"><<a href="mailto:simonmpilkington@icloud.com" target="_blank">simonmpilkington@icloud.com</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>The problem is that conceptually and behaviourally Box<Bottom> *is indeed not* a Box<Top> and cannot be treated the same as one. The proposal attempts to get around this difference with a runtime failure but this would result in very fragile code - you get passed a Box<Top> and want to pass it a subclass of Top, will it succeed, who knows. You probably would be able to check the types but the complier wouldn’t highlight that this is an operation that could potentially fail.</div><div><br></div><div>This seems to be very much against Swift’s goal of safety being enforced by the compiler as much as possible.</div><div><br></div><div>Java uses the wildcard syntax to highlight this conceptual and behavioural difference - Box<Bottom> is not covariant with Box<Top> but rather with Box<? extends Top>. The compiler can then enforce that a programmer doesn’t try to pass an incompatible type to a variable of such type. Even though this is a complication to the language (many Java programmers struggle with correctly using the wildcard syntax) I don’t see covariance for generics being added to Swift in a robust manner without some kind of similar syntax.</div><div><br></div><div>-Simon</div><div><br><div><blockquote type="cite"><div><div><div>On 12 Jan 2016, at 8:45 PM, Howard Lovatt via swift-evolution <<a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a>> wrote:</div><br></div></div><div><div style="word-wrap:break-word"><div><div><div style="margin:0px;line-height:normal"><font face="Menlo"><span style="font-size:11px">Currently you generics are invariant whereas function arguments etc. are covariant. I am suggesting that if the way generics are implemented is changed then they can be made covariant and that this will add considerable utility to Swift generics.</span></font></div><div style="margin:0px;line-height:normal"><font face="Menlo"><span style="font-size:11px"><br></span></font></div><div style="margin:0px;line-height:normal"><font face="Menlo"><span style="font-size:11px">1st a demonstration of the current situation of invariant generics:</span></font></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span><br></span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Current system</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#bb2ca2">class</span> Top {}</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#bb2ca2">class</span> Bottom: <span style="color:#4f8187">Top</span> {}</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#bb2ca2">struct</span> Box<T: AnyObject> {</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#bb2ca2">var</span> value: <span style="color:#703daa">T</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#bb2ca2">init</span>(<span style="color:#bb2ca2">_</span> initialValue: <span style="color:#703daa">T</span>) {</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#4f8187">value</span> = initialValue;</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> }</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> }</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#bb2ca2">let</span> boxB = <span style="color:#4f8187">Box</span>(<span style="color:#4f8187">Bottom</span>())</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// let boxT: Box<Top> = boxB // Covariance currently not allowed</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">The key point is although `Bottom` 'is a’ `Top`, `Box<Bottom>` *is not* a `Box<Top>`.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">I am suggesting:</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">1. That `Box<Bottom>` should be a `Box<Top>` (covariance).</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">2. An implementation that allows the above covariance.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px">3. That protocols are made generic, i.e. `protocol Box<T> { var value: T { get set } }` and that this mechanism replaces associated types for protocols.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Proposal:</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// 1. No change to Box, i.e. programmer would just write Box as before</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// 2. Code transformed by comiler with write check for each specific, generic type instance</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Best approximation of resulting code in current Swift to demonstrate spirit of idea:</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Compiler writes a universal form using the upper bound (it writes the underlyting representation).</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// In practice this would be called `Box` but used `BoxAnyObject` to indicate that it has a generic argument bounded by `AnyObject`.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#bb2ca2">struct</span> BoxAnyObject {</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Generated from generic argument `<T: AnyObject>`.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span><span style="color:#bb2ca2">let</span><span> T: </span><span style="color:#703daa">AnyObject</span><span>.Type </span>// Store the actual type.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"> <br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Generated from stored property `var value: T` and noting that `T`'s upper bound is `AnyObject`.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span><span style="color:#bb2ca2">private</span><span> </span><span style="color:#bb2ca2">var</span><span> _value: </span><span style="color:#703daa">AnyObject</span><span> </span>// Access the stored property through a setter so that type can be checked</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#bb2ca2">var</span> value: <span style="color:#703daa">AnyObject</span> {</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#bb2ca2">get</span> {</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#bb2ca2">return</span> <span style="color:#4f8187">_value</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> }</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#bb2ca2">set</span> {</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// In all functions check that args declared as `T` are actually a `T` or a sub-type.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Note: `is` only works with type literal and there is no `>=` operator for types :(.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// `is` would need changing or `>=` for types adding, nearest at moment `==`.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(209,47,27)"><span> </span><span style="color:#3d1d81">precondition</span><span>(</span><span style="color:#4f8187">T</span><span> == </span><span style="color:#008400">/* >= */</span><span> newValue.</span><span style="color:#bb2ca2">dynamicType</span><span>, </span>"Type of newValue, <span>\</span>(<span>newValue.</span><span style="color:#bb2ca2">dynamicType</span>), is not a sub-type of generic type T, <span>\</span>(<span style="color:#4f8187">T</span>)"<span>)</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#4f8187">_value</span> = newValue</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> }</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> }</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"> <br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Generated from `init(_ initialValue: T)` and noting that `T`'s upper bound is `AnyObject`.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#bb2ca2">init</span>(<span style="color:#bb2ca2">_</span> lowestCommonDeclaredT: <span style="color:#703daa">AnyObject</span>.Type, <span style="color:#bb2ca2">_</span> initialValue: <span style="color:#703daa">AnyObject</span>) {</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#4f8187">T</span> = lowestCommonDeclaredT</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#4f8187">_value</span> = initialValue</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> }</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> }</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Demonstrate that all `Box`es are the same size and therefore can be bitwise copied</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Compiler supplies lowest-common, declared, generic type for all the `T`s in the `init` call.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span><span style="color:#bb2ca2">var</span><span> bT = </span><span style="color:#4f8187">BoxAnyObject</span><span>(</span><span style="color:#4f8187">Top</span><span>.</span><span style="color:#bb2ca2">self</span><span>, </span><span style="color:#4f8187">Top</span><span>()) </span>// In practice user would write `let bT = Box(Top())`.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span><span style="color:#4f8187">bT</span><span>.</span><span style="color:#4f8187">T</span><span> </span>// Top.Type</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(61,29,129)"><span> </span>sizeofValue<span>(</span><span style="color:#4f8187">bT</span><span>) </span><span style="color:#008400">// 16</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span><span style="color:#bb2ca2">var</span><span> bB = </span><span style="color:#4f8187">BoxAnyObject</span><span>(</span><span style="color:#4f8187">Bottom</span><span>.</span><span style="color:#bb2ca2">self</span><span>, </span><span style="color:#4f8187">Bottom</span><span>()) </span>// In practice user would write `let bB = Box(Bottom())`.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span><span style="color:#4f8187">bB</span><span>.</span><span style="color:#4f8187">T</span><span> </span>// Bottom.Type</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(61,29,129)"><span> </span>sizeofValue<span>(</span><span style="color:#4f8187">bB</span><span>) </span><span style="color:#008400">// 16</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Demonstration covariance.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span><span style="color:#4f8187">bT</span><span> = </span><span style="color:#4f8187">bB</span><span> </span>// Compiler would check covariance of declared generic types.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span><span style="color:#4f8187">bT</span><span>.</span><span style="color:#4f8187">T</span><span> </span>// Bottom.Type</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Demonstrate generic returned type</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Compiler would add cast to declared, generic type.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span><span style="color:#4f8187">bB</span><span>.</span><span style="color:#4f8187">value</span><span> </span><span style="color:#bb2ca2">as</span><span>! </span><span style="color:#4f8187">Bottom</span><span> </span>// In practice user would write `bB.value`.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;min-height:13px"><br></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// Demonstrate type safety</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span><span style="color:#4f8187">bT</span><span> = </span><span style="color:#4f8187">BoxAnyObject</span><span>(</span><span style="color:#4f8187">Top</span><span>.</span><span style="color:#bb2ca2">self</span><span>, </span><span style="color:#4f8187">Top</span><span>()) </span>// In practice user would write `bT = Box(Top())`.</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo"> <span style="color:#4f8187">bT</span>.<span style="color:#4f8187">value</span> = <span style="color:#4f8187">Top</span>() <span style="color:#008400">// OK</span></div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// bT.value = Bottom() // Doesn't work at present because need `>=` for types, but would work in practice</div><div style="margin:0px;font-size:11px;line-height:normal;font-family:Menlo;color:rgb(0,132,0)"><span> </span>// bB.value = Top() // Runtime error - wrong type</div><div><br></div><div>The implications of this proposal are:</div><div><br></div><div>1. The compiler can statically type check a read from a stored property.</div><div>2. A write to a stored property is type checked at runtime.</div><div>3. Protocols can be made generic instead of having an associated type and then they become a proper type with dynamic dispatch.</div><div>4. Generic protocols can be a type just like non-generic protocols, structs, and classes and unlike associated type protocols that can only be a generic constraint.</div><div>5. The awkwardness of dealing with associated type generics is replaced by a more powerful and easier to understand semantic of a type, just like the other types.</div><div>6. There is a lot of ‘non-obvoius’, long code, for example `inits`, that use a `where` clause to constrain an associated type protocol, this would be unnecessary.</div><div>7. There are whole types, `AnySequence`, `AnyGenerator`, etc., that would be replaced by a generic protocols, `Sequence`, `Generator`, etc.</div><div><br></div><div>Advantages:</div><div><br></div><div>1. Covariant generics are a powerful addition to the language.</div><div>2. Generics’ invariance are inconsistent with the rest of the language.</div><div>3. Generic protocols would become a ‘proper’ type and you could have arrays and fields of a generic protocol.</div><div>4. There are many threads on swift-evolution looking at how protocols can be made into a ‘proper’ type or at least a concept that is easier to understand.</div><div><br></div><div>Compatibility:</div><div><br></div><div>1. This would be a major change since associated types in protocols would be replaced by generics.</div><div>2. The new implementation of generics might break some existing `struct` and `class` code, for example if it is dependent on the exact size of an object because the class will have extra fields, one for each generic type, and therefore will be larger.</div><div><br></div><div>Disadvantages:</div><div><br></div><div>1. Major change.</div><div>2. Object size increases.</div><div><br>Thanks in advance for any comments,</div><div><br></div><div> — Howard.</div><div><br></div><div>PS This is part of a collection of proposals previously presented as “Protocols on Steroids”.</div>
<br>
</div></div><img src="https://u2002410.ct.sendgrid.net/wf/open?upn=t1lXJ9jBaqmhI-2F639qqRIv6GBQuIzl35AVl5PWMKokCrmW5RYfNBeoAeoL3QdFfVx3rPNQq53b3E-2BXtIrfGZD6BWDbeHevI6aXpB216n-2BXAzdhfAiJOmo2pYaWogM-2BA6FvDS-2BoqwOTpWlb18dvbbNvFImgTJnxidNrNIMC2nI3XrvpMWHLepYAMFhpLnSg14aCNI-2Fw1iOcR5Jy1UXBsVx7H49Ko6rxAcKzwWU-2BzhB5Y-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><span>
_______________________________________________<br>swift-evolution mailing list<br><a href="mailto:swift-evolution@swift.org" target="_blank">swift-evolution@swift.org</a><br><a href="https://lists.swift.org/mailman/listinfo/swift-evolution" target="_blank">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></span></div></blockquote></div><br></div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div> -- Howard.<br></div>
</div>
</div></blockquote></div><br></div></div></div></div></div></div></div></blockquote></div><br><br clear="all"><div><br></div></div></div><span class="HOEnZb"><font color="#888888">-- <br><div> -- Howard.<br></div>
</font></span></div><span class="HOEnZb"><font color="#888888">
<img src="https://u2002410.ct.sendgrid.net/wf/open?upn=7XtDdMHRjqIUi4tzSjSp2pWQIyxYdP6woIWn4vwV5gcc0Fpefp9j5vUxBnnEapVGnpKNYIjwPlpB3WN9nUIXd2hQJZyfOq9YRZoDUqHX8jpu9-2FzIqvv7YW6ccr4N4C00lppFwX0soxMB0lICjJ2bkITLEmn4-2B-2BjC8XNzrWOx1H2vCm18WcqNsnMC-2F4sQUWEP0Gvp53pzO6bP6hua4MZTj8zi3fqdZvgZ0NNRK3SQ9to-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">
</font></span><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>