<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="#![feature(unsafe_destructor)]
struct A;

impl Drop for A {
    fn drop(&amp;mut self) {}
}

struct B&lt;'a&gt; {
    a: &amp;'a A,
}

#[unsafe_destructor]
impl&lt;'a&gt; Drop for B&lt;'a&gt; {
    fn drop(&amp;mut self) {}
}

impl A {
    fn b(&amp;self) -&gt; B {
        B { a: self }
    }
}

fn main() {
    let a = A;
    match a.b() {
        _ =&gt; {}
    }
}"><pre class="notranslate"><span class="pl-c1">#!<span class="pl-kos">[</span>feature<span class="pl-kos">(</span>unsafe_destructor<span class="pl-kos">)</span><span class="pl-kos">]</span></span>
<span class="pl-k">struct</span> <span class="pl-smi">A</span><span class="pl-kos">;</span>

<span class="pl-k">impl</span> <span class="pl-smi">Drop</span> <span class="pl-k">for</span> <span class="pl-smi">A</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">drop</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span><span class="pl-k">mut</span> <span class="pl-smi">self</span><span class="pl-kos">)</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">struct</span> <span class="pl-smi">B</span><span class="pl-kos">&lt;</span><span class="pl-c1">'</span><span class="pl-ent">a</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-c1">a</span><span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-c1">'</span><span class="pl-ent">a</span> <span class="pl-smi">A</span><span class="pl-kos">,</span>
<span class="pl-kos">}</span>

<span class="pl-c1">#<span class="pl-kos">[</span>unsafe_destructor<span class="pl-kos">]</span></span>
<span class="pl-k">impl</span><span class="pl-kos">&lt;</span><span class="pl-c1">'</span><span class="pl-ent">a</span><span class="pl-kos">&gt;</span> <span class="pl-smi">Drop</span> <span class="pl-k">for</span> <span class="pl-smi">B</span><span class="pl-kos">&lt;</span><span class="pl-c1">'</span><span class="pl-ent">a</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">drop</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span><span class="pl-k">mut</span> <span class="pl-smi">self</span><span class="pl-kos">)</span> <span class="pl-kos">{</span><span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">impl</span> <span class="pl-smi">A</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">b</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span><span class="pl-smi">self</span><span class="pl-kos">)</span> -&gt; <span class="pl-smi">B</span> <span class="pl-kos">{</span>
        <span class="pl-smi">B</span> <span class="pl-kos">{</span> <span class="pl-c1">a</span><span class="pl-kos">:</span> <span class="pl-smi">self</span> <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> a = <span class="pl-v">A</span><span class="pl-kos">;</span>
    <span class="pl-k">match</span> a<span class="pl-kos">.</span><span class="pl-en">b</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        _ =&gt; <span class="pl-kos">{</span><span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span></pre></div>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="test.rs:25:11: 25:12 error: `a` does not live long enough
test.rs:25     match a.b() {
                     ^
test.rs:23:11: 28:2 note: reference must be valid for the destruction scope surrounding block at 23:10...
test.rs:23 fn main() {
test.rs:24     let a = A;
test.rs:25     match a.b() {
test.rs:26         _ =&gt; {}
test.rs:27     }
test.rs:28 }
test.rs:24:14: 28:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 24:13
test.rs:24     let a = A;
test.rs:25     match a.b() {
test.rs:26         _ =&gt; {}
test.rs:27     }
test.rs:28 }
error: aborting due to previous error"><pre class="notranslate"><code class="notranslate">test.rs:25:11: 25:12 error: `a` does not live long enough
test.rs:25     match a.b() {
                     ^
test.rs:23:11: 28:2 note: reference must be valid for the destruction scope surrounding block at 23:10...
test.rs:23 fn main() {
test.rs:24     let a = A;
test.rs:25     match a.b() {
test.rs:26         _ =&gt; {}
test.rs:27     }
test.rs:28 }
test.rs:24:14: 28:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 24:13
test.rs:24     let a = A;
test.rs:25     match a.b() {
test.rs:26         _ =&gt; {}
test.rs:27     }
test.rs:28 }
error: aborting due to previous error
</code></pre></div>
<p dir="auto">Adding anything after the match (like <code class="notranslate">;</code> or <code class="notranslate">()</code>) causes the error to go away.</p>
<p dir="auto">cc <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/pnkfelix/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/pnkfelix">@pnkfelix</a></p>
<p dir="auto">Found while investigating the remaining wrong case in <a class="issue-link js-issue-link" data-error-text="Failed to load title" data-id="142747894" data-permission-text="Title is private" data-url="https://github.com/rust-lang/rust/issues/32433" data-hovercard-type="issue" data-hovercard-url="/rust-lang/rust/issues/32433/hovercard" href="https://github.com/rust-lang/rust/issues/32433">#32433</a>. Effectively use-after-free.</p>
<p dir="auto">Can be used to cause a segmentation fault (check out on <a href="https://play.rust-lang.org/?gist=27e782c076159255e6c142acc310c1bd&amp;version=nightly&amp;backtrace=0" rel="nofollow">playpen</a>):</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="struct Fine&lt;T: std::fmt::Debug&gt;(T);

impl&lt;T: std::fmt::Debug&gt; Drop for Fine&lt;T&gt; {
    fn drop(&amp;mut self) {
        print!(&quot;Fine({:?}) &quot;, self.0);
    }
}

enum Evil&lt;'a, T: 'a+std::fmt::Debug&gt; {
    None,
    Some(&amp;'a Fine&lt;T&gt;)
}

impl&lt;'a, T: std::fmt::Debug&gt; Drop for Evil&lt;'a, T&gt; {
    fn drop(&amp;mut self) {
        if let Evil::Some(x) = *self {
            print!(&quot;Evil({:?}) &quot;, x.0);
        }
    }
}

// Allocates a new 3-usize Box on drop.
struct Dirty;
impl Drop for Dirty {
    fn drop(&amp;mut self) {
        let _ = Box::new((1usize, 1usize, 1usize));
    }
}

fn assign&lt;'a, T: std::fmt::Debug&gt;(x: &amp;mut Evil&lt;'a, T&gt;, _: &amp;Dirty, y: &amp;'a Fine&lt;T&gt;) {
    *x = Evil::Some(y);
}

fn main() {
    let mut _x = Evil::None;
    assign(&amp;mut _x, &amp;Dirty, &amp;Fine(Box::new(vec![1, 2, 3])))
}"><pre class="notranslate"><span class="pl-k">struct</span> <span class="pl-smi">Fine</span><span class="pl-kos">&lt;</span><span class="pl-smi">T</span><span class="pl-kos">:</span> std<span class="pl-kos">::</span>fmt<span class="pl-kos">::</span><span class="pl-smi">Debug</span><span class="pl-kos">&gt;</span><span class="pl-kos">(</span><span class="pl-smi">T</span><span class="pl-kos">)</span><span class="pl-kos">;</span>

<span class="pl-k">impl</span><span class="pl-kos">&lt;</span><span class="pl-smi">T</span><span class="pl-kos">:</span> std<span class="pl-kos">::</span>fmt<span class="pl-kos">::</span><span class="pl-smi">Debug</span><span class="pl-kos">&gt;</span> <span class="pl-smi">Drop</span> <span class="pl-k">for</span> <span class="pl-smi">Fine</span><span class="pl-kos">&lt;</span><span class="pl-smi">T</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">drop</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span><span class="pl-k">mut</span> <span class="pl-smi">self</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-en">print</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"Fine({:?}) "</span>, <span class="pl-smi">self</span>.<span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">enum</span> <span class="pl-smi">Evil</span><span class="pl-kos">&lt;</span><span class="pl-c1">'</span><span class="pl-ent">a</span><span class="pl-kos">,</span> <span class="pl-smi">T</span><span class="pl-kos">:</span> <span class="pl-c1">'</span><span class="pl-ent">a</span>+std<span class="pl-kos">::</span>fmt<span class="pl-kos">::</span><span class="pl-smi">Debug</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-v">None</span><span class="pl-kos">,</span>
    <span class="pl-v">Some</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span><span class="pl-c1">'</span><span class="pl-ent">a</span> <span class="pl-smi">Fine</span><span class="pl-kos">&lt;</span><span class="pl-smi">T</span><span class="pl-kos">&gt;</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span>

<span class="pl-k">impl</span><span class="pl-kos">&lt;</span><span class="pl-c1">'</span><span class="pl-ent">a</span><span class="pl-kos">,</span> <span class="pl-smi">T</span><span class="pl-kos">:</span> std<span class="pl-kos">::</span>fmt<span class="pl-kos">::</span><span class="pl-smi">Debug</span><span class="pl-kos">&gt;</span> <span class="pl-smi">Drop</span> <span class="pl-k">for</span> <span class="pl-smi">Evil</span><span class="pl-kos">&lt;</span><span class="pl-c1">'</span><span class="pl-ent">a</span><span class="pl-kos">,</span> <span class="pl-smi">T</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">drop</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span><span class="pl-k">mut</span> <span class="pl-smi">self</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">if</span> <span class="pl-k">let</span> <span class="pl-smi">Evil</span><span class="pl-kos">::</span><span class="pl-v">Some</span><span class="pl-kos">(</span>x<span class="pl-kos">)</span> = <span class="pl-c1">*</span><span class="pl-smi">self</span> <span class="pl-kos">{</span>
            <span class="pl-en">print</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"Evil({:?}) "</span>, x.<span class="pl-c1">0</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
        <span class="pl-kos">}</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-c">// Allocates a new 3-usize Box on drop.</span>
<span class="pl-k">struct</span> <span class="pl-smi">Dirty</span><span class="pl-kos">;</span>
<span class="pl-k">impl</span> <span class="pl-smi">Drop</span> <span class="pl-k">for</span> <span class="pl-smi">Dirty</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">drop</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span><span class="pl-k">mut</span> <span class="pl-smi">self</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
        <span class="pl-k">let</span> _ = <span class="pl-smi">Box</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-kos">(</span><span class="pl-c1">1usize</span><span class="pl-kos">,</span> <span class="pl-c1">1usize</span><span class="pl-kos">,</span> <span class="pl-c1">1usize</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-kos">}</span>
<span class="pl-kos">}</span>

<span class="pl-k">fn</span> <span class="pl-en">assign</span><span class="pl-kos">&lt;</span><span class="pl-c1">'</span><span class="pl-ent">a</span><span class="pl-kos">,</span> <span class="pl-smi">T</span><span class="pl-kos">:</span> std<span class="pl-kos">::</span>fmt<span class="pl-kos">::</span><span class="pl-smi">Debug</span><span class="pl-kos">&gt;</span><span class="pl-kos">(</span><span class="pl-s1">x</span><span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-k">mut</span> <span class="pl-smi">Evil</span><span class="pl-kos">&lt;</span><span class="pl-c1">'</span><span class="pl-ent">a</span><span class="pl-kos">,</span> <span class="pl-smi">T</span><span class="pl-kos">&gt;</span><span class="pl-kos">,</span> _<span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-smi">Dirty</span><span class="pl-kos">,</span> <span class="pl-s1">y</span><span class="pl-kos">:</span> <span class="pl-c1">&amp;</span><span class="pl-c1">'</span><span class="pl-ent">a</span> <span class="pl-smi">Fine</span><span class="pl-kos">&lt;</span><span class="pl-smi">T</span><span class="pl-kos">&gt;</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-c1">*</span>x = <span class="pl-smi">Evil</span><span class="pl-kos">::</span><span class="pl-v">Some</span><span class="pl-kos">(</span>y<span class="pl-kos">)</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">fn</span> <span class="pl-en">main</span><span class="pl-kos">(</span><span class="pl-kos">)</span> <span class="pl-kos">{</span>
    <span class="pl-k">let</span> <span class="pl-k">mut</span> _x = <span class="pl-smi">Evil</span><span class="pl-kos">::</span><span class="pl-v">None</span><span class="pl-kos">;</span>
    <span class="pl-en">assign</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span><span class="pl-k">mut</span> _x<span class="pl-kos">,</span> <span class="pl-c1">&amp;</span><span class="pl-v">Dirty</span><span class="pl-kos">,</span> <span class="pl-c1">&amp;</span><span class="pl-v">Fine</span><span class="pl-kos">(</span><span class="pl-smi">Box</span><span class="pl-kos">::</span><span class="pl-en">new</span><span class="pl-kos">(</span><span class="pl-en">vec</span><span class="pl-en">!</span><span class="pl-kos">[</span><span class="pl-c1">1</span>, <span class="pl-c1">2</span>, <span class="pl-c1">3</span><span class="pl-kos">]</span><span class="pl-kos">)</span><span class="pl-kos">)</span><span class="pl-kos">)</span>
<span class="pl-kos">}</span></pre></div>
<p dir="auto">The <code class="notranslate">Fine</code> pointee drops before the <code class="notranslate">Evil</code> holding of the pointer, and in between those the destructor of <code class="notranslate">Dirty</code> overwrites the same heap location of the deallocated <code class="notranslate">Box&lt;Vec&lt;i32&gt;&gt;</code> with a different 3-<code class="notranslate">usize</code> <code class="notranslate">Box</code>, causing a segmentation fault on Debug mode and garbage to be printed on Release mode.</p>
<p dir="auto"><strong>EDIT</strong>: Works fine even with old trans if there is any sort of block nesting (i.e. only the outermost block of a function has the broken behavior) - check out on <a href="https://play.rust-lang.org/?gist=e7f1ad8f28af947f2984ebebdfc6ca0c&amp;version=nightly&amp;backtrace=0" rel="nofollow">playpen</a>.</p>
<p dir="auto">cc <a class="team-mention js-team-mention notranslate" data-error-text="Failed to load team members" data-id="1508062" data-permission-text="Team members are private" data-url="/orgs/rust-lang/teams/compiler/members" data-hovercard-type="team" data-hovercard-url="/orgs/rust-lang/teams/compiler/hovercard" href="https://github.com/orgs/rust-lang/teams/compiler">@rust-lang/compiler</a> <a class="team-mention js-team-mention notranslate" data-error-text="Failed to load team members" data-id="1508058" data-permission-text="Team members are private" data-url="/orgs/rust-lang/teams/lang/members" data-hovercard-type="team" data-hovercard-url="/orgs/rust-lang/teams/lang/hovercard" href="https://github.com/orgs/rust-lang/teams/lang">@rust-lang/lang</a></p>