<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="">I’ve run into this problem as well, when dealing with legacy file formats (similar to the example in the proposal), and I agree it would be nice to be able to address it. We’ve got a few “permanent” warnings in our code base right now due to this. I’m not sure whether the deprecation should be disabled for the entire file, though; perhaps it should be disabled just within the type itself? I don’t know how that would contribute to the complexity of the implementation, but it seems like we would still want to warn about deprecated accesses between two types declared in the same file.<div class=""><br class=""></div><div class=""><div class="">-BJ Homer</div><div class=""><br class=""><div class=""><div><blockquote type="cite" class=""><div class="">On May 5, 2017, at 12:12 PM, Tony Allevato 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=""><div dir="ltr" class=""><div class="">Hey Swift Evolvers,</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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.</div><div class=""><br class=""></div><div class="">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" class="">branch</a> and it's fairly straightforward.</div><div class=""><br class=""></div>Gist link: <a href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb" class="">https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb</a><div class=""><br class=""></div><div class=""><br class=""></div><div class=""><h1 style="box-sizing:border-box;margin:0px 0px 16px;line-height:1.25;padding-bottom:0.3em;border-bottom:1px solid 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"" class="">Omit deprecation warnings for same-file references</h1><ul style="box-sizing:border-box;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" class=""><li style="box-sizing:border-box" class="">Proposal:<span class="inbox-inbox-Apple-converted-space"> </span><a href="https://github.com/apple/swift-evolution/blob/master/proposals/NNNN-name.md" style="box-sizing:border-box;background-color:transparent;color:rgb(3,102,214);text-decoration-line:none" class="">SE-0000</a></li><li style="box-sizing:border-box;margin-top:0.25em" class="">Author(s):<span class="inbox-inbox-Apple-converted-space"> </span><a href="https://github.com/allevato" style="box-sizing:border-box;background-color:transparent;color:rgb(3,102,214);text-decoration-line:none" class="">Tony Allevato</a></li><li style="box-sizing:border-box;margin-top:0.25em" class="">Status:<span class="inbox-inbox-Apple-converted-space"> </span><span style="box-sizing:border-box;font-weight:600" class=""><a href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#rationale" style="box-sizing:border-box;background-color:transparent;color:rgb(3,102,214);text-decoration-line:none" class="">Awaiting review</a></span></li><li style="box-sizing:border-box;margin-top:0.25em" class="">Review manager: TBD</li></ul><h2 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom:1px solid 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"" class=""><a id="inbox-inbox-user-content-introduction" class="inbox-inbox-anchor" href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#introduction" style="box-sizing:border-box;background-color:transparent;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Introduction</h2><p style="box-sizing:border-box;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" class="">Public API developers can use the<span class="inbox-inbox-Apple-converted-space"> </span><code style="box-sizing:border-box;font-family:sfmono-regular,consolas,"liberation mono",menlo,courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.05);border-radius:3px" class="">@available</code><span class="inbox-inbox-Apple-converted-space"> </span>attribute in Swift to mark APIs as<span class="inbox-inbox-Apple-converted-space"> </span><span style="box-sizing:border-box;font-weight:600" class="">deprecated,</span><span class="inbox-inbox-Apple-converted-space"> </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.</p><p style="box-sizing:border-box;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" class="">These warnings are emitted for<span class="inbox-inbox-Apple-converted-space"> </span><em style="box-sizing:border-box" class="">any</em><span class="inbox-inbox-Apple-converted-space"> </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.</p><p style="box-sizing:border-box;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" class="">Swift-evolution thread:<span class="inbox-inbox-Apple-converted-space"> </span><a href="http://thread.gmane.org/gmane.comp.lang.swift.evolution/" style="box-sizing:border-box;background-color:transparent;color:rgb(3,102,214);text-decoration-line:none" class="">TBD</a></p><h2 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom:1px solid 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"" class=""><a id="inbox-inbox-user-content-motivation" class="inbox-inbox-anchor" href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#motivation" style="box-sizing:border-box;background-color:transparent;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Motivation</h2><p style="box-sizing:border-box;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" class="">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):</p><div class="inbox-inbox-highlight inbox-inbox-highlight-source-swift" style="box-sizing:border-box;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="box-sizing:border-box;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:16px;overflow:auto;background-color:rgb(246,248,250);border-radius:3px;word-break:normal" class=""><span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">class</span> <span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">Person</span> {
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">var</span> name<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">:</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span>
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">var</span> phoneNumber<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">:</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span><span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">?</span>
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">init</span>(<span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)"><span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">name</span></span>: <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span>, <span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)"><span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">phoneNumber</span></span>: <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span><span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">?</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">nil</span>) {
<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">self</span>.<span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)">name</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> name
<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">self</span>.<span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)">phoneNumber</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> phoneNumber
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">convenience</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">init?</span>(<span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">from</span> <span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)">reader</span>: Reader) {
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">guard</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">let</span> name <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> reader.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">readString</span>(<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">withKey</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>name<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>) <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">else</span> {
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">return</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">nil</span>
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">let</span> phoneNumber <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> reader.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">readString</span>(<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">withKey</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>phoneNumber<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">self</span>.<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">init</span>(<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">name</span>: name, <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">phoneNumber</span>: phoneNumber)
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">func</span> <span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">write</span>(<span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">to</span> <span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)">writer</span>: Writer) {
writer.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">write</span>(name, <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">key</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>name<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">if</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">let</span> phoneNumber <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> phoneNumber {
writer.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">write</span>(phoneNumber, <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">key</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>phoneNumber<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
}
}
}</pre></div><p style="box-sizing:border-box;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" class="">Later, we decide that we need to support storing multiple phone numbers for a<span class="inbox-inbox-Apple-converted-space"> </span><code style="box-sizing:border-box;font-family:sfmono-regular,consolas,"liberation mono",menlo,courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.05);border-radius:3px" class="">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:</p><div class="inbox-inbox-highlight inbox-inbox-highlight-source-swift" style="box-sizing:border-box;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="box-sizing:border-box;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:16px;overflow:auto;background-color:rgb(246,248,250);border-radius:3px;word-break:normal" class=""><span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">class</span> <span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">Person</span> {
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">var</span> name<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">:</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span>
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">@available</span>(<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">*</span>, <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">deprecated</span>, <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">message</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>use 'phoneNumbers' instead<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">var</span> phoneNumber<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">:</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span><span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">?</span>
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">var</span> phoneNumbers<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">:</span> [<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span>]
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">@available</span>(<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">*</span>, <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">deprecated</span>, <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">message</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>use 'init(name:phoneNumbers:)' instead<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">convenience</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">init</span>(<span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)"><span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">name</span></span>: <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span>, <span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)"><span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">phoneNumber</span></span>: <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span><span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">?</span>) {
<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">self</span>.<span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)">phoneNumber</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> phoneNumber
<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">self</span>.<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">init</span>(<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">name</span>: name, <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">phoneNumbers</span>: [])
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">init</span>(<span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)"><span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">name</span></span>: <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span>, <span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)"><span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">phoneNumbers</span></span>: [<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span>] <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> []) {
<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">self</span>.<span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)">name</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> name
<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">self</span>.<span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)">phoneNumber</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">nil</span>
<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">self</span>.<span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)">phoneNumbers</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> phoneNumbers
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">convenience</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">init?</span>(<span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">from</span> <span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)">reader</span>: Reader) {
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">guard</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">let</span> name <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> reader.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">readString</span>(<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">withKey</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>name<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>) <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">else</span> {
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">return</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">nil</span>
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">let</span> phoneNumbers <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> reader.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">readStringArray</span>(<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">withKey</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>phoneNumbers<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>) <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">??</span> []
<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">self</span>.<span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)">phoneNumber</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> reader.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">readString</span>(<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">withKey</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>phoneNumber<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">self</span>.<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">init</span>(<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">name</span>: name, <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">phoneNumbers</span>: phoneNumbers)
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">public</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">func</span> <span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">write</span>(<span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">to</span> <span class="inbox-inbox-pl-smi" style="box-sizing:border-box;color:rgb(51,51,51)">writer</span>: Writer) {
writer.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">write</span>(name, <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">key</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>name<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">if</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">let</span> phoneNumber <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> phoneNumber {
writer.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">write</span>(phoneNumber, <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">key</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>phoneNumber<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">if</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">!</span>phoneNumbers.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">isEmpty</span> {
writer.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">write</span>(phoneNumbers, <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">key</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>phoneNumbers<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
}
}
}</pre></div><p style="box-sizing:border-box;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" class="">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.</p><p style="box-sizing:border-box;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" class="">The problem, however, is that the references to<span class="inbox-inbox-Apple-converted-space"> </span><code style="box-sizing:border-box;font-family:sfmono-regular,consolas,"liberation mono",menlo,courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.05);border-radius:3px" class="">phoneNumber</code><span class="inbox-inbox-Apple-converted-space"> </span>in<span class="inbox-inbox-Apple-converted-space"> </span><code style="box-sizing:border-box;font-family:sfmono-regular,consolas,"liberation mono",menlo,courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.05);border-radius:3px" class="">Person</code>'s<span class="inbox-inbox-Apple-converted-space"> </span><em style="box-sizing:border-box" class="">own methods</em><span class="inbox-inbox-Apple-converted-space"> </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:</p><ol style="box-sizing:border-box;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" class=""><li style="box-sizing:border-box" class=""><p style="box-sizing:border-box;margin-top:16px;margin-bottom:16px" class="">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.</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="">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.</p></li></ol><p style="box-sizing:border-box;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" class="">This proposal aims to solve the second issue.</p><h3 style="box-sizing:border-box;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"" class=""><a id="inbox-inbox-user-content-workarounds-and-their-problems" class="inbox-inbox-anchor" href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#workarounds-and-their-problems" style="box-sizing:border-box;background-color:transparent;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Workarounds and their problems</h3><p style="box-sizing:border-box;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" class="">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.</p><p style="box-sizing:border-box;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" class="">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.</p><p style="box-sizing:border-box;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" class="">Secondly, and more importantly, this shadowing can have significant performance penalties. Consider this example:</p><div class="inbox-inbox-highlight inbox-inbox-highlight-source-swift" style="box-sizing:border-box;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="box-sizing:border-box;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:16px;overflow:auto;background-color:rgb(246,248,250);border-radius:3px;word-break:normal" class=""><span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">class</span> <span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">DirectArrayHolder</span> {
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">@available</span>(<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">*</span>, <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">deprecated</span>, <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">message</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>Use something else instead<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">var</span> array<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">:</span> [<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span>] <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> []
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">class</span> <span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">IndirectArrayHolder</span> {
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">var</span> _array<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">:</span> [<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span>] <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> []
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">@available</span>(<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">*</span>, <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">deprecated</span>, <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">message</span>: <span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>Use something else instead<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">var</span> array<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">:</span> [<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">String</span>] {
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">get</span> { <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">return</span> _array }
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">set</span> { _array <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> newValue }
}
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">func</span> <span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">useDirectHolder</span>() <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">-></span> DirectArrayHolder {
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">let</span> holder <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">DirectArrayHolder</span>()
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">for</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">_</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">in</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">0</span><span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">...</span><span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">10_000</span> {
holder.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">array</span>.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">append</span>(<span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>foo<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">return</span> holder
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">func</span> <span class="inbox-inbox-pl-en" style="box-sizing:border-box;color:rgb(121,93,163)">useIndirectHolder</span>() <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">-></span> IndirectArrayHolder {
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">let</span> holder <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">=</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">IndirectArrayHolder</span>()
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">for</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">_</span> <span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">in</span> <span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">0</span><span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">...</span><span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">10_000</span> {
holder.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">array</span>.<span class="inbox-inbox-pl-c1" style="box-sizing:border-box;color:rgb(0,134,179)">append</span>(<span class="inbox-inbox-pl-s" style="box-sizing:border-box;color:rgb(24,54,145)"><span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span>foo<span class="inbox-inbox-pl-pds" style="box-sizing:border-box">"</span></span>)
}
<span class="inbox-inbox-pl-k" style="box-sizing:border-box;color:rgb(167,29,93)">return</span> holder
}</pre></div><p style="box-sizing:border-box;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" class="">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 class="inbox-inbox-Apple-converted-space"> </span><code style="box-sizing:border-box;font-family:sfmono-regular,consolas,"liberation mono",menlo,courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.05);border-radius:3px" class="">useDirectHolder</code><span class="inbox-inbox-Apple-converted-space"> </span>executes in 1.360 sec while<span class="inbox-inbox-Apple-converted-space"> </span><code style="box-sizing:border-box;font-family:sfmono-regular,consolas,"liberation mono",menlo,courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.05);border-radius:3px" class="">useIndirectHolder</code><span class="inbox-inbox-Apple-converted-space"> </span>executes in 235.8 sec—over two orders of magnitude slower!</p><p style="box-sizing:border-box;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" class="">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.</p><h2 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom:1px solid 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"" class=""><a id="inbox-inbox-user-content-proposed-solution" class="inbox-inbox-anchor" href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#proposed-solution" style="box-sizing:border-box;background-color:transparent;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Proposed solution</h2><p style="box-sizing:border-box;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" class="">Do not print deprecation warnings for references to deprecated declarations that are in the same file.</p><p style="box-sizing:border-box;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" class="">There would be no change for declarations marked<span class="inbox-inbox-Apple-converted-space"> </span><code style="box-sizing:border-box;font-family:sfmono-regular,consolas,"liberation mono",menlo,courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.05);border-radius:3px" class="">unavailable</code>. A declaration marked<span class="inbox-inbox-Apple-converted-space"> </span><code style="box-sizing:border-box;font-family:sfmono-regular,consolas,"liberation mono",menlo,courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.05);border-radius:3px" class="">unavailable</code><span class="inbox-inbox-Apple-converted-space"> </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.</p><h3 style="box-sizing:border-box;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"" class=""><a id="inbox-inbox-user-content-implementation-details" class="inbox-inbox-anchor" href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#implementation-details" style="box-sizing:border-box;background-color:transparent;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Implementation details</h3><p style="box-sizing:border-box;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" class="">A small addition would be made to<span class="inbox-inbox-Apple-converted-space"> </span><code style="box-sizing:border-box;font-family:sfmono-regular,consolas,"liberation mono",menlo,courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.05);border-radius:3px" class="">TypeChecker::diagnoseIfDeprecated</code><span class="inbox-inbox-Apple-converted-space"> </span>so that it returns early if the declaration is in the same source file as the reference.</p><h2 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom:1px solid 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"" class=""><a id="inbox-inbox-user-content-impact-on-existing-code" class="inbox-inbox-anchor" href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#impact-on-existing-code" style="box-sizing:border-box;background-color:transparent;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Impact on existing code</h2><p style="box-sizing:border-box;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" class="">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.</p><h2 style="box-sizing:border-box;margin-top:24px;margin-bottom:16px;line-height:1.25;padding-bottom:0.3em;border-bottom:1px solid 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"" class=""><a id="inbox-inbox-user-content-alternatives-considered" class="inbox-inbox-anchor" href="https://gist.github.com/allevato/76f098a761147f3be5017d10a6f4ecbb#alternatives-considered" style="box-sizing:border-box;background-color:transparent;color:rgb(3,102,214);text-decoration-line:none;float:left;padding-right:4px;line-height:1"></a>Alternatives considered</h2><p style="box-sizing:border-box;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" class="">Omitting deprecation warnings for references in the same<span class="inbox-inbox-Apple-converted-space"> </span><em style="box-sizing:border-box" class="">module</em>, not only the same<span class="inbox-inbox-Apple-converted-space"> </span><em style="box-sizing:border-box" class="">file</em>, was also considered. An argument could be made that deprecation warnings are intended as messaging for<span class="inbox-inbox-Apple-converted-space"> </span><span style="box-sizing:border-box;font-weight:600" class="">external</span><span class="inbox-inbox-Apple-converted-space"> </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 class="inbox-inbox-Apple-converted-space"> </span><code style="box-sizing:border-box;font-family:sfmono-regular,consolas,"liberation mono",menlo,courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.05);border-radius:3px" class="">@available</code><span class="inbox-inbox-Apple-converted-space"> </span>attribute to phase out particular APIs for<span class="inbox-inbox-Apple-converted-space"> </span><span style="box-sizing:border-box;font-weight:600" class="">internal</span><span class="inbox-inbox-Apple-converted-space"> </span>use as well. Omitting deprecation warnings for anything in the same module takes that useful tool away for those users.</p><p style="box-sizing:border-box;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" class="">Another idea that was brought up in a<span class="inbox-inbox-Apple-converted-space"> </span><a href="https://bugs.swift.org/browse/SR-3357" style="box-sizing:border-box;background-color:transparent;color:rgb(3,102,214);text-decoration-line:none" class="">feature request</a><span class="inbox-inbox-Apple-converted-space"> </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 class="inbox-inbox-Apple-converted-space"> </span><code style="box-sizing:border-box;font-family:sfmono-regular,consolas,"liberation mono",menlo,courier,monospace;font-size:13.6px;padding:0.2em 0px;margin:0px;background-color:rgba(27,31,35,0.05);border-radius:3px" class="">@SuppressWarnings("deprecation")</code><span class="inbox-inbox-Apple-converted-space"> </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.</p></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></div></div></body></html>