Skip to content

Commit 21dd5e6

Browse files
committed
Rollup merge of rust-lang#26982 - nham:orphan-explanations, r=Gankro
part of rust-lang#24407 I'm not sure whether I should be trying to explain the general rule in the E0210 explanation or just point people to the RFC. However, if we go with the latter option I think that the RFC will need to be revised slightly, since it is not quite as gentle as I would like. Also, the link to RFC 1023 is not the correct one (it should be https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md), but the correct one is too long. I'm aware of @michaelsproul's PR rust-lang#26290 from awhile back, but it doesn't seem to be working. Has there not been a new snapshot yet?
2 parents f50518e + 2439824 commit 21dd5e6

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
@@ -1227,16 +1227,22 @@ impl Bytes { ... } // error, same as above
12271227
"##,
12281228

12291229
E0117: r##"
1230-
You got this error because because you tried to implement a foreign
1231-
trait for a foreign type (with maybe a foreign type parameter). Erroneous
1232-
code example:
1230+
This error indicates a violation of one of Rust's orphan rules for trait
1231+
implementations. The rule prohibits any implementation of a foreign trait (a
1232+
trait defined in another crate) where
1233+
1234+
- the type that is implementing the trait is foreign
1235+
- all of the parameters being passed to the trait (if there are any) are also
1236+
foreign.
1237+
1238+
Here's one example of this error:
12331239
12341240
```
12351241
impl Drop for u32 {}
12361242
```
12371243
1238-
The type, trait or the type parameter (or all of them) has to be defined
1239-
in your crate. Example:
1244+
To avoid this kind of error, ensure that at least one local type is referenced
1245+
by the `impl`:
12401246
12411247
```
12421248
pub struct Foo; // you define your type in your crate
@@ -1245,21 +1251,29 @@ impl Drop for Foo { // and you can implement the trait on it!
12451251
// code of trait implementation here
12461252
}
12471253
1248-
trait Bar { // or define your trait in your crate
1249-
fn get(&self) -> usize;
1250-
}
1251-
1252-
impl Bar for u32 { // and then you implement it on a foreign type
1253-
fn get(&self) -> usize { 0 }
1254-
}
1255-
12561254
impl From<Foo> for i32 { // or you use a type from your crate as
12571255
// a type parameter
12581256
fn from(i: Foo) -> i32 {
12591257
0
12601258
}
12611259
}
12621260
```
1261+
1262+
Alternatively, define a trait locally and implement that instead:
1263+
1264+
```
1265+
trait Bar {
1266+
fn get(&self) -> usize;
1267+
}
1268+
1269+
impl Bar for u32 {
1270+
fn get(&self) -> usize { 0 }
1271+
}
1272+
```
1273+
1274+
For information on the design of the orphan rules, see [RFC 1023].
1275+
1276+
[RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
12631277
"##,
12641278

12651279
E0119: r##"
@@ -1889,6 +1903,71 @@ impl MyTrait for Foo {
18891903
```
18901904
"##,
18911905

1906+
E0210: r##"
1907+
This error indicates a violation of one of Rust's orphan rules for trait
1908+
implementations. The rule concerns the use of type parameters in an
1909+
implementation of a foreign trait (a trait defined in another crate), and
1910+
states that type parameters must be "covered" by a local type. To understand
1911+
what this means, it is perhaps easiest to consider a few examples.
1912+
1913+
If `ForeignTrait` is a trait defined in some external crate `foo`, then the
1914+
following trait `impl` is an error:
1915+
1916+
```
1917+
extern crate foo;
1918+
use foo::ForeignTrait;
1919+
1920+
impl<T> ForeignTrait for T { ... } // error
1921+
```
1922+
1923+
To work around this, it can be covered with a local type, `MyType`:
1924+
1925+
```
1926+
struct MyType<T>(T);
1927+
impl<T> ForeignTrait for MyType<T> { ... } // Ok
1928+
```
1929+
1930+
For another example of an error, suppose there's another trait defined in `foo`
1931+
named `ForeignTrait2` that takes two type parameters. Then this `impl` results
1932+
in the same rule violation:
1933+
1934+
```
1935+
struct MyType2;
1936+
impl<T> ForeignTrait2<T, MyType<T>> for MyType2 { ... } // error
1937+
```
1938+
1939+
The reason for this is that there are two appearances of type parameter `T` in
1940+
the `impl` header, both as parameters for `ForeignTrait2`. The first appearance
1941+
is uncovered, and so runs afoul of the orphan rule.
1942+
1943+
Consider one more example:
1944+
1945+
```
1946+
impl<T> ForeignTrait2<MyType<T>, T> for MyType2 { ... } // Ok
1947+
```
1948+
1949+
This only differs from the previous `impl` in that the parameters `T` and
1950+
`MyType<T>` for `ForeignTrait2` have been swapped. This example does *not*
1951+
violate the orphan rule; it is permitted.
1952+
1953+
To see why that last example was allowed, you need to understand the general
1954+
rule. Unfortunately this rule is a bit tricky to state. Consider an `impl`:
1955+
1956+
```
1957+
impl<P1, ..., Pm> ForeignTrait<T1, ..., Tn> for T0 { ... }
1958+
```
1959+
1960+
where `P1, ..., Pm` are the type parameters of the `impl` and `T0, ..., Tn`
1961+
are types. One of the types `T0, ..., Tn` must be a local type (this is another
1962+
orphan rule, see the explanation for E0117). Let `i` be the smallest integer
1963+
such that `Ti` is a local type. Then no type parameter can appear in any of the
1964+
`Tj` for `j < i`.
1965+
1966+
For information on the design of the orphan rules, see [RFC 1023].
1967+
1968+
[RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
1969+
"##,
1970+
18921971
E0211: r##"
18931972
You used an intrinsic function which doesn't correspond to its
18941973
definition. Erroneous code example:
@@ -2335,7 +2414,6 @@ register_diagnostics! {
23352414
// and only one is supported
23362415
E0208,
23372416
E0209, // builtin traits can only be implemented on structs or enums
2338-
E0210, // type parameter is not constrained by any local type
23392417
E0212, // cannot extract an associated type from a higher-ranked trait bound
23402418
E0213, // associated types are not accepted in this context
23412419
E0214, // parenthesized parameters may only be used with a trait

0 commit comments

Comments
 (0)