Sophie

Sophie

distrib > Mageia > 6 > armv7hl > by-pkgid > 4e2dbb669434a7691662cb2f0ad38972 > files > 10986

rust-doc-1.28.0-1.mga6.armv7hl.rpm

<!DOCTYPE HTML>
<html lang="en" class="sidebar-visible no-js">
    <head>
        <!-- Book generated using mdBook -->
        <meta charset="UTF-8">
        <title>Subtyping and Variance - </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" class="active"><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"><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></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="subtyping.html#subtyping-and-variance" id="subtyping-and-variance"><h1>Subtyping and Variance</h1></a>
<p>Subtyping is a relationship between types that allows statically typed
languages to be a bit more flexible and permissive.</p>
<p>The most common and easy to understand example of this can be found in
languages with inheritance. Consider an Animal type which has an <code>eat()</code>
method, and a Cat type which extends Animal, adding a <code>meow()</code> method.
Without subtyping, if someone were to write a <code>feed(Animal)</code> function, they
wouldn't be able to pass a Cat to this function, because a Cat isn't <em>exactly</em>
an Animal. But being able to pass a Cat where an Animal is expected seems
fairly reasonable. After all, a Cat is just an Animal <em>and more</em>. Something
having extra features that can be ignored shouldn't be any impediment to
using it!</p>
<p>This is exactly what subtyping lets us do. Because a Cat is an Animal <em>and more</em>
we say that Cat is a <em>subtype</em> of Animal. We then say that anywhere a value of
a certain type is expected, a value with a subtype can also be supplied. Ok
actually it's a lot more complicated and subtle than that, but that's the
basic intuition that gets you by in 99% of the cases. We'll cover why it's
<em>only</em> 99% later in this section.</p>
<p>Although Rust doesn't have any notion of structural inheritance, it <em>does</em>
include subtyping. In Rust, subtyping derives entirely from lifetimes. Since
lifetimes are regions of code, we can partially order them based on the
<em>contains</em> (outlives) relationship.</p>
<p>Subtyping on lifetimes is in terms of that relationship: if <code>'big: 'small</code>
(&quot;big contains small&quot; or &quot;big outlives small&quot;), then <code>'big</code> is a subtype
of <code>'small</code>. This is a large source of confusion, because it seems backwards
to many: the bigger region is a <em>subtype</em> of the smaller region. But it makes
sense if you consider our Animal example: <em>Cat</em> is an Animal <em>and more</em>,
just as <code>'big</code> is <code>'small</code> <em>and more</em>.</p>
<p>Put another way, if someone wants a reference that lives for <code>'small</code>,
usually what they actually mean is that they want a reference that lives
for <em>at least</em> <code>'small</code>. They don't actually care if the lifetimes match
exactly. For this reason <code>'static</code>, the forever lifetime, is a subtype
of every lifetime.</p>
<p>Higher-ranked lifetimes are also subtypes of every concrete lifetime. This is
because taking an arbitrary lifetime is strictly more general than taking a
specific one.</p>
<p>(The typed-ness of lifetimes is a fairly arbitrary construct that some
disagree with. However it simplifies our analysis to treat lifetimes
and types uniformly.)</p>
<p>However you can't write a function that takes a value of type <code>'a</code>! Lifetimes
are always just part of another type, so we need a way of handling that.
To handle it, we need to talk about <em>variance</em>.</p>
<a class="header" href="subtyping.html#variance" id="variance"><h1>Variance</h1></a>
<p>Variance is where things get a bit complicated.</p>
<p>Variance is a property that <em>type constructors</em> have with respect to their
arguments. A type constructor in Rust is a generic type with unbound arguments.
For instance <code>Vec</code> is a type constructor that takes a <code>T</code> and returns a
<code>Vec&lt;T&gt;</code>. <code>&amp;</code> and <code>&amp;mut</code> are type constructors that take two inputs: a
lifetime, and a type to point to.</p>
<p>A type constructor's <em>variance</em> is how the subtyping of its inputs affects the
subtyping of its outputs. There are three kinds of variance in Rust:</p>
<ul>
<li>F is <em>covariant</em> over <code>T</code> if <code>T</code> being a subtype of <code>U</code> implies
<code>F&lt;T&gt;</code> is a subtype of <code>F&lt;U&gt;</code> (subtyping &quot;passes through&quot;)</li>
<li>F is <em>contravariant</em> over <code>T</code> if <code>T</code> being a subtype of <code>U</code> implies
<code>F&lt;U&gt;</code> is a subtype of <code>F&lt;U&gt;</code> (subtyping is &quot;inverted&quot;)</li>
<li>F is <em>invariant</em> over <code>T</code> otherwise (no subtyping relation can be derived)</li>
</ul>
<p>It should be noted that covariance is <em>far</em> more common and important than
contravariance in Rust. The existence of contravariance in Rust can mostly
be ignored.</p>
<p>Some important variances (which we will explain in detail below):</p>
<ul>
<li><code>&amp;'a T</code> is covariant over <code>'a</code> and <code>T</code> (as is <code>*const T</code> by metaphor)</li>
<li><code>&amp;'a mut T</code> is covariant over <code>'a</code> but invariant over <code>T</code></li>
<li><code>fn(T) -&gt; U</code> is <strong>contra</strong>variant over <code>T</code>, but covariant over <code>U</code></li>
<li><code>Box</code>, <code>Vec</code>, and all other collections are covariant over the types of
their contents</li>
<li><code>UnsafeCell&lt;T&gt;</code>, <code>Cell&lt;T&gt;</code>, <code>RefCell&lt;T&gt;</code>, <code>Mutex&lt;T&gt;</code> and all other
interior mutability types are invariant over T (as is <code>*mut T</code> by metaphor)</li>
</ul>
<p>To understand why these variances are correct and desirable, we will consider
several examples.</p>
<p>We have already covered why <code>&amp;'a T</code> should be covariant over <code>'a</code> when
introducing subtyping: it's desirable to be able to pass longer-lived things
where shorter-lived things are needed.</p>
<p>Similar reasoning applies to why it should be covariant over T: it's reasonable
to be able to pass <code>&amp;&amp;'static str</code> where an <code>&amp;&amp;'a str</code> is expected. The
additional level of indirection doesn't change the desire to be able to pass
longer lived things where shorter lived things are expected.</p>
<p>However this logic doesn't apply to <code>&amp;mut</code>. To see why <code>&amp;mut</code> should
be invariant over T, consider the following code:</p>
<pre><code class="language-rust ignore">fn overwrite&lt;T: Copy&gt;(input: &amp;mut T, new: &amp;mut T) {
    *input = *new;
}

fn main() {
    let mut forever_str: &amp;'static str = &quot;hello&quot;;
    {
        let string = String::from(&quot;world&quot;);
        overwrite(&amp;mut forever_str, &amp;mut &amp;*string);
    }
    // Oops, printing free'd memory
    println!(&quot;{}&quot;, forever_str);
}
</code></pre>
<p>The signature of <code>overwrite</code> is clearly valid: it takes mutable references to
two values of the same type, and overwrites one with the other.</p>
<p>But, if <code>&amp;mut T</code> was covariant over T, then <code>&amp;mut &amp;'static str</code> would be a
subtype of <code>&amp;mut &amp;'a str</code>, since <code>&amp;'static str</code> is a subtype of <code>&amp;'a str</code>.
Therefore the lifetime of <code>forever_str</code> would successfully be &quot;shrunk&quot; down
to the shorter lifetime of <code>string</code>, and <code>overwrite</code> would be called successfully.
<code>string</code> would subsequently be dropped, and <code>forever_str</code> would point to
freed memory when we print it! Therefore <code>&amp;mut</code> should be invariant.</p>
<p>This is the general theme of variance vs invariance: if variance would allow you
to store a short-lived value in a longer-lived slot, then invariance must be used.</p>
<p>More generally, the soundness of subtyping and variance is based on the idea that its ok to
forget details, but with mutable references there's always someone (the original
value being referenced) that remembers the forgotten details and will assume
that those details haven't changed. If we do something to invalidate those details,
the original location can behave unsoundly.</p>
<p>However it <em>is</em> sound for <code>&amp;'a mut T</code> to be covariant over <code>'a</code>. The key difference
between <code>'a</code> and T is that <code>'a</code> is a property of the reference itself,
while T is something the reference is borrowing. If you change T's type, then
the source still remembers the original type. However if you change the
lifetime's type, no one but the reference knows this information, so it's fine.
Put another way: <code>&amp;'a mut T</code> owns <code>'a</code>, but only <em>borrows</em> T.</p>
<p><code>Box</code> and <code>Vec</code> are interesting cases because they're covariant, but you can
definitely store values in them! This is where Rust's typesystem allows it to
be a bit more clever than others. To understand why it's sound for owning
containers to be covariant over their contents, we must consider
the two ways in which a mutation may occur: by-value or by-reference.</p>
<p>If mutation is by-value, then the old location that remembers extra details is
moved out of, meaning it can't use the value anymore. So we simply don't need to
worry about anyone remembering dangerous details. Put another way, applying
subtyping when passing by-value <em>destroys details forever</em>. For example, this
compiles and is fine:</p>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
fn get_box&lt;'a&gt;(str: &amp;'a str) -&gt; Box&lt;&amp;'a str&gt; {
    // String literals are `&amp;'static str`s, but it's fine for us to
    // &quot;forget&quot; this and let the caller think the string won't live that long.
    Box::new(&quot;hello&quot;)
}
#}</code></pre></pre>
<p>If mutation is by-reference, then our container is passed as <code>&amp;mut Vec&lt;T&gt;</code>. But
<code>&amp;mut</code> is invariant over its value, so <code>&amp;mut Vec&lt;T&gt;</code> is actually invariant over <code>T</code>.
So the fact that <code>Vec&lt;T&gt;</code> is covariant over <code>T</code> doesn't matter at all when
mutating by-reference.</p>
<p>But being covariant still allows <code>Box</code> and <code>Vec</code> to be weakened when shared
immutably. So you can pass a <code>&amp;Vec&lt;&amp;'static str&gt;</code> where a <code>&amp;Vec&lt;&amp;'a str&gt;</code> is
expected.</p>
<p>The invariance of the cell types can be seen as follows: <code>&amp;</code> is like an <code>&amp;mut</code>
for a cell, because you can still store values in them through an <code>&amp;</code>. Therefore
cells must be invariant to avoid lifetime smuggling.</p>
<p><code>fn</code> is the most subtle case because they have mixed variance, and in fact are
the only source of <strong>contra</strong>variance. To see why <code>fn(T) -&gt; U</code> should be contravariant
over T, consider the following function signature:</p>
<pre><code class="language-rust ignore">// 'a is derived from some parent scope
fn foo(&amp;'a str) -&gt; usize;
</code></pre>
<p>This signature claims that it can handle any <code>&amp;str</code> that lives at least as
long as <code>'a</code>. Now if this signature was <strong>co</strong>variant over <code>&amp;'a str</code>, that
would mean</p>
<pre><code class="language-rust ignore">fn foo(&amp;'static str) -&gt; usize;
</code></pre>
<p>could be provided in its place, as it would be a subtype. However this function
has a stronger requirement: it says that it can only handle <code>&amp;'static str</code>s,
and nothing else. Giving <code>&amp;'a str</code>s to it would be unsound, as it's free to
assume that what it's given lives forever. Therefore functions definitely shouldn't
be <strong>co</strong>variant over their arguments.</p>
<p>However if we flip it around and use <strong>contra</strong>variance, it <em>does</em> work! If
something expects a function which can handle strings that live forever,
it makes perfect sense to instead provide a function that can handle
strings that live for <em>less</em> than forever. So</p>
<pre><code class="language-rust ignore">fn foo(&amp;'a str) -&gt; usize;
</code></pre>
<p>can be passed where</p>
<pre><code class="language-rust ignore">fn foo(&amp;'static str) -&gt; usize;
</code></pre>
<p>is expected.</p>
<p>To see why <code>fn(T) -&gt; U</code> should be <strong>co</strong>variant over U, consider the following
function signature:</p>
<pre><code class="language-rust ignore">// 'a is derived from some parent scope
fn foo(usize) -&gt; &amp;'a str;
</code></pre>
<p>This signature claims that it will return something that outlives <code>'a</code>. It is
therefore completely reasonable to provide</p>
<pre><code class="language-rust ignore">fn foo(usize) -&gt; &amp;'static str;
</code></pre>
<p>in its place, as it does indeed return things that outlive <code>'a</code>. Therefore
functions are covariant over their return type.</p>
<p><code>*const</code> has the exact same semantics as <code>&amp;</code>, so variance follows. <code>*mut</code> on the
other hand can dereference to an <code>&amp;mut</code> whether shared or not, so it is marked
as invariant just like cells.</p>
<p>This is all well and good for the types the standard library provides, but
how is variance determined for type that <em>you</em> define? A struct, informally
speaking, inherits the variance of its fields. If a struct <code>Foo</code>
has a generic argument <code>A</code> that is used in a field <code>a</code>, then Foo's variance
over <code>A</code> is exactly <code>a</code>'s variance. However if <code>A</code> is used in multiple fields:</p>
<ul>
<li>If all uses of A are covariant, then Foo is covariant over A</li>
<li>If all uses of A are contravariant, then Foo is contravariant over A</li>
<li>Otherwise, Foo is invariant over A</li>
</ul>
<pre><pre class="playpen"><code class="language-rust">
# #![allow(unused_variables)]
#fn main() {
use std::cell::Cell;

struct Foo&lt;'a, 'b, A: 'a, B: 'b, C, D, E, F, G, H, In, Out, Mixed&gt; {
    a: &amp;'a A,     // covariant over 'a and A
    b: &amp;'b mut B, // covariant over 'b and invariant over B

    c: *const C,  // covariant over C
    d: *mut D,    // invariant over D

    e: E,         // covariant over E
    f: Vec&lt;F&gt;,    // covariant over F
    g: Cell&lt;G&gt;,   // invariant over G

    h1: H,        // would also be variant over H except...
    h2: Cell&lt;H&gt;,  // invariant over H, because invariance wins all conflicts

    i: fn(In) -&gt; Out,       // contravariant over In, covariant over Out

    k1: fn(Mixed) -&gt; usize, // would be contravariant over Mixed except..
    k2: Mixed,              // invariant over Mixed, because invariance wins all conflicts
}
#}</code></pre></pre>

                    </main>

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