<p dir="auto">With an iterator that returns a borrowed reference to its contents, it’s possible to hold the reference longer than the reference is valid. In particular, if the iterator changes its internal state, the new state can be observed via the saved reference. Check it out:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="fn crash_please() {
    let mut iter = Newtype(Some(Box::new(0)));
    let saved = iter.next().unwrap();
    println!(&quot;{}&quot;, saved);
    iter.0 = None;
    println!(&quot;{}&quot;, saved);
}

struct Newtype(Option&lt;Box&lt;usize&gt;&gt;);

impl&lt;'a&gt; Iterator for Newtype {
    type Item = &amp;'a Box&lt;usize&gt;;

    fn next(&amp;mut self) -&gt; Option&lt;&amp;Box&lt;usize&gt;&gt; {
        self.0.as_ref()
    }
}"><pre class="notranslate"><span class="pl-k">fn</span> <span class="pl-en">crash_please</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> iter = <span class="pl-v">Newtype</span><span class="pl-kos">(</span><span class="pl-v">Some</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-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">let</span> saved = iter<span class="pl-kos">.</span><span class="pl-en">next</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">.</span><span class="pl-en">unwrap</span><span class="pl-kos">(</span><span class="pl-kos">)</span><span class="pl-kos">;</span>
    <span class="pl-en">println</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"{}"</span>, saved<span class="pl-kos">)</span><span class="pl-kos">;</span>
    iter<span class="pl-kos">.</span><span class="pl-c1">0</span> = <span class="pl-v">None</span><span class="pl-kos">;</span>
    <span class="pl-en">println</span><span class="pl-en">!</span><span class="pl-kos">(</span><span class="pl-s">"{}"</span>, saved<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">Newtype</span><span class="pl-kos">(</span><span class="pl-smi">Option</span><span class="pl-kos">&lt;</span><span class="pl-smi">Box</span><span class="pl-kos">&lt;</span><span class="pl-smi">usize</span><span class="pl-kos">&gt;</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">&gt;</span> <span class="pl-smi">Iterator</span> <span class="pl-k">for</span> <span class="pl-smi">Newtype</span> <span class="pl-kos">{</span>
    <span class="pl-k">type</span> <span class="pl-smi">Item</span> = <span class="pl-c1">&amp;</span><span class="pl-c1">'</span><span class="pl-ent">a</span> <span class="pl-smi">Box</span><span class="pl-kos">&lt;</span><span class="pl-smi">usize</span><span class="pl-kos">&gt;</span><span class="pl-kos">;</span>

    <span class="pl-k">fn</span> <span class="pl-en">next</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> -&gt; <span class="pl-smi">Option</span><span class="pl-kos">&lt;</span><span class="pl-c1">&amp;</span><span class="pl-smi">Box</span><span class="pl-kos">&lt;</span><span class="pl-smi">usize</span><span class="pl-kos">&gt;</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-smi">self</span><span class="pl-kos">.</span><span class="pl-c1">0</span><span class="pl-kos">.</span><span class="pl-en">as_ref</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">This clearly shouldn’t type check, but it does, and runs, and crashes:</p>
<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="0
zsh: illegal hardware instruction  target/collect_bug"><pre class="notranslate">0
zsh: illegal hardware instruction  target/collect_bug</pre></div>
<p dir="auto">Where the type error should be, I’m not sure. It seems like it’s actually a problem with traits. If we change the above code to define <code class="notranslate">next</code> in a non-trait impl, then it no longer passes the borrow checker:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="impl&lt;'a&gt; Newtype {
    fn next(&amp;mut self) -&gt; Option&lt;&amp;Box&lt;usize&gt;&gt; {
        self.0.as_ref()
    }
}"><pre class="notranslate"><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">Newtype</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">next</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> -&gt; <span class="pl-smi">Option</span><span class="pl-kos">&lt;</span><span class="pl-c1">&amp;</span><span class="pl-smi">Box</span><span class="pl-kos">&lt;</span><span class="pl-smi">usize</span><span class="pl-kos">&gt;</span><span class="pl-kos">&gt;</span> <span class="pl-kos">{</span>
        <span class="pl-smi">self</span><span class="pl-kos">.</span><span class="pl-c1">0</span><span class="pl-kos">.</span><span class="pl-en">as_ref</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">I originally observed this bug when testing an iterator that owns a <code class="notranslate">String</code>; at each iteration it modifies the string and then returns a string slice borrowed from it. My non-test code worked fine because it finished with each value from the iterator before calling <code class="notranslate">next()</code> again, but the test code collected the iterator into a vector. This meant that all the slices in the vector continued to point to the same buffer, even after it had been modified. So for example, if the strings written to the buffer were <code class="notranslate">"aaa"</code>, <code class="notranslate">"bb"</code>, and <code class="notranslate">"c"</code>, then in the end the vector would contain <code class="notranslate">"cba"</code>, <code class="notranslate">"cb"</code>, and <code class="notranslate">"b"</code>. Creepy.</p>
<h2 dir="auto">Version</h2>
<p dir="auto">I’m using 1.0.0-alpha still, because I’m teaching a class and we don’t want to follow a moving target, but I confirmed that the Feb. 26 nightly has the same bug.</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="rustc 1.0.0-alpha (44a287e6e 2015-01-08 17:03:40 -0800)
binary: rustc
commit-hash: 44a287e6eb22ec3c2a687fc156813577464017f7
commit-date: 2015-01-08 17:03:40 -0800
host: x86_64-apple-darwin
release: 1.0.0-alpha"><pre class="notranslate"><code class="notranslate">rustc 1.0.0-alpha (44a287e6e 2015-01-08 17:03:40 -0800)
binary: rustc
commit-hash: 44a287e6eb22ec3c2a687fc156813577464017f7
commit-date: 2015-01-08 17:03:40 -0800
host: x86_64-apple-darwin
release: 1.0.0-alpha
</code></pre></div>
<p dir="auto">(Sorry for the bad title)</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="trait Fun {
    type Output;
    fn call&lt;'x&gt;(&amp;'x self) -&gt; Self::Output;
}

struct Holder { x: String }

impl&lt;'a&gt; Fun for Holder {
    type Output = &amp;'a str;
    fn call&lt;'b&gt;(&amp;'b self) -&gt; &amp;'b str {
        &amp;self.x[]
    }
}"><pre class="notranslate"><span class="pl-k">trait</span> <span class="pl-smi">Fun</span> <span class="pl-kos">{</span>
    <span class="pl-k">type</span> <span class="pl-smi">Output</span><span class="pl-kos">;</span>
    <span class="pl-k">fn</span> <span class="pl-en">call</span><span class="pl-kos">&lt;</span><span class="pl-c1">'</span><span class="pl-ent">x</span><span class="pl-kos">&gt;</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span><span class="pl-c1">'</span><span class="pl-ent">x</span> <span class="pl-smi">self</span><span class="pl-kos">)</span> -&gt; <span class="pl-smi">Self</span><span class="pl-kos">::</span><span class="pl-smi">Output</span><span class="pl-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">struct</span> <span class="pl-smi">Holder</span> <span class="pl-kos">{</span> <span class="pl-c1">x</span><span class="pl-kos">:</span> <span class="pl-smi">String</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">&gt;</span> <span class="pl-smi">Fun</span> <span class="pl-k">for</span> <span class="pl-smi">Holder</span> <span class="pl-kos">{</span>
    <span class="pl-k">type</span> <span class="pl-smi">Output</span> = <span class="pl-c1">&amp;</span><span class="pl-c1">'</span><span class="pl-ent">a</span> <span class="pl-smi">str</span><span class="pl-kos">;</span>
    <span class="pl-k">fn</span> <span class="pl-en">call</span><span class="pl-kos">&lt;</span><span class="pl-c1">'</span><span class="pl-ent">b</span><span class="pl-kos">&gt;</span><span class="pl-kos">(</span><span class="pl-c1">&amp;</span><span class="pl-c1">'</span><span class="pl-ent">b</span> <span class="pl-smi">self</span><span class="pl-kos">)</span> -&gt; <span class="pl-c1">&amp;</span><span class="pl-c1">'</span><span class="pl-ent">b</span> <span class="pl-smi">str</span> <span class="pl-kos">{</span>
        <span class="pl-c1">&amp;</span><span class="pl-smi">self</span><span class="pl-kos">.</span><span class="pl-c1">x</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">This compiles even though the trait's definition should require <code class="notranslate">call</code>'s signature in the impl to be <code class="notranslate">fn call&lt;'b&gt;(&amp;'b self) -&gt; &amp;'a str</code>.</p>