<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><div><blockquote type="cite" class=""><div class="">On Sep 12, 2017, at 6:30 PM, Jordan Rose &lt;<a href="mailto:jordan_rose@apple.com" class="">jordan_rose@apple.com</a>&gt; wrote:</div><br class="Apple-interchange-newline"><div class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">It gets a little tricky if layout matters—Optional&lt;AnyObject&gt; fits exactly in a single word-sized value, but Optional&lt;Optional&lt;AnyObject&gt;&gt; does not on Apple platforms—but that just means it should be opt-in or tied to -enable-testing in some way.</span></div></blockquote></div><div class=""><br class=""></div><div class="">I forgot to state this explicitly, but I agree—unless the module was compiled with -enable-testing, the generated code should not permit #invalid values and would be identical to a version without any @testable parameters/types.</div><div class=""><br class=""></div><div class="">Here's a more explicit sketch of a design for this feature (albeit one that has some impact on the type system and a couple weird corners):</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• `@testable T` is a supertype of `T` which, when the module is compiled with `-enable-testing`, has an additional `#invalid` inhabitant. (We can bikeshed `@testable` and `#invalid` some other time.) Notionally, `@testable` is sort of like an enum which has one case (`valid(Wrapped)`) in a non-`-enable-testing` build, and an additional case (`invalid`) in an `-enable-testing` build.</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• `T` implicitly converts to `@testable T`; `@testable T` can be explicitly downcast to `T`.* When `-enable-testing` is *not* provided, these downcasts will always succeed, and the trap in `as!` or the code for a `nil` result from `as?` are unreachable. We should ignore and potentially optimize away this unreachable code without warning about it.</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• Any pattern that matches against `T` can also match against `@testable T` with no alteration. Only `_` or a capture can match `#invalid`.** Otherwise, `#invalid` values will be handled by the `default` case of a `switch` or the `else` block of an `if` or `guard`.</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• A given `@testable T` value (i.e. property, variable, subscript, parameter, return value, etc.) may only be assigned `#invalid` if it is either in the current module or is in a module imported with `@testable import`.</div><div class=""><br class=""></div><div class=""><span class="Apple-tab-span" style="white-space:pre">        </span>• When `-enable-testing` is *not* provided, all code which creates an `#invalid` value must be unreachable. This is even true in `default:` cases and other constructs which could be reached by unknown future values of a type. Only constructs like `guard let t = testableT as? T else { return #invalid }` can be successfully compiled with `-enable-testing` disabled.</div><div class=""><br class=""></div><div class="">The memory representation of `#invalid` does not have to be the same for all types, so it could try to find a spare bit or bit pattern that's unused in the original type (as long as, for non-exhaustive enums, it also avoids using any bit pattern a future version of the type *might* use). Or, for simplicity, we could just add a tag byte unconditionally. This tag byte would only be needed when built with `-enable-testing`, so basically only debug builds would pay this price, and only in places where the author explicitly asked to be able to test with `#invalid` values.</div><div class=""><br class=""></div><div class=""><br class=""></div><div class="">* There's an argument to be made for an IUO-style implicit conversion from `@testable Foo` to `Foo` which traps on `#invalid`. This seems dangerous to me, but on the other hand, you should only ever encounter it in testing or development, never in production.</div><div class=""><br class=""></div><div class="">** I'm not sure captures can work here—wouldn't they still be the `@testable` type?—so I'm actually wondering if we should introduce a subtle distinction between `case _`/`case let x` and `default`: the former cannot match `#invalid`, while the latter can. That would be a little bit…odd, though.</div><br class=""><div class="">
<span class="Apple-style-span" style="border-collapse: separate; font-variant-ligatures: normal; font-variant-east-asian: normal; font-variant-position: normal; line-height: normal; border-spacing: 0px;"><div class=""><div style="font-size: 12px; " class="">--&nbsp;</div><div style="font-size: 12px; " class="">Brent Royal-Gordon</div><div style="font-size: 12px; " class="">Architechies</div></div></span>

</div>
<br class=""></body></html>