<div dir="ltr"><div class="markdown-here-wrapper" style=""><p style="margin:0px 0px 1.2em!important">Consider this code:</p>
<pre style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;font-size:1em;line-height:1.2em;margin:1.2em 0px"><code class="hljs language-swift" style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline;white-space:pre;overflow:auto;border-radius:3px;border:1px solid rgb(204,204,204);padding:0.5em 0.7em;display:block!important;display:block;overflow-x:auto;padding:0.5em;color:rgb(51,51,51);background:rgb(248,248,248) none repeat scroll 0% 0%"><span class="hljs-class"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">struct</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">Pet</span> </span>{
    <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">let</span> name: <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">String</span>
    <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">weak</span> <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">var</span> owner: <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Person</span>?

    <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">init</span>(name: <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">String</span>, owner: <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Person</span>?) {
        <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">self</span>.name = name
        <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">self</span>.owner = owner
        owner?.pet = <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">self</span>
    }

    <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">mutating</span> <span class="hljs-func"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">func</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">transferOwnership</span><span class="hljs-params">(to newOwner: Person)</span> </span>{
        <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">let</span> previousOwner = owner
        owner = newOwner
        newOwner.pet = <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">self</span>
        <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">if</span>(previousOwner != <span class="hljs-built_in" style="color:rgb(0,134,179)">nil</span>) {
            previousOwner!.pet = <span class="hljs-built_in" style="color:rgb(0,134,179)">nil</span>
        }
    }

    <span class="hljs-func"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">func</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">feed</span><span class="hljs-params">()</span> </span>{
    }
}

<span class="hljs-class"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">class</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold;color:rgb(68,85,136);font-weight:bold">Person</span> </span>{
    <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">let</span> name: <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">String</span>
    <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">var</span> pet: <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Pet</span>?

    <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">init</span>(name: <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">String</span>) {
        <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">self</span>.name = name
    }

    <span class="hljs-func"><span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">func</span> <span class="hljs-title" style="color:rgb(153,0,0);font-weight:bold">givePetAway</span><span class="hljs-params">(to someone: Person)</span> </span>{
        <span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">if</span> pet != <span class="hljs-built_in" style="color:rgb(0,134,179)">nil</span> {
            pet!.transferOwnership(to: someone)
            <span class="hljs-comment" style="color:rgb(153,153,136);font-style:italic">//pet!.feed()</span>
        }
    }
}

<span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">let</span> bert = <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Person</span>(name: <span class="hljs-string" style="color:rgb(221,17,68)">&quot;Bert&quot;</span>)
<span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">let</span> ernie = <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Person</span>(name: <span class="hljs-string" style="color:rgb(221,17,68)">&quot;Ernie&quot;</span>)
<span class="hljs-keyword" style="color:rgb(51,51,51);font-weight:bold">var</span> elmo = <span class="hljs-type" style="color:rgb(68,85,136);font-weight:bold">Pet</span>(name: <span class="hljs-string" style="color:rgb(221,17,68)">&quot;Elmo&quot;</span>, owner: <span class="hljs-built_in" style="color:rgb(0,134,179)">nil</span>)

elmo.transferOwnership(to: bert)
<span class="hljs-built_in" style="color:rgb(0,134,179)">print</span>(<span class="hljs-string" style="color:rgb(221,17,68)">&quot;Bert&#39;s pet is <span class="hljs-subst" style="color:rgb(51,51,51);font-weight:bold;font-weight:normal">\(bert.pet)</span> - Ernie&#39;s pet is <span class="hljs-subst" style="color:rgb(51,51,51);font-weight:bold;font-weight:normal">\(ernie.pet)</span>&quot;</span>)

bert.givePetAway(to: ernie)
<span class="hljs-built_in" style="color:rgb(0,134,179)">print</span>(<span class="hljs-string" style="color:rgb(221,17,68)">&quot;Bert&#39;s pet is <span class="hljs-subst" style="color:rgb(51,51,51);font-weight:bold;font-weight:normal">\(bert.pet)</span> - Ernie&#39;s pet is <span class="hljs-subst" style="color:rgb(51,51,51);font-weight:bold;font-weight:normal">\(ernie.pet)</span>&quot;</span>)
</code></pre>
<p style="margin:0px 0px 1.2em!important">This works as expected, but if you uncomment <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">pet!.feed()</code> in <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">givePetAway(to:)</code> it will crash, because the mutating function modifies the two-way relationship between <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">pet</code> and <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">owner</code>.</p>
<p style="margin:0px 0px 1.2em!important">In the code I use <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">if pet != nil</code> to demonstrate, in your proposal for <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">unwrap</code>, if I used it to <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">unwrap pet</code> (a value-type, but accessed through <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">self</code> so it can be modified after unwrapping because it’s not nil at the moment) the compiler would assume I could use it and <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">pet.feed()</code> would crash, just as <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">pet!.feed()</code> does now. In your proposal for type narrowing, it would be the same problem. This is like your <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">foo.value</code> example from the proposal.</p>
<p style="margin:0px 0px 1.2em!important">I don’t think you can get around the fact that the compiler can’t guarantee a type-narrowed or even unwrapped mutable value, which is why <code style="font-size:1em;font-family:Consolas,Inconsolata,Courier,monospace;margin:0px 0.15em;padding:0px 0.3em;white-space:pre-wrap;border:1px solid rgb(234,234,234);background-color:rgb(248,248,248);border-radius:3px;display:inline">if let</code> works as it does with an immutable snapshot.</p>
<p style="margin:0px 0px 1.2em!important">However, type narrowing for immutable values would still be good.</p></div></div>