From 5559d2ba046268a4597aba7901a48884ad7a97c0 Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Sat, 11 Jul 2015 19:48:42 -0500 Subject: [PATCH 1/5] Add explanation for E0210 and revise E0117. --- src/librustc_typeck/diagnostics.rs | 106 +++++++++++++++++++++++++---- 1 file changed, 92 insertions(+), 14 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 5027be5fb62a3..57a637da9502d 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -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 @@ -1263,14 +1269,6 @@ 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 for i32 { // or you use a type from your crate as // a type parameter fn from(i: Foo) -> i32 { @@ -1278,6 +1276,22 @@ impl From for i32 { // or you use a type from your crate as } } ``` + +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##" @@ -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 ForeignTrait for T { ... } // error +``` + +To work around this, it can be covered with a local type, `MyType`: + +``` +struct MyType(T); +impl ForeignTrait for MyType { ... } // 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 ForeignTrait2> 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 ForeignTrait2, T> for MyType2 { ... } // Ok +``` + +This only differs from the previous `impl` in that the parameters `T` and +`MyType` 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 ForeignTrait 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 +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: @@ -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 From 243982443f0b94c8fb7dca42b7d8f3d5f7f0209f Mon Sep 17 00:00:00 2001 From: Nick Hamann Date: Mon, 13 Jul 2015 15:55:53 -0500 Subject: [PATCH 2/5] Clarify E0117 explanation. --- src/librustc_typeck/diagnostics.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs index 57a637da9502d..3e4a2c3116ea4 100644 --- a/src/librustc_typeck/diagnostics.rs +++ b/src/librustc_typeck/diagnostics.rs @@ -1259,8 +1259,8 @@ Here's one example of this error: impl Drop for u32 {} ``` -To avoid this error, ensure that at least one local type is referenced by -the `impl`: +To avoid this kind of error, ensure that at least one local type is referenced +by the `impl`: ``` pub struct Foo; // you define your type in your crate From d10953e5a2a50912a62b7cbab6775caccaecbdf2 Mon Sep 17 00:00:00 2001 From: Cole Reynolds Date: Thu, 30 Jul 2015 23:40:04 -0400 Subject: [PATCH 3/5] Minor grammatical changes to send-and-sync. Corrects formatting of bullet-ed sentences and changes 'pervasive use raw pointers' to 'pervasive use of raw pointers' --- src/doc/tarpl/send-and-sync.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/tarpl/send-and-sync.md b/src/doc/tarpl/send-and-sync.md index 5b00709a1bf40..e65dbb9b13102 100644 --- a/src/doc/tarpl/send-and-sync.md +++ b/src/doc/tarpl/send-and-sync.md @@ -5,8 +5,8 @@ multiply alias a location in memory while mutating it. Unless these types use synchronization to manage this access, they are absolutely not thread safe. Rust captures this with through the `Send` and `Sync` traits. -* A type is Send if it is safe to send it to another thread. A type is Sync if -* it is safe to share between threads (`&T` is Send). +* A type is Send if it is safe to send it to another thread. +* A type is Sync if it is safe to share between threads (`&T` is Send). Send and Sync are *very* fundamental to Rust's concurrency story. As such, a substantial amount of special tooling exists to make them work right. First and @@ -25,9 +25,9 @@ ever interact with are Send and Sync. Major exceptions include: -* raw pointers are neither Send nor Sync (because they have no safety guards) -* `UnsafeCell` isn't Sync (and therefore `Cell` and `RefCell` aren't) `Rc` isn't -* Send or Sync (because the refcount is shared and unsynchronized) +* raw pointers are neither Send nor Sync (because they have no safety guards). +* `UnsafeCell` isn't Sync (and therefore `Cell` and `RefCell` aren't). +* `Rc` isn't Send or Sync (because the refcount is shared and unsynchronized). `Rc` and `UnsafeCell` are very fundamentally not thread-safe: they enable unsynchronized shared mutable state. However raw pointers are, strictly @@ -71,7 +71,7 @@ possible cause trouble by being incorrectly Send or Sync. Most uses of raw pointers should be encapsulated behind a sufficient abstraction that Send and Sync can be derived. For instance all of Rust's standard collections are Send and Sync (when they contain Send and Sync types) in spite -of their pervasive use raw pointers to manage allocations and complex ownership. +of their pervasive use of raw pointers to manage allocations and complex ownership. Similarly, most iterators into these collections are Send and Sync because they largely behave like an `&` or `&mut` into the collection. From 6a86a0c89c932b971bc4e5846abcf54769d3b6b4 Mon Sep 17 00:00:00 2001 From: Oliver Schneider Date: Fri, 31 Jul 2015 09:32:53 +0200 Subject: [PATCH 4/5] fix code and error to match the surronding text --- src/doc/tarpl/borrow-splitting.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/src/doc/tarpl/borrow-splitting.md b/src/doc/tarpl/borrow-splitting.md index 123e2baf8fafd..a394d8f964766 100644 --- a/src/doc/tarpl/borrow-splitting.md +++ b/src/doc/tarpl/borrow-splitting.md @@ -27,19 +27,27 @@ However borrowck doesn't understand arrays or slices in any way, so this doesn't work: ```rust,ignore -let x = [1, 2, 3]; +let mut x = [1, 2, 3]; let a = &mut x[0]; let b = &mut x[1]; println!("{} {}", a, b); ``` ```text -:3:18: 3:22 error: cannot borrow immutable indexed content `x[..]` as mutable -:3 let a = &mut x[0]; - ^~~~ -:4:18: 4:22 error: cannot borrow immutable indexed content `x[..]` as mutable -:4 let b = &mut x[1]; - ^~~~ +:4:14: 4:18 error: cannot borrow `x[..]` as mutable more than once at a time +:4 let b = &mut x[1]; + ^~~~ +:3:14: 3:18 note: previous borrow of `x[..]` occurs here; the mutable borrow prevents subsequent moves, borrows, or modification of `x[..]` until the borrow ends +:3 let a = &mut x[0]; + ^~~~ +:6:2: 6:2 note: previous borrow ends here +:1 fn main() { +:2 let mut x = [1, 2, 3]; +:3 let a = &mut x[0]; +:4 let b = &mut x[1]; +:5 println!("{} {}", a, b); +:6 } + ^ error: aborting due to 2 previous errors ``` From b399729298ae5fa4f98a46d40682fb9e404f8e00 Mon Sep 17 00:00:00 2001 From: FuGangqiang Date: Fri, 31 Jul 2015 16:25:17 +0800 Subject: [PATCH 5/5] trpl: fix link error --- src/libstd/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 61de7eafbb5a3..010e2cc7bb2d4 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -15,7 +15,7 @@ //! for the [broader Rust ecosystem](https://crates.io). It offers //! core types (e.g. [`Vec`](vec/index.html) //! and [`Option`](option/index.html)), library-defined [operations on -//! language primitives](#primitive) (e.g. [`u32`](u32/index.html) and +//! language primitives](#primitives) (e.g. [`u32`](u32/index.html) and //! [`str`](str/index.html)), [standard macros](#macros), //! [I/O](io/index.html) and [multithreading](thread/index.html), among //! [many other lovely