<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body><div style="font-family:Arial;">I understand the reasoning and am in favor of it for those reasons, but I will note that I use deprecations extremely frequently while refactoring, and this would defeat that use case. As I have a few larger projects with long compile times, losing that functionality would be disappointing.<br></div>
<div style="font-family:Arial;"><br></div>
<div id="sig40804545"><div class="signature"><span class="font" style="font-family:arial, sans-serif, sans-serif">Sincerely,</span><span class="font" style="font-family:arial, sans-serif, sans-serif"></span><br></div>
<div class="signature"><span class="font" style="font-family:arial, sans-serif, sans-serif"> Zachary Waldowski</span><span class="font" style="font-family:arial, sans-serif, sans-serif"></span><br></div>
<div class="signature"><span class="font" style="font-family:arial, sans-serif, sans-serif"> </span><a href="mailto:zach@waldowski.me"><span class="font" style="font-family:arial, sans-serif, sans-serif">zach@waldowski.me</span></a><br></div>
</div>
<div><br></div>
<div><br></div>
<div>On Fri, May 5, 2017, at 02:12 PM, Tony Allevato via swift-evolution wrote:<br></div>
<blockquote type="cite"><div dir="ltr"><div>Hey Swift Evolvers,<br></div>
<div><br></div>
<div>I'd like to propose a change that would suppress deprecation warnings when the reference to the deprecated declaration is in the same file as that declaration.<br></div>
<div><br></div>
<div>This personally affects one of my projects (Swift protocol buffers) because .proto files allow declarations to be declared as deprecated, and we'd like to surface that by deprecating the equivalent declaration in the Swift code that we generate. We can't do this without generating noisy build logs, because we still need to reference the deprecated declarations to encode/decode the messages correctly; and the workarounds have significant performance penalties as described in the draft.<br></div>
<div><br></div>
<div>I'd love some feedback from folks to know whether this—or something like it—is something that seems desirable/undesirable for the language. I've tinkered with an implementation in a <a href="https://github.com/apple/swift/compare/master...allevato:omit-deprecation-same-file">branch</a> and it's fairly straightforward.<br></div>
<div><br></div>
<div style="font-family:Arial;">Gist link: <a href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb">https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb</a><br></div>
<div><br></div>
<div><br></div>
<div><h1 style="margin-top:0px;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(234, 236, 239);color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';">Omit deprecation warnings for same-file references<br></h1><ul style="padding-left:2em;margin-top:0px;margin-bottom:16px;color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';font-size:16px;"><li style="">Proposal:<span> </span><a href="https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md" style="background-color:transparent;color:rgb(3, 102, 214);">SE-0000</a><br></li><li style="margin-top:0.25em;">Author(s):<span> </span><a href="https://github.com/allevato" style="background-color:transparent;color:rgb(3, 102, 214);">Tony Allevato</a><br></li><li style="margin-top:0.25em;">Status:<span> </span><span style="font-weight:600;"><a href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#rationale" style="background-color:transparent;color:rgb(3, 102, 214);">Awaiting review</a></span><br></li><li style="margin-top:0.25em;">Review manager: TBD<br></li></ul><h2 style="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(234, 236, 239);color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';"><a href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#introduction" style="background-color:transparent;color:rgb(3, 102, 214);float:left;padding-right:4px;line-height:1;"></a>Introduction<br></h2><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">Public API developers can use the<span> </span><code style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;padding-top:0.2em;padding-right:0px;padding-bottom:0.2em;padding-left:0px;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;background-color:rgba(27, 31, 35, 0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;">@available</code><span> </span>attribute in Swift to mark APIs as<span> </span><span style="font-weight:600;">deprecated,</span><span> </span>which will emit warnings when a user references that API to notify them that that particular API is no longer preferred or may disappear in the future.</span></span></span><br></p><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">These warnings are emitted for<span> </span><i>any</i><span> </span>reference to a deprecated entity, including those in the same file. In some cases, however, it may be necessary and correct to continue referring to the deprecated entity privately while discouraging its external use. In these scenarios, the warnings are superfluous and generate noise in the build logs. We propose eliminating these warnings for references made in the same file.</span></span></span><br></p><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">Swift-evolution thread:<span> </span><a href="http://thread.gmane.org/gmane.comp.lang.swift.evolution/" style="background-color:transparent;color:rgb(3, 102, 214);">TBD</a></span></span></span><br></p><h2 style="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(234, 236, 239);color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';"><a href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#motivation" style="background-color:transparent;color:rgb(3, 102, 214);float:left;padding-right:4px;line-height:1;"></a>Motivation<br></h2><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">As APIs evolve, declarations may become deprecated but still need to be referenced privately in order to function correctly. For example, consider an object that is serialized/parsed between a client and server. The first iteration of such a type might look like this (the examples use a strawman API to avoid tying the discussion too closely with the new coding APIs, which is not the focus):</span></span></span><br></p><div style="margin-bottom:16px;color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';font-size:16px;"><pre style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;word-wrap:normal;padding-top:16px;padding-right:16px;padding-bottom:16px;padding-left:16px;overflow-x:auto;overflow-y:auto;background-color:rgb(246, 248, 250);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal;"><span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">class</span> <span class="colour" style="color:rgb(121, 93, 163)">Person</span> {
<span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">var</span> name<span class="colour" style="color:rgb(167, 29, 93)">:</span> <span class="colour" style="color:rgb(0, 134, 179)">String</span>
<span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">var</span> phoneNumber<span class="colour" style="color:rgb(167, 29, 93)">:</span> <span class="colour" style="color:rgb(0, 134, 179)">String</span><span class="colour" style="color:rgb(167, 29, 93)">?</span>
<span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">init</span>(<span class="colour" style="color:rgb(51, 51, 51)"><span class="colour" style="color:rgb(121, 93, 163)">name</span></span>: <span class="colour" style="color:rgb(0, 134, 179)">String</span>, <span class="colour" style="color:rgb(51, 51, 51)"><span class="colour" style="color:rgb(121, 93, 163)">phoneNumber</span></span>: <span class="colour" style="color:rgb(0, 134, 179)">String</span><span class="colour" style="color:rgb(167, 29, 93)">?</span> <span class="colour" style="color:rgb(167, 29, 93)">=</span> <span class="colour" style="color:rgb(0, 134, 179)">nil</span>) {
<span class="colour" style="color:rgb(0, 134, 179)">self</span>.<span class="colour" style="color:rgb(51, 51, 51)">name</span> <span class="colour" style="color:rgb(167, 29, 93)">=</span> name
<span class="colour" style="color:rgb(0, 134, 179)">self</span>.<span class="colour" style="color:rgb(51, 51, 51)">phoneNumber</span> <span class="colour" style="color:rgb(167, 29, 93)">=</span> phoneNumber
}
<span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">convenience</span> <span class="colour" style="color:rgb(167, 29, 93)">init?</span>(<span class="colour" style="color:rgb(121, 93, 163)">from</span> <span class="colour" style="color:rgb(51, 51, 51)">reader</span>: Reader) {
<span class="colour" style="color:rgb(167, 29, 93)">guard</span> <span class="colour" style="color:rgb(167, 29, 93)">let</span> name <span class="colour" style="color:rgb(167, 29, 93)">=</span> reader.<span class="colour" style="color:rgb(0, 134, 179)">readString</span>(<span class="colour" style="color:rgb(0, 134, 179)">withKey</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>name<span style="">"</span></span>) <span class="colour" style="color:rgb(167, 29, 93)">else</span> {
<span class="colour" style="color:rgb(167, 29, 93)">return</span> <span class="colour" style="color:rgb(0, 134, 179)">nil</span>
}
<span class="colour" style="color:rgb(167, 29, 93)">let</span> phoneNumber <span class="colour" style="color:rgb(167, 29, 93)">=</span> reader.<span class="colour" style="color:rgb(0, 134, 179)">readString</span>(<span class="colour" style="color:rgb(0, 134, 179)">withKey</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>phoneNumber<span style="">"</span></span>)
<span class="colour" style="color:rgb(0, 134, 179)">self</span>.<span class="colour" style="color:rgb(167, 29, 93)">init</span>(<span class="colour" style="color:rgb(0, 134, 179)">name</span>: name, <span class="colour" style="color:rgb(0, 134, 179)">phoneNumber</span>: phoneNumber)
}
<span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">func</span> <span class="colour" style="color:rgb(121, 93, 163)">write</span>(<span class="colour" style="color:rgb(121, 93, 163)">to</span> <span class="colour" style="color:rgb(51, 51, 51)">writer</span>: Writer) {
writer.<span class="colour" style="color:rgb(0, 134, 179)">write</span>(name, <span class="colour" style="color:rgb(0, 134, 179)">key</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>name<span style="">"</span></span>)
<span class="colour" style="color:rgb(167, 29, 93)">if</span> <span class="colour" style="color:rgb(167, 29, 93)">let</span> phoneNumber <span class="colour" style="color:rgb(167, 29, 93)">=</span> phoneNumber {
writer.<span class="colour" style="color:rgb(0, 134, 179)">write</span>(phoneNumber, <span class="colour" style="color:rgb(0, 134, 179)">key</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>phoneNumber<span style="">"</span></span>)
}
}
}<br></pre></div>
<p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">Later, we decide that we need to support storing multiple phone numbers for a<span> </span><code style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;padding-top:0.2em;padding-right:0px;padding-bottom:0.2em;padding-left:0px;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;background-color:rgba(27, 31, 35, 0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;">Person</code>. To avoid breaking source compatibility, we deprecate the old property and add a new one. We still wish the encoding/decoding process to preserve the integrity of the old data, however—for example, a middleman process used for logging should not modify the data stream, so the encoding/decoding process should not be also migrating the data. Thus, we update the class to the following:</span></span></span><br></p><div style="margin-bottom:16px;color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';font-size:16px;"><pre style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;word-wrap:normal;padding-top:16px;padding-right:16px;padding-bottom:16px;padding-left:16px;overflow-x:auto;overflow-y:auto;background-color:rgb(246, 248, 250);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal;"><span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">class</span> <span class="colour" style="color:rgb(121, 93, 163)">Person</span> {
<span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">var</span> name<span class="colour" style="color:rgb(167, 29, 93)">:</span> <span class="colour" style="color:rgb(0, 134, 179)">String</span>
<span class="colour" style="color:rgb(167, 29, 93)">@available</span>(<span class="colour" style="color:rgb(167, 29, 93)">*</span>, <span class="colour" style="color:rgb(167, 29, 93)">deprecated</span>, <span class="colour" style="color:rgb(167, 29, 93)">message</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>use 'phoneNumbers' instead<span style="">"</span></span>)
<span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">var</span> phoneNumber<span class="colour" style="color:rgb(167, 29, 93)">:</span> <span class="colour" style="color:rgb(0, 134, 179)">String</span><span class="colour" style="color:rgb(167, 29, 93)">?</span>
<span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">var</span> phoneNumbers<span class="colour" style="color:rgb(167, 29, 93)">:</span> [<span class="colour" style="color:rgb(0, 134, 179)">String</span>]
<span class="colour" style="color:rgb(167, 29, 93)">@available</span>(<span class="colour" style="color:rgb(167, 29, 93)">*</span>, <span class="colour" style="color:rgb(167, 29, 93)">deprecated</span>, <span class="colour" style="color:rgb(167, 29, 93)">message</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>use 'init(name:phoneNumbers:)' instead<span style="">"</span></span>)
<span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">convenience</span> <span class="colour" style="color:rgb(167, 29, 93)">init</span>(<span class="colour" style="color:rgb(51, 51, 51)"><span class="colour" style="color:rgb(121, 93, 163)">name</span></span>: <span class="colour" style="color:rgb(0, 134, 179)">String</span>, <span class="colour" style="color:rgb(51, 51, 51)"><span class="colour" style="color:rgb(121, 93, 163)">phoneNumber</span></span>: <span class="colour" style="color:rgb(0, 134, 179)">String</span><span class="colour" style="color:rgb(167, 29, 93)">?</span>) {
<span class="colour" style="color:rgb(0, 134, 179)">self</span>.<span class="colour" style="color:rgb(51, 51, 51)">phoneNumber</span> <span class="colour" style="color:rgb(167, 29, 93)">=</span> phoneNumber
<span class="colour" style="color:rgb(0, 134, 179)">self</span>.<span class="colour" style="color:rgb(167, 29, 93)">init</span>(<span class="colour" style="color:rgb(0, 134, 179)">name</span>: name, <span class="colour" style="color:rgb(0, 134, 179)">phoneNumbers</span>: [])
}
<span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">init</span>(<span class="colour" style="color:rgb(51, 51, 51)"><span class="colour" style="color:rgb(121, 93, 163)">name</span></span>: <span class="colour" style="color:rgb(0, 134, 179)">String</span>, <span class="colour" style="color:rgb(51, 51, 51)"><span class="colour" style="color:rgb(121, 93, 163)">phoneNumbers</span></span>: [<span class="colour" style="color:rgb(0, 134, 179)">String</span>] <span class="colour" style="color:rgb(167, 29, 93)">=</span> []) {
<span class="colour" style="color:rgb(0, 134, 179)">self</span>.<span class="colour" style="color:rgb(51, 51, 51)">name</span> <span class="colour" style="color:rgb(167, 29, 93)">=</span> name
<span class="colour" style="color:rgb(0, 134, 179)">self</span>.<span class="colour" style="color:rgb(51, 51, 51)">phoneNumber</span> <span class="colour" style="color:rgb(167, 29, 93)">=</span> <span class="colour" style="color:rgb(0, 134, 179)">nil</span>
<span class="colour" style="color:rgb(0, 134, 179)">self</span>.<span class="colour" style="color:rgb(51, 51, 51)">phoneNumbers</span> <span class="colour" style="color:rgb(167, 29, 93)">=</span> phoneNumbers
}
<span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">convenience</span> <span class="colour" style="color:rgb(167, 29, 93)">init?</span>(<span class="colour" style="color:rgb(121, 93, 163)">from</span> <span class="colour" style="color:rgb(51, 51, 51)">reader</span>: Reader) {
<span class="colour" style="color:rgb(167, 29, 93)">guard</span> <span class="colour" style="color:rgb(167, 29, 93)">let</span> name <span class="colour" style="color:rgb(167, 29, 93)">=</span> reader.<span class="colour" style="color:rgb(0, 134, 179)">readString</span>(<span class="colour" style="color:rgb(0, 134, 179)">withKey</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>name<span style="">"</span></span>) <span class="colour" style="color:rgb(167, 29, 93)">else</span> {
<span class="colour" style="color:rgb(167, 29, 93)">return</span> <span class="colour" style="color:rgb(0, 134, 179)">nil</span>
}
<span class="colour" style="color:rgb(167, 29, 93)">let</span> phoneNumbers <span class="colour" style="color:rgb(167, 29, 93)">=</span> reader.<span class="colour" style="color:rgb(0, 134, 179)">readStringArray</span>(<span class="colour" style="color:rgb(0, 134, 179)">withKey</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>phoneNumbers<span style="">"</span></span>) <span class="colour" style="color:rgb(167, 29, 93)">??</span> []
<span class="colour" style="color:rgb(0, 134, 179)">self</span>.<span class="colour" style="color:rgb(51, 51, 51)">phoneNumber</span> <span class="colour" style="color:rgb(167, 29, 93)">=</span> reader.<span class="colour" style="color:rgb(0, 134, 179)">readString</span>(<span class="colour" style="color:rgb(0, 134, 179)">withKey</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>phoneNumber<span style="">"</span></span>)
<span class="colour" style="color:rgb(0, 134, 179)">self</span>.<span class="colour" style="color:rgb(167, 29, 93)">init</span>(<span class="colour" style="color:rgb(0, 134, 179)">name</span>: name, <span class="colour" style="color:rgb(0, 134, 179)">phoneNumbers</span>: phoneNumbers)
}
<span class="colour" style="color:rgb(167, 29, 93)">public</span> <span class="colour" style="color:rgb(167, 29, 93)">func</span> <span class="colour" style="color:rgb(121, 93, 163)">write</span>(<span class="colour" style="color:rgb(121, 93, 163)">to</span> <span class="colour" style="color:rgb(51, 51, 51)">writer</span>: Writer) {
writer.<span class="colour" style="color:rgb(0, 134, 179)">write</span>(name, <span class="colour" style="color:rgb(0, 134, 179)">key</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>name<span style="">"</span></span>)
<span class="colour" style="color:rgb(167, 29, 93)">if</span> <span class="colour" style="color:rgb(167, 29, 93)">let</span> phoneNumber <span class="colour" style="color:rgb(167, 29, 93)">=</span> phoneNumber {
writer.<span class="colour" style="color:rgb(0, 134, 179)">write</span>(phoneNumber, <span class="colour" style="color:rgb(0, 134, 179)">key</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>phoneNumber<span style="">"</span></span>)
}
<span class="colour" style="color:rgb(167, 29, 93)">if</span> <span class="colour" style="color:rgb(167, 29, 93)">!</span>phoneNumbers.<span class="colour" style="color:rgb(0, 134, 179)">isEmpty</span> {
writer.<span class="colour" style="color:rgb(0, 134, 179)">write</span>(phoneNumbers, <span class="colour" style="color:rgb(0, 134, 179)">key</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>phoneNumbers<span style="">"</span></span>)
}
}
}<br></pre></div>
<p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">This type is backwards-compatible with the previous version and will warn external users that they should migrate to the new version of the API; it will also have its values preserved exactly if a middleman process parses and then reserializes it.</span></span></span><br></p><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">The problem, however, is that the references to<span> </span><code style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;padding-top:0.2em;padding-right:0px;padding-bottom:0.2em;padding-left:0px;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;background-color:rgba(27, 31, 35, 0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;">phoneNumber</code><span> </span>in<span> </span><code style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;padding-top:0.2em;padding-right:0px;padding-bottom:0.2em;padding-left:0px;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;background-color:rgba(27, 31, 35, 0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;">Person</code>'s<span> </span><i>own methods</i><span> </span>also emit deprecation warnings. This is undesirable because the warnings cannot be easily avoided (see workarounds below). The crux of the issue is that one of the two statements is likely to be true:</span></span></span><br></p><ol style="padding-left:2em;margin-top:0px;margin-bottom:16px;color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';font-size:16px;"><li style=""><p style="margin-top:16px;margin-bottom:16px;">At the time the user deprecates something, they also have the opportunity to migrate all references to it within the same file, thus eliminating the warnings there and making the file build cleanly.<br></p></li><li style="margin-top:0.25em;"><p style="margin-top:16px;margin-bottom:16px;">At the time the user deprecates something, they must continue to reference it internally to achieve correct and performant behavior, thus making it currently impossible to achieve a clean build for the file containing that declaration.<br></p></li></ol><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">This proposal aims to solve the second issue.</span></span></span><br></p><h3 style="margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25;color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';"><a href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#workarounds-and-their-problems" style="background-color:transparent;color:rgb(3, 102, 214);float:left;padding-right:4px;line-height:1;"></a>Workarounds and their problems<br></h3><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">One workaround would be to shadow deprecated declarations by making the declaration itself private (and prepending something like an underscore to the name) and then using a public passthrough property or method. The private declaration would not be deprecated while the public one would be.</span></span></span><br></p><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">There are two main problems with this approach. First, it increases the development and maintanence cost of the deprecation because the new declaration has to be added and all internal references to the declaration must be updated.</span></span></span><br></p><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">Secondly, and more importantly, this shadowing can have significant performance penalties. Consider this example:</span></span></span><br></p><div style="margin-bottom:16px;color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';font-size:16px;"><pre style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;margin-top:0px;margin-bottom:0px;font-stretch:normal;line-height:1.45;word-wrap:normal;padding-top:16px;padding-right:16px;padding-bottom:16px;padding-left:16px;overflow-x:auto;overflow-y:auto;background-color:rgb(246, 248, 250);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;word-break:normal;"><span class="colour" style="color:rgb(167, 29, 93)">class</span> <span class="colour" style="color:rgb(121, 93, 163)">DirectArrayHolder</span> {
<span class="colour" style="color:rgb(167, 29, 93)">@available</span>(<span class="colour" style="color:rgb(167, 29, 93)">*</span>, <span class="colour" style="color:rgb(167, 29, 93)">deprecated</span>, <span class="colour" style="color:rgb(167, 29, 93)">message</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>Use something else instead<span style="">"</span></span>)
<span class="colour" style="color:rgb(167, 29, 93)">var</span> array<span class="colour" style="color:rgb(167, 29, 93)">:</span> [<span class="colour" style="color:rgb(0, 134, 179)">String</span>] <span class="colour" style="color:rgb(167, 29, 93)">=</span> []
}
<span class="colour" style="color:rgb(167, 29, 93)">class</span> <span class="colour" style="color:rgb(121, 93, 163)">IndirectArrayHolder</span> {
<span class="colour" style="color:rgb(167, 29, 93)">var</span> _array<span class="colour" style="color:rgb(167, 29, 93)">:</span> [<span class="colour" style="color:rgb(0, 134, 179)">String</span>] <span class="colour" style="color:rgb(167, 29, 93)">=</span> []
<span class="colour" style="color:rgb(167, 29, 93)">@available</span>(<span class="colour" style="color:rgb(167, 29, 93)">*</span>, <span class="colour" style="color:rgb(167, 29, 93)">deprecated</span>, <span class="colour" style="color:rgb(167, 29, 93)">message</span>: <span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>Use something else instead<span style="">"</span></span>)
<span class="colour" style="color:rgb(167, 29, 93)">var</span> array<span class="colour" style="color:rgb(167, 29, 93)">:</span> [<span class="colour" style="color:rgb(0, 134, 179)">String</span>] {
<span class="colour" style="color:rgb(167, 29, 93)">get</span> { <span class="colour" style="color:rgb(167, 29, 93)">return</span> _array }
<span class="colour" style="color:rgb(167, 29, 93)">set</span> { _array <span class="colour" style="color:rgb(167, 29, 93)">=</span> newValue }
}
}
<span class="colour" style="color:rgb(167, 29, 93)">func</span> <span class="colour" style="color:rgb(121, 93, 163)">useDirectHolder</span>() <span class="colour" style="color:rgb(167, 29, 93)">-></span> DirectArrayHolder {
<span class="colour" style="color:rgb(167, 29, 93)">let</span> holder <span class="colour" style="color:rgb(167, 29, 93)">=</span> <span class="colour" style="color:rgb(0, 134, 179)">DirectArrayHolder</span>()
<span class="colour" style="color:rgb(167, 29, 93)">for</span> <span class="colour" style="color:rgb(0, 134, 179)">_</span> <span class="colour" style="color:rgb(167, 29, 93)">in</span> <span class="colour" style="color:rgb(0, 134, 179)">0</span><span class="colour" style="color:rgb(167, 29, 93)">...</span><span class="colour" style="color:rgb(0, 134, 179)">10_000</span> {
holder.<span class="colour" style="color:rgb(0, 134, 179)">array</span>.<span class="colour" style="color:rgb(0, 134, 179)">append</span>(<span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>foo<span style="">"</span></span>)
}
<span class="colour" style="color:rgb(167, 29, 93)">return</span> holder
}
<span class="colour" style="color:rgb(167, 29, 93)">func</span> <span class="colour" style="color:rgb(121, 93, 163)">useIndirectHolder</span>() <span class="colour" style="color:rgb(167, 29, 93)">-></span> IndirectArrayHolder {
<span class="colour" style="color:rgb(167, 29, 93)">let</span> holder <span class="colour" style="color:rgb(167, 29, 93)">=</span> <span class="colour" style="color:rgb(0, 134, 179)">IndirectArrayHolder</span>()
<span class="colour" style="color:rgb(167, 29, 93)">for</span> <span class="colour" style="color:rgb(0, 134, 179)">_</span> <span class="colour" style="color:rgb(167, 29, 93)">in</span> <span class="colour" style="color:rgb(0, 134, 179)">0</span><span class="colour" style="color:rgb(167, 29, 93)">...</span><span class="colour" style="color:rgb(0, 134, 179)">10_000</span> {
holder.<span class="colour" style="color:rgb(0, 134, 179)">array</span>.<span class="colour" style="color:rgb(0, 134, 179)">append</span>(<span class="colour" style="color:rgb(24, 54, 145)"><span style="">"</span>foo<span style="">"</span></span>)
}
<span class="colour" style="color:rgb(167, 29, 93)">return</span> holder
}<br></pre></div>
<p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">Behaviorally, these are the same. However, the generated code is different because the memory management semantics change due to the passthrough property. With full optimizations on,<span> </span><code style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;padding-top:0.2em;padding-right:0px;padding-bottom:0.2em;padding-left:0px;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;background-color:rgba(27, 31, 35, 0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;">useDirectHolder</code><span> </span>executes in 1.360 sec while<span> </span><code style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;padding-top:0.2em;padding-right:0px;padding-bottom:0.2em;padding-left:0px;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;background-color:rgba(27, 31, 35, 0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;">useIndirectHolder</code><span> </span>executes in 235.8 sec—over two orders of magnitude slower!</span></span></span><br></p><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">It could be argued that this performance issue is something that could be solved separately, but this should be considered just one motivating example and not the sole motivation for this proposed change.</span></span></span><br></p><h2 style="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(234, 236, 239);color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';"><a href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#proposed-solution" style="background-color:transparent;color:rgb(3, 102, 214);float:left;padding-right:4px;line-height:1;"></a>Proposed solution<br></h2><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">Do not print deprecation warnings for references to deprecated declarations that are in the same file.</span></span></span><br></p><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">There would be no change for declarations marked<span> </span><code style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;padding-top:0.2em;padding-right:0px;padding-bottom:0.2em;padding-left:0px;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;background-color:rgba(27, 31, 35, 0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;">unavailable</code>. A declaration marked<span> </span><code style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;padding-top:0.2em;padding-right:0px;padding-bottom:0.2em;padding-left:0px;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;background-color:rgba(27, 31, 35, 0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;">unavailable</code><span> </span>is making a stronger statement about its existence such that referencing it is an error; unlike marking a declaration deprecated, marking it unavailable is a breaking change for downstream clients, so the behavior of that attribute value should be unchanged whether references are in the same file or elsewhere.</span></span></span><br></p><h3 style="margin-top:24px;margin-bottom:16px;font-size:1.25em;line-height:1.25;color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';"><a href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#implementation-details" style="background-color:transparent;color:rgb(3, 102, 214);float:left;padding-right:4px;line-height:1;"></a>Implementation details<br></h3><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">A small addition would be made to<span> </span><code style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;padding-top:0.2em;padding-right:0px;padding-bottom:0.2em;padding-left:0px;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;background-color:rgba(27, 31, 35, 0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;">TypeChecker::diagnoseIfDeprecated</code><span> </span>so that it returns early if the declaration is in the same source file as the reference.</span></span></span><br></p><h2 style="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(234, 236, 239);color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';"><a href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#impact-on-existing-code" style="background-color:transparent;color:rgb(3, 102, 214);float:left;padding-right:4px;line-height:1;"></a>Impact on existing code<br></h2><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">This is not a source-breaking change. The only side effect for existing code is that deprecation warnings that were emitted for same-file references in the past will no longer be emitted.</span></span></span><br></p><h2 style="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(234, 236, 239);color:rgb(36, 41, 46);font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol';"><a href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#alternatives-considered" style="background-color:transparent;color:rgb(3, 102, 214);float:left;padding-right:4px;line-height:1;"></a>Alternatives considered<br></h2><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">Omitting deprecation warnings for references in the same<span> </span><i>module</i>, not only the same<span> </span><i>file</i>, was also considered. An argument could be made that deprecation warnings are intended as messaging for<span> </span><span style="font-weight:600;">external</span><span> </span>users of an API, so drawing the line at the module level would be more appropriate than at the file level. However, modules can be large and span a broad set of APIs contributed by many developers on multi-person teams, and they may want to use the<span> </span><code style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;padding-top:0.2em;padding-right:0px;padding-bottom:0.2em;padding-left:0px;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;background-color:rgba(27, 31, 35, 0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;">@available</code><span> </span>attribute to phase out particular APIs for<span> </span><span style="font-weight:600;">internal</span><span> </span>use as well. Omitting deprecation warnings for anything in the same module takes that useful tool away for those users.</span></span></span><br></p><p style="margin-top: 0px; margin-bottom: 16px;"><span class="colour" style="color:rgb(36, 41, 46)"><span class="font" style="font-family:-apple-system, system-ui, 'segoe ui', helvetica, arial, sans-serif, 'apple color emoji', 'segoe ui emoji', 'segoe ui symbol'"><span class="size" style="font-size:16px">Another idea that was brought up in a<span> </span><a href="https://bugs.swift.org/browse/SR-3357" style="background-color:transparent;color:rgb(3, 102, 214);">feature request</a><span> </span>filed for this was to allow a "deprecated block" that would suppress all deprecation warnings inside it. This would also solve the problem motivating this proposal and is similar to the approach taken by other languages (such as Java's<span> </span><code style="font-family:sfmono-regular, consolas, 'liberation mono', menlo, courier, monospace;font-size:13.6px;padding-top:0.2em;padding-right:0px;padding-bottom:0.2em;padding-left:0px;margin-top:0px;margin-right:0px;margin-bottom:0px;margin-left:0px;background-color:rgba(27, 31, 35, 0.0470588);border-top-left-radius:3px;border-top-right-radius:3px;border-bottom-right-radius:3px;border-bottom-left-radius:3px;">@SuppressWarnings("deprecation")</code><span> </span>annotation), but this approach has drawbacks as well. It would not distinguish between deprecation warnings in the same file or module vs. those in other files or modules (unless modifiers were added to it, which runs the risk of adding too much complexity for too little gain). Furthermore, it has the potential to be harmful if abused—developers could surround large code blocks with the deprecation suppressor and then lose any deprecation warnings that would have been emitted for APIs used inside that block.</span></span></span><br></p></div>
</div>
<div><u>_______________________________________________</u><br></div>
<div>swift-evolution mailing list<br></div>
<div><a href="mailto:swift-evolution@swift.org">swift-evolution@swift.org</a><br></div>
<div><a href="https://lists.swift.org/mailman/listinfo/swift-evolution">https://lists.swift.org/mailman/listinfo/swift-evolution</a><br></div>
</blockquote><div style="font-family:Arial;"><br></div>
</body>
</html>