Sophie

Sophie

distrib > Mageia > 6 > x86_64 > media > core-updates > by-pkgid > fdedb3cf2140df9b6d419a2338ab1caa > files > 520

rust-doc-1.25.0-1.mga6.x86_64.rpm

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Trait Objects - The Rust Programming Language</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="https://maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">

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

        <!-- Custom theme -->
        

        

        <!-- Fetch Clipboard.js from CDN but have a local fallback -->
        <script src="https://cdn.jsdelivr.net/clipboard.js/1.6.1/clipboard.min.js"></script>
        <script>
            if (typeof Clipboard == 'undefined') {
                document.write(unescape("%3Cscript src='clipboard.min.js'%3E%3C/script%3E"));
            }
        </script>

    </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;
        </script>

        <!-- Hide / unhide sidebar before it is displayed -->
        <script type="text/javascript">
            var sidebar = 'hidden';
            if (document.body.clientWidth >= 1080) {
                try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
                sidebar = sidebar || 'visible';
            }
            document.querySelector('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="getting-started.html"><strong aria-hidden="true">1.</strong> Getting Started</a></li><li><a href="guessing-game.html"><strong aria-hidden="true">2.</strong> Tutorial: Guessing Game</a></li><li><a href="syntax-and-semantics.html"><strong aria-hidden="true">3.</strong> Syntax and Semantics</a></li><li><ol class="section"><li><a href="variable-bindings.html"><strong aria-hidden="true">3.1.</strong> Variable Bindings</a></li><li><a href="functions.html"><strong aria-hidden="true">3.2.</strong> Functions</a></li><li><a href="primitive-types.html"><strong aria-hidden="true">3.3.</strong> Primitive Types</a></li><li><a href="comments.html"><strong aria-hidden="true">3.4.</strong> Comments</a></li><li><a href="if.html"><strong aria-hidden="true">3.5.</strong> if</a></li><li><a href="loops.html"><strong aria-hidden="true">3.6.</strong> Loops</a></li><li><a href="vectors.html"><strong aria-hidden="true">3.7.</strong> Vectors</a></li><li><a href="ownership.html"><strong aria-hidden="true">3.8.</strong> Ownership</a></li><li><a href="references-and-borrowing.html"><strong aria-hidden="true">3.9.</strong> References and Borrowing</a></li><li><a href="lifetimes.html"><strong aria-hidden="true">3.10.</strong> Lifetimes</a></li><li><a href="mutability.html"><strong aria-hidden="true">3.11.</strong> Mutability</a></li><li><a href="structs.html"><strong aria-hidden="true">3.12.</strong> Structs</a></li><li><a href="enums.html"><strong aria-hidden="true">3.13.</strong> Enums</a></li><li><a href="match.html"><strong aria-hidden="true">3.14.</strong> Match</a></li><li><a href="patterns.html"><strong aria-hidden="true">3.15.</strong> Patterns</a></li><li><a href="method-syntax.html"><strong aria-hidden="true">3.16.</strong> Method Syntax</a></li><li><a href="strings.html"><strong aria-hidden="true">3.17.</strong> Strings</a></li><li><a href="generics.html"><strong aria-hidden="true">3.18.</strong> Generics</a></li><li><a href="traits.html"><strong aria-hidden="true">3.19.</strong> Traits</a></li><li><a href="drop.html"><strong aria-hidden="true">3.20.</strong> Drop</a></li><li><a href="if-let.html"><strong aria-hidden="true">3.21.</strong> if let</a></li><li><a href="trait-objects.html" class="active"><strong aria-hidden="true">3.22.</strong> Trait Objects</a></li><li><a href="closures.html"><strong aria-hidden="true">3.23.</strong> Closures</a></li><li><a href="ufcs.html"><strong aria-hidden="true">3.24.</strong> Universal Function Call Syntax</a></li><li><a href="crates-and-modules.html"><strong aria-hidden="true">3.25.</strong> Crates and Modules</a></li><li><a href="const-and-static.html"><strong aria-hidden="true">3.26.</strong> const and static</a></li><li><a href="attributes.html"><strong aria-hidden="true">3.27.</strong> Attributes</a></li><li><a href="type-aliases.html"><strong aria-hidden="true">3.28.</strong> type aliases</a></li><li><a href="casting-between-types.html"><strong aria-hidden="true">3.29.</strong> Casting between types</a></li><li><a href="associated-types.html"><strong aria-hidden="true">3.30.</strong> Associated Types</a></li><li><a href="unsized-types.html"><strong aria-hidden="true">3.31.</strong> Unsized Types</a></li><li><a href="operators-and-overloading.html"><strong aria-hidden="true">3.32.</strong> Operators and Overloading</a></li><li><a href="deref-coercions.html"><strong aria-hidden="true">3.33.</strong> Deref coercions</a></li><li><a href="macros.html"><strong aria-hidden="true">3.34.</strong> Macros</a></li><li><a href="raw-pointers.html"><strong aria-hidden="true">3.35.</strong> Raw Pointers</a></li><li><a href="unsafe.html"><strong aria-hidden="true">3.36.</strong> unsafe</a></li></ol></li><li><a href="effective-rust.html"><strong aria-hidden="true">4.</strong> Effective Rust</a></li><li><ol class="section"><li><a href="the-stack-and-the-heap.html"><strong aria-hidden="true">4.1.</strong> The Stack and the Heap</a></li><li><a href="testing.html"><strong aria-hidden="true">4.2.</strong> Testing</a></li><li><a href="conditional-compilation.html"><strong aria-hidden="true">4.3.</strong> Conditional Compilation</a></li><li><a href="documentation.html"><strong aria-hidden="true">4.4.</strong> Documentation</a></li><li><a href="iterators.html"><strong aria-hidden="true">4.5.</strong> Iterators</a></li><li><a href="concurrency.html"><strong aria-hidden="true">4.6.</strong> Concurrency</a></li><li><a href="error-handling.html"><strong aria-hidden="true">4.7.</strong> Error Handling</a></li><li><a href="choosing-your-guarantees.html"><strong aria-hidden="true">4.8.</strong> Choosing your Guarantees</a></li><li><a href="ffi.html"><strong aria-hidden="true">4.9.</strong> FFI</a></li><li><a href="borrow-and-asref.html"><strong aria-hidden="true">4.10.</strong> Borrow and AsRef</a></li><li><a href="release-channels.html"><strong aria-hidden="true">4.11.</strong> Release Channels</a></li><li><a href="using-rust-without-the-standard-library.html"><strong aria-hidden="true">4.12.</strong> Using Rust without the standard library</a></li><li><a href="procedural-macros.html"><strong aria-hidden="true">4.13.</strong> Procedural Macros (and custom derive)</a></li></ol></li><li><a href="glossary.html"><strong aria-hidden="true">5.</strong> Glossary</a></li><li><a href="syntax-index.html"><strong aria-hidden="true">6.</strong> Syntax Index</a></li><li><a href="bibliography.html"><strong aria-hidden="true">7.</strong> Bibliography</a></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="submenu">
                                <li><button class="theme" id="light">Light <span class="default">(default)</span></button></li>
                                <li><button class="theme" id="rust">Rust</button></li>
                                <li><button class="theme" id="coal">Coal</button></li>
                                <li><button class="theme" id="navy">Navy</button></li>
                                <li><button class="theme" id="ayu">Ayu</button></li>
                            </ul>
                        </div>

                        <h1 class="menu-title">The Rust Programming Language</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>

                <!-- 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="trait-objects.html#trait-objects" id="trait-objects"><h1>Trait Objects</h1></a>
<p>When code involves polymorphism, there needs to be a mechanism to determine
which specific version is actually run. This is called ‘dispatch’. There are
two major forms of dispatch: static dispatch and dynamic dispatch. While Rust
favors static dispatch, it also supports dynamic dispatch through a mechanism
called ‘trait objects’.</p>
<a class="header" href="trait-objects.html#background" id="background"><h2>Background</h2></a>
<p>For the rest of this chapter, we’ll need a trait and some implementations.
Let’s make a simple one, <code>Foo</code>. It has one method that is expected to return a
<code>String</code>.</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
trait Foo {
    fn method(&amp;self) -&gt; String;
}
#}</code></pre></pre>
<p>We’ll also implement this trait for <code>u8</code> and <code>String</code>:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
# trait Foo { fn method(&amp;self) -&gt; String; }
impl Foo for u8 {
    fn method(&amp;self) -&gt; String { format!(&quot;u8: {}&quot;, *self) }
}

impl Foo for String {
    fn method(&amp;self) -&gt; String { format!(&quot;string: {}&quot;, *self) }
}
#}</code></pre></pre>
<a class="header" href="trait-objects.html#static-dispatch" id="static-dispatch"><h2>Static dispatch</h2></a>
<p>We can use this trait to perform static dispatch with trait bounds:</p>
<pre><pre class="playpen"><code class="language-rust"># trait Foo { fn method(&amp;self) -&gt; String; }
# impl Foo for u8 { fn method(&amp;self) -&gt; String { format!(&quot;u8: {}&quot;, *self) } }
# impl Foo for String { fn method(&amp;self) -&gt; String { format!(&quot;string: {}&quot;, *self) } }
fn do_something&lt;T: Foo&gt;(x: T) {
    x.method();
}

fn main() {
    let x = 5u8;
    let y = &quot;Hello&quot;.to_string();

    do_something(x);
    do_something(y);
}
</code></pre></pre>
<p>Rust uses ‘monomorphization’ to perform static dispatch here. This means that
Rust will create a special version of <code>do_something()</code> for both <code>u8</code> and
<code>String</code>, and then replace the call sites with calls to these specialized
functions. In other words, Rust generates something like this:</p>
<pre><pre class="playpen"><code class="language-rust"># trait Foo { fn method(&amp;self) -&gt; String; }
# impl Foo for u8 { fn method(&amp;self) -&gt; String { format!(&quot;u8: {}&quot;, *self) } }
# impl Foo for String { fn method(&amp;self) -&gt; String { format!(&quot;string: {}&quot;, *self) } }
fn do_something_u8(x: u8) {
    x.method();
}

fn do_something_string(x: String) {
    x.method();
}

fn main() {
    let x = 5u8;
    let y = &quot;Hello&quot;.to_string();

    do_something_u8(x);
    do_something_string(y);
}
</code></pre></pre>
<p>This has a great upside: static dispatch allows function calls to be
inlined because the callee is known at compile time, and inlining is
the key to good optimization. Static dispatch is fast, but it comes at
a tradeoff: ‘code bloat’, due to many copies of the same function
existing in the binary, one for each type.</p>
<p>Furthermore, compilers aren’t perfect and may “optimize” code to become slower.
For example, functions inlined too eagerly will bloat the instruction cache
(cache rules everything around us). This is part of the reason that <code>#[inline]</code>
and <code>#[inline(always)]</code> should be used carefully, and one reason why using a
dynamic dispatch is sometimes more efficient.</p>
<p>However, the common case is that it is more efficient to use static dispatch,
and one can always have a thin statically-dispatched wrapper function that does
a dynamic dispatch, but not vice versa, meaning static calls are more flexible.
The standard library tries to be statically dispatched where possible for this
reason.</p>
<a class="header" href="trait-objects.html#dynamic-dispatch" id="dynamic-dispatch"><h2>Dynamic dispatch</h2></a>
<p>Rust provides dynamic dispatch through a feature called ‘trait objects’. Trait
objects, like <code>&amp;Foo</code> or <code>Box&lt;Foo&gt;</code>, are normal values that store a value of
<em>any</em> type that implements the given trait, where the precise type can only be
known at runtime.</p>
<p>A trait object can be obtained from a pointer to a concrete type that
implements the trait by <em>casting</em> it (e.g. <code>&amp;x as &amp;Foo</code>) or <em>coercing</em> it
(e.g. using <code>&amp;x</code> as an argument to a function that takes <code>&amp;Foo</code>).</p>
<p>These trait object coercions and casts also work for pointers like <code>&amp;mut T</code> to
<code>&amp;mut Foo</code> and <code>Box&lt;T&gt;</code> to <code>Box&lt;Foo&gt;</code>, but that’s all at the moment. Coercions
and casts are identical.</p>
<p>This operation can be seen as ‘erasing’ the compiler’s knowledge about the
specific type of the pointer, and hence trait objects are sometimes referred to
as ‘type erasure’.</p>
<p>Coming back to the example above, we can use the same trait to perform dynamic
dispatch with trait objects by casting:</p>
<pre><pre class="playpen"><code class="language-rust"># trait Foo { fn method(&amp;self) -&gt; String; }
# impl Foo for u8 { fn method(&amp;self) -&gt; String { format!(&quot;u8: {}&quot;, *self) } }
# impl Foo for String { fn method(&amp;self) -&gt; String { format!(&quot;string: {}&quot;, *self) } }
fn do_something(x: &amp;Foo) {
    x.method();
}

fn main() {
    let x = 5u8;
    do_something(&amp;x as &amp;Foo);
}
</code></pre></pre>
<p>or by coercing:</p>
<pre><pre class="playpen"><code class="language-rust"># trait Foo { fn method(&amp;self) -&gt; String; }
# impl Foo for u8 { fn method(&amp;self) -&gt; String { format!(&quot;u8: {}&quot;, *self) } }
# impl Foo for String { fn method(&amp;self) -&gt; String { format!(&quot;string: {}&quot;, *self) } }
fn do_something(x: &amp;Foo) {
    x.method();
}

fn main() {
    let x = &quot;Hello&quot;.to_string();
    do_something(&amp;x);
}
</code></pre></pre>
<p>A function that takes a trait object is not specialized to each of the types
that implements <code>Foo</code>: only one copy is generated, often (but not always)
resulting in less code bloat. However, this comes at the cost of requiring
slower virtual function calls, and effectively inhibiting any chance of
inlining and related optimizations from occurring.</p>
<a class="header" href="trait-objects.html#why-pointers" id="why-pointers"><h3>Why pointers?</h3></a>
<p>Rust does not put things behind a pointer by default, unlike many managed
languages, so types can have different sizes. Knowing the size of the value at
compile time is important for things like passing it as an argument to a
function, moving it about on the stack and allocating (and deallocating) space
on the heap to store it.</p>
<p>For <code>Foo</code>, we would need to have a value that could be at least either a
<code>String</code> (24 bytes) or a <code>u8</code> (1 byte), as well as any other type for which
dependent crates may implement <code>Foo</code> (any number of bytes at all). There’s no
way to guarantee that this last point can work if the values are stored without
a pointer, because those other types can be arbitrarily large.</p>
<p>Putting the value behind a pointer means the size of the value is not relevant
when we are tossing a trait object around, only the size of the pointer itself.</p>
<a class="header" href="trait-objects.html#representation" id="representation"><h3>Representation</h3></a>
<p>The methods of the trait can be called on a trait object via a special record
of function pointers traditionally called a ‘vtable’ (created and managed by
the compiler).</p>
<p>Trait objects are both simple and complicated: their core representation and
layout is quite straight-forward, but there are some curly error messages and
surprising behaviors to discover.</p>
<p>Let’s start simple, with the runtime representation of a trait object. The
<code>std::raw</code> module contains structs with layouts that are the same as the
complicated built-in types, <a href="../../std/raw/struct.TraitObject.html">including trait objects</a>:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
# mod foo {
pub struct TraitObject {
    pub data: *mut (),
    pub vtable: *mut (),
}
# }
#}</code></pre></pre>
<p>That is, a trait object like <code>&amp;Foo</code> consists of a ‘data’ pointer and a ‘vtable’
pointer.</p>
<p>The data pointer addresses the data (of some unknown type <code>T</code>) that the trait
object is storing, and the vtable pointer points to the vtable (‘virtual method
table’) corresponding to the implementation of <code>Foo</code> for <code>T</code>.</p>
<p>A vtable is essentially a struct of function pointers, pointing to the concrete
piece of machine code for each method in the implementation. A method call like
<code>trait_object.method()</code> will retrieve the correct pointer out of the vtable and
then do a dynamic call of it. For example:</p>
<pre><code class="language-rust ignore">struct FooVtable {
    destructor: fn(*mut ()),
    size: usize,
    align: usize,
    method: fn(*const ()) -&gt; String,
}

// u8:

fn call_method_on_u8(x: *const ()) -&gt; String {
    // The compiler guarantees that this function is only called
    // with `x` pointing to a u8.
    let byte: &amp;u8 = unsafe { &amp;*(x as *const u8) };

    byte.method()
}

static Foo_for_u8_vtable: FooVtable = FooVtable {
    destructor: /* compiler magic */,
    size: 1,
    align: 1,

    // Cast to a function pointer:
    method: call_method_on_u8 as fn(*const ()) -&gt; String,
};


// String:

fn call_method_on_String(x: *const ()) -&gt; String {
    // The compiler guarantees that this function is only called
    // with `x` pointing to a String.
    let string: &amp;String = unsafe { &amp;*(x as *const String) };

    string.method()
}

static Foo_for_String_vtable: FooVtable = FooVtable {
    destructor: /* compiler magic */,
    // Values for a 64-bit computer, halve them for 32-bit ones.
    size: 24,
    align: 8,

    method: call_method_on_String as fn(*const ()) -&gt; String,
};
</code></pre>
<p>The <code>destructor</code> field in each vtable points to a function that will clean up
any resources of the vtable’s type: for <code>u8</code> it is trivial, but for <code>String</code> it
will free the memory. This is necessary for owning trait objects like
<code>Box&lt;Foo&gt;</code>, which need to clean-up both the <code>Box</code> allocation as well as the
internal type when they go out of scope. The <code>size</code> and <code>align</code> fields store
the size of the erased type, and its alignment requirements.</p>
<p>Suppose we’ve got some values that implement <code>Foo</code>. The explicit form of
construction and use of <code>Foo</code> trait objects might look a bit like (ignoring the
type mismatches: they’re all pointers anyway):</p>
<pre><code class="language-rust ignore">let a: String = &quot;foo&quot;.to_string();
let x: u8 = 1;

// let b: &amp;Foo = &amp;a;
let b = TraitObject {
    // Store the data:
    data: &amp;a,
    // Store the methods:
    vtable: &amp;Foo_for_String_vtable
};

// let y: &amp;Foo = x;
let y = TraitObject {
    // Store the data:
    data: &amp;x,
    // Store the methods:
    vtable: &amp;Foo_for_u8_vtable
};

// b.method();
(b.vtable.method)(b.data);

// y.method();
(y.vtable.method)(y.data);
</code></pre>
<a class="header" href="trait-objects.html#object-safety" id="object-safety"><h2>Object Safety</h2></a>
<p>Not every trait can be used to make a trait object. For example, vectors implement
<code>Clone</code>, but if we try to make a trait object:</p>
<pre><code class="language-rust ignore">let v = vec![1, 2, 3];
let o = &amp;v as &amp;Clone;
</code></pre>
<p>We get an error:</p>
<pre><code class="language-text">error: cannot convert to a trait object because trait `core::clone::Clone` is not object-safe [E0038]
let o = &amp;v as &amp;Clone;
        ^~
note: the trait cannot require that `Self : Sized`
let o = &amp;v as &amp;Clone;
        ^~
</code></pre>
<p>The error says that <code>Clone</code> is not ‘object-safe’. Only traits that are
object-safe can be made into trait objects. A trait is object-safe if both of
these are true:</p>
<ul>
<li>the trait does not require that <code>Self: Sized</code></li>
<li>all of its methods are object-safe</li>
</ul>
<p>So what makes a method object-safe? Each method must require that <code>Self: Sized</code>
or all of the following:</p>
<ul>
<li>must not have any type parameters</li>
<li>must not use <code>Self</code></li>
</ul>
<p>Whew! As we can see, almost all of these rules talk about <code>Self</code>. A good intuition
is “except in special circumstances, if your trait’s method uses <code>Self</code>, it is not
object-safe.”</p>

                    </main>

                    <nav class="nav-wrapper" aria-label="Page navigation">
                        <!-- Mobile navigation buttons -->
                        
                            <a rel="prev" href="if-let.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="closures.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="if-let.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="closures.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>


        <!-- Local fallback for Font Awesome -->
        <script>
            if (getComputedStyle(document.querySelector(".fa")).fontFamily !== "FontAwesome") {
                var link = document.createElement('link');
                link.rel = 'stylesheet';
                link.type = 'text/css';
                link.href = '_FontAwesome/css/font-awesome.css';
                document.head.insertBefore(link, document.head.firstChild)
            }
        </script>

        

        

        

        

        <script src="highlight.js"></script>
        <script src="book.js"></script>

        <!-- Custom JS script -->
        

    </body>
</html>