about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2016-05-15 20:13:40 +0530
committerManish Goregaokar <manishsmail@gmail.com>2016-05-15 20:13:40 +0530
commita9a130f6af7fa29bd3fbe5c5327dd7e2eb585ecd (patch)
tree38b16c99f3ca4ea3f6e8059167f4e1f4d464871c
parent03ec483a72a76e63fc09c64b34f0bbd293a4c162 (diff)
parent1e901de9e878519b962dbca0c6e39f0bdf39af8f (diff)
downloadrust-a9a130f6af7fa29bd3fbe5c5327dd7e2eb585ecd.tar.gz
rust-a9a130f6af7fa29bd3fbe5c5327dd7e2eb585ecd.zip
Rollup merge of #33415 - dfockler:master, r=steveklabnik
Add error explanations for E0374, E0375, E0376 on issue #32777
-rw-r--r--src/librustc_typeck/diagnostics.rs165
1 files changed, 158 insertions, 7 deletions
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index 05e4c79a7e8..629a715d6bf 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -3284,6 +3284,164 @@ impl Baz for Bar { } // Note: This is OK
 ```
 "##,
 
+E0374: r##"
+A struct without a field containing an unsized type cannot implement
+`CoerceUnsized`. An
+[unsized type](https://doc.rust-lang.org/book/unsized-types.html)
+is any type that the compiler doesn't know the length or alignment of at
+compile time. Any struct containing an unsized type is also unsized.
+
+Example of erroneous code:
+
+```compile_fail
+#![feature(coerce_unsized)]
+use std::ops::CoerceUnsized;
+
+struct Foo<T: ?Sized> {
+    a: i32,
+}
+
+// error: Struct `Foo` has no unsized fields that need `CoerceUnsized`.
+impl<T, U> CoerceUnsized<Foo<U>> for Foo<T>
+    where T: CoerceUnsized<U> {}
+```
+
+`CoerceUnsized` is used to coerce one struct containing an unsized type
+into another struct containing a different unsized type. If the struct
+doesn't have any fields of unsized types then you don't need explicit
+coercion to get the types you want. To fix this you can either
+not try to implement `CoerceUnsized` or you can add a field that is
+unsized to the struct.
+
+Example:
+
+```
+#![feature(coerce_unsized)]
+use std::ops::CoerceUnsized;
+
+// We don't need to impl `CoerceUnsized` here.
+struct Foo {
+    a: i32,
+}
+
+// We add the unsized type field to the struct.
+struct Bar<T: ?Sized> {
+    a: i32,
+    b: T,
+}
+
+// The struct has an unsized field so we can implement
+// `CoerceUnsized` for it.
+impl<T, U> CoerceUnsized<Bar<U>> for Bar<T>
+    where T: CoerceUnsized<U> {}
+```
+
+Note that `CoerceUnsized` is mainly used by smart pointers like `Box`, `Rc`
+and `Arc` to be able to mark that they can coerce unsized types that they
+are pointing at.
+"##,
+
+E0375: r##"
+A struct with more than one field containing an unsized type cannot implement
+`CoerceUnsized`. This only occurs when you are trying to coerce one of the
+types in your struct to another type in the struct. In this case we try to
+impl `CoerceUnsized` from `T` to `U` which are both types that the struct
+takes. An [unsized type](https://doc.rust-lang.org/book/unsized-types.html)
+is any type that the compiler doesn't know the length or alignment of at
+compile time. Any struct containing an unsized type is also unsized.
+
+Example of erroneous code:
+
+```compile_fail
+#![feature(coerce_unsized)]
+use std::ops::CoerceUnsized;
+
+struct Foo<T: ?Sized, U: ?Sized> {
+    a: i32,
+    b: T,
+    c: U,
+}
+
+// error: Struct `Foo` has more than one unsized field.
+impl<T, U> CoerceUnsized<Foo<U, T>> for Foo<T, U> {}
+```
+
+`CoerceUnsized` only allows for coercion from a structure with a single
+unsized type field to another struct with a single unsized type field.
+In fact Rust only allows for a struct to have one unsized type in a struct
+and that unsized type must be the last field in the struct. So having two
+unsized types in a single struct is not allowed by the compiler. To fix this
+use only one field containing an unsized type in the struct and then use
+multiple structs to manage each unsized type field you need.
+
+Example:
+
+```
+#![feature(coerce_unsized)]
+use std::ops::CoerceUnsized;
+
+struct Foo<T: ?Sized> {
+    a: i32,
+    b: T,
+}
+
+impl <T, U> CoerceUnsized<Foo<U>> for Foo<T>
+    where T: CoerceUnsized<U> {}
+
+fn coerce_foo<T: CoerceUnsized<U>, U>(t: T) -> Foo<U> {
+    Foo { a: 12i32, b: t } // we use coercion to get the `Foo<U>` type we need
+}
+```
+
+"##,
+
+E0376: r##"
+The type you are trying to impl `CoerceUnsized` for is not a struct.
+`CoerceUnsized` can only be implemented for a struct. Unsized types are
+already able to be coerced without an implementation of `CoerceUnsized`
+whereas a struct containing an unsized type needs to know the unsized type
+field it's containing is able to be coerced. An
+[unsized type](https://doc.rust-lang.org/book/unsized-types.html)
+is any type that the compiler doesn't know the length or alignment of at
+compile time. Any struct containing an unsized type is also unsized.
+
+Example of erroneous code:
+
+```compile_fail
+#![feature(coerce_unsized)]
+use std::ops::CoerceUnsized;
+
+struct Foo<T: ?Sized> {
+    a: T,
+}
+
+// error: The type `U` is not a struct
+impl<T, U> CoerceUnsized<U> for Foo<T> {}
+```
+
+The `CoerceUnsized` trait takes a struct type. Make sure the type you are
+providing to `CoerceUnsized` is a struct with only the last field containing an
+unsized type.
+
+Example:
+
+```
+#![feature(coerce_unsized)]
+use std::ops::CoerceUnsized;
+
+struct Foo<T> {
+    a: T,
+}
+
+// The `Foo<U>` is a struct so `CoerceUnsized` can be implemented
+impl<T, U> CoerceUnsized<Foo<U>> for Foo<T> where T: CoerceUnsized<U> {}
+```
+
+Note that in Rust, structs can only contain an unsized type if the field
+containing the unsized type is the last and only unsized type field in the
+struct.
+"##,
+
 E0379: r##"
 Trait methods cannot be declared `const` by design. For more information, see
 [RFC 911].
@@ -3777,13 +3935,6 @@ register_diagnostics! {
     E0320, // recursive overflow during dropck
     E0328, // cannot implement Unsize explicitly
 //  E0372, // coherence not object safe
-    E0374, // the trait `CoerceUnsized` may only be implemented for a coercion
-           // between structures with one field being coerced, none found
-    E0375, // the trait `CoerceUnsized` may only be implemented for a coercion
-           // between structures with one field being coerced, but multiple
-           // fields need coercions
-    E0376, // the trait `CoerceUnsized` may only be implemented for a coercion
-           // between structures
     E0377, // the trait `CoerceUnsized` may only be implemented for a coercion
            // between structures with the same definition
     E0399, // trait items need to be implemented because the associated