Sophie

Sophie

distrib > Mageia > 7 > armv7hl > media > core-release > by-pkgid > 0c2243f8a1696816431e7210e991fa52 > files > 13184

rust-doc-1.35.0-1.mga7.armv7hl.rpm

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>Splitting Borrows - </title>
        <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="theme-color" content="#ffffff" />

        <base href="">

        <link rel="stylesheet" href="book.css">
        <link href="https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800" rel="stylesheet" type="text/css">
        <link href="https://fonts.googleapis.com/css?family=Source+Code+Pro:500" rel="stylesheet" type="text/css">

        <link rel="shortcut icon" href="favicon.png">

        <!-- Font Awesome -->
        <link rel="stylesheet" href="_FontAwesome/css/font-awesome.css">

        <link rel="stylesheet" href="highlight.css">
        <link rel="stylesheet" href="tomorrow-night.css">
        <link rel="stylesheet" href="ayu-highlight.css">

        <!-- Custom theme stylesheets -->
        

        

    </head>
    <body class="light">
        <!-- Work around some values being stored in localStorage wrapped in quotes -->
        <script type="text/javascript">
            try {
                var theme = localStorage.getItem('mdbook-theme');
                var sidebar = localStorage.getItem('mdbook-sidebar');

                if (theme.startsWith('"') && theme.endsWith('"')) {
                    localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
                }

                if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
                    localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
                }
            } catch (e) { }
        </script>

        <!-- Set the theme before any content is loaded, prevents flash -->
        <script type="text/javascript">
            var theme;
            try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { } 
            if (theme === null || theme === undefined) { theme = 'light'; }
            document.body.className = theme;
            document.querySelector('html').className = theme + ' js';
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var html = document.querySelector('html');
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            html.classList.remove('sidebar-visible');
            html.classList.add("sidebar-" + sidebar);
        </script>

        <nav id="sidebar" class="sidebar" aria-label="Table of contents">
            <ol class="chapter"><li class="affix"><a href="README.html">Introduction</a></li><li><a href="meet-safe-and-unsafe.html"><strong aria-hidden="true">1.</strong> Meet Safe and Unsafe</a></li><li><ol class="section"><li><a href="safe-unsafe-meaning.html"><strong aria-hidden="true">1.1.</strong> How Safe and Unsafe Interact</a></li><li><a href="what-unsafe-does.html"><strong aria-hidden="true">1.2.</strong> What Unsafe Can Do</a></li><li><a href="working-with-unsafe.html"><strong aria-hidden="true">1.3.</strong> Working with Unsafe</a></li></ol></li><li><a href="data.html"><strong aria-hidden="true">2.</strong> Data Layout</a></li><li><ol class="section"><li><a href="repr-rust.html"><strong aria-hidden="true">2.1.</strong> repr(Rust)</a></li><li><a href="exotic-sizes.html"><strong aria-hidden="true">2.2.</strong> Exotically Sized Types</a></li><li><a href="other-reprs.html"><strong aria-hidden="true">2.3.</strong> Other reprs</a></li></ol></li><li><a href="ownership.html"><strong aria-hidden="true">3.</strong> Ownership</a></li><li><ol class="section"><li><a href="references.html"><strong aria-hidden="true">3.1.</strong> References</a></li><li><a href="aliasing.html"><strong aria-hidden="true">3.2.</strong> Aliasing</a></li><li><a href="lifetimes.html"><strong aria-hidden="true">3.3.</strong> Lifetimes</a></li><li><a href="lifetime-mismatch.html"><strong aria-hidden="true">3.4.</strong> Limits of Lifetimes</a></li><li><a href="lifetime-elision.html"><strong aria-hidden="true">3.5.</strong> Lifetime Elision</a></li><li><a href="unbounded-lifetimes.html"><strong aria-hidden="true">3.6.</strong> Unbounded Lifetimes</a></li><li><a href="hrtb.html"><strong aria-hidden="true">3.7.</strong> Higher-Rank Trait Bounds</a></li><li><a href="subtyping.html"><strong aria-hidden="true">3.8.</strong> Subtyping and Variance</a></li><li><a href="dropck.html"><strong aria-hidden="true">3.9.</strong> Drop Check</a></li><li><a href="phantom-data.html"><strong aria-hidden="true">3.10.</strong> PhantomData</a></li><li><a href="borrow-splitting.html" class="active"><strong aria-hidden="true">3.11.</strong> Splitting Borrows</a></li></ol></li><li><a href="conversions.html"><strong aria-hidden="true">4.</strong> Type Conversions</a></li><li><ol class="section"><li><a href="coercions.html"><strong aria-hidden="true">4.1.</strong> Coercions</a></li><li><a href="dot-operator.html"><strong aria-hidden="true">4.2.</strong> The Dot Operator</a></li><li><a href="casts.html"><strong aria-hidden="true">4.3.</strong> Casts</a></li><li><a href="transmutes.html"><strong aria-hidden="true">4.4.</strong> Transmutes</a></li></ol></li><li><a href="uninitialized.html"><strong aria-hidden="true">5.</strong> Uninitialized Memory</a></li><li><ol class="section"><li><a href="checked-uninit.html"><strong aria-hidden="true">5.1.</strong> Checked</a></li><li><a href="drop-flags.html"><strong aria-hidden="true">5.2.</strong> Drop Flags</a></li><li><a href="unchecked-uninit.html"><strong aria-hidden="true">5.3.</strong> Unchecked</a></li></ol></li><li><a href="obrm.html"><strong aria-hidden="true">6.</strong> Ownership Based Resource Management</a></li><li><ol class="section"><li><a href="constructors.html"><strong aria-hidden="true">6.1.</strong> Constructors</a></li><li><a href="destructors.html"><strong aria-hidden="true">6.2.</strong> Destructors</a></li><li><a href="leaking.html"><strong aria-hidden="true">6.3.</strong> Leaking</a></li></ol></li><li><a href="unwinding.html"><strong aria-hidden="true">7.</strong> Unwinding</a></li><li><ol class="section"><li><a href="exception-safety.html"><strong aria-hidden="true">7.1.</strong> Exception Safety</a></li><li><a href="poisoning.html"><strong aria-hidden="true">7.2.</strong> Poisoning</a></li></ol></li><li><a href="concurrency.html"><strong aria-hidden="true">8.</strong> Concurrency</a></li><li><ol class="section"><li><a href="races.html"><strong aria-hidden="true">8.1.</strong> Races</a></li><li><a href="send-and-sync.html"><strong aria-hidden="true">8.2.</strong> Send and Sync</a></li><li><a href="atomics.html"><strong aria-hidden="true">8.3.</strong> Atomics</a></li></ol></li><li><a href="vec.html"><strong aria-hidden="true">9.</strong> Implementing Vec</a></li><li><ol class="section"><li><a href="vec-layout.html"><strong aria-hidden="true">9.1.</strong> Layout</a></li><li><a href="vec-alloc.html"><strong aria-hidden="true">9.2.</strong> Allocating</a></li><li><a href="vec-push-pop.html"><strong aria-hidden="true">9.3.</strong> Push and Pop</a></li><li><a href="vec-dealloc.html"><strong aria-hidden="true">9.4.</strong> Deallocating</a></li><li><a href="vec-deref.html"><strong aria-hidden="true">9.5.</strong> Deref</a></li><li><a href="vec-insert-remove.html"><strong aria-hidden="true">9.6.</strong> Insert and Remove</a></li><li><a href="vec-into-iter.html"><strong aria-hidden="true">9.7.</strong> IntoIter</a></li><li><a href="vec-raw.html"><strong aria-hidden="true">9.8.</strong> RawVec</a></li><li><a href="vec-drain.html"><strong aria-hidden="true">9.9.</strong> Drain</a></li><li><a href="vec-zsts.html"><strong aria-hidden="true">9.10.</strong> Handling Zero-Sized Types</a></li><li><a href="vec-final.html"><strong aria-hidden="true">9.11.</strong> Final Code</a></li></ol></li><li><a href="arc-and-mutex.html"><strong aria-hidden="true">10.</strong> Implementing Arc and Mutex</a></li><li><a href="ffi.html"><strong aria-hidden="true">11.</strong> FFI</a></li><li><a href="beneath-std.html"><strong aria-hidden="true">12.</strong> Beneath std</a></li><li><ol class="section"><li><a href="panic-handler.html"><strong aria-hidden="true">12.1.</strong> #[panic_handler]</a></li></ol></li></ol>
        </nav>

        <div id="page-wrapper" class="page-wrapper">

            <div class="page">
                
                <div id="menu-bar" class="menu-bar">
                    <div id="menu-bar-sticky-container">
                        <div class="left-buttons">
                            <button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
                                <i class="fa fa-bars"></i>
                            </button>
                            <button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
                                <i class="fa fa-paint-brush"></i>
                            </button>
                            <ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
                                <li role="none"><button role="menuitem" class="theme" id="light">Light <span class="default">(default)</span></button></li>
                                <li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
                                <li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
                                <li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
                                <li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
                            </ul>
                            
                            <button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
                                <i class="fa fa-search"></i>
                            </button>
                            
                        </div>

                        <h1 class="menu-title"></h1> 

                        <div class="right-buttons">
                            <a href="print.html" title="Print this book" aria-label="Print this book">
                                <i id="print-button" class="fa fa-print"></i>
                            </a>
                        </div>
                    </div>
                </div>

                
                <div id="search-wrapper" class="hidden">
                    <form id="searchbar-outer" class="searchbar-outer">
                        <input type="search" name="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
                    </form>
                    <div id="searchresults-outer" class="searchresults-outer hidden">
                        <div id="searchresults-header" class="searchresults-header"></div>
                        <ul id="searchresults">
                        </ul>
                    </div>
                </div>
                

                <!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
                <script type="text/javascript">
                    document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
                    document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
                    Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
                        link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
                    });
                </script>

                <div id="content" class="content">
                    <main>
                        <a class="header" href="borrow-splitting.html#splitting-borrows" id="splitting-borrows"><h1>Splitting Borrows</h1></a>
<p>The mutual exclusion property of mutable references can be very limiting when
working with a composite structure. The borrow checker understands some basic
stuff, but will fall over pretty easily. It does understand structs
sufficiently to know that it's possible to borrow disjoint fields of a struct
simultaneously. So this works today:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
struct Foo {
    a: i32,
    b: i32,
    c: i32,
}

let mut x = Foo {a: 0, b: 0, c: 0};
let a = &amp;mut x.a;
let b = &amp;mut x.b;
let c = &amp;x.c;
*b += 1;
let c2 = &amp;x.c;
*a += 10;
println!(&quot;{} {} {} {}&quot;, a, b, c, c2);
#}</code></pre></pre>
<p>However borrowck doesn't understand arrays or slices in any way, so this doesn't
work:</p>
<pre><code class="language-rust ignore">let mut x = [1, 2, 3];
let a = &amp;mut x[0];
let b = &amp;mut x[1];
println!(&quot;{} {}&quot;, a, b);
</code></pre>
<pre><code class="language-text">error[E0499]: cannot borrow `x[..]` as mutable more than once at a time
 --&gt; src/lib.rs:4:18
  |
3 |     let a = &amp;mut x[0];
  |                  ---- first mutable borrow occurs here
4 |     let b = &amp;mut x[1];
  |                  ^^^^ second mutable borrow occurs here
5 |     println!(&quot;{} {}&quot;, a, b);
6 | }
  | - first borrow ends here

error: aborting due to previous error
</code></pre>
<p>While it was plausible that borrowck could understand this simple case, it's
pretty clearly hopeless for borrowck to understand disjointness in general
container types like a tree, especially if distinct keys actually <em>do</em> map
to the same value.</p>
<p>In order to &quot;teach&quot; borrowck that what we're doing is ok, we need to drop down
to unsafe code. For instance, mutable slices expose a <code>split_at_mut</code> function
that consumes the slice and returns two mutable slices. One for everything to
the left of the index, and one for everything to the right. Intuitively we know
this is safe because the slices don't overlap, and therefore alias. However
the implementation requires some unsafety:</p>
<pre><code class="language-rust ignore">fn split_at_mut(&amp;mut self, mid: usize) -&gt; (&amp;mut [T], &amp;mut [T]) {
    let len = self.len();
    let ptr = self.as_mut_ptr();
    assert!(mid &lt;= len);
    unsafe {
        (from_raw_parts_mut(ptr, mid),
         from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
    }
}
</code></pre>
<p>This is actually a bit subtle. So as to avoid ever making two <code>&amp;mut</code>'s to the
same value, we explicitly construct brand-new slices through raw pointers.</p>
<p>However more subtle is how iterators that yield mutable references work.
The iterator trait is defined as follows:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
trait Iterator {
    type Item;

    fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt;;
}
#}</code></pre></pre>
<p>Given this definition, Self::Item has <em>no</em> connection to <code>self</code>. This means that
we can call <code>next</code> several times in a row, and hold onto all the results
<em>concurrently</em>. This is perfectly fine for by-value iterators, which have
exactly these semantics. It's also actually fine for shared references, as they
admit arbitrarily many references to the same thing (although the iterator needs
to be a separate object from the thing being shared).</p>
<p>But mutable references make this a mess. At first glance, they might seem
completely incompatible with this API, as it would produce multiple mutable
references to the same object!</p>
<p>However it actually <em>does</em> work, exactly because iterators are one-shot objects.
Everything an IterMut yields will be yielded at most once, so we don't
actually ever yield multiple mutable references to the same piece of data.</p>
<p>Perhaps surprisingly, mutable iterators don't require unsafe code to be
implemented for many types!</p>
<p>For instance here's a singly linked list:</p>
<pre><pre class="playpen"><code class="language-rust"># fn main() {}
type Link&lt;T&gt; = Option&lt;Box&lt;Node&lt;T&gt;&gt;&gt;;

struct Node&lt;T&gt; {
    elem: T,
    next: Link&lt;T&gt;,
}

pub struct LinkedList&lt;T&gt; {
    head: Link&lt;T&gt;,
}

pub struct IterMut&lt;'a, T: 'a&gt;(Option&lt;&amp;'a mut Node&lt;T&gt;&gt;);

impl&lt;T&gt; LinkedList&lt;T&gt; {
    fn iter_mut(&amp;mut self) -&gt; IterMut&lt;T&gt; {
        IterMut(self.head.as_mut().map(|node| &amp;mut **node))
    }
}

impl&lt;'a, T&gt; Iterator for IterMut&lt;'a, T&gt; {
    type Item = &amp;'a mut T;

    fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
        self.0.take().map(|node| {
            self.0 = node.next.as_mut().map(|node| &amp;mut **node);
            &amp;mut node.elem
        })
    }
}
</code></pre></pre>
<p>Here's a mutable slice:</p>
<pre><pre class="playpen"><code class="language-rust"># fn main() {}
use std::mem;

pub struct IterMut&lt;'a, T: 'a&gt;(&amp;'a mut[T]);

impl&lt;'a, T&gt; Iterator for IterMut&lt;'a, T&gt; {
    type Item = &amp;'a mut T;

    fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
        let slice = mem::replace(&amp;mut self.0, &amp;mut []);
        if slice.is_empty() { return None; }

        let (l, r) = slice.split_at_mut(1);
        self.0 = r;
        l.get_mut(0)
    }
}

impl&lt;'a, T&gt; DoubleEndedIterator for IterMut&lt;'a, T&gt; {
    fn next_back(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
        let slice = mem::replace(&amp;mut self.0, &amp;mut []);
        if slice.is_empty() { return None; }

        let new_len = slice.len() - 1;
        let (l, r) = slice.split_at_mut(new_len);
        self.0 = l;
        r.get_mut(0)
    }
}
</code></pre></pre>
<p>And here's a binary tree:</p>
<pre><pre class="playpen"><code class="language-rust"># fn main() {}
use std::collections::VecDeque;

type Link&lt;T&gt; = Option&lt;Box&lt;Node&lt;T&gt;&gt;&gt;;

struct Node&lt;T&gt; {
    elem: T,
    left: Link&lt;T&gt;,
    right: Link&lt;T&gt;,
}

pub struct Tree&lt;T&gt; {
    root: Link&lt;T&gt;,
}

struct NodeIterMut&lt;'a, T: 'a&gt; {
    elem: Option&lt;&amp;'a mut T&gt;,
    left: Option&lt;&amp;'a mut Node&lt;T&gt;&gt;,
    right: Option&lt;&amp;'a mut Node&lt;T&gt;&gt;,
}

enum State&lt;'a, T: 'a&gt; {
    Elem(&amp;'a mut T),
    Node(&amp;'a mut Node&lt;T&gt;),
}

pub struct IterMut&lt;'a, T: 'a&gt;(VecDeque&lt;NodeIterMut&lt;'a, T&gt;&gt;);

impl&lt;T&gt; Tree&lt;T&gt; {
    pub fn iter_mut(&amp;mut self) -&gt; IterMut&lt;T&gt; {
        let mut deque = VecDeque::new();
        self.root.as_mut().map(|root| deque.push_front(root.iter_mut()));
        IterMut(deque)
    }
}

impl&lt;T&gt; Node&lt;T&gt; {
    pub fn iter_mut(&amp;mut self) -&gt; NodeIterMut&lt;T&gt; {
        NodeIterMut {
            elem: Some(&amp;mut self.elem),
            left: self.left.as_mut().map(|node| &amp;mut **node),
            right: self.right.as_mut().map(|node| &amp;mut **node),
        }
    }
}


impl&lt;'a, T&gt; Iterator for NodeIterMut&lt;'a, T&gt; {
    type Item = State&lt;'a, T&gt;;

    fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
        match self.left.take() {
            Some(node) =&gt; Some(State::Node(node)),
            None =&gt; match self.elem.take() {
                Some(elem) =&gt; Some(State::Elem(elem)),
                None =&gt; match self.right.take() {
                    Some(node) =&gt; Some(State::Node(node)),
                    None =&gt; None,
                }
            }
        }
    }
}

impl&lt;'a, T&gt; DoubleEndedIterator for NodeIterMut&lt;'a, T&gt; {
    fn next_back(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
        match self.right.take() {
            Some(node) =&gt; Some(State::Node(node)),
            None =&gt; match self.elem.take() {
                Some(elem) =&gt; Some(State::Elem(elem)),
                None =&gt; match self.left.take() {
                    Some(node) =&gt; Some(State::Node(node)),
                    None =&gt; None,
                }
            }
        }
    }
}

impl&lt;'a, T&gt; Iterator for IterMut&lt;'a, T&gt; {
    type Item = &amp;'a mut T;
    fn next(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
        loop {
            match self.0.front_mut().and_then(|node_it| node_it.next()) {
                Some(State::Elem(elem)) =&gt; return Some(elem),
                Some(State::Node(node)) =&gt; self.0.push_front(node.iter_mut()),
                None =&gt; if let None = self.0.pop_front() { return None },
            }
        }
    }
}

impl&lt;'a, T&gt; DoubleEndedIterator for IterMut&lt;'a, T&gt; {
    fn next_back(&amp;mut self) -&gt; Option&lt;Self::Item&gt; {
        loop {
            match self.0.back_mut().and_then(|node_it| node_it.next_back()) {
                Some(State::Elem(elem)) =&gt; return Some(elem),
                Some(State::Node(node)) =&gt; self.0.push_back(node.iter_mut()),
                None =&gt; if let None = self.0.pop_back() { return None },
            }
        }
    }
}
</code></pre></pre>
<p>All of these are completely safe and work on stable Rust! This ultimately
falls out of the simple struct case we saw before: Rust understands that you
can safely split a mutable reference into subfields. We can then encode
permanently consuming a reference via Options (or in the case of slices,
replacing with an empty slice).</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                        
                            <a rel="prev" href="phantom-data.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                                <i class="fa fa-angle-left"></i>
                            </a>
                        

                        
                            <a rel="next" href="conversions.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                                <i class="fa fa-angle-right"></i>
                            </a>
                        

                        <div style="clear: both"></div>
                    </nav>
                </div>
            </div>

            <nav class="nav-wide-wrapper" aria-label="Page navigation">
                
                    <a href="phantom-data.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
                        <i class="fa fa-angle-left"></i>
                    </a>
                

                
                    <a href="conversions.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
                        <i class="fa fa-angle-right"></i>
                    </a>
                
            </nav>

        </div>

        

        

        

        

        
        <script src="searchindex.js" type="text/javascript" charset="utf-8"></script>
        
        
        <script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="searcher.js" type="text/javascript" charset="utf-8"></script>
        

        <script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
        <script src="highlight.js" type="text/javascript" charset="utf-8"></script>
        <script src="book.js" type="text/javascript" charset="utf-8"></script>

        <!-- Custom JS scripts -->
        

    </body>
</html>