Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add explanation for E0210 and revise E0117. #26982

Merged
merged 2 commits into from
Aug 1, 2015
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 92 additions & 14 deletions src/librustc_typeck/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1245,16 +1245,22 @@ impl Bytes { ... } // error, same as above
"##,

E0117: r##"
You got this error because because you tried to implement a foreign
trait for a foreign type (with maybe a foreign type parameter). Erroneous
code example:
This error indicates a violation of one of Rust's orphan rules for trait
implementations. The rule prohibits any implementation of a foreign trait (a
trait defined in another crate) where

- the type that is implementing the trait is foreign
- all of the parameters being passed to the trait (if there are any) are also
foreign.

Here's one example of this error:

```
impl Drop for u32 {}
```

The type, trait or the type parameter (or all of them) has to be defined
in your crate. Example:
To avoid this error, ensure that at least one local type is referenced by
the `impl`:

```
pub struct Foo; // you define your type in your crate
Expand All @@ -1263,21 +1269,29 @@ impl Drop for Foo { // and you can implement the trait on it!
// code of trait implementation here
}

trait Bar { // or define your trait in your crate
fn get(&self) -> usize;
}

impl Bar for u32 { // and then you implement it on a foreign type
fn get(&self) -> usize { 0 }
}

impl From<Foo> for i32 { // or you use a type from your crate as
// a type parameter
fn from(i: Foo) -> i32 {
0
}
}
```

Alternatively, define a trait locally and implement that instead:

```
trait Bar {
fn get(&self) -> usize;
}

impl Bar for u32 {
fn get(&self) -> usize { 0 }
}
```

For information on the design of the orphan rules, see [RFC 1023].

[RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
"##,

E0119: r##"
Expand Down Expand Up @@ -1833,6 +1847,71 @@ impl MyTrait for Foo {
```
"##,

E0210: r##"
This error indicates a violation of one of Rust's orphan rules for trait
implementations. The rule concerns the use of type parameters in an
implementation of a foreign trait (a trait defined in another crate), and
states that type parameters must be "covered" by a local type. To understand
what this means, it is perhaps easiest to consider a few examples.

If `ForeignTrait` is a trait defined in some external crate `foo`, then the
following trait `impl` is an error:

```
extern crate foo;
use foo::ForeignTrait;

impl<T> ForeignTrait for T { ... } // error
```

To work around this, it can be covered with a local type, `MyType`:

```
struct MyType<T>(T);
impl<T> ForeignTrait for MyType<T> { ... } // Ok
```

For another example of an error, suppose there's another trait defined in `foo`
named `ForeignTrait2` that takes two type parameters. Then this `impl` results
in the same rule violation:

```
struct MyType2;
impl<T> ForeignTrait2<T, MyType<T>> for MyType2 { ... } // error
```

The reason for this is that there are two appearances of type parameter `T` in
the `impl` header, both as parameters for `ForeignTrait2`. The first appearance
is uncovered, and so runs afoul of the orphan rule.

Consider one more example:

```
impl<T> ForeignTrait2<MyType<T>, T> for MyType2 { ... } // Ok
```

This only differs from the previous `impl` in that the parameters `T` and
`MyType<T>` for `ForeignTrait2` have been swapped. This example does *not*
violate the orphan rule; it is permitted.

To see why that last example was allowed, you need to understand the general
rule. Unfortunately this rule is a bit tricky to state. Consider an `impl`:

```
impl<P1, ..., Pm> ForeignTrait<T1, ..., Tn> for T0 { ... }
```

where `P1, ..., Pm` are the type parameters of the `impl` and `T0, ..., Tn`
are types. One of the types `T0, ..., Tn` must be a local type (this is another
orphan rule, see the explanation for E0117). Let `i` be the smallest integer
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a spurious tidy failure due to the use of "E0117" in this line. I'm looking into how fixable it is

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is fixed now

such that `Ti` is a local type. Then no type parameter can appear in any of the
`Tj` for `j < i`.

For information on the design of the orphan rules, see [RFC 1023].

[RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
"##,

E0211: r##"
You used an intrinsic function which doesn't correspond to its
definition. Erroneous code example:
Expand Down Expand Up @@ -2148,7 +2227,6 @@ register_diagnostics! {
// and only one is supported
E0208,
E0209, // builtin traits can only be implemented on structs or enums
E0210, // type parameter is not constrained by any local type
E0212, // cannot extract an associated type from a higher-ranked trait bound
E0213, // associated types are not accepted in this context
E0214, // parenthesized parameters may only be used with a trait
Expand Down