Skip to content

Commit 5559d2b

Browse files
author
Nick Hamann
committed
Add explanation for E0210 and revise E0117.
1 parent 1b28ffa commit 5559d2b

File tree

1 file changed

+92
-14
lines changed

1 file changed

+92
-14
lines changed

src/librustc_typeck/diagnostics.rs

Lines changed: 92 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,16 +1245,22 @@ impl Bytes { ... } // error, same as above
12451245
"##,
12461246

12471247
E0117: r##"
1248-
You got this error because because you tried to implement a foreign
1249-
trait for a foreign type (with maybe a foreign type parameter). Erroneous
1250-
code example:
1248+
This error indicates a violation of one of Rust's orphan rules for trait
1249+
implementations. The rule prohibits any implementation of a foreign trait (a
1250+
trait defined in another crate) where
1251+
1252+
- the type that is implementing the trait is foreign
1253+
- all of the parameters being passed to the trait (if there are any) are also
1254+
foreign.
1255+
1256+
Here's one example of this error:
12511257
12521258
```
12531259
impl Drop for u32 {}
12541260
```
12551261
1256-
The type, trait or the type parameter (or all of them) has to be defined
1257-
in your crate. Example:
1262+
To avoid this error, ensure that at least one local type is referenced by
1263+
the `impl`:
12581264
12591265
```
12601266
pub struct Foo; // you define your type in your crate
@@ -1263,21 +1269,29 @@ impl Drop for Foo { // and you can implement the trait on it!
12631269
// code of trait implementation here
12641270
}
12651271
1266-
trait Bar { // or define your trait in your crate
1267-
fn get(&self) -> usize;
1268-
}
1269-
1270-
impl Bar for u32 { // and then you implement it on a foreign type
1271-
fn get(&self) -> usize { 0 }
1272-
}
1273-
12741272
impl From<Foo> for i32 { // or you use a type from your crate as
12751273
// a type parameter
12761274
fn from(i: Foo) -> i32 {
12771275
0
12781276
}
12791277
}
12801278
```
1279+
1280+
Alternatively, define a trait locally and implement that instead:
1281+
1282+
```
1283+
trait Bar {
1284+
fn get(&self) -> usize;
1285+
}
1286+
1287+
impl Bar for u32 {
1288+
fn get(&self) -> usize { 0 }
1289+
}
1290+
```
1291+
1292+
For information on the design of the orphan rules, see [RFC 1023].
1293+
1294+
[RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
12811295
"##,
12821296

12831297
E0119: r##"
@@ -1833,6 +1847,71 @@ impl MyTrait for Foo {
18331847
```
18341848
"##,
18351849

1850+
E0210: r##"
1851+
This error indicates a violation of one of Rust's orphan rules for trait
1852+
implementations. The rule concerns the use of type parameters in an
1853+
implementation of a foreign trait (a trait defined in another crate), and
1854+
states that type parameters must be "covered" by a local type. To understand
1855+
what this means, it is perhaps easiest to consider a few examples.
1856+
1857+
If `ForeignTrait` is a trait defined in some external crate `foo`, then the
1858+
following trait `impl` is an error:
1859+
1860+
```
1861+
extern crate foo;
1862+
use foo::ForeignTrait;
1863+
1864+
impl<T> ForeignTrait for T { ... } // error
1865+
```
1866+
1867+
To work around this, it can be covered with a local type, `MyType`:
1868+
1869+
```
1870+
struct MyType<T>(T);
1871+
impl<T> ForeignTrait for MyType<T> { ... } // Ok
1872+
```
1873+
1874+
For another example of an error, suppose there's another trait defined in `foo`
1875+
named `ForeignTrait2` that takes two type parameters. Then this `impl` results
1876+
in the same rule violation:
1877+
1878+
```
1879+
struct MyType2;
1880+
impl<T> ForeignTrait2<T, MyType<T>> for MyType2 { ... } // error
1881+
```
1882+
1883+
The reason for this is that there are two appearances of type parameter `T` in
1884+
the `impl` header, both as parameters for `ForeignTrait2`. The first appearance
1885+
is uncovered, and so runs afoul of the orphan rule.
1886+
1887+
Consider one more example:
1888+
1889+
```
1890+
impl<T> ForeignTrait2<MyType<T>, T> for MyType2 { ... } // Ok
1891+
```
1892+
1893+
This only differs from the previous `impl` in that the parameters `T` and
1894+
`MyType<T>` for `ForeignTrait2` have been swapped. This example does *not*
1895+
violate the orphan rule; it is permitted.
1896+
1897+
To see why that last example was allowed, you need to understand the general
1898+
rule. Unfortunately this rule is a bit tricky to state. Consider an `impl`:
1899+
1900+
```
1901+
impl<P1, ..., Pm> ForeignTrait<T1, ..., Tn> for T0 { ... }
1902+
```
1903+
1904+
where `P1, ..., Pm` are the type parameters of the `impl` and `T0, ..., Tn`
1905+
are types. One of the types `T0, ..., Tn` must be a local type (this is another
1906+
orphan rule, see the explanation for E0117). Let `i` be the smallest integer
1907+
such that `Ti` is a local type. Then no type parameter can appear in any of the
1908+
`Tj` for `j < i`.
1909+
1910+
For information on the design of the orphan rules, see [RFC 1023].
1911+
1912+
[RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
1913+
"##,
1914+
18361915
E0211: r##"
18371916
You used an intrinsic function which doesn't correspond to its
18381917
definition. Erroneous code example:
@@ -2148,7 +2227,6 @@ register_diagnostics! {
21482227
// and only one is supported
21492228
E0208,
21502229
E0209, // builtin traits can only be implemented on structs or enums
2151-
E0210, // type parameter is not constrained by any local type
21522230
E0212, // cannot extract an associated type from a higher-ranked trait bound
21532231
E0213, // associated types are not accepted in this context
21542232
E0214, // parenthesized parameters may only be used with a trait

0 commit comments

Comments
 (0)