<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class="">I've already suggested this quite some time back and was told that this doesn't need to go through evolution. It's filed here: <a href="https://bugs.swift.org/browse/SR-1882" class="">https://bugs.swift.org/browse/SR-1882</a><div class=""><br class=""></div><div class="">Unfortunately, I haven't had time to look into it myself and I'm unlikely to have the time anytime soon...</div><div class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Oct 3, 2016, at 7:52 PM, Harlan Haskins via swift-evolution <<a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="content-type" content="text/html; charset=utf-8" class=""><div dir="auto" class=""><div class=""><span class=""></span></div><div class=""><div class="">Hey all,</div><div class=""><br class=""></div><div class="">Julio Carrettoni, Robert Widmann, and I have been working on a proposal to mitigate something that's burned us all since Swift 1. We'd love some feedback!</div><div class=""><br class=""></div><div class="">It's available here: <a href="https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd" class="">https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd</a></div><div class=""><br class=""></div><div class="">I've posted the current draft below.</div><div class=""><br class=""></div><div class="">Thanks,</div><div class="">Harlan Haskins<br class=""></div><div class=""><br class=""></div><div class=""><h1 style="box-sizing: border-box; margin-right: 0px; margin-bottom: 16px; margin-left: 0px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238); margin-top: 0px !important;" class=""><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Disallow Optionals in String Interpolation Segments</span></font></h1><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 16px;" class=""><li style="box-sizing: border-box;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Proposal: <a href="https://gist.github.com/harlanhaskins/NNNN-filename.md" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; text-decoration: none;" class="">SE-NNNN</a></span></li><li style="box-sizing: border-box; margin-top: 0.25em;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Authors: <a href="https://github.com/harlanhaskins" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; text-decoration: none;" class="">Harlan Haskins</a>, <a href="https://github.com/Julioacarrettoni" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; text-decoration: none;" class="">Julio Carrettoni</a>, <a href="https://github.com/CodaFi" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; text-decoration: none;" class="">Robert Widmann</a></span></li><li style="box-sizing: border-box; margin-top: 0.25em;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Review Manager: TBD</span></li><li style="box-sizing: border-box; margin-top: 0.25em;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Status: <span style="box-sizing: border-box; font-weight: 600;" class="">Awaiting revie</span></span></li></ul><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-introduction" class="anchor" href="https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#introduction" aria-hidden="true" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"></svg><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z" class=""></path></span></font></a><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Introduction</span></font></h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Swift developers frequently use string interpolation as a convenient, concise syntax for interweaving variable values with strings. The interpolation machinery, however, has surprising behavior in one specific case: <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Optional<T></code>. If a user puts an optional value into a string interpolation segment, it will insert either <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">"Optional("value")"</code> or <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">"nil"</code> in the resulting string. Neither of these is particularly desirable, so we propose a warning and fix-it to surface solutions to these potential mistakes.</span></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Swift-evolution thread: <a href="https://lists.swift.org/pipermail/swift-evolution/" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; text-decoration: none;" class="">Discussion thread topic for that proposal</a></span></p><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-motivation" class="anchor" href="https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#motivation" aria-hidden="true" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"></svg><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z" class=""></path></span></font></a><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Motivation</span></font></h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><em style="box-sizing: border-box;" class="">The Swift Programming Language</em> defines string interpolation segments as "a way to construct a new String value from a mix of constants, variables, literals, and expressions". There is one type that runs counter to this definition: <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Optional</code>. The <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">.none</code> case in particular is used to indicate the absence of a value. Moreover, its inclusion in interpolation segments leads to the dreaded <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">"nil"</code> in output that is often fed to UI elements. Even barring that, interpolating a non-nil optional value yields <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">"Optional("value")"</code>, a result that is not useful even in logged output.</span></p><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Given that the <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Optional</code> type is never fit for display to the end user, and can often be a surprising find in the console, we propose that requesting an <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Optional</code>'s debug description be an explicit act. This proposal now requires a warning when using an expression of <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Optional</code> type within a string interpolation segment.</span></p><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-proposed-solution" class="anchor" href="https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#proposed-solution" aria-hidden="true" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"></svg><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z" class=""></path></span></font></a><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Proposed solution</span></font></h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">The user will be warned after attempting to use an expression with type <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Optional<T></code> in a string interpolation segment. They will then be offered a fixit suggesting they explicitly request the <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">debugDescription</code> of the <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Optional</code> value instead.</span></p><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-detailed-design" class="anchor" href="https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#detailed-design" aria-hidden="true" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"></svg><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z" class=""></path></span></font></a><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Detailed design</span></font></h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Semantic analysis currently does not do much but guarantee the well-formedness of expressions in interpolation segments. These are then fed directly to <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">String.init(stringInterpolationSegment:)</code> and are run through the runtime reflection system to generate a description. Semantic analysis will be tweaked to inspect the result of solving an interpolation segment for an <code style="box-sizing: border-box; padding: 0.2em 0px; margin: 0px; border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px;" class="">Optional</code> and will offer a fixit in that case.</span></p><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-impact-on-existing-code" class="anchor" href="https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#impact-on-existing-code" aria-hidden="true" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"></svg><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z" class=""></path></span></font></a><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Impact on existing code</span></font></h2><p style="box-sizing: border-box; margin-top: 0px; margin-bottom: 16px;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">As this is a warning, code written before this proposal will continue to compile and run with the same semantics as before. Authors of code that makes use of this unsafe pattern will be offered a migration path to the safer, more explicit form.</span></p><h2 style="box-sizing: border-box; margin-top: 24px; margin-bottom: 16px; line-height: 1.25; padding-bottom: 0.3em; border-bottom-width: 1px; border-bottom-style: solid; border-bottom-color: rgb(238, 238, 238);" class=""><a id="user-content-alternatives-considered" class="anchor" href="https://gist.github.com/harlanhaskins/63b7343e7fe4e5f4c6cfbe9413a98fdd#alternatives-considered" aria-hidden="true" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; text-decoration: none; float: left; padding-right: 4px; margin-left: -20px; line-height: 1;"><svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewBox="0 0 16 16" width="16"></svg><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class=""><path d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z" class=""></path></span></font></a><font size="3" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Alternatives considered</span></font></h2><ul style="box-sizing: border-box; padding-left: 2em; margin-top: 0px; margin-bottom: 0px !important;" class=""><li style="box-sizing: border-box;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">A fixit that suggests a default value be inserted would be entirely appropriate (following the style of the fixit introduced in <a href="https://github.com/apple/swift-evolution/blob/master/proposals/0140-bridge-optional-to-nsnull.md" style="box-sizing: border-box; -webkit-text-decoration-skip: objects; text-decoration: none;" class="">SE-0140</a>).</span></p></li><li style="box-sizing: border-box; margin-top: 0.25em;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">Forbidding this pattern by hard error would make this proposal a breaking change that is out of scope for this stage of Swift's development.</span></p></li><li style="box-sizing: border-box; margin-top: 0.25em;" class=""><p style="box-sizing: border-box; margin-top: 16px; margin-bottom: 16px;" class=""><span style="background-color: rgba(255, 255, 255, 0);" class="">A fixit that introduces a force-unwrapping would technically work as well, however it would be fixing a dangerous operation with yet another dangerous operation.</span></p></li></ul></div></div><div class=""><br class=""><br class="">Sent from my iPad</div></div>_______________________________________________<br class="">swift-evolution mailing list<br class=""><a href="mailto:swift-evolution@swift.org" class="">swift-evolution@swift.org</a><br class="">https://lists.swift.org/mailman/listinfo/swift-evolution<br class=""></div></blockquote></div><br class=""></div></body></html>