<p dir="auto"><strong>UPDATED DESCRIPTION:</strong></p>
<p dir="auto">We now allow the original problem, but some corner cases are still unhandled. See comments below.</p>
<p dir="auto"><strong>ORIGINAL DESCRIPTION:</strong></p>
<p dir="auto">Where clauses right now require predicates to contain type parameters, as in:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="trait Foo {
    fn foo(&amp;self);
}

struct Bar&lt;T&gt; {
    x: T,
}

impl&lt;T&gt; Foo for Bar&lt;T&gt; where T: Foo {
    fn foo(&amp;self) {
        self.x.foo()
    }
}"><pre class="notranslate"><span class="pl-k">trait</span> <span class="pl-smi">Foo</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">foo</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-kos">;</span>
<span class="pl-kos">}</span>

<span class="pl-k">struct</span> <span class="pl-smi">Bar</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-c1">x</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">&gt;</span> <span class="pl-smi">Foo</span> <span class="pl-k">for</span> <span class="pl-smi">Bar</span><span class="pl-kos">&lt;</span><span class="pl-smi">T</span><span class="pl-kos">&gt;</span> <span class="pl-k">where</span> <span class="pl-smi">T</span><span class="pl-kos">:</span> <span class="pl-smi">Foo</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">foo</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-kos">{</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-en">foo</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">But we cannot add constraints on non-generic types:</p>
<div class="highlight highlight-source-rust notranslate position-relative overflow-auto" dir="auto" data-snippet-clipboard-copy-content="struct Baz { x: i32 }

impl Foo for Baz where i32: Foo {
    fn foo(&amp;self) {
        self.x.foo()
    }
}"><pre class="notranslate"><span class="pl-k">struct</span> <span class="pl-smi">Baz</span> <span class="pl-kos">{</span> <span class="pl-c1">x</span><span class="pl-kos">:</span> <span class="pl-smi">i32</span> <span class="pl-kos">}</span>

<span class="pl-k">impl</span> <span class="pl-smi">Foo</span> <span class="pl-k">for</span> <span class="pl-smi">Baz</span> <span class="pl-k">where</span> <span class="pl-smi">i32</span><span class="pl-kos">:</span> <span class="pl-smi">Foo</span> <span class="pl-kos">{</span>
    <span class="pl-k">fn</span> <span class="pl-en">foo</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-kos">{</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-en">foo</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">Will error out with:</p>
<div class="snippet-clipboard-content notranslate position-relative overflow-auto" data-snippet-clipboard-copy-content="test.rs:15:1: 19:2 error: cannot bound type `i32`, where clause bounds may only be attached to types involving type parameters
test.rs:15 impl Foo for Baz where i32: Foo {
test.rs:16     fn foo(&amp;self) {
test.rs:17         self.x.foo()
test.rs:18     }
test.rs:19 }"><pre class="notranslate"><code class="notranslate">test.rs:15:1: 19:2 error: cannot bound type `i32`, where clause bounds may only be attached to types involving type parameters
test.rs:15 impl Foo for Baz where i32: Foo {
test.rs:16     fn foo(&amp;self) {
test.rs:17         self.x.foo()
test.rs:18     }
test.rs:19 }
</code></pre></div>
<p dir="auto">In hand written code this usually won't come up, but this would be really helpful for a code generator like <code class="notranslate">macro_rules!</code> or <code class="notranslate">#[derive]</code>, especially when dealing with associated types. Currently the only way to know if a type is generic or not is to manually walk it and see if any of the type paths start with the same name as a type parameter. If so, add that type to the predicate list. Instead, it would be much simpler if we could just add all the types listed in a field or enum to the predicate list and let the type checker report an error if one of those types doesn't implement the trait.</p>
<p dir="auto">cc <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/nikomatsakis/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/nikomatsakis">@nikomatsakis</a>, <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/jroesch/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/jroesch">@jroesch</a></p>
<p dir="auto">Today’s <a href="http://static.rust-lang.org/dist/rust-nightly-x86_64-unknown-linux-gnu.tar.gz" rel="nofollow">rust-nightly-x86_64-unknown-linux-gnu.tar.gz</a> is 125MiB in size. I did a <code class="notranslate">make dist-tar-bins</code> which output <del>the same</del> tarball, but only 88MiB in size. <del>This is 70% of whatever we publish to s3.</del></p>
<p dir="auto">I took liberty to also test:</p>
<ul dir="auto">
<li><del>xz (the default level, -6) → 69MiB (55% original);</del></li>
<li><del>xz -9 → 59MiB (47% original, but has high memory requirements to decompress)</del></li>
<li><del>bz2 → 82MiB (65% original);</del></li>
<li><del>lzma → 69MiB, but took longer than xz.</del></li>
</ul>
<p dir="auto">I strongly propose to either migrate to a more modern compression algorithm (xz) <del>or at least investigating why gzip does such a bad job on the build bots</del>.</p>
<p dir="auto">cc <a class="user-mention notranslate" data-hovercard-type="user" data-hovercard-url="/users/brson/hovercard" data-octo-click="hovercard-link-click" data-octo-dimensions="link_type:self" href="https://github.com/brson">@brson</a></p>